xref: /rk3399_rockchip-uboot/drivers/ram/rockchip/sdram_rv1126.c (revision 0367dfefd7dceefdbde5f0517ac8e0aa6f34e4cd)
1f520bb22SYouMin Chen // SPDX-License-Identifier: GPL-2.0
2f520bb22SYouMin Chen /*
3f520bb22SYouMin Chen  * (C) Copyright 2020 Rockchip Electronics Co., Ltd.
4f520bb22SYouMin Chen  */
5f520bb22SYouMin Chen 
6f520bb22SYouMin Chen #include <common.h>
7f520bb22SYouMin Chen #include <debug_uart.h>
8f520bb22SYouMin Chen #include <dm.h>
9f520bb22SYouMin Chen #include <ram.h>
10f520bb22SYouMin Chen #include <syscon.h>
11f520bb22SYouMin Chen #include <asm/io.h>
12f520bb22SYouMin Chen #include <asm/arch/clock.h>
13f520bb22SYouMin Chen #include <asm/arch/hardware.h>
14f520bb22SYouMin Chen #include <asm/arch/rk_atags.h>
15f520bb22SYouMin Chen #include <asm/arch/cru_rv1126.h>
16f520bb22SYouMin Chen #include <asm/arch/grf_rv1126.h>
17f520bb22SYouMin Chen #include <asm/arch/sdram_common.h>
18f520bb22SYouMin Chen #include <asm/arch/sdram_rv1126.h>
19f520bb22SYouMin Chen 
20f520bb22SYouMin Chen /* define training flag */
21f520bb22SYouMin Chen #define CA_TRAINING			(0x1 << 0)
22f520bb22SYouMin Chen #define READ_GATE_TRAINING		(0x1 << 1)
23f520bb22SYouMin Chen #define WRITE_LEVELING			(0x1 << 2)
24f520bb22SYouMin Chen #define WRITE_TRAINING			(0x1 << 3)
25f520bb22SYouMin Chen #define READ_TRAINING			(0x1 << 4)
26f520bb22SYouMin Chen #define FULL_TRAINING			(0xff)
27f520bb22SYouMin Chen 
28f520bb22SYouMin Chen #define SKEW_RX_SIGNAL			(0)
29f520bb22SYouMin Chen #define SKEW_TX_SIGNAL			(1)
30f520bb22SYouMin Chen #define SKEW_CA_SIGNAL			(2)
31f520bb22SYouMin Chen 
32f520bb22SYouMin Chen #define DESKEW_MDF_ABS_VAL		(0)
33f520bb22SYouMin Chen #define DESKEW_MDF_DIFF_VAL		(1)
34f520bb22SYouMin Chen 
35f520bb22SYouMin Chen #ifdef CONFIG_TPL_BUILD
36f520bb22SYouMin Chen #ifndef CONFIG_TPL_TINY_FRAMEWORK
37f520bb22SYouMin Chen #error please defined CONFIG_TPL_TINY_FRAMEWORK for RV1126 !!!
38f520bb22SYouMin Chen #endif
39f520bb22SYouMin Chen #endif
40f520bb22SYouMin Chen 
41f520bb22SYouMin Chen #ifdef CONFIG_TPL_BUILD
42f520bb22SYouMin Chen 
43f520bb22SYouMin Chen struct dram_info {
44f520bb22SYouMin Chen 	void __iomem *pctl;
45f520bb22SYouMin Chen 	void __iomem *phy;
46f520bb22SYouMin Chen 	struct rv1126_cru *cru;
47f520bb22SYouMin Chen 	struct msch_regs *msch;
48f520bb22SYouMin Chen 	struct rv1126_ddrgrf *ddrgrf;
49f520bb22SYouMin Chen 	struct rv1126_grf *grf;
50f520bb22SYouMin Chen 	struct ram_info info;
51f520bb22SYouMin Chen 	struct rv1126_pmugrf *pmugrf;
52f520bb22SYouMin Chen 	u32 sr_idle;
53f520bb22SYouMin Chen 	u32 pd_idle;
54f520bb22SYouMin Chen };
55f520bb22SYouMin Chen 
56f520bb22SYouMin Chen #define GRF_BASE_ADDR			0xfe000000
57f520bb22SYouMin Chen #define PMU_GRF_BASE_ADDR		0xfe020000
58f520bb22SYouMin Chen #define DDR_GRF_BASE_ADDR		0xfe030000
59f520bb22SYouMin Chen #define BUS_SGRF_BASE_ADDR		0xfe0a0000
60f520bb22SYouMin Chen #define SERVER_MSCH_BASE_ADDR		0xfe800000
61f520bb22SYouMin Chen #define CRU_BASE_ADDR			0xff490000
62f520bb22SYouMin Chen #define DDR_PHY_BASE_ADDR		0xff4a0000
63f520bb22SYouMin Chen #define UPCTL2_BASE_ADDR		0xffa50000
64f520bb22SYouMin Chen 
65f520bb22SYouMin Chen #define SGRF_SOC_CON12			0x30
66f520bb22SYouMin Chen #define SGRF_SOC_CON13			0x34
67f520bb22SYouMin Chen 
68f520bb22SYouMin Chen struct dram_info dram_info;
69f520bb22SYouMin Chen 
70970fa5d8STang Yun ping #if (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 3)
71f520bb22SYouMin Chen struct rv1126_sdram_params sdram_configs[] = {
72112c8ab5SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-328.inc"
73f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-396.inc"
74f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-528.inc"
75f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-664.inc"
76f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-784.inc"
77f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-924.inc"
7805431850SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-1056.inc"
79f520bb22SYouMin Chen };
80970fa5d8STang Yun ping #elif (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 0)
81f520bb22SYouMin Chen struct rv1126_sdram_params sdram_configs[] = {
82112c8ab5SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-328.inc"
83f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-396.inc"
84f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-528.inc"
85f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-664.inc"
86f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-784.inc"
87f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-924.inc"
88f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-1056.inc"
89f520bb22SYouMin Chen };
90970fa5d8STang Yun ping #elif (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 6)
91f520bb22SYouMin Chen struct rv1126_sdram_params sdram_configs[] = {
92112c8ab5SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-328.inc"
93f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-396.inc"
94f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-528.inc"
95f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-664.inc"
96f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-784.inc"
97f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-924.inc"
9805431850SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-1056.inc"
99f520bb22SYouMin Chen };
100970fa5d8STang Yun ping #elif (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 7)
101f520bb22SYouMin Chen struct rv1126_sdram_params sdram_configs[] = {
102112c8ab5SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-328.inc"
103f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-396.inc"
104f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-528.inc"
105f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-664.inc"
106f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-784.inc"
107f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-924.inc"
108f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-1056.inc"
109f520bb22SYouMin Chen };
110f520bb22SYouMin Chen #endif
111f520bb22SYouMin Chen 
112f520bb22SYouMin Chen u32 common_info[] = {
113f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-loader_params.inc"
114f520bb22SYouMin Chen };
115f520bb22SYouMin Chen 
116c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL)
117c71eeac4SWesley Yao static struct rw_trn_result rw_trn_result;
118c71eeac4SWesley Yao #endif
119c71eeac4SWesley Yao 
120f520bb22SYouMin Chen static struct rv1126_fsp_param fsp_param[MAX_IDX];
121f520bb22SYouMin Chen 
122f520bb22SYouMin Chen static u8 lp3_odt_value;
123f520bb22SYouMin Chen 
124d5bb9a92STang Yun ping static s8 wrlvl_result[2][4];
125f520bb22SYouMin Chen 
126f520bb22SYouMin Chen /* DDR configuration 0-9 */
127f520bb22SYouMin Chen u16 ddr_cfg_2_rbc[] = {
128f520bb22SYouMin Chen 	((0 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 3), /* 0 */
129f520bb22SYouMin Chen 	((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 2), /* 1 */
130f520bb22SYouMin Chen 	((1 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 3), /* 2 */
131f520bb22SYouMin Chen 	((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 1), /* 3 */
132f520bb22SYouMin Chen 	((0 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 4), /* 4 */
133f520bb22SYouMin Chen 	((0 << 8) | (3 << 5) | (1 << 4) | (1 << 3) | 1), /* 5 */
134f520bb22SYouMin Chen 	((0 << 8) | (3 << 5) | (1 << 4) | (1 << 3) | 2), /* 6 */
135f520bb22SYouMin Chen 	((0 << 8) | (2 << 5) | (1 << 4) | (1 << 3) | 3), /* 7 */
136f520bb22SYouMin Chen 	((1 << 8) | (3 << 5) | (0 << 4) | (0 << 3) | 2), /* 8 */
137f520bb22SYouMin Chen 	((1 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 2) /* 9 */
138f520bb22SYouMin Chen };
139f520bb22SYouMin Chen 
140f520bb22SYouMin Chen /* DDR configuration 10-21 */
141f520bb22SYouMin Chen u8 ddr4_cfg_2_rbc[] = {
142f520bb22SYouMin Chen 	((0 << 7) | (3 << 4) | (0 << 3) | (2 << 1) | 0), /* 10 */
143f520bb22SYouMin Chen 	((1 << 7) | (2 << 4) | (0 << 3) | (2 << 1) | 0), /* 11 */
144f520bb22SYouMin Chen 	((0 << 7) | (4 << 4) | (0 << 3) | (1 << 1) | 0), /* 12 */
145f520bb22SYouMin Chen 	((1 << 7) | (3 << 4) | (0 << 3) | (1 << 1) | 0), /* 13 */
146f520bb22SYouMin Chen 	((0 << 7) | (4 << 4) | (0 << 3) | (2 << 1) | 1), /* 14 */
147f520bb22SYouMin Chen 	((1 << 7) | (3 << 4) | (0 << 3) | (2 << 1) | 1), /* 15 */
148f520bb22SYouMin Chen 	((1 << 7) | (4 << 4) | (0 << 3) | (1 << 1) | 1), /* 16 */
149f520bb22SYouMin Chen 	((0 << 7) | (2 << 4) | (1 << 3) | (2 << 1) | 0), /* 17 */
150f520bb22SYouMin Chen 	((0 << 7) | (3 << 4) | (1 << 3) | (1 << 1) | 0), /* 18 */
151f520bb22SYouMin Chen 	((0 << 7) | (3 << 4) | (1 << 3) | (2 << 1) | 1), /* 19 */
152f520bb22SYouMin Chen 	((0 << 7) | (4 << 4) | (1 << 3) | (1 << 1) | 1), /* 20 */
153f520bb22SYouMin Chen 	((1 << 7) | (4 << 4) | (0 << 3) | (0 << 1) | 0) /* 21 */
154f520bb22SYouMin Chen };
155f520bb22SYouMin Chen 
156f520bb22SYouMin Chen /* DDR configuration 22-28 */
157f520bb22SYouMin Chen u16 ddr_cfg_2_rbc_p2[] = {
158f520bb22SYouMin Chen 	((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 0), /* 22 */
159f520bb22SYouMin Chen 	((0 << 8) | (4 << 5) | (0 << 4) | (1 << 3) | 2), /* 23 */
160f520bb22SYouMin Chen 	((1 << 8) | (3 << 5) | (0 << 4) | (0 << 3) | 3), /* 24 */
161f520bb22SYouMin Chen 	((0 << 8) | (3 << 5) | (1 << 4) | (0 << 3) | 3), /* 25 */
162f520bb22SYouMin Chen 	((0 << 8) | (4 << 5) | (1 << 4) | (0 << 3) | 2), /* 26 */
163f520bb22SYouMin Chen 	((1 << 8) | (4 << 5) | (0 << 4) | (0 << 3) | 2), /* 27 */
164f520bb22SYouMin Chen 	((0 << 8) | (4 << 5) | (0 << 4) | (0 << 3) | 3) /* 28 */
165f520bb22SYouMin Chen };
166f520bb22SYouMin Chen 
167f520bb22SYouMin Chen u8 d4_rbc_2_d3_rbc[][2] = {
168f520bb22SYouMin Chen 	{10, 0},
169f520bb22SYouMin Chen 	{11, 2},
170f520bb22SYouMin Chen 	{12, 23},
171f520bb22SYouMin Chen 	{13, 1},
172f520bb22SYouMin Chen 	{14, 28},
173f520bb22SYouMin Chen 	{15, 24},
174f520bb22SYouMin Chen 	{16, 27},
175f520bb22SYouMin Chen 	{17, 7},
176f520bb22SYouMin Chen 	{18, 6},
177f520bb22SYouMin Chen 	{19, 25},
178f520bb22SYouMin Chen 	{20, 26},
179f520bb22SYouMin Chen 	{21, 3}
180f520bb22SYouMin Chen };
181f520bb22SYouMin Chen 
182f520bb22SYouMin Chen u32 addrmap[23][9] = {
183f520bb22SYouMin Chen 	{24, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
184f520bb22SYouMin Chen 		0x08080808, 0x00000f0f, 0x3f3f}, /* 0 */
185f520bb22SYouMin Chen 	{23, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
186f520bb22SYouMin Chen 		0x07070707, 0x00000f0f, 0x3f3f}, /* 1 */
187f520bb22SYouMin Chen 	{23, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
188f520bb22SYouMin Chen 		0x0f080808, 0x00000f0f, 0x3f3f}, /* 2 */
189f520bb22SYouMin Chen 	{22, 0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x06060606,
190f520bb22SYouMin Chen 		0x06060606, 0x00000f0f, 0x3f3f}, /* 3 */
191f520bb22SYouMin Chen 	{24, 0x000a0a0a, 0x00000000, 0x00000000, 0x00000000, 0x09090909,
192f520bb22SYouMin Chen 		0x0f090909, 0x00000f0f, 0x3f3f}, /* 4 */
193f520bb22SYouMin Chen 	{6, 0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x07070707,
194f520bb22SYouMin Chen 		0x07070707, 0x00000f0f, 0x3f3f}, /* 5 */
195f520bb22SYouMin Chen 	{7, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x08080808,
196f520bb22SYouMin Chen 		0x08080808, 0x00000f0f, 0x3f3f}, /* 6 */
197f520bb22SYouMin Chen 	{8, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x09090909,
198f520bb22SYouMin Chen 		0x0f090909, 0x00000f0f, 0x3f3f}, /* 7 */
199f520bb22SYouMin Chen 	{22, 0x001f0808, 0x00000000, 0x00000000, 0x00001f1f, 0x06060606,
200f520bb22SYouMin Chen 		0x06060606, 0x00000f0f, 0x3f3f}, /* 8 */
201f520bb22SYouMin Chen 	{23, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
202f520bb22SYouMin Chen 		0x0f070707, 0x00000f0f, 0x3f3f}, /* 9 */
203f520bb22SYouMin Chen 
204f520bb22SYouMin Chen 	{24, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
205f520bb22SYouMin Chen 		0x08080808, 0x00000f0f, 0x0801}, /* 10 */
206f520bb22SYouMin Chen 	{23, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
207f520bb22SYouMin Chen 		0x0f080808, 0x00000f0f, 0x0801}, /* 11 */
208f520bb22SYouMin Chen 	{24, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
209f520bb22SYouMin Chen 		0x07070707, 0x00000f07, 0x0700}, /* 12 */
210f520bb22SYouMin Chen 	{23, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
211f520bb22SYouMin Chen 		0x07070707, 0x00000f0f, 0x0700}, /* 13 */
212f520bb22SYouMin Chen 	{24, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
213f520bb22SYouMin Chen 		0x07070707, 0x00000f07, 0x3f01}, /* 14 */
214f520bb22SYouMin Chen 	{23, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
215f520bb22SYouMin Chen 		0x07070707, 0x00000f0f, 0x3f01}, /* 15 */
216f520bb22SYouMin Chen 	{23, 0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x06060606,
217f520bb22SYouMin Chen 		0x06060606, 0x00000f06, 0x3f00}, /* 16 */
218f520bb22SYouMin Chen 	{8, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x09090909,
219f520bb22SYouMin Chen 		0x0f090909, 0x00000f0f, 0x0801}, /* 17 */
220f520bb22SYouMin Chen 	{7, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x08080808,
221f520bb22SYouMin Chen 		0x08080808, 0x00000f0f, 0x0700}, /* 18 */
222f520bb22SYouMin Chen 	{7, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
223f520bb22SYouMin Chen 		0x08080808, 0x00000f0f, 0x3f01}, /* 19 */
224f520bb22SYouMin Chen 
225f520bb22SYouMin Chen 	{6, 0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
226f520bb22SYouMin Chen 		0x07070707, 0x00000f07, 0x3f00}, /* 20 */
227f520bb22SYouMin Chen 	{23, 0x003f0909, 0x00000006, 0x1f1f0000, 0x00001f1f, 0x06060606,
228f520bb22SYouMin Chen 		0x06060606, 0x00000f06, 0x0600}, /* 21 */
229f520bb22SYouMin Chen 	{21, 0x00060606, 0x00000000, 0x1f1f0000, 0x00001f1f, 0x05050505,
230f520bb22SYouMin Chen 		0x05050505, 0x00000f0f, 0x3f3f} /* 22 */
231f520bb22SYouMin Chen };
232f520bb22SYouMin Chen 
233f520bb22SYouMin Chen static u8 dq_sel[22][3] = {
234f520bb22SYouMin Chen 	{0x0, 0x17, 0x22},
235f520bb22SYouMin Chen 	{0x1, 0x18, 0x23},
236f520bb22SYouMin Chen 	{0x2, 0x19, 0x24},
237f520bb22SYouMin Chen 	{0x3, 0x1a, 0x25},
238f520bb22SYouMin Chen 	{0x4, 0x1b, 0x26},
239f520bb22SYouMin Chen 	{0x5, 0x1c, 0x27},
240f520bb22SYouMin Chen 	{0x6, 0x1d, 0x28},
241f520bb22SYouMin Chen 	{0x7, 0x1e, 0x29},
242f520bb22SYouMin Chen 	{0x8, 0x16, 0x21},
243f520bb22SYouMin Chen 	{0x9, 0x1f, 0x2a},
244f520bb22SYouMin Chen 	{0xa, 0x20, 0x2b},
245f520bb22SYouMin Chen 	{0x10, 0x1, 0xc},
246f520bb22SYouMin Chen 	{0x11, 0x2, 0xd},
247f520bb22SYouMin Chen 	{0x12, 0x3, 0xe},
248f520bb22SYouMin Chen 	{0x13, 0x4, 0xf},
249f520bb22SYouMin Chen 	{0x14, 0x5, 0x10},
250f520bb22SYouMin Chen 	{0x15, 0x6, 0x11},
251f520bb22SYouMin Chen 	{0x16, 0x7, 0x12},
252f520bb22SYouMin Chen 	{0x17, 0x8, 0x13},
253f520bb22SYouMin Chen 	{0x18, 0x0, 0xb},
254f520bb22SYouMin Chen 	{0x19, 0x9, 0x14},
255f520bb22SYouMin Chen 	{0x1a, 0xa, 0x15}
256f520bb22SYouMin Chen };
257f520bb22SYouMin Chen 
258f520bb22SYouMin Chen static u16 grp_addr[4] = {
259f520bb22SYouMin Chen 	ADD_GROUP_CS0_A,
260f520bb22SYouMin Chen 	ADD_GROUP_CS0_B,
261f520bb22SYouMin Chen 	ADD_GROUP_CS1_A,
262f520bb22SYouMin Chen 	ADD_GROUP_CS1_B
263f520bb22SYouMin Chen };
264f520bb22SYouMin Chen 
265f520bb22SYouMin Chen static u8 wrlvl_result_offset[2][4] = {
266f520bb22SYouMin Chen 	{0xa0 + 0x26, 0xa0 + 0x27, 0xd0 + 0x26, 0xd0 + 0x27},
267f520bb22SYouMin Chen 	{0xa0 + 0x28, 0xa0 + 0x29, 0xd0 + 0x28, 0xd0 + 0x29},
268f520bb22SYouMin Chen };
269f520bb22SYouMin Chen 
270f520bb22SYouMin Chen static u16 dqs_dq_skew_adr[16] = {
271f520bb22SYouMin Chen 	0x170 + 0,	/* SKEW_UPDATE_RX_CS0_DQS0 */
272f520bb22SYouMin Chen 	0x170 + 0xb,	/* SKEW_UPDATE_RX_CS0_DQS1 */
273f520bb22SYouMin Chen 	0x1d0 + 0,	/* SKEW_UPDATE_RX_CS0_DQS2 */
274f520bb22SYouMin Chen 	0x1d0 + 0xb,	/* SKEW_UPDATE_RX_CS0_DQS3 */
275f520bb22SYouMin Chen 	0x1a0 + 0,	/* SKEW_UPDATE_RX_CS1_DQS0 */
276f520bb22SYouMin Chen 	0x1a0 + 0xb,	/* SKEW_UPDATE_RX_CS1_DQS1 */
277f520bb22SYouMin Chen 	0x200 + 0,	/* SKEW_UPDATE_RX_CS1_DQS2 */
278f520bb22SYouMin Chen 	0x200 + 0xb,	/* SKEW_UPDATE_RX_CS1_DQS3 */
279f520bb22SYouMin Chen 	0x170 + 0x16,	/* SKEW_UPDATE_TX_CS0_DQS0 */
280f520bb22SYouMin Chen 	0x170 + 0x21,	/* SKEW_UPDATE_TX_CS0_DQS1 */
281f520bb22SYouMin Chen 	0x1d0 + 0x16,	/* SKEW_UPDATE_TX_CS0_DQS2 */
282f520bb22SYouMin Chen 	0x1d0 + 0x21,	/* SKEW_UPDATE_TX_CS0_DQS3 */
283f520bb22SYouMin Chen 	0x1a0 + 0x16,	/* SKEW_UPDATE_TX_CS1_DQS0 */
284f520bb22SYouMin Chen 	0x1a0 + 0x21,	/* SKEW_UPDATE_TX_CS1_DQS1 */
285f520bb22SYouMin Chen 	0x200 + 0x16,	/* SKEW_UPDATE_TX_CS1_DQS2 */
286f520bb22SYouMin Chen 	0x200 + 0x21,	/* SKEW_UPDATE_TX_CS1_DQS3 */
287f520bb22SYouMin Chen };
288f520bb22SYouMin Chen 
289f520bb22SYouMin Chen static void rkclk_ddr_reset(struct dram_info *dram,
290f520bb22SYouMin Chen 			    u32 ctl_srstn, u32 ctl_psrstn,
291f520bb22SYouMin Chen 			    u32 phy_srstn, u32 phy_psrstn)
292f520bb22SYouMin Chen {
293f520bb22SYouMin Chen 	writel(UPCTL2_SRSTN_REQ(ctl_srstn) | UPCTL2_PSRSTN_REQ(ctl_psrstn) |
294f520bb22SYouMin Chen 	       UPCTL2_ASRSTN_REQ(ctl_srstn),
295f520bb22SYouMin Chen 	       BUS_SGRF_BASE_ADDR + SGRF_SOC_CON13);
296f520bb22SYouMin Chen 
297f520bb22SYouMin Chen 	writel(DDRPHY_SRSTN_REQ(phy_srstn) | DDRPHY_PSRSTN_REQ(phy_psrstn),
298f520bb22SYouMin Chen 	       &dram->cru->softrst_con[12]);
299f520bb22SYouMin Chen }
300f520bb22SYouMin Chen 
301f520bb22SYouMin Chen static void rkclk_set_dpll(struct dram_info *dram, unsigned int hz)
302f520bb22SYouMin Chen {
303f520bb22SYouMin Chen 	unsigned int refdiv, postdiv1, postdiv2, fbdiv;
304f520bb22SYouMin Chen 	int delay = 1000;
305f520bb22SYouMin Chen 	u32 mhz = hz / MHz;
306*0367dfefSZhihuan He 	struct global_info *gbl_info;
307*0367dfefSZhihuan He 	struct sdram_head_info_index_v2 *index =
308*0367dfefSZhihuan He 		(struct sdram_head_info_index_v2 *)common_info;
309*0367dfefSZhihuan He 	u32 ssmod_info;
310*0367dfefSZhihuan He 	u32 dsmpd = 1;
311f520bb22SYouMin Chen 
312*0367dfefSZhihuan He 	gbl_info = (struct global_info *)((void *)common_info +
313*0367dfefSZhihuan He 		    index->global_index.offset * 4);
314*0367dfefSZhihuan He 	ssmod_info = gbl_info->info_2t;
315f520bb22SYouMin Chen 	refdiv = 1;
316f520bb22SYouMin Chen 	if (mhz <= 100) {
317f520bb22SYouMin Chen 		postdiv1 = 6;
318f520bb22SYouMin Chen 		postdiv2 = 4;
319f520bb22SYouMin Chen 	} else if (mhz <= 150) {
320f520bb22SYouMin Chen 		postdiv1 = 4;
321f520bb22SYouMin Chen 		postdiv2 = 4;
322f520bb22SYouMin Chen 	} else if (mhz <= 200) {
323f520bb22SYouMin Chen 		postdiv1 = 6;
324f520bb22SYouMin Chen 		postdiv2 = 2;
325f520bb22SYouMin Chen 	} else if (mhz <= 300) {
326f520bb22SYouMin Chen 		postdiv1 = 4;
327f520bb22SYouMin Chen 		postdiv2 = 2;
328f520bb22SYouMin Chen 	} else if (mhz <= 400) {
329f520bb22SYouMin Chen 		postdiv1 = 6;
330f520bb22SYouMin Chen 		postdiv2 = 1;
331f520bb22SYouMin Chen 	} else {
332f520bb22SYouMin Chen 		postdiv1 = 4;
333f520bb22SYouMin Chen 		postdiv2 = 1;
334f520bb22SYouMin Chen 	}
335f520bb22SYouMin Chen 	fbdiv = (mhz * refdiv * postdiv1 * postdiv2) / 24;
336f520bb22SYouMin Chen 
337f520bb22SYouMin Chen 	writel(DPLL_MODE(CLOCK_FROM_XIN_OSC), &dram->cru->mode);
338f520bb22SYouMin Chen 
339f520bb22SYouMin Chen 	writel(0x1f000000, &dram->cru->clksel_con[64]);
340f520bb22SYouMin Chen 	writel(POSTDIV1(postdiv1) | FBDIV(fbdiv), &dram->cru->pll[1].con0);
341*0367dfefSZhihuan He 	/* enable ssmod */
342*0367dfefSZhihuan He 	if (PLL_SSMOD_SPREAD(ssmod_info)) {
343*0367dfefSZhihuan He 		dsmpd = 0;
344*0367dfefSZhihuan He 		clrsetbits_le32(&dram->cru->pll[1].con2,
345*0367dfefSZhihuan He 				0xffffff << 0, 0x0 << 0);
346*0367dfefSZhihuan He 		writel(SSMOD_SPREAD(PLL_SSMOD_SPREAD(ssmod_info)) |
347*0367dfefSZhihuan He 		       SSMOD_DIVVAL(PLL_SSMOD_DIV(ssmod_info)) |
348*0367dfefSZhihuan He 		       SSMOD_DOWNSPREAD(PLL_SSMOD_DOWNSPREAD(ssmod_info)) |
349*0367dfefSZhihuan He 		       SSMOD_RESET(0) |
350*0367dfefSZhihuan He 		       SSMOD_DIS_SSCG(0) |
351*0367dfefSZhihuan He 		       SSMOD_BP(0),
352*0367dfefSZhihuan He 		       &dram->cru->pll[1].con3);
353*0367dfefSZhihuan He 	}
354*0367dfefSZhihuan He 	writel(DSMPD(dsmpd) | POSTDIV2(postdiv2) | REFDIV(refdiv),
355f520bb22SYouMin Chen 	       &dram->cru->pll[1].con1);
356f520bb22SYouMin Chen 
357f520bb22SYouMin Chen 	while (delay > 0) {
358f520bb22SYouMin Chen 		udelay(1);
359f520bb22SYouMin Chen 		if (LOCK(readl(&dram->cru->pll[1].con1)))
360f520bb22SYouMin Chen 			break;
361f520bb22SYouMin Chen 		delay--;
362f520bb22SYouMin Chen 	}
363f520bb22SYouMin Chen 
364f520bb22SYouMin Chen 	writel(DPLL_MODE(CLOCK_FROM_PLL), &dram->cru->mode);
365f520bb22SYouMin Chen }
366f520bb22SYouMin Chen 
367f520bb22SYouMin Chen static void rkclk_configure_ddr(struct dram_info *dram,
368f520bb22SYouMin Chen 				struct rv1126_sdram_params *sdram_params)
369f520bb22SYouMin Chen {
370f520bb22SYouMin Chen 	/* for inno ddr phy need freq / 2 */
371f520bb22SYouMin Chen 	rkclk_set_dpll(dram, sdram_params->base.ddr_freq * MHZ / 2);
372f520bb22SYouMin Chen }
373f520bb22SYouMin Chen 
374f520bb22SYouMin Chen static unsigned int
375f520bb22SYouMin Chen 	calculate_ddrconfig(struct rv1126_sdram_params *sdram_params)
376f520bb22SYouMin Chen {
377f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
378f520bb22SYouMin Chen 	u32 cs, bw, die_bw, col, row, bank;
379f520bb22SYouMin Chen 	u32 cs1_row;
380f520bb22SYouMin Chen 	u32 i, tmp;
381f520bb22SYouMin Chen 	u32 ddrconf = -1;
382f520bb22SYouMin Chen 	u32 row_3_4;
383f520bb22SYouMin Chen 
384f520bb22SYouMin Chen 	cs = cap_info->rank;
385f520bb22SYouMin Chen 	bw = cap_info->bw;
386f520bb22SYouMin Chen 	die_bw = cap_info->dbw;
387f520bb22SYouMin Chen 	col = cap_info->col;
388f520bb22SYouMin Chen 	row = cap_info->cs0_row;
389f520bb22SYouMin Chen 	cs1_row = cap_info->cs1_row;
390f520bb22SYouMin Chen 	bank = cap_info->bk;
391f520bb22SYouMin Chen 	row_3_4 = cap_info->row_3_4;
392f520bb22SYouMin Chen 
393f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4) {
394f520bb22SYouMin Chen 		if (cs == 2 && row == cs1_row && !row_3_4) {
395f520bb22SYouMin Chen 			tmp = ((row - 13) << 4) | (1 << 3) | (bw << 1) |
396f520bb22SYouMin Chen 			      die_bw;
397f520bb22SYouMin Chen 			for (i = 17; i < 21; i++) {
398f520bb22SYouMin Chen 				if (((tmp & 0xf) ==
399f520bb22SYouMin Chen 				     (ddr4_cfg_2_rbc[i - 10] & 0xf)) &&
400f520bb22SYouMin Chen 				    ((tmp & 0x70) <=
401f520bb22SYouMin Chen 				     (ddr4_cfg_2_rbc[i - 10] & 0x70))) {
402f520bb22SYouMin Chen 					ddrconf = i;
403f520bb22SYouMin Chen 					goto out;
404f520bb22SYouMin Chen 				}
405f520bb22SYouMin Chen 			}
406f520bb22SYouMin Chen 		}
407f520bb22SYouMin Chen 
408f520bb22SYouMin Chen 		tmp = ((cs - 1) << 7) | ((row - 13) << 4) | (bw << 1) | die_bw;
409f520bb22SYouMin Chen 		for (i = 10; i < 21; i++) {
410f520bb22SYouMin Chen 			if (((tmp & 0xf) == (ddr4_cfg_2_rbc[i - 10] & 0xf)) &&
411f520bb22SYouMin Chen 			    ((tmp & 0x70) <= (ddr4_cfg_2_rbc[i - 10] & 0x70)) &&
412f520bb22SYouMin Chen 			    ((tmp & 0x80) <= (ddr4_cfg_2_rbc[i - 10] & 0x80))) {
413f520bb22SYouMin Chen 				ddrconf = i;
414f520bb22SYouMin Chen 				goto out;
415f520bb22SYouMin Chen 			}
416f520bb22SYouMin Chen 		}
417f520bb22SYouMin Chen 	} else {
418f520bb22SYouMin Chen 		if (cs == 2 && row == cs1_row && bank == 3) {
419f520bb22SYouMin Chen 			for (i = 5; i < 8; i++) {
420f520bb22SYouMin Chen 				if (((bw + col - 10) == (ddr_cfg_2_rbc[i] &
421f520bb22SYouMin Chen 							 0x7)) &&
422f520bb22SYouMin Chen 				    ((row - 13) << 5) <= (ddr_cfg_2_rbc[i] &
423f520bb22SYouMin Chen 							  (0x7 << 5))) {
424f520bb22SYouMin Chen 					ddrconf = i;
425f520bb22SYouMin Chen 					goto out;
426f520bb22SYouMin Chen 				}
427f520bb22SYouMin Chen 			}
428f520bb22SYouMin Chen 		}
429f520bb22SYouMin Chen 
430f520bb22SYouMin Chen 		tmp = ((cs - 1) << 8) | ((row - 13) << 5) |
431f520bb22SYouMin Chen 		      ((bw + col - 10) << 0);
432f520bb22SYouMin Chen 		if (bank == 3)
433f520bb22SYouMin Chen 			tmp |= (1 << 3);
434f520bb22SYouMin Chen 
435f520bb22SYouMin Chen 		for (i = 0; i < 9; i++)
436f520bb22SYouMin Chen 			if (((tmp & 0x1f) == (ddr_cfg_2_rbc[i] & 0x1f)) &&
437f520bb22SYouMin Chen 			    ((tmp & (7 << 5)) <=
438f520bb22SYouMin Chen 			     (ddr_cfg_2_rbc[i] & (7 << 5))) &&
439f520bb22SYouMin Chen 			    ((tmp & (1 << 8)) <=
440f520bb22SYouMin Chen 			     (ddr_cfg_2_rbc[i] & (1 << 8)))) {
441f520bb22SYouMin Chen 				ddrconf = i;
442f520bb22SYouMin Chen 				goto out;
443f520bb22SYouMin Chen 			}
4449d5c314bSWesley Yao 
4459d5c314bSWesley Yao 		for (i = 0; i < 7; i++)
4469d5c314bSWesley Yao 			if (((tmp & 0x1f) == (ddr_cfg_2_rbc_p2[i] & 0x1f)) &&
4479d5c314bSWesley Yao 			    ((tmp & (7 << 5)) <=
4489d5c314bSWesley Yao 			     (ddr_cfg_2_rbc_p2[i] & (7 << 5))) &&
4499d5c314bSWesley Yao 			    ((tmp & (1 << 8)) <=
4509d5c314bSWesley Yao 			     (ddr_cfg_2_rbc_p2[i] & (1 << 8)))) {
4519d5c314bSWesley Yao 				ddrconf = i + 22;
4529d5c314bSWesley Yao 				goto out;
4539d5c314bSWesley Yao 			}
4549d5c314bSWesley Yao 
455f520bb22SYouMin Chen 		if (cs == 1 && bank == 3 && row <= 17 &&
456f520bb22SYouMin Chen 		    (col + bw) == 12)
457f520bb22SYouMin Chen 			ddrconf = 23;
458f520bb22SYouMin Chen 	}
459f520bb22SYouMin Chen 
460f520bb22SYouMin Chen out:
461f520bb22SYouMin Chen 	if (ddrconf > 28)
462f520bb22SYouMin Chen 		printascii("calculate ddrconfig error\n");
463f520bb22SYouMin Chen 
464f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4) {
465f520bb22SYouMin Chen 		for (i = 0; i < ARRAY_SIZE(d4_rbc_2_d3_rbc) ; i++) {
466f520bb22SYouMin Chen 			if (ddrconf == d4_rbc_2_d3_rbc[i][0]) {
467f520bb22SYouMin Chen 				if (ddrconf == 21 && row > 16)
468f520bb22SYouMin Chen 					printascii("warn:ddrconf21 row > 16\n");
469f520bb22SYouMin Chen 				else
470f520bb22SYouMin Chen 					ddrconf = d4_rbc_2_d3_rbc[i][1];
471f520bb22SYouMin Chen 				break;
472f520bb22SYouMin Chen 			}
473f520bb22SYouMin Chen 		}
474f520bb22SYouMin Chen 	}
475f520bb22SYouMin Chen 
476f520bb22SYouMin Chen 	return ddrconf;
477f520bb22SYouMin Chen }
478f520bb22SYouMin Chen 
479f520bb22SYouMin Chen static void sw_set_req(struct dram_info *dram)
480f520bb22SYouMin Chen {
481f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
482f520bb22SYouMin Chen 
483f520bb22SYouMin Chen 	/* clear sw_done=0 */
484f520bb22SYouMin Chen 	writel(PCTL2_SW_DONE_CLEAR, pctl_base + DDR_PCTL2_SWCTL);
485f520bb22SYouMin Chen }
486f520bb22SYouMin Chen 
487f520bb22SYouMin Chen static void sw_set_ack(struct dram_info *dram)
488f520bb22SYouMin Chen {
489f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
490f520bb22SYouMin Chen 
491f520bb22SYouMin Chen 	/* set sw_done=1 */
492f520bb22SYouMin Chen 	writel(PCTL2_SW_DONE, pctl_base + DDR_PCTL2_SWCTL);
493f520bb22SYouMin Chen 	while (1) {
494f520bb22SYouMin Chen 		/* wait programming done */
495f520bb22SYouMin Chen 		if (readl(pctl_base + DDR_PCTL2_SWSTAT) &
496f520bb22SYouMin Chen 				PCTL2_SW_DONE_ACK)
497f520bb22SYouMin Chen 			break;
498f520bb22SYouMin Chen 	}
499f520bb22SYouMin Chen }
500f520bb22SYouMin Chen 
501f520bb22SYouMin Chen static void set_ctl_address_map(struct dram_info *dram,
502f520bb22SYouMin Chen 				struct rv1126_sdram_params *sdram_params)
503f520bb22SYouMin Chen {
504f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
505f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
506f520bb22SYouMin Chen 	u32 ddrconf = cap_info->ddrconfig;
507f520bb22SYouMin Chen 	u32 i, row;
508f520bb22SYouMin Chen 
509f520bb22SYouMin Chen 	row = cap_info->cs0_row;
510f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4) {
511f520bb22SYouMin Chen 		for (i = 0; i < ARRAY_SIZE(d4_rbc_2_d3_rbc) ; i++) {
512f520bb22SYouMin Chen 			if (ddrconf == d4_rbc_2_d3_rbc[i][1]) {
513f520bb22SYouMin Chen 				ddrconf = d4_rbc_2_d3_rbc[i][0];
514f520bb22SYouMin Chen 				break;
515f520bb22SYouMin Chen 			}
516f520bb22SYouMin Chen 		}
517f520bb22SYouMin Chen 	}
518f520bb22SYouMin Chen 
519f520bb22SYouMin Chen 	if (ddrconf > ARRAY_SIZE(addrmap)) {
520f520bb22SYouMin Chen 		printascii("set ctl address map fail\n");
521f520bb22SYouMin Chen 		return;
522f520bb22SYouMin Chen 	}
523f520bb22SYouMin Chen 
524f520bb22SYouMin Chen 	sdram_copy_to_reg((u32 *)(pctl_base + DDR_PCTL2_ADDRMAP0),
525f520bb22SYouMin Chen 			  &addrmap[ddrconf][0], 9 * 4);
526f520bb22SYouMin Chen 
527f520bb22SYouMin Chen 	/* unused row set to 0xf */
528f520bb22SYouMin Chen 	for (i = 17; i >= row; i--)
529f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6 +
530f520bb22SYouMin Chen 			((i - 12) * 8 / 32) * 4,
531f520bb22SYouMin Chen 			0xf << ((i - 12) * 8 % 32));
532f520bb22SYouMin Chen 
533f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == LPDDR3 && cap_info->row_3_4)
534f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6, 1 << 31);
535f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4 && cap_info->bw == 0x1)
536f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_PCCFG, 1 << 8);
537f520bb22SYouMin Chen 
538f520bb22SYouMin Chen 	if (cap_info->rank == 1)
539f520bb22SYouMin Chen 		clrsetbits_le32(pctl_base + DDR_PCTL2_ADDRMAP0, 0x1f, 0x1f);
540f520bb22SYouMin Chen }
541f520bb22SYouMin Chen 
542f520bb22SYouMin Chen static void phy_pll_set(struct dram_info *dram, u32 freq, u32 wait)
543f520bb22SYouMin Chen {
544f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
545f520bb22SYouMin Chen 	u32 fbdiv, prediv, postdiv, postdiv_en;
546f520bb22SYouMin Chen 
547f520bb22SYouMin Chen 	if (wait) {
548f520bb22SYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x53), PHY_PD_DISB);
549f520bb22SYouMin Chen 		while (!(readl(PHY_REG(phy_base, 0x90)) & PHY_PLL_LOCK))
550f520bb22SYouMin Chen 			continue;
551f520bb22SYouMin Chen 	} else {
552f520bb22SYouMin Chen 		freq /= MHz;
553f520bb22SYouMin Chen 		prediv = 1;
554f520bb22SYouMin Chen 		if (freq <= 200) {
555f520bb22SYouMin Chen 			fbdiv = 16;
556f520bb22SYouMin Chen 			postdiv = 2;
557f520bb22SYouMin Chen 			postdiv_en = 1;
558f520bb22SYouMin Chen 		} else if (freq <= 456) {
559f520bb22SYouMin Chen 			fbdiv = 8;
560f520bb22SYouMin Chen 			postdiv = 1;
561f520bb22SYouMin Chen 			postdiv_en = 1;
562f520bb22SYouMin Chen 		} else {
563f520bb22SYouMin Chen 			fbdiv = 4;
564f520bb22SYouMin Chen 			postdiv = 0;
565f520bb22SYouMin Chen 			postdiv_en = 0;
566f520bb22SYouMin Chen 		}
567f520bb22SYouMin Chen 		writel(fbdiv & 0xff, PHY_REG(phy_base, 0x50));
568f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x51), PHY_PBDIV_BIT9_MASK,
569f520bb22SYouMin Chen 				(fbdiv >> 8) & 1);
570f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x51), PHY_POSTDIV_EN_MASK,
571f520bb22SYouMin Chen 				postdiv_en << PHY_POSTDIV_EN_SHIFT);
572f520bb22SYouMin Chen 
573f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x52),
574f520bb22SYouMin Chen 				PHY_PREDIV_MASK << PHY_PREDIV_SHIFT, prediv);
575f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x53),
576f520bb22SYouMin Chen 				PHY_POSTDIV_MASK << PHY_POSTDIV_SHIFT,
577f520bb22SYouMin Chen 				postdiv << PHY_POSTDIV_SHIFT);
578f520bb22SYouMin Chen 	}
579f520bb22SYouMin Chen }
580f520bb22SYouMin Chen 
581f520bb22SYouMin Chen static const u16 d3_phy_drv_2_ohm[][2] = {
58270fee8b3STang Yun ping 	{PHY_DDR3_RON_455ohm, 455},
58370fee8b3STang Yun ping 	{PHY_DDR3_RON_230ohm, 230},
58470fee8b3STang Yun ping 	{PHY_DDR3_RON_153ohm, 153},
58570fee8b3STang Yun ping 	{PHY_DDR3_RON_115ohm, 115},
58670fee8b3STang Yun ping 	{PHY_DDR3_RON_91ohm, 91},
58770fee8b3STang Yun ping 	{PHY_DDR3_RON_76ohm, 76},
58870fee8b3STang Yun ping 	{PHY_DDR3_RON_65ohm, 65},
58970fee8b3STang Yun ping 	{PHY_DDR3_RON_57ohm, 57},
590f520bb22SYouMin Chen 	{PHY_DDR3_RON_51ohm, 51},
591f520bb22SYouMin Chen 	{PHY_DDR3_RON_46ohm, 46},
59270fee8b3STang Yun ping 	{PHY_DDR3_RON_41ohm, 41},
59370fee8b3STang Yun ping 	{PHY_DDR3_RON_38ohm, 38},
59470fee8b3STang Yun ping 	{PHY_DDR3_RON_35ohm, 35},
595f520bb22SYouMin Chen 	{PHY_DDR3_RON_32ohm, 32},
596f520bb22SYouMin Chen 	{PHY_DDR3_RON_30ohm, 30},
597f520bb22SYouMin Chen 	{PHY_DDR3_RON_28ohm, 28},
598f520bb22SYouMin Chen 	{PHY_DDR3_RON_27ohm, 27},
599f520bb22SYouMin Chen 	{PHY_DDR3_RON_25ohm, 25},
600f520bb22SYouMin Chen 	{PHY_DDR3_RON_24ohm, 24},
601f520bb22SYouMin Chen 	{PHY_DDR3_RON_23ohm, 23},
60270fee8b3STang Yun ping 	{PHY_DDR3_RON_22ohm, 22},
60370fee8b3STang Yun ping 	{PHY_DDR3_RON_21ohm, 21},
60470fee8b3STang Yun ping 	{PHY_DDR3_RON_20ohm, 20}
605f520bb22SYouMin Chen };
606f520bb22SYouMin Chen 
607f520bb22SYouMin Chen static u16 d3_phy_odt_2_ohm[][2] = {
608f520bb22SYouMin Chen 	{PHY_DDR3_RTT_DISABLE, 0},
60970fee8b3STang Yun ping 	{PHY_DDR3_RTT_561ohm, 561},
61070fee8b3STang Yun ping 	{PHY_DDR3_RTT_282ohm, 282},
61170fee8b3STang Yun ping 	{PHY_DDR3_RTT_188ohm, 188},
61270fee8b3STang Yun ping 	{PHY_DDR3_RTT_141ohm, 141},
61370fee8b3STang Yun ping 	{PHY_DDR3_RTT_113ohm, 113},
61470fee8b3STang Yun ping 	{PHY_DDR3_RTT_94ohm, 94},
61570fee8b3STang Yun ping 	{PHY_DDR3_RTT_81ohm, 81},
61670fee8b3STang Yun ping 	{PHY_DDR3_RTT_72ohm, 72},
617f520bb22SYouMin Chen 	{PHY_DDR3_RTT_64ohm, 64},
61870fee8b3STang Yun ping 	{PHY_DDR3_RTT_58ohm, 58},
61970fee8b3STang Yun ping 	{PHY_DDR3_RTT_52ohm, 52},
620f520bb22SYouMin Chen 	{PHY_DDR3_RTT_48ohm, 48},
621f520bb22SYouMin Chen 	{PHY_DDR3_RTT_44ohm, 44},
62270fee8b3STang Yun ping 	{PHY_DDR3_RTT_41ohm, 41},
62370fee8b3STang Yun ping 	{PHY_DDR3_RTT_38ohm, 38},
62470fee8b3STang Yun ping 	{PHY_DDR3_RTT_37ohm, 37},
62570fee8b3STang Yun ping 	{PHY_DDR3_RTT_34ohm, 34},
62670fee8b3STang Yun ping 	{PHY_DDR3_RTT_32ohm, 32},
62770fee8b3STang Yun ping 	{PHY_DDR3_RTT_31ohm, 31},
62870fee8b3STang Yun ping 	{PHY_DDR3_RTT_29ohm, 29},
62970fee8b3STang Yun ping 	{PHY_DDR3_RTT_28ohm, 28},
63070fee8b3STang Yun ping 	{PHY_DDR3_RTT_27ohm, 27},
63170fee8b3STang Yun ping 	{PHY_DDR3_RTT_25ohm, 25}
632f520bb22SYouMin Chen };
633f520bb22SYouMin Chen 
634f520bb22SYouMin Chen static u16 d4lp3_phy_drv_2_ohm[][2] = {
63570fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_482ohm, 482},
63670fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_244ohm, 244},
63770fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_162ohm, 162},
63870fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_122ohm, 122},
63970fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_97ohm, 97},
640f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_81ohm, 81},
64170fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_69ohm, 69},
64270fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_61ohm, 61},
64370fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_54ohm, 54},
64470fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_48ohm, 48},
645f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_44ohm, 44},
64670fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_40ohm, 40},
64770fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_37ohm, 37},
648f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_34ohm, 34},
649f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_32ohm, 32},
650f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_30ohm, 30},
651f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_28ohm, 28},
652f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_27ohm, 27},
65370fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_25ohm, 25},
65470fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_24ohm, 24},
65570fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_23ohm, 23},
65670fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_22ohm, 22},
65770fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_21ohm, 21}
658f520bb22SYouMin Chen };
659f520bb22SYouMin Chen 
660f520bb22SYouMin Chen static u16 d4lp3_phy_odt_2_ohm[][2] = {
661f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_DISABLE, 0},
66270fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_586ohm, 586},
66370fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_294ohm, 294},
66470fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_196ohm, 196},
66570fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_148ohm, 148},
66670fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_118ohm, 118},
667f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_99ohm, 99},
66870fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_85ohm, 58},
669f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_76ohm, 76},
67070fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_67ohm, 67},
67170fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_60ohm, 60},
672f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_55ohm, 55},
67370fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_50ohm, 50},
67470fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_46ohm, 46},
67570fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_43ohm, 43},
67670fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_40ohm, 40},
67770fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_38ohm, 38},
67870fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_36ohm, 36},
67970fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_34ohm, 34},
68070fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_32ohm, 32},
68170fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_31ohm, 31},
68270fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_29ohm, 29},
68370fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_28ohm, 28},
68470fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_27ohm, 27}
685f520bb22SYouMin Chen };
686f520bb22SYouMin Chen 
687f520bb22SYouMin Chen static u16 lp4_phy_drv_2_ohm[][2] = {
68870fee8b3STang Yun ping 	{PHY_LPDDR4_RON_501ohm, 501},
68970fee8b3STang Yun ping 	{PHY_LPDDR4_RON_253ohm, 253},
69070fee8b3STang Yun ping 	{PHY_LPDDR4_RON_168ohm, 168},
69170fee8b3STang Yun ping 	{PHY_LPDDR4_RON_126ohm, 126},
692f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_101ohm, 101},
69370fee8b3STang Yun ping 	{PHY_LPDDR4_RON_84ohm, 84},
69470fee8b3STang Yun ping 	{PHY_LPDDR4_RON_72ohm, 72},
69570fee8b3STang Yun ping 	{PHY_LPDDR4_RON_63ohm, 63},
69670fee8b3STang Yun ping 	{PHY_LPDDR4_RON_56ohm, 56},
69770fee8b3STang Yun ping 	{PHY_LPDDR4_RON_50ohm, 50},
69870fee8b3STang Yun ping 	{PHY_LPDDR4_RON_46ohm, 46},
69970fee8b3STang Yun ping 	{PHY_LPDDR4_RON_42ohm, 42},
700f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_38ohm, 38},
701f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_36ohm, 36},
70270fee8b3STang Yun ping 	{PHY_LPDDR4_RON_33ohm, 33},
70370fee8b3STang Yun ping 	{PHY_LPDDR4_RON_31ohm, 31},
704f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_29ohm, 29},
705f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_28ohm, 28},
70670fee8b3STang Yun ping 	{PHY_LPDDR4_RON_26ohm, 26},
70770fee8b3STang Yun ping 	{PHY_LPDDR4_RON_25ohm, 25},
70870fee8b3STang Yun ping 	{PHY_LPDDR4_RON_24ohm, 24},
70970fee8b3STang Yun ping 	{PHY_LPDDR4_RON_23ohm, 23},
71070fee8b3STang Yun ping 	{PHY_LPDDR4_RON_22ohm, 22}
711f520bb22SYouMin Chen };
712f520bb22SYouMin Chen 
713f520bb22SYouMin Chen static u16 lp4_phy_odt_2_ohm[][2] = {
714f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_DISABLE, 0},
71570fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_604ohm, 604},
71670fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_303ohm, 303},
717f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_202ohm, 202},
71870fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_152ohm, 152},
71970fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_122ohm, 122},
720f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_101ohm, 101},
72170fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_87ohm,	87},
722f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_78ohm, 78},
72370fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_69ohm, 69},
72470fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_62ohm, 62},
725f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_56ohm, 56},
72670fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_52ohm, 52},
727f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_48ohm, 48},
72870fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_44ohm, 44},
72970fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_41ohm, 41},
73070fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_39ohm, 39},
73170fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_37ohm, 37},
73270fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_35ohm, 35},
73370fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_33ohm, 33},
73470fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_32ohm, 32},
73570fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_30ohm, 30},
73670fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_29ohm, 29},
73770fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_27ohm, 27}
738f520bb22SYouMin Chen };
739f520bb22SYouMin Chen 
740f520bb22SYouMin Chen static u32 lp4_odt_calc(u32 odt_ohm)
741f520bb22SYouMin Chen {
742f520bb22SYouMin Chen 	u32 odt;
743f520bb22SYouMin Chen 
744f520bb22SYouMin Chen 	if (odt_ohm == 0)
745f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_DIS;
746f520bb22SYouMin Chen 	else if (odt_ohm <= 40)
747f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_40;
748f520bb22SYouMin Chen 	else if (odt_ohm <= 48)
749f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_48;
750f520bb22SYouMin Chen 	else if (odt_ohm <= 60)
751f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_60;
752f520bb22SYouMin Chen 	else if (odt_ohm <= 80)
753f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_80;
754f520bb22SYouMin Chen 	else if (odt_ohm <= 120)
755f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_120;
756f520bb22SYouMin Chen 	else
757f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_240;
758f520bb22SYouMin Chen 
759f520bb22SYouMin Chen 	return odt;
760f520bb22SYouMin Chen }
761f520bb22SYouMin Chen 
762f520bb22SYouMin Chen static void *get_ddr_drv_odt_info(u32 dramtype)
763f520bb22SYouMin Chen {
764f520bb22SYouMin Chen 	struct sdram_head_info_index_v2 *index =
765f520bb22SYouMin Chen 		(struct sdram_head_info_index_v2 *)common_info;
766f520bb22SYouMin Chen 	void *ddr_info = 0;
767f520bb22SYouMin Chen 
768f520bb22SYouMin Chen 	if (dramtype == DDR4)
769f520bb22SYouMin Chen 		ddr_info = (void *)common_info + index->ddr4_index.offset * 4;
770f520bb22SYouMin Chen 	else if (dramtype == DDR3)
771f520bb22SYouMin Chen 		ddr_info = (void *)common_info + index->ddr3_index.offset * 4;
772f520bb22SYouMin Chen 	else if (dramtype == LPDDR3)
773f520bb22SYouMin Chen 		ddr_info = (void *)common_info + index->lp3_index.offset * 4;
774f520bb22SYouMin Chen 	else if (dramtype == LPDDR4)
775f520bb22SYouMin Chen 		ddr_info = (void *)common_info + index->lp4_index.offset * 4;
776f520bb22SYouMin Chen 	else
777f520bb22SYouMin Chen 		printascii("unsupported dram type\n");
778f520bb22SYouMin Chen 	return ddr_info;
779f520bb22SYouMin Chen }
780f520bb22SYouMin Chen 
781f520bb22SYouMin Chen static void set_lp4_vref(struct dram_info *dram, struct lp4_info *lp4_info,
782f520bb22SYouMin Chen 			 u32 freq_mhz, u32 dst_fsp)
783f520bb22SYouMin Chen {
784f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
785f520bb22SYouMin Chen 	u32 ca_vref, dq_vref;
786f520bb22SYouMin Chen 
787f520bb22SYouMin Chen 	if (freq_mhz <= LP4_CA_ODT_EN_FREQ(lp4_info->ca_odten_freq))
788f520bb22SYouMin Chen 		ca_vref = LP4_CA_VREF(lp4_info->vref_when_odtoff);
789f520bb22SYouMin Chen 	else
790f520bb22SYouMin Chen 		ca_vref = LP4_CA_VREF(lp4_info->vref_when_odten);
791f520bb22SYouMin Chen 
792f520bb22SYouMin Chen 	if (freq_mhz <= LP4_DQ_ODT_EN_FREQ(lp4_info->dq_odten_freq))
793f520bb22SYouMin Chen 		dq_vref = LP4_DQ_VREF(lp4_info->vref_when_odtoff);
794f520bb22SYouMin Chen 	else
795f520bb22SYouMin Chen 		dq_vref = LP4_DQ_VREF(lp4_info->vref_when_odten);
796f520bb22SYouMin Chen 
797f520bb22SYouMin Chen 	if (ca_vref < 100)
798f520bb22SYouMin Chen 		ca_vref = 100;
799f520bb22SYouMin Chen 	if (ca_vref > 420)
800f520bb22SYouMin Chen 		ca_vref = 420;
801f520bb22SYouMin Chen 
802f520bb22SYouMin Chen 	if (ca_vref <= 300)
803f520bb22SYouMin Chen 		ca_vref = (0 << 6) | (ca_vref - 100) / 4;
804f520bb22SYouMin Chen 	else
805f520bb22SYouMin Chen 		ca_vref = (1 << 6) | (ca_vref - 220) / 4;
806f520bb22SYouMin Chen 
807f520bb22SYouMin Chen 	if (dq_vref < 100)
808f520bb22SYouMin Chen 		dq_vref = 100;
809f520bb22SYouMin Chen 	if (dq_vref > 420)
810f520bb22SYouMin Chen 		dq_vref = 420;
811f520bb22SYouMin Chen 
812f520bb22SYouMin Chen 	if (dq_vref <= 300)
813f520bb22SYouMin Chen 		dq_vref = (0 << 6) | (dq_vref - 100) / 4;
814f520bb22SYouMin Chen 	else
815f520bb22SYouMin Chen 		dq_vref = (1 << 6) | (dq_vref - 220) / 4;
816f520bb22SYouMin Chen 
817f520bb22SYouMin Chen 	sw_set_req(dram);
818f520bb22SYouMin Chen 	clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
819f520bb22SYouMin Chen 			DDR_PCTL2_INIT6,
820f520bb22SYouMin Chen 			PCTL2_MR_MASK << PCTL2_LPDDR4_MR12_SHIFT,
821f520bb22SYouMin Chen 			ca_vref << PCTL2_LPDDR4_MR12_SHIFT);
822f520bb22SYouMin Chen 
823f520bb22SYouMin Chen 	clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
824f520bb22SYouMin Chen 			DDR_PCTL2_INIT7,
825f520bb22SYouMin Chen 			PCTL2_MR_MASK << PCTL2_LPDDR4_MR14_SHIFT,
826f520bb22SYouMin Chen 			dq_vref << PCTL2_LPDDR4_MR14_SHIFT);
827f520bb22SYouMin Chen 	sw_set_ack(dram);
828f520bb22SYouMin Chen }
829f520bb22SYouMin Chen 
830f520bb22SYouMin Chen static void set_ds_odt(struct dram_info *dram,
831f520bb22SYouMin Chen 		       struct rv1126_sdram_params *sdram_params, u32 dst_fsp)
832f520bb22SYouMin Chen {
833f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
834f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
835f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
836f520bb22SYouMin Chen 	struct ddr2_3_4_lp2_3_info *ddr_info;
837f520bb22SYouMin Chen 	struct lp4_info *lp4_info;
838f520bb22SYouMin Chen 	u32 i, j, tmp;
839f520bb22SYouMin Chen 	const u16 (*p_drv)[2];
840f520bb22SYouMin Chen 	const u16 (*p_odt)[2];
841f520bb22SYouMin Chen 	u32 drv_info, sr_info;
842f520bb22SYouMin Chen 	u32 phy_dq_drv_ohm, phy_clk_drv_ohm, phy_ca_drv_ohm, dram_drv_ohm;
843f520bb22SYouMin Chen 	u32 phy_odt_ohm, dram_odt_ohm;
844f520bb22SYouMin Chen 	u32 lp4_pu_cal, phy_lp4_drv_pd_en;
845f520bb22SYouMin Chen 	u32 phy_odt_up_en, phy_odt_dn_en;
846f520bb22SYouMin Chen 	u32 sr_dq, sr_clk;
847f520bb22SYouMin Chen 	u32 freq = sdram_params->base.ddr_freq;
848f520bb22SYouMin Chen 	u32 mr1_mr3, mr11, mr22, vref_out, vref_inner;
849f520bb22SYouMin Chen 	u32 phy_clk_drv = 0, phy_odt = 0, phy_ca_drv = 0, dram_caodt_ohm = 0;
850f520bb22SYouMin Chen 	u32 phy_dq_drv = 0;
851f520bb22SYouMin Chen 	u32 phy_odt_up = 0, phy_odt_dn = 0;
852f520bb22SYouMin Chen 
853f520bb22SYouMin Chen 	ddr_info = get_ddr_drv_odt_info(dramtype);
854f520bb22SYouMin Chen 	lp4_info = (void *)ddr_info;
855f520bb22SYouMin Chen 
856f520bb22SYouMin Chen 	if (!ddr_info)
857f520bb22SYouMin Chen 		return;
858f520bb22SYouMin Chen 
859f520bb22SYouMin Chen 	/* dram odt en freq control phy drv, dram odt and phy sr */
860f520bb22SYouMin Chen 	if (freq <= DRAMODT_EN_FREQ(ddr_info->odten_freq)) {
861f520bb22SYouMin Chen 		drv_info = ddr_info->drv_when_odtoff;
862f520bb22SYouMin Chen 		dram_odt_ohm = 0;
863f520bb22SYouMin Chen 		sr_info = ddr_info->sr_when_odtoff;
864f520bb22SYouMin Chen 		phy_lp4_drv_pd_en =
865f520bb22SYouMin Chen 			PHY_LP4_DRV_PULLDOWN_EN_ODTOFF(lp4_info->odt_info);
866f520bb22SYouMin Chen 	} else {
867f520bb22SYouMin Chen 		drv_info = ddr_info->drv_when_odten;
868f520bb22SYouMin Chen 		dram_odt_ohm = ODT_INFO_DRAM_ODT(ddr_info->odt_info);
869f520bb22SYouMin Chen 		sr_info = ddr_info->sr_when_odten;
870f520bb22SYouMin Chen 		phy_lp4_drv_pd_en =
871f520bb22SYouMin Chen 			PHY_LP4_DRV_PULLDOWN_EN_ODTEN(lp4_info->odt_info);
872f520bb22SYouMin Chen 	}
873f520bb22SYouMin Chen 	phy_dq_drv_ohm =
874f520bb22SYouMin Chen 		DRV_INFO_PHY_DQ_DRV(drv_info);
875f520bb22SYouMin Chen 	phy_clk_drv_ohm =
876f520bb22SYouMin Chen 		DRV_INFO_PHY_CLK_DRV(drv_info);
877f520bb22SYouMin Chen 	phy_ca_drv_ohm =
878f520bb22SYouMin Chen 		DRV_INFO_PHY_CA_DRV(drv_info);
879f520bb22SYouMin Chen 
880f520bb22SYouMin Chen 	sr_dq = DQ_SR_INFO(sr_info);
881f520bb22SYouMin Chen 	sr_clk = CLK_SR_INFO(sr_info);
882f520bb22SYouMin Chen 
883f520bb22SYouMin Chen 	/* phy odt en freq control dram drv and phy odt */
884f520bb22SYouMin Chen 	if (freq <= PHYODT_EN_FREQ(ddr_info->odten_freq)) {
885f520bb22SYouMin Chen 		dram_drv_ohm = DRV_INFO_DRAM_DQ_DRV(ddr_info->drv_when_odtoff);
886f520bb22SYouMin Chen 		lp4_pu_cal = LP4_DRV_PU_CAL_ODTOFF(lp4_info->odt_info);
887f520bb22SYouMin Chen 		phy_odt_ohm = 0;
888f520bb22SYouMin Chen 		phy_odt_up_en = 0;
889f520bb22SYouMin Chen 		phy_odt_dn_en = 0;
890f520bb22SYouMin Chen 	} else {
891f520bb22SYouMin Chen 		dram_drv_ohm =
892f520bb22SYouMin Chen 			DRV_INFO_DRAM_DQ_DRV(ddr_info->drv_when_odten);
893f520bb22SYouMin Chen 		phy_odt_ohm = ODT_INFO_PHY_ODT(ddr_info->odt_info);
894f520bb22SYouMin Chen 		phy_odt_up_en =
895f520bb22SYouMin Chen 			ODT_INFO_PULLUP_EN(ddr_info->odt_info);
896f520bb22SYouMin Chen 		phy_odt_dn_en =
897f520bb22SYouMin Chen 			ODT_INFO_PULLDOWN_EN(ddr_info->odt_info);
898f520bb22SYouMin Chen 		lp4_pu_cal = LP4_DRV_PU_CAL_ODTEN(lp4_info->odt_info);
899f520bb22SYouMin Chen 	}
900f520bb22SYouMin Chen 
901f520bb22SYouMin Chen 	if (dramtype == LPDDR4) {
902f520bb22SYouMin Chen 		if (phy_odt_ohm) {
903f520bb22SYouMin Chen 			phy_odt_up_en = 0;
904f520bb22SYouMin Chen 			phy_odt_dn_en = 1;
905f520bb22SYouMin Chen 		}
906f520bb22SYouMin Chen 		if (freq <= LP4_CA_ODT_EN_FREQ(lp4_info->ca_odten_freq))
907f520bb22SYouMin Chen 			dram_caodt_ohm = 0;
908f520bb22SYouMin Chen 		else
909f520bb22SYouMin Chen 			dram_caodt_ohm =
910f520bb22SYouMin Chen 				ODT_INFO_LP4_CA_ODT(lp4_info->odt_info);
911f520bb22SYouMin Chen 	}
912f520bb22SYouMin Chen 
913f520bb22SYouMin Chen 	if (dramtype == DDR3) {
914f520bb22SYouMin Chen 		p_drv = d3_phy_drv_2_ohm;
915f520bb22SYouMin Chen 		p_odt = d3_phy_odt_2_ohm;
916f520bb22SYouMin Chen 	} else if (dramtype == LPDDR4) {
917f520bb22SYouMin Chen 		p_drv = lp4_phy_drv_2_ohm;
918f520bb22SYouMin Chen 		p_odt = lp4_phy_odt_2_ohm;
919f520bb22SYouMin Chen 	} else {
920f520bb22SYouMin Chen 		p_drv = d4lp3_phy_drv_2_ohm;
921f520bb22SYouMin Chen 		p_odt = d4lp3_phy_odt_2_ohm;
922f520bb22SYouMin Chen 	}
923f520bb22SYouMin Chen 
924f520bb22SYouMin Chen 	for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
925f520bb22SYouMin Chen 		if (phy_dq_drv_ohm <= *(*(p_drv + i) + 1)) {
926f520bb22SYouMin Chen 			phy_dq_drv = **(p_drv + i);
927f520bb22SYouMin Chen 			break;
928f520bb22SYouMin Chen 		}
929f520bb22SYouMin Chen 		if (i == 0)
930f520bb22SYouMin Chen 			break;
931f520bb22SYouMin Chen 	}
932f520bb22SYouMin Chen 	for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
933f520bb22SYouMin Chen 		if (phy_clk_drv_ohm <= *(*(p_drv + i) + 1)) {
934f520bb22SYouMin Chen 			phy_clk_drv = **(p_drv + i);
935f520bb22SYouMin Chen 			break;
936f520bb22SYouMin Chen 		}
937f520bb22SYouMin Chen 		if (i == 0)
938f520bb22SYouMin Chen 			break;
939f520bb22SYouMin Chen 	}
940f520bb22SYouMin Chen 	for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
941f520bb22SYouMin Chen 		if (phy_ca_drv_ohm <= *(*(p_drv + i) + 1)) {
942f520bb22SYouMin Chen 			phy_ca_drv = **(p_drv + i);
943f520bb22SYouMin Chen 			break;
944f520bb22SYouMin Chen 		}
945f520bb22SYouMin Chen 		if (i == 0)
946f520bb22SYouMin Chen 			break;
947f520bb22SYouMin Chen 	}
948f520bb22SYouMin Chen 	if (!phy_odt_ohm)
949f520bb22SYouMin Chen 		phy_odt = 0;
950f520bb22SYouMin Chen 	else
951f520bb22SYouMin Chen 		for (i = ARRAY_SIZE(d4lp3_phy_odt_2_ohm) - 1; ; i--) {
952f520bb22SYouMin Chen 			if (phy_odt_ohm <= *(*(p_odt + i) + 1)) {
953f520bb22SYouMin Chen 				phy_odt = **(p_odt + i);
954f520bb22SYouMin Chen 				break;
955f520bb22SYouMin Chen 			}
956f520bb22SYouMin Chen 			if (i == 0)
957f520bb22SYouMin Chen 				break;
958f520bb22SYouMin Chen 		}
959f520bb22SYouMin Chen 
960f520bb22SYouMin Chen 	if (dramtype != LPDDR4) {
961f520bb22SYouMin Chen 		if (!phy_odt_ohm || (phy_odt_up_en && phy_odt_dn_en))
962f520bb22SYouMin Chen 			vref_inner = 0x80;
963f520bb22SYouMin Chen 		else if (phy_odt_up_en)
964f520bb22SYouMin Chen 			vref_inner = (2 * dram_drv_ohm + phy_odt_ohm) * 128 /
965f520bb22SYouMin Chen 				     (dram_drv_ohm + phy_odt_ohm);
966f520bb22SYouMin Chen 		else
967f520bb22SYouMin Chen 			vref_inner = phy_odt_ohm * 128 /
968f520bb22SYouMin Chen 				(phy_odt_ohm + dram_drv_ohm);
969f520bb22SYouMin Chen 
970f520bb22SYouMin Chen 		if (dramtype != DDR3 && dram_odt_ohm)
971f520bb22SYouMin Chen 			vref_out = (2 * phy_dq_drv_ohm + dram_odt_ohm) * 128 /
972f520bb22SYouMin Chen 				   (phy_dq_drv_ohm + dram_odt_ohm);
973f520bb22SYouMin Chen 		else
974f520bb22SYouMin Chen 			vref_out = 0x80;
975f520bb22SYouMin Chen 	} else {
976f520bb22SYouMin Chen 		/* for lp4 */
977f520bb22SYouMin Chen 		if (phy_odt_ohm)
978f520bb22SYouMin Chen 			vref_inner =
979f520bb22SYouMin Chen 				(PHY_LP4_DQ_VREF(lp4_info->vref_when_odten) *
980f520bb22SYouMin Chen 				 256) / 1000;
981f520bb22SYouMin Chen 		else
982f520bb22SYouMin Chen 			vref_inner =
983f520bb22SYouMin Chen 				(PHY_LP4_DQ_VREF(lp4_info->vref_when_odtoff) *
984f520bb22SYouMin Chen 				 256) / 1000;
985f520bb22SYouMin Chen 
986f520bb22SYouMin Chen 		vref_out = 0x80;
987f520bb22SYouMin Chen 	}
988f520bb22SYouMin Chen 
989f520bb22SYouMin Chen 	/* default ZQCALIB bypass mode */
990f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x100), 0x1f, phy_ca_drv);
991f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x101), 0x1f, phy_ca_drv);
992f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x102), 0x1f, phy_clk_drv);
993f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x103), 0x1f, phy_clk_drv);
994a5033de0STang Yun ping 	if (dramtype == LPDDR4) {
995a5033de0STang Yun ping 		clrsetbits_le32(PHY_REG(phy_base, 0x107), 0x1f, phy_clk_drv);
996a5033de0STang Yun ping 		clrsetbits_le32(PHY_REG(phy_base, 0x108), 0x1f, phy_clk_drv);
997a5033de0STang Yun ping 	} else {
998a5033de0STang Yun ping 		clrsetbits_le32(PHY_REG(phy_base, 0x107), 0x1f, phy_ca_drv);
999a5033de0STang Yun ping 		clrsetbits_le32(PHY_REG(phy_base, 0x108), 0x1f, phy_ca_drv);
1000a5033de0STang Yun ping 	}
1001f520bb22SYouMin Chen 	/* clk / cmd slew rate */
1002f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x106), 0x1f, sr_clk);
1003f520bb22SYouMin Chen 
1004f520bb22SYouMin Chen 	phy_lp4_drv_pd_en = (~phy_lp4_drv_pd_en) & 1;
1005f520bb22SYouMin Chen 	if (phy_odt_up_en)
1006f520bb22SYouMin Chen 		phy_odt_up = phy_odt;
1007f520bb22SYouMin Chen 	if (phy_odt_dn_en)
1008f520bb22SYouMin Chen 		phy_odt_dn = phy_odt;
1009f520bb22SYouMin Chen 
1010f520bb22SYouMin Chen 	for (i = 0; i < 4; i++) {
1011f520bb22SYouMin Chen 		j = 0x110 + i * 0x10;
1012f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, j + 1), 0x1f, phy_odt_up);
1013f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, j), 0x1f, phy_odt_dn);
1014f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, j + 2), 0x1f, phy_dq_drv);
1015f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, j + 3), 0x1f, phy_dq_drv);
1016f520bb22SYouMin Chen 		writel(vref_inner, PHY_REG(phy_base, 0x118 + i * 0x10));
1017f520bb22SYouMin Chen 
1018f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x114 + i * 0x10),
1019f520bb22SYouMin Chen 				1 << 3, phy_lp4_drv_pd_en << 3);
1020f520bb22SYouMin Chen 		/* dq slew rate */
1021f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x117 + i * 0x10),
1022f520bb22SYouMin Chen 				0x1f, sr_dq);
1023f520bb22SYouMin Chen 	}
1024f520bb22SYouMin Chen 
1025f520bb22SYouMin Chen 	/* reg_rx_vref_value_update */
1026f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
1027f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
1028f520bb22SYouMin Chen 
1029f520bb22SYouMin Chen 	/* RAM VREF */
1030f520bb22SYouMin Chen 	writel(vref_out, PHY_REG(phy_base, 0x105));
1031d3f5f12cSTang Yun ping 	if (dramtype == LPDDR3)
1032d3f5f12cSTang Yun ping 		udelay(100);
1033f520bb22SYouMin Chen 
1034f520bb22SYouMin Chen 	if (dramtype == LPDDR4)
1035f520bb22SYouMin Chen 		set_lp4_vref(dram, lp4_info, freq, dst_fsp);
1036f520bb22SYouMin Chen 
1037f520bb22SYouMin Chen 	if (dramtype == DDR3 || dramtype == DDR4) {
1038f520bb22SYouMin Chen 		mr1_mr3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1039f520bb22SYouMin Chen 				DDR_PCTL2_INIT3);
1040f520bb22SYouMin Chen 		mr1_mr3 = mr1_mr3 >> PCTL2_DDR34_MR1_SHIFT & PCTL2_MR_MASK;
1041f520bb22SYouMin Chen 	} else {
1042f520bb22SYouMin Chen 		mr1_mr3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1043f520bb22SYouMin Chen 				DDR_PCTL2_INIT4);
1044f520bb22SYouMin Chen 		mr1_mr3 = mr1_mr3 >> PCTL2_LPDDR234_MR3_SHIFT & PCTL2_MR_MASK;
1045f520bb22SYouMin Chen 	}
1046f520bb22SYouMin Chen 
1047f520bb22SYouMin Chen 	if (dramtype == DDR3) {
1048f520bb22SYouMin Chen 		mr1_mr3 &= ~(DDR3_DS_MASK | DDR3_RTT_NOM_MASK);
1049f520bb22SYouMin Chen 		if (dram_drv_ohm == 34)
1050f520bb22SYouMin Chen 			mr1_mr3 |= DDR3_DS_34;
1051f520bb22SYouMin Chen 
1052f520bb22SYouMin Chen 		if (dram_odt_ohm == 0)
1053f520bb22SYouMin Chen 			mr1_mr3 |= DDR3_RTT_NOM_DIS;
1054f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 40)
1055f520bb22SYouMin Chen 			mr1_mr3 |= DDR3_RTT_NOM_40;
1056f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 60)
1057f520bb22SYouMin Chen 			mr1_mr3 |= DDR3_RTT_NOM_60;
1058f520bb22SYouMin Chen 		else
1059f520bb22SYouMin Chen 			mr1_mr3 |= DDR3_RTT_NOM_120;
1060f520bb22SYouMin Chen 
1061f520bb22SYouMin Chen 	} else if (dramtype == DDR4) {
1062f520bb22SYouMin Chen 		mr1_mr3 &= ~(DDR4_DS_MASK | DDR4_RTT_NOM_MASK);
1063f520bb22SYouMin Chen 		if (dram_drv_ohm == 48)
1064f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_DS_48;
1065f520bb22SYouMin Chen 
1066f520bb22SYouMin Chen 		if (dram_odt_ohm == 0)
1067f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_DIS;
1068f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 34)
1069f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_34;
1070f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 40)
1071f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_40;
1072f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 48)
1073f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_48;
1074f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 60)
1075f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_60;
1076f520bb22SYouMin Chen 		else
1077f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_120;
1078f520bb22SYouMin Chen 
1079f520bb22SYouMin Chen 	} else if (dramtype == LPDDR3) {
1080f520bb22SYouMin Chen 		if (dram_drv_ohm <= 34)
1081f520bb22SYouMin Chen 			mr1_mr3 |= LPDDR3_DS_34;
1082f520bb22SYouMin Chen 		else if (dram_drv_ohm <= 40)
1083f520bb22SYouMin Chen 			mr1_mr3 |= LPDDR3_DS_40;
1084f520bb22SYouMin Chen 		else if (dram_drv_ohm <= 48)
1085f520bb22SYouMin Chen 			mr1_mr3 |= LPDDR3_DS_48;
1086f520bb22SYouMin Chen 		else if (dram_drv_ohm <= 60)
1087f520bb22SYouMin Chen 			mr1_mr3 |= LPDDR3_DS_60;
1088f520bb22SYouMin Chen 		else if (dram_drv_ohm <= 80)
1089f520bb22SYouMin Chen 			mr1_mr3 |= LPDDR3_DS_80;
1090f520bb22SYouMin Chen 
1091f520bb22SYouMin Chen 		if (dram_odt_ohm == 0)
1092f520bb22SYouMin Chen 			lp3_odt_value = LPDDR3_ODT_DIS;
1093f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 60)
1094f520bb22SYouMin Chen 			lp3_odt_value = LPDDR3_ODT_60;
1095f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 120)
1096f520bb22SYouMin Chen 			lp3_odt_value = LPDDR3_ODT_120;
1097f520bb22SYouMin Chen 		else
1098f520bb22SYouMin Chen 			lp3_odt_value = LPDDR3_ODT_240;
1099f520bb22SYouMin Chen 	} else {/* for lpddr4 */
1100f520bb22SYouMin Chen 		/* MR3 for lp4 PU-CAL and PDDS */
1101f520bb22SYouMin Chen 		mr1_mr3 &= ~(LPDDR4_PDDS_MASK | LPDDR4_PU_CAL_MASK);
1102f520bb22SYouMin Chen 		mr1_mr3 |= lp4_pu_cal;
1103f520bb22SYouMin Chen 
1104f520bb22SYouMin Chen 		tmp = lp4_odt_calc(dram_drv_ohm);
1105f520bb22SYouMin Chen 		if (!tmp)
1106f520bb22SYouMin Chen 			tmp = LPDDR4_PDDS_240;
1107f520bb22SYouMin Chen 		mr1_mr3 |= (tmp << LPDDR4_PDDS_SHIFT);
1108f520bb22SYouMin Chen 
1109f520bb22SYouMin Chen 		/* MR11 for lp4 ca odt, dq odt set */
1110f520bb22SYouMin Chen 		mr11 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1111f520bb22SYouMin Chen 			     DDR_PCTL2_INIT6);
1112f520bb22SYouMin Chen 		mr11 = mr11 >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK;
1113f520bb22SYouMin Chen 
1114f520bb22SYouMin Chen 		mr11 &= ~(LPDDR4_DQODT_MASK | LPDDR4_CAODT_MASK);
1115f520bb22SYouMin Chen 
1116f520bb22SYouMin Chen 		tmp = lp4_odt_calc(dram_odt_ohm);
1117f520bb22SYouMin Chen 		mr11 |= (tmp << LPDDR4_DQODT_SHIFT);
1118f520bb22SYouMin Chen 
1119f520bb22SYouMin Chen 		tmp = lp4_odt_calc(dram_caodt_ohm);
1120f520bb22SYouMin Chen 		mr11 |= (tmp << LPDDR4_CAODT_SHIFT);
1121f520bb22SYouMin Chen 		sw_set_req(dram);
1122f520bb22SYouMin Chen 		clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1123f520bb22SYouMin Chen 				DDR_PCTL2_INIT6,
1124f520bb22SYouMin Chen 				PCTL2_MR_MASK << PCTL2_LPDDR4_MR11_SHIFT,
1125f520bb22SYouMin Chen 				mr11 << PCTL2_LPDDR4_MR11_SHIFT);
1126f520bb22SYouMin Chen 		sw_set_ack(dram);
1127f520bb22SYouMin Chen 
1128f520bb22SYouMin Chen 		/* MR22 for soc odt/odt-ck/odt-cs/odt-ca */
1129f520bb22SYouMin Chen 		mr22 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1130f520bb22SYouMin Chen 			     DDR_PCTL2_INIT7);
1131f520bb22SYouMin Chen 		mr22 = mr22 >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK;
1132f520bb22SYouMin Chen 		mr22 &= ~LPDDR4_SOC_ODT_MASK;
1133f520bb22SYouMin Chen 
1134f520bb22SYouMin Chen 		tmp = lp4_odt_calc(phy_odt_ohm);
1135f520bb22SYouMin Chen 		mr22 |= tmp;
1136f520bb22SYouMin Chen 		mr22 = mr22 |
1137f520bb22SYouMin Chen 		       (LP4_ODTE_CK_EN(lp4_info->cs_drv_ca_odt_info) <<
1138f520bb22SYouMin Chen 			LPDDR4_ODTE_CK_SHIFT) |
1139f520bb22SYouMin Chen 		       (LP4_ODTE_CS_EN(lp4_info->cs_drv_ca_odt_info) <<
1140f520bb22SYouMin Chen 			LPDDR4_ODTE_CS_SHIFT) |
1141f520bb22SYouMin Chen 		       (LP4_ODTD_CA_EN(lp4_info->cs_drv_ca_odt_info) <<
1142f520bb22SYouMin Chen 			LPDDR4_ODTD_CA_SHIFT);
1143f520bb22SYouMin Chen 
1144f520bb22SYouMin Chen 		sw_set_req(dram);
1145f520bb22SYouMin Chen 		clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1146f520bb22SYouMin Chen 				DDR_PCTL2_INIT7,
1147f520bb22SYouMin Chen 				PCTL2_MR_MASK << PCTL2_LPDDR4_MR22_SHIFT,
1148f520bb22SYouMin Chen 				mr22 << PCTL2_LPDDR4_MR22_SHIFT);
1149f520bb22SYouMin Chen 		sw_set_ack(dram);
1150f520bb22SYouMin Chen 	}
1151f520bb22SYouMin Chen 
1152f520bb22SYouMin Chen 	if (dramtype == DDR4 || dramtype == DDR3) {
1153f520bb22SYouMin Chen 		sw_set_req(dram);
1154f520bb22SYouMin Chen 		clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1155f520bb22SYouMin Chen 				DDR_PCTL2_INIT3,
1156f520bb22SYouMin Chen 				PCTL2_MR_MASK << PCTL2_DDR34_MR1_SHIFT,
1157f520bb22SYouMin Chen 				mr1_mr3 << PCTL2_DDR34_MR1_SHIFT);
1158f520bb22SYouMin Chen 		sw_set_ack(dram);
1159f520bb22SYouMin Chen 	} else {
1160f520bb22SYouMin Chen 		sw_set_req(dram);
1161f520bb22SYouMin Chen 		clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1162f520bb22SYouMin Chen 				DDR_PCTL2_INIT4,
1163f520bb22SYouMin Chen 				PCTL2_MR_MASK << PCTL2_LPDDR234_MR3_SHIFT,
1164f520bb22SYouMin Chen 				mr1_mr3 << PCTL2_LPDDR234_MR3_SHIFT);
1165f520bb22SYouMin Chen 		sw_set_ack(dram);
1166f520bb22SYouMin Chen 	}
1167f520bb22SYouMin Chen }
1168f520bb22SYouMin Chen 
1169f520bb22SYouMin Chen static int sdram_cmd_dq_path_remap(struct dram_info *dram,
1170f520bb22SYouMin Chen 				   struct rv1126_sdram_params *sdram_params)
1171f520bb22SYouMin Chen {
1172f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1173f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
1174f520bb22SYouMin Chen 	struct sdram_head_info_index_v2 *index =
1175f520bb22SYouMin Chen 		(struct sdram_head_info_index_v2 *)common_info;
1176f520bb22SYouMin Chen 	struct dq_map_info *map_info;
1177f520bb22SYouMin Chen 
1178f520bb22SYouMin Chen 	map_info = (struct dq_map_info *)((void *)common_info +
1179f520bb22SYouMin Chen 		index->dq_map_index.offset * 4);
1180f520bb22SYouMin Chen 
1181f520bb22SYouMin Chen 	if (dramtype <= LPDDR4)
1182f520bb22SYouMin Chen 		writel((map_info->byte_map[dramtype / 4] >>
1183f520bb22SYouMin Chen 			((dramtype % 4) * 8)) & 0xff,
1184f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x4f));
1185f520bb22SYouMin Chen 
1186f520bb22SYouMin Chen 	return 0;
1187f520bb22SYouMin Chen }
1188f520bb22SYouMin Chen 
1189f520bb22SYouMin Chen static void phy_cfg(struct dram_info *dram,
1190f520bb22SYouMin Chen 		    struct rv1126_sdram_params *sdram_params)
1191f520bb22SYouMin Chen {
1192f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
1193f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1194f520bb22SYouMin Chen 	u32 i, dq_map, tmp;
1195f520bb22SYouMin Chen 	u32 byte1 = 0, byte0 = 0;
1196f520bb22SYouMin Chen 
1197f520bb22SYouMin Chen 	sdram_cmd_dq_path_remap(dram, sdram_params);
1198f520bb22SYouMin Chen 
1199f520bb22SYouMin Chen 	phy_pll_set(dram, sdram_params->base.ddr_freq * MHZ, 0);
1200f520bb22SYouMin Chen 	for (i = 0; sdram_params->phy_regs.phy[i][0] != 0xFFFFFFFF; i++) {
1201f520bb22SYouMin Chen 		writel(sdram_params->phy_regs.phy[i][1],
1202f520bb22SYouMin Chen 		       phy_base + sdram_params->phy_regs.phy[i][0]);
1203f520bb22SYouMin Chen 	}
1204f520bb22SYouMin Chen 
1205f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x62), BIT(5));
1206f520bb22SYouMin Chen 	dq_map = readl(PHY_REG(phy_base, 0x4f));
1207f520bb22SYouMin Chen 	for (i = 0; i < 4; i++) {
1208f520bb22SYouMin Chen 		if (((dq_map >> (i * 2)) & 0x3) == 0)
1209f520bb22SYouMin Chen 			byte0 = i;
1210f520bb22SYouMin Chen 		if (((dq_map >> (i * 2)) & 0x3) == 1)
1211f520bb22SYouMin Chen 			byte1 = i;
1212f520bb22SYouMin Chen 	}
1213f520bb22SYouMin Chen 
1214f520bb22SYouMin Chen 	tmp = readl(PHY_REG(phy_base, 0xf)) & (~PHY_DQ_WIDTH_MASK);
1215f520bb22SYouMin Chen 	if (cap_info->bw == 2)
1216f520bb22SYouMin Chen 		tmp |= 0xf;
1217f520bb22SYouMin Chen 	else if (cap_info->bw == 1)
1218f520bb22SYouMin Chen 		tmp |= ((1 << byte0) | (1 << byte1));
1219f520bb22SYouMin Chen 	else
1220f520bb22SYouMin Chen 		tmp |= (1 << byte0);
1221f520bb22SYouMin Chen 
1222f520bb22SYouMin Chen 	writel(tmp, PHY_REG(phy_base, 0xf));
1223f520bb22SYouMin Chen 
1224f520bb22SYouMin Chen 	/* lpddr4 odt control by phy, enable cs0 odt */
1225f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4)
1226f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x20), 0x7 << 4,
1227f520bb22SYouMin Chen 				(1 << 6) | (1 << 4));
1228f520bb22SYouMin Chen 	/* for ca training ca vref choose range1 */
1229f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x1e), BIT(6));
1230f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x1f), BIT(6));
1231f520bb22SYouMin Chen 	/* for wr training PHY_0x7c[5], choose range0 */
1232f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x7c), BIT(5));
1233f520bb22SYouMin Chen }
1234f520bb22SYouMin Chen 
1235f520bb22SYouMin Chen static int update_refresh_reg(struct dram_info *dram)
1236f520bb22SYouMin Chen {
1237f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1238f520bb22SYouMin Chen 	u32 ret;
1239f520bb22SYouMin Chen 
1240f520bb22SYouMin Chen 	ret = readl(pctl_base + DDR_PCTL2_RFSHCTL3) ^ (1 << 1);
1241f520bb22SYouMin Chen 	writel(ret, pctl_base + DDR_PCTL2_RFSHCTL3);
1242f520bb22SYouMin Chen 
1243f520bb22SYouMin Chen 	return 0;
1244f520bb22SYouMin Chen }
1245f520bb22SYouMin Chen 
1246f520bb22SYouMin Chen /*
1247f520bb22SYouMin Chen  * rank = 1: cs0
1248f520bb22SYouMin Chen  * rank = 2: cs1
1249f520bb22SYouMin Chen  */
1250f520bb22SYouMin Chen int read_mr(struct dram_info *dram, u32 rank, u32 mr_num, u32 dramtype)
1251f520bb22SYouMin Chen {
1252f520bb22SYouMin Chen 	u32 ret;
1253f520bb22SYouMin Chen 	u32 i, temp;
1254f520bb22SYouMin Chen 	u32 dqmap;
1255f520bb22SYouMin Chen 
1256f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1257f520bb22SYouMin Chen 	struct sdram_head_info_index_v2 *index =
1258f520bb22SYouMin Chen 		(struct sdram_head_info_index_v2 *)common_info;
1259f520bb22SYouMin Chen 	struct dq_map_info *map_info;
1260f520bb22SYouMin Chen 
1261f520bb22SYouMin Chen 	map_info = (struct dq_map_info *)((void *)common_info +
1262f520bb22SYouMin Chen 		index->dq_map_index.offset * 4);
1263f520bb22SYouMin Chen 
1264f520bb22SYouMin Chen 	if (dramtype == LPDDR2)
1265f520bb22SYouMin Chen 		dqmap = map_info->lp2_dq0_7_map;
1266f520bb22SYouMin Chen 	else
1267f520bb22SYouMin Chen 		dqmap = map_info->lp3_dq0_7_map;
1268f520bb22SYouMin Chen 
1269f520bb22SYouMin Chen 	pctl_read_mr(pctl_base, rank, mr_num);
1270f520bb22SYouMin Chen 
1271f520bb22SYouMin Chen 	ret = (readl(&dram->ddrgrf->ddr_grf_status[0]) & 0xff);
1272f520bb22SYouMin Chen 
1273f520bb22SYouMin Chen 	if (dramtype != LPDDR4) {
1274f520bb22SYouMin Chen 		temp = 0;
1275f520bb22SYouMin Chen 		for (i = 0; i < 8; i++) {
1276f520bb22SYouMin Chen 			temp = temp | (((ret >> i) & 0x1) <<
1277f520bb22SYouMin Chen 				       ((dqmap >> (i * 4)) & 0xf));
1278f520bb22SYouMin Chen 		}
1279f520bb22SYouMin Chen 	} else {
1280330cd12fSWesley Yao 		temp = (readl(&dram->ddrgrf->ddr_grf_status[1]) & 0xff);
1281f520bb22SYouMin Chen 	}
1282f520bb22SYouMin Chen 
1283330cd12fSWesley Yao 	return temp;
1284f520bb22SYouMin Chen }
1285f520bb22SYouMin Chen 
1286f520bb22SYouMin Chen /* before call this function autorefresh should be disabled */
1287f520bb22SYouMin Chen void send_a_refresh(struct dram_info *dram)
1288f520bb22SYouMin Chen {
1289f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1290f520bb22SYouMin Chen 
1291f520bb22SYouMin Chen 	while (readl(pctl_base + DDR_PCTL2_DBGSTAT) & 0x3)
1292f520bb22SYouMin Chen 		continue;
1293f520bb22SYouMin Chen 	writel(0x3, pctl_base + DDR_PCTL2_DBGCMD);
1294f520bb22SYouMin Chen }
1295f520bb22SYouMin Chen 
1296f4f57f8eSTang Yun ping static void enter_sr(struct dram_info *dram, u32 en)
1297f4f57f8eSTang Yun ping {
1298f4f57f8eSTang Yun ping 	void __iomem *pctl_base = dram->pctl;
1299f4f57f8eSTang Yun ping 
1300f4f57f8eSTang Yun ping 	if (en) {
1301f4f57f8eSTang Yun ping 		setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, PCTL2_SELFREF_SW);
1302f4f57f8eSTang Yun ping 		while (1) {
1303f4f57f8eSTang Yun ping 			if (((readl(pctl_base + DDR_PCTL2_STAT) &
1304f4f57f8eSTang Yun ping 			      PCTL2_SELFREF_TYPE_MASK) ==
1305f4f57f8eSTang Yun ping 			     PCTL2_SELFREF_TYPE_SR_NOT_AUTO) &&
1306f4f57f8eSTang Yun ping 			    ((readl(pctl_base + DDR_PCTL2_STAT) &
1307f4f57f8eSTang Yun ping 			      PCTL2_OPERATING_MODE_MASK) ==
1308f4f57f8eSTang Yun ping 			     PCTL2_OPERATING_MODE_SR))
1309f4f57f8eSTang Yun ping 				break;
1310f4f57f8eSTang Yun ping 		}
1311f4f57f8eSTang Yun ping 	} else {
1312f4f57f8eSTang Yun ping 		clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, PCTL2_SELFREF_SW);
1313f4f57f8eSTang Yun ping 		while ((readl(pctl_base + DDR_PCTL2_STAT) &
1314f4f57f8eSTang Yun ping 		       PCTL2_OPERATING_MODE_MASK) == PCTL2_OPERATING_MODE_SR)
1315f4f57f8eSTang Yun ping 			continue;
1316f4f57f8eSTang Yun ping 	}
1317f4f57f8eSTang Yun ping }
1318f4f57f8eSTang Yun ping 
1319f520bb22SYouMin Chen void record_dq_prebit(struct dram_info *dram)
1320f520bb22SYouMin Chen {
1321f520bb22SYouMin Chen 	u32 group, i, tmp;
1322f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1323f520bb22SYouMin Chen 
1324f520bb22SYouMin Chen 	for (group = 0; group < 4; group++) {
1325f520bb22SYouMin Chen 		for (i = 0; i < ARRAY_SIZE(dq_sel); i++) {
1326f520bb22SYouMin Chen 			/* l_loop_invdelaysel */
1327f520bb22SYouMin Chen 			writel(dq_sel[i][0], PHY_REG(phy_base,
1328f520bb22SYouMin Chen 						     grp_addr[group] + 0x2c));
1329f520bb22SYouMin Chen 			tmp = readl(PHY_REG(phy_base, grp_addr[group] + 0x2e));
1330f520bb22SYouMin Chen 			writel(tmp, PHY_REG(phy_base,
1331f520bb22SYouMin Chen 					    grp_addr[group] + dq_sel[i][1]));
1332f520bb22SYouMin Chen 
1333f520bb22SYouMin Chen 			/* r_loop_invdelaysel */
1334f520bb22SYouMin Chen 			writel(dq_sel[i][0], PHY_REG(phy_base,
1335f520bb22SYouMin Chen 						     grp_addr[group] + 0x2d));
1336f520bb22SYouMin Chen 			tmp = readl(PHY_REG(phy_base, grp_addr[group] + 0x2f));
1337f520bb22SYouMin Chen 			writel(tmp, PHY_REG(phy_base,
1338f520bb22SYouMin Chen 					    grp_addr[group] + dq_sel[i][2]));
1339f520bb22SYouMin Chen 		}
1340f520bb22SYouMin Chen 	}
1341f520bb22SYouMin Chen }
1342f520bb22SYouMin Chen 
1343f520bb22SYouMin Chen static void update_dq_rx_prebit(struct dram_info *dram)
1344f520bb22SYouMin Chen {
1345f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1346f520bb22SYouMin Chen 
1347f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x70), BIT(1) | BIT(6) | BIT(4),
1348f520bb22SYouMin Chen 			BIT(4));
1349f520bb22SYouMin Chen 	udelay(1);
1350f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x70), BIT(4));
1351f520bb22SYouMin Chen }
1352f520bb22SYouMin Chen 
1353f520bb22SYouMin Chen static void update_dq_tx_prebit(struct dram_info *dram)
1354f520bb22SYouMin Chen {
1355f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1356f520bb22SYouMin Chen 
1357f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
1358f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x2), BIT(3));
1359f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0xc), BIT(6));
1360f520bb22SYouMin Chen 	udelay(1);
1361f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0xc), BIT(6));
1362f520bb22SYouMin Chen }
1363f520bb22SYouMin Chen 
1364f520bb22SYouMin Chen static void update_ca_prebit(struct dram_info *dram)
1365f520bb22SYouMin Chen {
1366f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1367f520bb22SYouMin Chen 
1368f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x25), BIT(2));
1369f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x22), BIT(6));
1370f520bb22SYouMin Chen 	udelay(1);
1371f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x22), BIT(6));
1372f520bb22SYouMin Chen }
1373f520bb22SYouMin Chen 
1374f520bb22SYouMin Chen /*
1375f520bb22SYouMin Chen  * dir: 0: de-skew = delta_*
1376f520bb22SYouMin Chen  *	1: de-skew = reg val - delta_*
1377f520bb22SYouMin Chen  * delta_dir: value for differential signal: clk/
1378f520bb22SYouMin Chen  * delta_sig: value for single signal: ca/cmd
1379f520bb22SYouMin Chen  */
1380f520bb22SYouMin Chen static void modify_ca_deskew(struct dram_info *dram, u32 dir, int delta_dif,
1381f520bb22SYouMin Chen 			     int delta_sig, u32 cs, u32 dramtype)
1382f520bb22SYouMin Chen {
1383f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1384f520bb22SYouMin Chen 	u32 i, cs_en, tmp;
1385f4f57f8eSTang Yun ping 	u32 dfi_lp_stat = 0;
1386f520bb22SYouMin Chen 
1387f520bb22SYouMin Chen 	if (cs == 0)
1388f520bb22SYouMin Chen 		cs_en = 1;
1389f520bb22SYouMin Chen 	else if (cs == 2)
1390f520bb22SYouMin Chen 		cs_en = 2;
1391f520bb22SYouMin Chen 	else
1392f520bb22SYouMin Chen 		cs_en = 3;
1393f520bb22SYouMin Chen 
1394f4f57f8eSTang Yun ping 	if (dramtype == LPDDR4 &&
1395f4f57f8eSTang Yun ping 	    ((readl(PHY_REG(phy_base, 0x60)) & BIT(5)) == 0)) {
1396f4f57f8eSTang Yun ping 		dfi_lp_stat = 1;
1397f4f57f8eSTang Yun ping 		setbits_le32(PHY_REG(phy_base, 0x60), BIT(5));
1398f4f57f8eSTang Yun ping 	}
1399f4f57f8eSTang Yun ping 	enter_sr(dram, 1);
1400f4f57f8eSTang Yun ping 
1401f520bb22SYouMin Chen 	for (i = 0; i < 0x20; i++) {
1402f520bb22SYouMin Chen 		if (dir == DESKEW_MDF_ABS_VAL)
1403f520bb22SYouMin Chen 			tmp = delta_sig;
1404f520bb22SYouMin Chen 		else
1405f520bb22SYouMin Chen 			tmp = readl(PHY_REG(phy_base, 0x150 + i)) +
1406f520bb22SYouMin Chen 			      delta_sig;
1407f520bb22SYouMin Chen 		writel(tmp, PHY_REG(phy_base, 0x150 + i));
1408f520bb22SYouMin Chen 	}
1409f520bb22SYouMin Chen 
1410f520bb22SYouMin Chen 	if (dir == DESKEW_MDF_ABS_VAL)
1411f520bb22SYouMin Chen 		tmp = delta_dif;
1412f520bb22SYouMin Chen 	else
1413f520bb22SYouMin Chen 		tmp = readl(PHY_REG(phy_base, 0x150 + 0x17)) -
1414f520bb22SYouMin Chen 		       delta_sig + delta_dif;
1415f520bb22SYouMin Chen 	writel(tmp, PHY_REG(phy_base, 0x150 + 0x17));
1416f520bb22SYouMin Chen 	writel(tmp, PHY_REG(phy_base, 0x150 + 0x18));
1417f520bb22SYouMin Chen 	if (dramtype == LPDDR4) {
1418f520bb22SYouMin Chen 		writel(tmp, PHY_REG(phy_base, 0x150 + 0x4));
1419f520bb22SYouMin Chen 		writel(tmp, PHY_REG(phy_base, 0x150 + 0xa));
1420f520bb22SYouMin Chen 
1421f520bb22SYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x10), cs_en << 6);
1422f520bb22SYouMin Chen 		update_ca_prebit(dram);
1423f520bb22SYouMin Chen 	}
1424f4f57f8eSTang Yun ping 	enter_sr(dram, 0);
1425f4f57f8eSTang Yun ping 
1426f4f57f8eSTang Yun ping 	if (dfi_lp_stat)
1427f4f57f8eSTang Yun ping 		clrbits_le32(PHY_REG(phy_base, 0x60), BIT(5));
1428f4f57f8eSTang Yun ping 
1429f520bb22SYouMin Chen }
1430f520bb22SYouMin Chen 
1431f520bb22SYouMin Chen static u32 get_min_value(struct dram_info *dram, u32 signal, u32 rank)
1432f520bb22SYouMin Chen {
1433f520bb22SYouMin Chen 	u32 i, j, offset = 0;
1434f520bb22SYouMin Chen 	u32 min = 0x3f;
1435f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1436f520bb22SYouMin Chen 	u32 byte_en;
1437f520bb22SYouMin Chen 
1438f520bb22SYouMin Chen 	if (signal == SKEW_TX_SIGNAL)
1439f520bb22SYouMin Chen 		offset = 8;
1440f520bb22SYouMin Chen 
1441f520bb22SYouMin Chen 	if (signal == SKEW_CA_SIGNAL) {
1442f520bb22SYouMin Chen 		for (i = 0; i < 0x20; i++)
1443f520bb22SYouMin Chen 			min = MIN(min, readl(PHY_REG(phy_base, 0x150  + i)));
1444f520bb22SYouMin Chen 	} else {
1445f520bb22SYouMin Chen 		byte_en = readl(PHY_REG(phy_base, 0xf)) & 0xf;
1446f520bb22SYouMin Chen 		for (j = offset; j < offset + rank * 4; j++) {
1447f520bb22SYouMin Chen 			if (!((byte_en >> (j % 4)) & 1))
1448f520bb22SYouMin Chen 				continue;
1449f520bb22SYouMin Chen 			for (i = 0; i < 11; i++)
1450f520bb22SYouMin Chen 				min = MIN(min,
1451f520bb22SYouMin Chen 					  readl(PHY_REG(phy_base,
1452f520bb22SYouMin Chen 							dqs_dq_skew_adr[j] +
1453f520bb22SYouMin Chen 							i)));
1454f520bb22SYouMin Chen 		}
1455f520bb22SYouMin Chen 	}
1456f520bb22SYouMin Chen 
1457f520bb22SYouMin Chen 	return min;
1458f520bb22SYouMin Chen }
1459f520bb22SYouMin Chen 
1460f520bb22SYouMin Chen static u32 low_power_update(struct dram_info *dram, u32 en)
1461f520bb22SYouMin Chen {
1462f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1463f520bb22SYouMin Chen 	u32 lp_stat = 0;
1464f520bb22SYouMin Chen 
1465f520bb22SYouMin Chen 	if (en) {
1466f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, en & 0xf);
1467f520bb22SYouMin Chen 	} else {
1468f520bb22SYouMin Chen 		lp_stat = readl(pctl_base + DDR_PCTL2_PWRCTL) & 0xf;
1469f520bb22SYouMin Chen 		clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 0xf);
1470f520bb22SYouMin Chen 	}
1471f520bb22SYouMin Chen 
1472f520bb22SYouMin Chen 	return lp_stat;
1473f520bb22SYouMin Chen }
1474f520bb22SYouMin Chen 
1475f520bb22SYouMin Chen /*
1476f520bb22SYouMin Chen  * signal:
1477f520bb22SYouMin Chen  * dir: 0: de-skew = delta_*
1478f520bb22SYouMin Chen  *	1: de-skew = reg val - delta_*
1479f520bb22SYouMin Chen  * delta_dir: value for differential signal: dqs
1480f520bb22SYouMin Chen  * delta_sig: value for single signal: dq/dm
1481f520bb22SYouMin Chen  */
1482f520bb22SYouMin Chen static void modify_dq_deskew(struct dram_info *dram, u32 signal, u32 dir,
1483f520bb22SYouMin Chen 			     int delta_dif, int delta_sig, u32 rank)
1484f520bb22SYouMin Chen {
1485f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1486f520bb22SYouMin Chen 	u32 i, j, tmp, offset;
1487f520bb22SYouMin Chen 	u32 byte_en;
1488f520bb22SYouMin Chen 
1489f520bb22SYouMin Chen 	byte_en = readl(PHY_REG(phy_base, 0xf)) & 0xf;
1490f520bb22SYouMin Chen 
1491f520bb22SYouMin Chen 	if (signal == SKEW_RX_SIGNAL)
1492f520bb22SYouMin Chen 		offset = 0;
1493f520bb22SYouMin Chen 	else
1494f520bb22SYouMin Chen 		offset = 8;
1495f520bb22SYouMin Chen 
1496f520bb22SYouMin Chen 	for (j = offset; j < (offset + rank * 4); j++) {
1497f520bb22SYouMin Chen 		if (!((byte_en >> (j % 4)) & 1))
1498f520bb22SYouMin Chen 			continue;
1499f520bb22SYouMin Chen 		for (i = 0; i < 0x9; i++) {
1500f520bb22SYouMin Chen 			if (dir == DESKEW_MDF_ABS_VAL)
1501f520bb22SYouMin Chen 				tmp = delta_sig;
1502f520bb22SYouMin Chen 			else
1503f520bb22SYouMin Chen 				tmp = delta_sig + readl(PHY_REG(phy_base,
1504f520bb22SYouMin Chen 							dqs_dq_skew_adr[j] +
1505f520bb22SYouMin Chen 							i));
1506f520bb22SYouMin Chen 			writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + i));
1507f520bb22SYouMin Chen 		}
1508f520bb22SYouMin Chen 		if (dir == DESKEW_MDF_ABS_VAL)
1509f520bb22SYouMin Chen 			tmp = delta_dif;
1510f520bb22SYouMin Chen 		else
1511f520bb22SYouMin Chen 			tmp = delta_dif + readl(PHY_REG(phy_base,
1512f520bb22SYouMin Chen 						dqs_dq_skew_adr[j] + 9));
1513f520bb22SYouMin Chen 		writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + 9));
1514f520bb22SYouMin Chen 		writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + 0xa));
1515f520bb22SYouMin Chen 	}
1516f520bb22SYouMin Chen 	if (signal == SKEW_RX_SIGNAL)
1517f520bb22SYouMin Chen 		update_dq_rx_prebit(dram);
1518f520bb22SYouMin Chen 	else
1519f520bb22SYouMin Chen 		update_dq_tx_prebit(dram);
1520f520bb22SYouMin Chen }
1521f520bb22SYouMin Chen 
1522f520bb22SYouMin Chen static int data_training_rg(struct dram_info *dram, u32 cs, u32 dramtype)
1523f520bb22SYouMin Chen {
1524f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1525f520bb22SYouMin Chen 	u32 ret;
1526f520bb22SYouMin Chen 	u32 dis_auto_zq = 0;
1527f520bb22SYouMin Chen 	u32 odt_val_up, odt_val_dn;
1528f520bb22SYouMin Chen 	u32 i, j;
1529f520bb22SYouMin Chen 
1530f520bb22SYouMin Chen 	odt_val_dn = readl(PHY_REG(phy_base, 0x110));
1531f520bb22SYouMin Chen 	odt_val_up = readl(PHY_REG(phy_base, 0x111));
1532f520bb22SYouMin Chen 
1533f520bb22SYouMin Chen 	if (dramtype != LPDDR4) {
1534f520bb22SYouMin Chen 		for (i = 0; i < 4; i++) {
1535f520bb22SYouMin Chen 			j = 0x110 + i * 0x10;
153670fee8b3STang Yun ping 			writel(PHY_DDR4_LPDDR3_RTT_294ohm,
1537f520bb22SYouMin Chen 			       PHY_REG(phy_base, j));
1538f520bb22SYouMin Chen 			writel(PHY_DDR4_LPDDR3_RTT_DISABLE,
1539f520bb22SYouMin Chen 			       PHY_REG(phy_base, j + 0x1));
1540f520bb22SYouMin Chen 		}
1541f520bb22SYouMin Chen 	}
1542f520bb22SYouMin Chen 	dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
1543f520bb22SYouMin Chen 	/* use normal read mode for data training */
1544f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0xc), BIT(1));
1545f520bb22SYouMin Chen 
15462c5208e2STang Yun ping 	if (dramtype == DDR4)
15472c5208e2STang Yun ping 		setbits_le32(PHY_REG(phy_base, 0xc), BIT(1));
1548f520bb22SYouMin Chen 
1549f520bb22SYouMin Chen 	/* choose training cs */
1550f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs));
1551f520bb22SYouMin Chen 	/* enable gate training */
1552f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1);
1553f520bb22SYouMin Chen 	udelay(50);
1554f520bb22SYouMin Chen 	ret = readl(PHY_REG(phy_base, 0x91));
1555f520bb22SYouMin Chen 	/* disable gate training */
1556f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0);
1557f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 2), 0x30);
1558f520bb22SYouMin Chen 	pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
1559f520bb22SYouMin Chen 
1560f520bb22SYouMin Chen 	if (ret & 0x20)
1561f520bb22SYouMin Chen 		ret = -1;
1562f520bb22SYouMin Chen 	else
1563f520bb22SYouMin Chen 		ret = (ret & 0xf) ^ (readl(PHY_REG(phy_base, 0xf)) & 0xf);
1564f520bb22SYouMin Chen 
1565f520bb22SYouMin Chen 	if (dramtype != LPDDR4) {
1566f520bb22SYouMin Chen 		for (i = 0; i < 4; i++) {
1567f520bb22SYouMin Chen 			j = 0x110 + i * 0x10;
1568f520bb22SYouMin Chen 			writel(odt_val_dn, PHY_REG(phy_base, j));
1569f520bb22SYouMin Chen 			writel(odt_val_up, PHY_REG(phy_base, j + 0x1));
1570f520bb22SYouMin Chen 		}
1571f520bb22SYouMin Chen 	}
1572f520bb22SYouMin Chen 	return ret;
1573f520bb22SYouMin Chen }
1574f520bb22SYouMin Chen 
1575f520bb22SYouMin Chen static int data_training_wl(struct dram_info *dram, u32 cs, u32 dramtype,
1576f520bb22SYouMin Chen 			    u32 rank)
1577f520bb22SYouMin Chen {
1578f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1579f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1580f520bb22SYouMin Chen 	u32 dis_auto_zq = 0;
1581f520bb22SYouMin Chen 	u32 tmp;
1582f520bb22SYouMin Chen 	u32 cur_fsp;
1583f520bb22SYouMin Chen 	u32 timeout_us = 1000;
1584f520bb22SYouMin Chen 
1585f520bb22SYouMin Chen 	dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
1586f520bb22SYouMin Chen 
1587f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x7a), 0x1);
1588f520bb22SYouMin Chen 
1589f520bb22SYouMin Chen 	cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
1590f520bb22SYouMin Chen 	tmp = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + DDR_PCTL2_INIT3) &
1591f520bb22SYouMin Chen 	      0xffff;
1592f520bb22SYouMin Chen 	writel(tmp & 0xff, PHY_REG(phy_base, 0x3));
1593f520bb22SYouMin Chen 
1594f520bb22SYouMin Chen 	/* disable another cs's output */
1595f520bb22SYouMin Chen 	if ((dramtype == DDR3 || dramtype == DDR4) && rank == 2)
1596f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, (cs + 1) & 1, 1, tmp | (1 << 12),
1597f520bb22SYouMin Chen 			      dramtype);
1598f520bb22SYouMin Chen 	if (dramtype == DDR3 || dramtype == DDR4)
1599f520bb22SYouMin Chen 		writel(0x40 | ((tmp >> 8) & 0x3f), PHY_REG(phy_base, 0x4));
1600f520bb22SYouMin Chen 	else
1601f520bb22SYouMin Chen 		writel(0x80 | ((tmp >> 8) & 0x3f), PHY_REG(phy_base, 0x4));
1602f520bb22SYouMin Chen 
1603f520bb22SYouMin Chen 	/* choose cs */
1604f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
1605f520bb22SYouMin Chen 			((0x2 >> cs) << 6) | (0 << 2));
1606f520bb22SYouMin Chen 	/* enable write leveling */
1607f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
1608f520bb22SYouMin Chen 			((0x2 >> cs) << 6) | (1 << 2));
1609f520bb22SYouMin Chen 
1610f520bb22SYouMin Chen 	while (1) {
1611f520bb22SYouMin Chen 		if ((readl(PHY_REG(phy_base, 0x92)) & 0xf) ==
1612f520bb22SYouMin Chen 		    (readl(PHY_REG(phy_base, 0xf)) & 0xf))
1613f520bb22SYouMin Chen 			break;
1614f520bb22SYouMin Chen 
1615f520bb22SYouMin Chen 		udelay(1);
1616f520bb22SYouMin Chen 		if (timeout_us-- == 0) {
1617f520bb22SYouMin Chen 			printascii("error: write leveling timeout\n");
1618f520bb22SYouMin Chen 			while (1)
1619f520bb22SYouMin Chen 				;
1620f520bb22SYouMin Chen 		}
1621f520bb22SYouMin Chen 	}
1622f520bb22SYouMin Chen 
1623f520bb22SYouMin Chen 	/* disable write leveling */
1624f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
1625f520bb22SYouMin Chen 			((0x2 >> cs) << 6) | (0 << 2));
1626f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x3 << 6, 0 << 6);
1627f520bb22SYouMin Chen 
1628f520bb22SYouMin Chen 	/* enable another cs's output */
1629f520bb22SYouMin Chen 	if ((dramtype == DDR3 || dramtype == DDR4) && rank == 2)
1630f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, (cs + 1) & 1, 1, tmp & ~(1 << 12),
1631f520bb22SYouMin Chen 			      dramtype);
1632f520bb22SYouMin Chen 
1633f520bb22SYouMin Chen 	pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
1634f520bb22SYouMin Chen 
1635f520bb22SYouMin Chen 	return 0;
1636f520bb22SYouMin Chen }
1637f520bb22SYouMin Chen 
1638f520bb22SYouMin Chen char pattern[32] = {
1639f520bb22SYouMin Chen 	0xaa, 0x55, 0xaa, 0x55, 0x55, 0xaa, 0x55, 0xaa,
1640f520bb22SYouMin Chen 	0x55, 0xaa, 0x55, 0xaa, 0xaa, 0x55, 0xaa, 0x55,
1641f520bb22SYouMin Chen 	0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55,
1642f520bb22SYouMin Chen 	0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa
1643f520bb22SYouMin Chen };
1644f520bb22SYouMin Chen 
1645f520bb22SYouMin Chen static int data_training_rd(struct dram_info *dram, u32 cs, u32 dramtype,
1646f520bb22SYouMin Chen 			    u32 mhz)
1647f520bb22SYouMin Chen {
1648f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1649f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1650f520bb22SYouMin Chen 	u32 trefi_1x, trfc_1x;
1651f520bb22SYouMin Chen 	u32 dis_auto_zq = 0;
1652f520bb22SYouMin Chen 	u32 timeout_us = 1000;
1653f520bb22SYouMin Chen 	u32 dqs_default;
1654f520bb22SYouMin Chen 	u32 cur_fsp;
165548c0a787SYouMin Chen 	u32 vref_inner;
1656f520bb22SYouMin Chen 	u32 i;
1657f520bb22SYouMin Chen 	struct sdram_head_info_index_v2 *index =
1658f520bb22SYouMin Chen 		(struct sdram_head_info_index_v2 *)common_info;
1659f520bb22SYouMin Chen 	struct dq_map_info *map_info;
1660f520bb22SYouMin Chen 
166148c0a787SYouMin Chen 	vref_inner = readl(PHY_REG(phy_base, 0x128)) & 0xff;
166248c0a787SYouMin Chen 	if (dramtype == DDR3 && vref_inner == 0x80) {
166348c0a787SYouMin Chen 		for (i = 0; i < 4; i++)
166448c0a787SYouMin Chen 			writel(vref_inner - 0xa,
166548c0a787SYouMin Chen 			       PHY_REG(phy_base, 0x118 + i * 0x10));
166648c0a787SYouMin Chen 
166748c0a787SYouMin Chen 		/* reg_rx_vref_value_update */
166848c0a787SYouMin Chen 		setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
166948c0a787SYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
167048c0a787SYouMin Chen 	}
167148c0a787SYouMin Chen 
1672f520bb22SYouMin Chen 	map_info = (struct dq_map_info *)((void *)common_info +
1673f520bb22SYouMin Chen 		index->dq_map_index.offset * 4);
1674f520bb22SYouMin Chen 	/* only 1cs a time, 0:cs0 1 cs1 */
1675f520bb22SYouMin Chen 	if (cs > 1)
1676f520bb22SYouMin Chen 		return -1;
1677f520bb22SYouMin Chen 
1678f520bb22SYouMin Chen 	dqs_default = 0xf;
1679f520bb22SYouMin Chen 	dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
1680f520bb22SYouMin Chen 
1681f520bb22SYouMin Chen 	cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
1682f520bb22SYouMin Chen 	/* config refresh timing */
1683f520bb22SYouMin Chen 	trefi_1x = ((readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1684f520bb22SYouMin Chen 			   DDR_PCTL2_RFSHTMG) >> 16) & 0xfff) * 32;
1685f520bb22SYouMin Chen 	trfc_1x = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1686f520bb22SYouMin Chen 			DDR_PCTL2_RFSHTMG) & 0x3ff;
1687f520bb22SYouMin Chen 	/* reg_phy_trefi[7:0] and reg_phy_trefi[13:8] */
1688f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x6e), 0xff, trefi_1x & 0xff);
1689f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x6f), 0x3f, (trefi_1x >> 8) & 0x3f);
1690f520bb22SYouMin Chen 	/* reg_phy_trfc */
1691f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x57), 0xff, trfc_1x);
1692f520bb22SYouMin Chen 	/* reg_max_refi_cnt */
1693f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x61), 0xf << 4, 0x8 << 4);
1694f520bb22SYouMin Chen 
1695f520bb22SYouMin Chen 	/* choose training cs */
1696f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x71), 0x3 << 6, (0x2 >> cs) << 6);
1697f520bb22SYouMin Chen 
1698f520bb22SYouMin Chen 	/* set dq map for ddr4 */
1699f520bb22SYouMin Chen 	if (dramtype == DDR4) {
1700f520bb22SYouMin Chen 		setbits_le32(PHY_REG(phy_base, 0x70), BIT(7));
1701f520bb22SYouMin Chen 		for (i = 0; i < 4; i++) {
1702f520bb22SYouMin Chen 			writel((map_info->ddr4_dq_map[cs * 2] >>
1703f520bb22SYouMin Chen 				((i % 4) * 8)) & 0xff,
1704f520bb22SYouMin Chen 				PHY_REG(phy_base, 0x238 + i));
1705f520bb22SYouMin Chen 			writel((map_info->ddr4_dq_map[cs * 2 + 1] >>
1706f520bb22SYouMin Chen 				((i % 4) * 8)) & 0xff,
1707f520bb22SYouMin Chen 				PHY_REG(phy_base, 0x2b8 + i));
1708f520bb22SYouMin Chen 		}
1709f520bb22SYouMin Chen 	}
1710f520bb22SYouMin Chen 
1711f520bb22SYouMin Chen 	/* cha_l reg_l_rd_train_dqs_default[5:0] */
1712f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x230), 0x3f, dqs_default);
1713f520bb22SYouMin Chen 	/* cha_h reg_h_rd_train_dqs_default[5:0] */
1714f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x234), 0x3f, dqs_default);
1715f520bb22SYouMin Chen 	/* chb_l reg_l_rd_train_dqs_default[5:0] */
1716f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x2b0), 0x3f, dqs_default);
1717f520bb22SYouMin Chen 	/* chb_h reg_h_rd_train_dqs_default[5:0] */
1718f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x2b4), 0x3f, dqs_default);
1719f520bb22SYouMin Chen 
1720f520bb22SYouMin Chen 	/* Choose the read train auto mode */
1721f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x70), 0x3, 0x1);
1722f520bb22SYouMin Chen 	/* Enable the auto train of the read train */
1723f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x70), 0x3, 0x3);
1724f520bb22SYouMin Chen 
1725f520bb22SYouMin Chen 	/* Wait the train done. */
1726f520bb22SYouMin Chen 	while (1) {
1727f520bb22SYouMin Chen 		if ((readl(PHY_REG(phy_base, 0x93)) >> 7) & 0x1)
1728f520bb22SYouMin Chen 			break;
1729f520bb22SYouMin Chen 
1730f520bb22SYouMin Chen 		udelay(1);
1731f520bb22SYouMin Chen 		if (timeout_us-- == 0) {
1732f520bb22SYouMin Chen 			printascii("error: read training timeout\n");
1733f520bb22SYouMin Chen 			return -1;
1734f520bb22SYouMin Chen 		}
1735f520bb22SYouMin Chen 	}
1736f520bb22SYouMin Chen 
1737f520bb22SYouMin Chen 	/* Check the read train state */
1738f520bb22SYouMin Chen 	if ((readl(PHY_REG(phy_base, 0x240)) & 0x3) ||
1739f520bb22SYouMin Chen 	    (readl(PHY_REG(phy_base, 0x2c0)) & 0x3)) {
1740f520bb22SYouMin Chen 		printascii("error: read training error\n");
1741f520bb22SYouMin Chen 		return -1;
1742f520bb22SYouMin Chen 	}
1743f520bb22SYouMin Chen 
1744f520bb22SYouMin Chen 	/* Exit the Read Training by setting */
1745f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x70), BIT(1));
1746f520bb22SYouMin Chen 
1747f520bb22SYouMin Chen 	pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
1748f520bb22SYouMin Chen 
174948c0a787SYouMin Chen 	if (dramtype == DDR3 && vref_inner == 0x80) {
175048c0a787SYouMin Chen 		for (i = 0; i < 4; i++)
175148c0a787SYouMin Chen 			writel(vref_inner,
175248c0a787SYouMin Chen 			       PHY_REG(phy_base, 0x118 + i * 0x10));
175348c0a787SYouMin Chen 
175448c0a787SYouMin Chen 		/* reg_rx_vref_value_update */
175548c0a787SYouMin Chen 		setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
175648c0a787SYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
175748c0a787SYouMin Chen 	}
175848c0a787SYouMin Chen 
1759f520bb22SYouMin Chen 	return 0;
1760f520bb22SYouMin Chen }
1761f520bb22SYouMin Chen 
1762f520bb22SYouMin Chen static int data_training_wr(struct dram_info *dram, u32 cs, u32 dramtype,
1763f520bb22SYouMin Chen 			    u32 mhz, u32 dst_fsp)
1764f520bb22SYouMin Chen {
1765f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1766f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1767f520bb22SYouMin Chen 	u32 trefi_1x, trfc_1x;
1768f520bb22SYouMin Chen 	u32 dis_auto_zq = 0;
1769f520bb22SYouMin Chen 	u32 timeout_us = 1000;
1770f520bb22SYouMin Chen 	u32 cur_fsp;
1771f520bb22SYouMin Chen 	u32 mr_tmp, cl, cwl, phy_fsp, offset = 0;
1772f520bb22SYouMin Chen 
1773f520bb22SYouMin Chen 	if (dramtype == LPDDR3 && mhz <= 400) {
1774f520bb22SYouMin Chen 		phy_fsp = (readl(PHY_REG(phy_base, 0xc)) >> 0x2) & 0x3;
1775f520bb22SYouMin Chen 		offset = (phy_fsp == 0) ? 0x5 : 0x387 + (phy_fsp - 1) * 3;
1776f520bb22SYouMin Chen 		cl = readl(PHY_REG(phy_base, offset));
1777f520bb22SYouMin Chen 		cwl = readl(PHY_REG(phy_base, offset + 2));
1778f520bb22SYouMin Chen 
1779f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, offset), 0x1f, 0x8);
1780f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, offset + 2), 0x1f, 0x4);
1781f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 2, 0x6, dramtype);
1782f520bb22SYouMin Chen 	}
1783f520bb22SYouMin Chen 
1784f520bb22SYouMin Chen 	dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
1785f520bb22SYouMin Chen 
1786f520bb22SYouMin Chen 	/* PHY_0x7b[7:0] reg_train_col_addr[7:0] */
1787f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7b), 0xff, 0x0);
1788f520bb22SYouMin Chen 	/* PHY_0x7c[4:2] reg_train_ba_addr[2:0] */
1789f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x7 << 2, 0x0 << 2);
1790f520bb22SYouMin Chen 	/* PHY_0x7c[1:0] reg_train_col_addr[9:8] */
1791f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x3, 0x0);
1792f520bb22SYouMin Chen 	/* PHY_0x7d[7:0] reg_train_row_addr[7:0] */
1793f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7d), 0xff, 0x0);
1794f520bb22SYouMin Chen 	/* PHY_0x7e[7:0] reg_train_row_addr[15:8] */
1795f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7e), 0xff, 0x0);
1796f520bb22SYouMin Chen 
1797f520bb22SYouMin Chen 	/* PHY_0x71[3] wrtrain_check_data_value_random_gen */
1798f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x71), BIT(3));
1799f520bb22SYouMin Chen 
1800f520bb22SYouMin Chen 	/* config refresh timing */
1801f520bb22SYouMin Chen 	cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
1802f520bb22SYouMin Chen 	trefi_1x = ((readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1803f520bb22SYouMin Chen 			   DDR_PCTL2_RFSHTMG) >> 16) & 0xfff) * 32;
1804f520bb22SYouMin Chen 	trfc_1x = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1805f520bb22SYouMin Chen 			DDR_PCTL2_RFSHTMG) & 0x3ff;
1806f520bb22SYouMin Chen 	/* reg_phy_trefi[7:0] and reg_phy_trefi[13:8] */
1807f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x6e), 0xff, trefi_1x & 0xff);
1808f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x6f), 0x3f, (trefi_1x >> 8) & 0x3f);
1809f520bb22SYouMin Chen 	/* reg_phy_trfc */
1810f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x57), 0xff, trfc_1x);
1811f520bb22SYouMin Chen 	/* reg_max_refi_cnt */
1812f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x61), 0xf << 4, 0x8 << 4);
1813f520bb22SYouMin Chen 
1814f520bb22SYouMin Chen 	/* choose training cs */
1815f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x3 << 6, (0x2 >> cs) << 6);
1816f520bb22SYouMin Chen 
1817f520bb22SYouMin Chen 	/* PHY_0x7a [4] reg_wr_train_dqs_default_bypass */
1818f520bb22SYouMin Chen 	/* 0: Use the write-leveling value. */
1819f520bb22SYouMin Chen 	/* 1: use reg0x233 0x237 0x2b3 0x2b7 */
1820f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x7a), BIT(4));
1821f520bb22SYouMin Chen 
1822f520bb22SYouMin Chen 	/* PHY_0x7a [0] reg_dq_wr_train_auto */
1823f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x7a), 0x1);
1824f520bb22SYouMin Chen 
1825f520bb22SYouMin Chen 	/* PHY_0x7a [1] reg_dq_wr_train_en */
1826f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
1827f520bb22SYouMin Chen 
1828f520bb22SYouMin Chen 	send_a_refresh(dram);
1829f520bb22SYouMin Chen 
1830f520bb22SYouMin Chen 	while (1) {
1831f520bb22SYouMin Chen 		if ((readl(PHY_REG(phy_base, 0x92)) >> 7) & 0x1)
1832f520bb22SYouMin Chen 			break;
1833f520bb22SYouMin Chen 
1834f520bb22SYouMin Chen 		udelay(1);
1835f520bb22SYouMin Chen 		if (timeout_us-- == 0) {
1836f520bb22SYouMin Chen 			printascii("error: write training timeout\n");
1837f520bb22SYouMin Chen 			while (1)
1838f520bb22SYouMin Chen 				;
1839f520bb22SYouMin Chen 		}
1840f520bb22SYouMin Chen 	}
1841f520bb22SYouMin Chen 
1842f520bb22SYouMin Chen 	/* Check the write train state */
1843f520bb22SYouMin Chen 	if ((readl(PHY_REG(phy_base, 0x90)) >> 5) & 0x7) {
1844f520bb22SYouMin Chen 		printascii("error: write training error\n");
1845f520bb22SYouMin Chen 		return -1;
1846f520bb22SYouMin Chen 	}
1847f520bb22SYouMin Chen 
1848f520bb22SYouMin Chen 	/* PHY_0x7a [1] reg_dq_wr_train_en */
1849f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
1850f520bb22SYouMin Chen 
1851f520bb22SYouMin Chen 	pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
1852f520bb22SYouMin Chen 
1853f520bb22SYouMin Chen 	/* save LPDDR4 write vref to fsp_param for dfs */
1854f520bb22SYouMin Chen 	if (dramtype == LPDDR4) {
1855f520bb22SYouMin Chen 		fsp_param[dst_fsp].vref_dq[cs] =
1856f520bb22SYouMin Chen 			((readl(PHY_REG(phy_base, 0x384)) & 0x3f) +
1857f520bb22SYouMin Chen 			 (readl(PHY_REG(phy_base, 0x385)) & 0x3f)) / 2;
1858f520bb22SYouMin Chen 		/* add range info */
1859f520bb22SYouMin Chen 		fsp_param[dst_fsp].vref_dq[cs] |=
1860f520bb22SYouMin Chen 			((readl(PHY_REG(phy_base, 0x7c)) & BIT(5)) << 1);
1861f520bb22SYouMin Chen 	}
1862f520bb22SYouMin Chen 
1863f520bb22SYouMin Chen 	if (dramtype == LPDDR3 && mhz <= 400) {
1864f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, offset), 0x1f, cl);
1865f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, offset + 2), 0x1f, cwl);
1866f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1867f520bb22SYouMin Chen 			       DDR_PCTL2_INIT3);
1868f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 2, mr_tmp & PCTL2_MR_MASK,
1869f520bb22SYouMin Chen 			      dramtype);
1870f520bb22SYouMin Chen 	}
1871f520bb22SYouMin Chen 
1872f520bb22SYouMin Chen 	return 0;
1873f520bb22SYouMin Chen }
1874f520bb22SYouMin Chen 
1875f520bb22SYouMin Chen static int data_training(struct dram_info *dram, u32 cs,
1876f520bb22SYouMin Chen 			 struct rv1126_sdram_params *sdram_params, u32 dst_fsp,
1877f520bb22SYouMin Chen 			 u32 training_flag)
1878f520bb22SYouMin Chen {
1879f520bb22SYouMin Chen 	u32 ret = 0;
1880f520bb22SYouMin Chen 
1881f520bb22SYouMin Chen 	if (training_flag == FULL_TRAINING)
1882f520bb22SYouMin Chen 		training_flag = READ_GATE_TRAINING | WRITE_LEVELING |
1883f520bb22SYouMin Chen 				WRITE_TRAINING | READ_TRAINING;
1884f520bb22SYouMin Chen 
1885f520bb22SYouMin Chen 	if ((training_flag & WRITE_LEVELING) == WRITE_LEVELING) {
1886f520bb22SYouMin Chen 		ret = data_training_wl(dram, cs,
1887f520bb22SYouMin Chen 				       sdram_params->base.dramtype,
1888f520bb22SYouMin Chen 				       sdram_params->ch.cap_info.rank);
1889f520bb22SYouMin Chen 		if (ret != 0)
1890f520bb22SYouMin Chen 			goto out;
1891f520bb22SYouMin Chen 	}
1892f520bb22SYouMin Chen 
1893f520bb22SYouMin Chen 	if ((training_flag & READ_GATE_TRAINING) == READ_GATE_TRAINING) {
1894f520bb22SYouMin Chen 		ret = data_training_rg(dram, cs,
1895f520bb22SYouMin Chen 				       sdram_params->base.dramtype);
1896f520bb22SYouMin Chen 		if (ret != 0)
1897f520bb22SYouMin Chen 			goto out;
1898f520bb22SYouMin Chen 	}
1899f520bb22SYouMin Chen 
1900f520bb22SYouMin Chen 	if ((training_flag & READ_TRAINING) == READ_TRAINING) {
1901f520bb22SYouMin Chen 		ret = data_training_rd(dram, cs,
1902f520bb22SYouMin Chen 				       sdram_params->base.dramtype,
1903f520bb22SYouMin Chen 				       sdram_params->base.ddr_freq);
1904f520bb22SYouMin Chen 		if (ret != 0)
1905f520bb22SYouMin Chen 			goto out;
1906f520bb22SYouMin Chen 	}
1907f520bb22SYouMin Chen 
1908f520bb22SYouMin Chen 	if ((training_flag & WRITE_TRAINING) == WRITE_TRAINING) {
1909f520bb22SYouMin Chen 		ret = data_training_wr(dram, cs,
1910f520bb22SYouMin Chen 				       sdram_params->base.dramtype,
1911f520bb22SYouMin Chen 				       sdram_params->base.ddr_freq, dst_fsp);
1912f520bb22SYouMin Chen 		if (ret != 0)
1913f520bb22SYouMin Chen 			goto out;
1914f520bb22SYouMin Chen 	}
1915f520bb22SYouMin Chen 
1916f520bb22SYouMin Chen out:
1917f520bb22SYouMin Chen 	return ret;
1918f520bb22SYouMin Chen }
1919f520bb22SYouMin Chen 
1920f520bb22SYouMin Chen static int get_wrlvl_val(struct dram_info *dram,
1921f520bb22SYouMin Chen 			 struct rv1126_sdram_params *sdram_params)
1922f520bb22SYouMin Chen {
1923f520bb22SYouMin Chen 	u32 i, j, clk_skew;
1924f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1925f520bb22SYouMin Chen 	u32 lp_stat;
1926f520bb22SYouMin Chen 	int ret;
1927f520bb22SYouMin Chen 
1928f520bb22SYouMin Chen 	lp_stat = low_power_update(dram, 0);
1929f520bb22SYouMin Chen 
1930d5bb9a92STang Yun ping 	clk_skew = 0x1f;
1931d5bb9a92STang Yun ping 	modify_ca_deskew(dram, DESKEW_MDF_ABS_VAL, clk_skew, clk_skew, 3,
1932d5bb9a92STang Yun ping 			 sdram_params->base.dramtype);
1933f520bb22SYouMin Chen 
1934f520bb22SYouMin Chen 	ret = data_training(dram, 0, sdram_params, 0, WRITE_LEVELING);
1935f520bb22SYouMin Chen 	if (sdram_params->ch.cap_info.rank == 2)
1936f520bb22SYouMin Chen 		ret |= data_training(dram, 1, sdram_params, 0, WRITE_LEVELING);
1937f520bb22SYouMin Chen 
1938f520bb22SYouMin Chen 	for (j = 0; j < 2; j++)
1939f520bb22SYouMin Chen 		for (i = 0; i < 4; i++)
1940f520bb22SYouMin Chen 			wrlvl_result[j][i] =
1941f520bb22SYouMin Chen 				readl(PHY_REG(phy_base,
1942f520bb22SYouMin Chen 					      wrlvl_result_offset[j][i])) -
1943f520bb22SYouMin Chen 				clk_skew;
1944f520bb22SYouMin Chen 
1945f520bb22SYouMin Chen 	low_power_update(dram, lp_stat);
1946f520bb22SYouMin Chen 
1947f520bb22SYouMin Chen 	return ret;
1948f520bb22SYouMin Chen }
1949f520bb22SYouMin Chen 
1950c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL)
1951c71eeac4SWesley Yao static void init_rw_trn_result_struct(struct rw_trn_result *result,
1952c71eeac4SWesley Yao 				      void __iomem *phy_base, u8 cs_num)
1953c71eeac4SWesley Yao {
1954c71eeac4SWesley Yao 	int i;
1955c71eeac4SWesley Yao 
1956c71eeac4SWesley Yao 	result->cs_num = cs_num;
1957c71eeac4SWesley Yao 	result->byte_en = readb(PHY_REG(dram_info.phy, 0xf)) &
1958c71eeac4SWesley Yao 			  PHY_DQ_WIDTH_MASK;
1959c71eeac4SWesley Yao 	for (i = 0; i < FSP_NUM; i++)
1960c71eeac4SWesley Yao 		result->fsp_mhz[i] = 0;
1961c71eeac4SWesley Yao }
1962c71eeac4SWesley Yao 
1963c71eeac4SWesley Yao static void save_rw_trn_min_max(void __iomem *phy_base,
1964c71eeac4SWesley Yao 				struct cs_rw_trn_result *rd_result,
1965c71eeac4SWesley Yao 				struct cs_rw_trn_result *wr_result,
1966c71eeac4SWesley Yao 				u8 byte_en)
1967c71eeac4SWesley Yao {
1968c71eeac4SWesley Yao 	u16 phy_ofs;
1969c71eeac4SWesley Yao 	u8 dqs;
1970c71eeac4SWesley Yao 	u8 dq;
1971c71eeac4SWesley Yao 
19728889aef0SWesley Yao 	for (dqs = 0; dqs < BYTE_NUM; dqs++) {
19738889aef0SWesley Yao 		if ((byte_en & BIT(dqs)) == 0)
19748889aef0SWesley Yao 			continue;
19758889aef0SWesley Yao 
1976c71eeac4SWesley Yao 		/* Channel A or B (low or high 16 bit) */
1977c71eeac4SWesley Yao 		phy_ofs = dqs < 2 ? 0x230 : 0x2b0;
1978c71eeac4SWesley Yao 		/* low or high 8 bit */
1979c71eeac4SWesley Yao 		phy_ofs += (dqs & 0x1) == 0 ? 0 : 0x9;
1980c71eeac4SWesley Yao 		for (dq = 0; dq < 8; dq++) {
1981c71eeac4SWesley Yao 			rd_result->dqs[dqs].dq_min[dq] =
1982c71eeac4SWesley Yao 				readb(PHY_REG(phy_base, phy_ofs + 0x15 + dq));
1983c71eeac4SWesley Yao 			rd_result->dqs[dqs].dq_max[dq] =
1984c71eeac4SWesley Yao 				readb(PHY_REG(phy_base, phy_ofs + 0x27 + dq));
1985c71eeac4SWesley Yao 			wr_result->dqs[dqs].dq_min[dq] =
1986c71eeac4SWesley Yao 				readb(PHY_REG(phy_base, phy_ofs + 0x3d + dq));
1987c71eeac4SWesley Yao 			wr_result->dqs[dqs].dq_max[dq] =
1988c71eeac4SWesley Yao 				readb(PHY_REG(phy_base, phy_ofs + 0x4f + dq));
1989c71eeac4SWesley Yao 		}
1990c71eeac4SWesley Yao 	}
1991c71eeac4SWesley Yao }
1992c71eeac4SWesley Yao 
1993c71eeac4SWesley Yao static void save_rw_trn_deskew(void __iomem *phy_base,
1994c71eeac4SWesley Yao 			       struct fsp_rw_trn_result *result, u8 cs_num,
1995c71eeac4SWesley Yao 			       int min_val, bool rw)
1996c71eeac4SWesley Yao {
1997c71eeac4SWesley Yao 	u16 phy_ofs;
1998c71eeac4SWesley Yao 	u8 cs;
1999c71eeac4SWesley Yao 	u8 dq;
2000c71eeac4SWesley Yao 
2001c71eeac4SWesley Yao 	result->min_val = min_val;
2002c71eeac4SWesley Yao 
2003c71eeac4SWesley Yao 	for (cs = 0; cs < cs_num; cs++) {
2004c71eeac4SWesley Yao 		phy_ofs = cs == 0 ? 0x170 : 0x1a0;
2005c71eeac4SWesley Yao 		phy_ofs += rw == SKEW_RX_SIGNAL ? 0x1 : 0x17;
2006c71eeac4SWesley Yao 		for (dq = 0; dq < 8; dq++) {
2007c71eeac4SWesley Yao 			result->cs[cs].dqs[0].dq_deskew[dq] =
2008c71eeac4SWesley Yao 				readb(PHY_REG(phy_base, phy_ofs + dq));
2009c71eeac4SWesley Yao 			result->cs[cs].dqs[1].dq_deskew[dq] =
2010c71eeac4SWesley Yao 				readb(PHY_REG(phy_base, phy_ofs + 0xb + dq));
2011c71eeac4SWesley Yao 			result->cs[cs].dqs[2].dq_deskew[dq] =
2012c71eeac4SWesley Yao 				readb(PHY_REG(phy_base, phy_ofs + 0x60 + dq));
2013c71eeac4SWesley Yao 			result->cs[cs].dqs[3].dq_deskew[dq] =
2014c71eeac4SWesley Yao 				readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0xb + dq));
2015c71eeac4SWesley Yao 		}
2016c71eeac4SWesley Yao 
2017c71eeac4SWesley Yao 		result->cs[cs].dqs[0].dqs_deskew =
2018c71eeac4SWesley Yao 			readb(PHY_REG(phy_base, phy_ofs + 0x8));
2019c71eeac4SWesley Yao 		result->cs[cs].dqs[1].dqs_deskew =
2020c71eeac4SWesley Yao 			readb(PHY_REG(phy_base, phy_ofs + 0xb + 0x8));
2021c71eeac4SWesley Yao 		result->cs[cs].dqs[2].dqs_deskew =
2022c71eeac4SWesley Yao 			readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0x8));
2023c71eeac4SWesley Yao 		result->cs[cs].dqs[3].dqs_deskew =
2024c71eeac4SWesley Yao 			readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0xb + 0x8));
2025c71eeac4SWesley Yao 	}
2026c71eeac4SWesley Yao }
2027c71eeac4SWesley Yao 
2028c71eeac4SWesley Yao static void save_rw_trn_result_to_ddr(struct rw_trn_result *result)
2029c71eeac4SWesley Yao {
20307a110f3aSWesley Yao 	result->flag = DDR_DQ_EYE_FLAG;
2031c71eeac4SWesley Yao 	memcpy((void *)(RW_TRN_RESULT_ADDR), result, sizeof(*result));
2032c71eeac4SWesley Yao }
2033c71eeac4SWesley Yao #endif
2034c71eeac4SWesley Yao 
2035f520bb22SYouMin Chen static int high_freq_training(struct dram_info *dram,
2036f520bb22SYouMin Chen 			      struct rv1126_sdram_params *sdram_params,
2037f520bb22SYouMin Chen 			      u32 fsp)
2038f520bb22SYouMin Chen {
2039f520bb22SYouMin Chen 	u32 i, j;
2040f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
2041f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
2042f520bb22SYouMin Chen 	int min_val;
2043d5bb9a92STang Yun ping 	int dqs_skew, clk_skew, ca_skew;
204482ad70b5SWesley Yao 	u8 byte_en;
2045f520bb22SYouMin Chen 	int ret;
2046f520bb22SYouMin Chen 
204782ad70b5SWesley Yao 	byte_en = readl(PHY_REG(phy_base, 0xf)) & PHY_DQ_WIDTH_MASK;
2048f520bb22SYouMin Chen 	dqs_skew = 0;
204982ad70b5SWesley Yao 	for (j = 0; j < sdram_params->ch.cap_info.rank; j++) {
205082ad70b5SWesley Yao 		for (i = 0; i < ARRAY_SIZE(wrlvl_result[0]); i++) {
205182ad70b5SWesley Yao 			if ((byte_en & BIT(i)) != 0)
2052f520bb22SYouMin Chen 				dqs_skew += wrlvl_result[j][i];
205382ad70b5SWesley Yao 		}
205482ad70b5SWesley Yao 	}
2055f520bb22SYouMin Chen 	dqs_skew = dqs_skew / (sdram_params->ch.cap_info.rank *
205682ad70b5SWesley Yao 			       (1 << sdram_params->ch.cap_info.bw));
2057f520bb22SYouMin Chen 
2058f520bb22SYouMin Chen 	clk_skew = 0x20 - dqs_skew;
2059f520bb22SYouMin Chen 	dqs_skew = 0x20;
2060f520bb22SYouMin Chen 
2061f520bb22SYouMin Chen 	if (dramtype == LPDDR4) {
2062f520bb22SYouMin Chen 		clk_skew = 0;
2063f520bb22SYouMin Chen 		ca_skew = 0;
2064f520bb22SYouMin Chen 	} else if (dramtype == LPDDR3) {
2065f520bb22SYouMin Chen 		ca_skew = clk_skew - 4;
2066f520bb22SYouMin Chen 	} else {
2067f520bb22SYouMin Chen 		ca_skew = clk_skew;
2068f520bb22SYouMin Chen 	}
2069f520bb22SYouMin Chen 	modify_ca_deskew(dram, DESKEW_MDF_ABS_VAL, clk_skew, ca_skew, 3,
2070f520bb22SYouMin Chen 			 dramtype);
2071f520bb22SYouMin Chen 
2072f520bb22SYouMin Chen 	writel(wrlvl_result[0][0] + clk_skew, PHY_REG(phy_base, 0x233));
2073f520bb22SYouMin Chen 	writel(wrlvl_result[0][1] + clk_skew, PHY_REG(phy_base, 0x237));
2074f520bb22SYouMin Chen 	writel(wrlvl_result[0][2] + clk_skew, PHY_REG(phy_base, 0x2b3));
2075f520bb22SYouMin Chen 	writel(wrlvl_result[0][3] + clk_skew, PHY_REG(phy_base, 0x2b7));
2076f520bb22SYouMin Chen 	ret = data_training(dram, 0, sdram_params, fsp, READ_GATE_TRAINING |
2077f520bb22SYouMin Chen 			    READ_TRAINING | WRITE_TRAINING);
2078c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL)
2079c71eeac4SWesley Yao 	rw_trn_result.fsp_mhz[fsp] = (u16)sdram_params->base.ddr_freq;
2080c71eeac4SWesley Yao 	save_rw_trn_min_max(phy_base, &rw_trn_result.rd_fsp[fsp].cs[0],
2081c71eeac4SWesley Yao 			    &rw_trn_result.wr_fsp[fsp].cs[0],
2082c71eeac4SWesley Yao 			    rw_trn_result.byte_en);
2083c71eeac4SWesley Yao #endif
2084f520bb22SYouMin Chen 	if (sdram_params->ch.cap_info.rank == 2) {
2085f520bb22SYouMin Chen 		writel(wrlvl_result[1][0] + clk_skew, PHY_REG(phy_base, 0x233));
2086f520bb22SYouMin Chen 		writel(wrlvl_result[1][1] + clk_skew, PHY_REG(phy_base, 0x237));
2087f520bb22SYouMin Chen 		writel(wrlvl_result[1][2] + clk_skew, PHY_REG(phy_base, 0x2b3));
2088f520bb22SYouMin Chen 		writel(wrlvl_result[1][3] + clk_skew, PHY_REG(phy_base, 0x2b7));
2089f520bb22SYouMin Chen 		ret |= data_training(dram, 1, sdram_params, fsp,
2090f520bb22SYouMin Chen 				     READ_GATE_TRAINING | READ_TRAINING |
2091f520bb22SYouMin Chen 				     WRITE_TRAINING);
2092c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL)
2093c71eeac4SWesley Yao 		save_rw_trn_min_max(phy_base, &rw_trn_result.rd_fsp[fsp].cs[1],
2094c71eeac4SWesley Yao 				    &rw_trn_result.wr_fsp[fsp].cs[1],
2095c71eeac4SWesley Yao 				    rw_trn_result.byte_en);
2096c71eeac4SWesley Yao #endif
2097f520bb22SYouMin Chen 	}
2098f520bb22SYouMin Chen 	if (ret)
2099f520bb22SYouMin Chen 		goto out;
2100f520bb22SYouMin Chen 
2101f520bb22SYouMin Chen 	record_dq_prebit(dram);
2102f520bb22SYouMin Chen 
2103f520bb22SYouMin Chen 	min_val = get_min_value(dram, SKEW_RX_SIGNAL,
2104f520bb22SYouMin Chen 				sdram_params->ch.cap_info.rank) * -1;
2105f520bb22SYouMin Chen 	modify_dq_deskew(dram, SKEW_RX_SIGNAL, DESKEW_MDF_DIFF_VAL,
2106f520bb22SYouMin Chen 			 min_val, min_val, sdram_params->ch.cap_info.rank);
2107c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL)
2108c71eeac4SWesley Yao 	save_rw_trn_deskew(phy_base, &rw_trn_result.rd_fsp[fsp],
2109c71eeac4SWesley Yao 			   rw_trn_result.cs_num, (u8)(min_val * (-1)),
2110c71eeac4SWesley Yao 			   SKEW_RX_SIGNAL);
2111c71eeac4SWesley Yao #endif
2112f520bb22SYouMin Chen 
2113f520bb22SYouMin Chen 	min_val = MIN(get_min_value(dram, SKEW_TX_SIGNAL,
2114f520bb22SYouMin Chen 				    sdram_params->ch.cap_info.rank),
2115f520bb22SYouMin Chen 		      get_min_value(dram, SKEW_CA_SIGNAL,
2116f520bb22SYouMin Chen 				    sdram_params->ch.cap_info.rank)) * -1;
2117f520bb22SYouMin Chen 
2118f520bb22SYouMin Chen 	/* clk = 0, rx all skew -7, tx - min_value */
2119f520bb22SYouMin Chen 	modify_ca_deskew(dram, DESKEW_MDF_DIFF_VAL, min_val, min_val, 3,
2120f520bb22SYouMin Chen 			 dramtype);
2121f520bb22SYouMin Chen 
2122f520bb22SYouMin Chen 	modify_dq_deskew(dram, SKEW_TX_SIGNAL, DESKEW_MDF_DIFF_VAL,
2123f520bb22SYouMin Chen 			 min_val, min_val, sdram_params->ch.cap_info.rank);
2124c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL)
2125c71eeac4SWesley Yao 	save_rw_trn_deskew(phy_base, &rw_trn_result.wr_fsp[fsp],
2126c71eeac4SWesley Yao 			   rw_trn_result.cs_num, (u8)(min_val * (-1)),
2127c71eeac4SWesley Yao 			   SKEW_TX_SIGNAL);
2128c71eeac4SWesley Yao #endif
2129f520bb22SYouMin Chen 
2130f520bb22SYouMin Chen 	ret = data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING);
2131f520bb22SYouMin Chen 	if (sdram_params->ch.cap_info.rank == 2)
2132f520bb22SYouMin Chen 		ret |= data_training(dram, 1, sdram_params, 0,
2133f520bb22SYouMin Chen 				     READ_GATE_TRAINING);
2134f520bb22SYouMin Chen out:
2135f520bb22SYouMin Chen 	return ret;
2136f520bb22SYouMin Chen }
2137f520bb22SYouMin Chen 
2138f520bb22SYouMin Chen static void set_ddrconfig(struct dram_info *dram, u32 ddrconfig)
2139f520bb22SYouMin Chen {
2140f520bb22SYouMin Chen 	writel(ddrconfig, &dram->msch->deviceconf);
2141f520bb22SYouMin Chen 	clrsetbits_le32(&dram->grf->noc_con0, 0x3 << 0, 0 << 0);
2142f520bb22SYouMin Chen }
2143f520bb22SYouMin Chen 
2144f520bb22SYouMin Chen static void update_noc_timing(struct dram_info *dram,
2145f520bb22SYouMin Chen 			      struct rv1126_sdram_params *sdram_params)
2146f520bb22SYouMin Chen {
214738b16f08SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
214838b16f08SYouMin Chen 	u32 bw, bl;
214938b16f08SYouMin Chen 
215038b16f08SYouMin Chen 	bw = 8 << sdram_params->ch.cap_info.bw;
215138b16f08SYouMin Chen 	bl = ((readl(pctl_base + DDR_PCTL2_MSTR) >> 16) & 0xf) * 2;
215238b16f08SYouMin Chen 
215338b16f08SYouMin Chen 	/* update the noc timing related to data bus width */
21549d5c314bSWesley Yao 	if ((bw / 8 * bl) <= 16)
215538b16f08SYouMin Chen 		sdram_params->ch.noc_timings.ddrmode.b.burstsize = 0;
215638b16f08SYouMin Chen 	else if ((bw / 8 * bl) == 32)
215738b16f08SYouMin Chen 		sdram_params->ch.noc_timings.ddrmode.b.burstsize = 1;
215838b16f08SYouMin Chen 	else if ((bw / 8 * bl) == 64)
215938b16f08SYouMin Chen 		sdram_params->ch.noc_timings.ddrmode.b.burstsize = 2;
216038b16f08SYouMin Chen 	else
216138b16f08SYouMin Chen 		sdram_params->ch.noc_timings.ddrmode.b.burstsize = 3;
216238b16f08SYouMin Chen 
216338b16f08SYouMin Chen 	sdram_params->ch.noc_timings.ddrtimingc0.b.burstpenalty =
2164da1862e9SYouMin Chen 		(bl * bw / 8) > 16 ? (bl / 4) : (16 / (bl * bw / 8)) * bl / 4;
216538b16f08SYouMin Chen 
216638b16f08SYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4) {
216738b16f08SYouMin Chen 		sdram_params->ch.noc_timings.ddrmode.b.mwrsize =
216838b16f08SYouMin Chen 			(bw == 16) ? 0x1 : 0x2;
216938b16f08SYouMin Chen 		sdram_params->ch.noc_timings.ddrtimingc0.b.wrtomwr =
217038b16f08SYouMin Chen 			3 * sdram_params->ch.noc_timings.ddrtimingc0.b.burstpenalty;
217138b16f08SYouMin Chen 	}
217238b16f08SYouMin Chen 
2173f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.ddrtiminga0.d32,
2174f520bb22SYouMin Chen 	       &dram->msch->ddrtiminga0);
2175f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.ddrtimingb0.d32,
2176f520bb22SYouMin Chen 	       &dram->msch->ddrtimingb0);
2177f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.ddrtimingc0.d32,
2178f520bb22SYouMin Chen 	       &dram->msch->ddrtimingc0);
2179f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.devtodev0.d32,
2180f520bb22SYouMin Chen 	       &dram->msch->devtodev0);
2181f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.ddrmode.d32, &dram->msch->ddrmode);
2182f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.ddr4timing.d32,
2183f520bb22SYouMin Chen 	       &dram->msch->ddr4timing);
2184f520bb22SYouMin Chen }
2185f520bb22SYouMin Chen 
2186f520bb22SYouMin Chen static void dram_all_config(struct dram_info *dram,
2187f520bb22SYouMin Chen 			    struct rv1126_sdram_params *sdram_params)
2188f520bb22SYouMin Chen {
2189f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2190f520bb22SYouMin Chen 	u32 dram_type = sdram_params->base.dramtype;
2191f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2192f520bb22SYouMin Chen 	u32 sys_reg2 = 0;
2193f520bb22SYouMin Chen 	u32 sys_reg3 = 0;
2194f520bb22SYouMin Chen 	u64 cs_cap[2];
2195f520bb22SYouMin Chen 	u32 cs_pst;
2196f520bb22SYouMin Chen 
2197f520bb22SYouMin Chen 	set_ddrconfig(dram, cap_info->ddrconfig);
2198f520bb22SYouMin Chen 	sdram_org_config(cap_info, &sdram_params->base, &sys_reg2,
2199f520bb22SYouMin Chen 			 &sys_reg3, 0);
2200f520bb22SYouMin Chen 	writel(sys_reg2, &dram->pmugrf->os_reg[2]);
2201f520bb22SYouMin Chen 	writel(sys_reg3, &dram->pmugrf->os_reg[3]);
2202f520bb22SYouMin Chen 
2203f520bb22SYouMin Chen 	cs_cap[0] = sdram_get_cs_cap(cap_info, 0, dram_type);
2204f520bb22SYouMin Chen 	cs_cap[1] = sdram_get_cs_cap(cap_info, 1, dram_type);
2205f520bb22SYouMin Chen 
2206f520bb22SYouMin Chen 	if (cap_info->rank == 2) {
2207f520bb22SYouMin Chen 		cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) +
2208f520bb22SYouMin Chen 			6 + 2;
2209f520bb22SYouMin Chen 		if (cs_pst > 28)
2210bf922fc8SWesley Yao 			cs_cap[0] = 1llu << cs_pst;
2211f520bb22SYouMin Chen 	}
2212f520bb22SYouMin Chen 
2213f520bb22SYouMin Chen 	writel(((((cs_cap[1] >> 20) / 64) & 0xff) << 8) |
2214f520bb22SYouMin Chen 			(((cs_cap[0] >> 20) / 64) & 0xff),
2215f520bb22SYouMin Chen 			&dram->msch->devicesize);
2216f520bb22SYouMin Chen 	update_noc_timing(dram, sdram_params);
2217f520bb22SYouMin Chen }
2218f520bb22SYouMin Chen 
2219f520bb22SYouMin Chen static void enable_low_power(struct dram_info *dram,
2220f520bb22SYouMin Chen 			     struct rv1126_sdram_params *sdram_params)
2221f520bb22SYouMin Chen {
2222f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2223f520bb22SYouMin Chen 	u32 grf_lp_con;
2224f520bb22SYouMin Chen 
2225f520bb22SYouMin Chen 	writel(0x1f1f0617, &dram->ddrgrf->ddr_grf_con[1]);
2226f520bb22SYouMin Chen 
2227f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4)
2228f520bb22SYouMin Chen 		grf_lp_con = (0x7 << 16) | (1 << 1);
2229f520bb22SYouMin Chen 	else if (sdram_params->base.dramtype == DDR3)
2230f520bb22SYouMin Chen 		grf_lp_con = (0x7 << 16) | (1 << 0);
2231f520bb22SYouMin Chen 	else
2232f520bb22SYouMin Chen 		grf_lp_con = (0x7 << 16) | (1 << 2);
2233f520bb22SYouMin Chen 
2234f520bb22SYouMin Chen 	/* en lpckdis_en */
2235f520bb22SYouMin Chen 	grf_lp_con = grf_lp_con | (0x1 << (9 + 16)) | (0x1 << 9);
2236f520bb22SYouMin Chen 	writel(grf_lp_con, &dram->ddrgrf->ddr_grf_lp_con);
2237f520bb22SYouMin Chen 
2238f520bb22SYouMin Chen 	/* enable sr, pd */
2239f520bb22SYouMin Chen 	if (dram->pd_idle == 0)
2240f520bb22SYouMin Chen 		clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
2241f520bb22SYouMin Chen 	else
2242f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
2243f520bb22SYouMin Chen 	if (dram->sr_idle == 0)
2244f520bb22SYouMin Chen 		clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
2245f520bb22SYouMin Chen 	else
2246f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
2247f520bb22SYouMin Chen 	setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 3));
2248f520bb22SYouMin Chen }
2249f520bb22SYouMin Chen 
2250f520bb22SYouMin Chen static void ddr_set_atags(struct dram_info *dram,
2251f520bb22SYouMin Chen 			  struct rv1126_sdram_params *sdram_params)
2252f520bb22SYouMin Chen {
2253f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2254f520bb22SYouMin Chen 	u32 dram_type = sdram_params->base.dramtype;
2255f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2256f520bb22SYouMin Chen 	struct tag_serial t_serial;
2257f520bb22SYouMin Chen 	struct tag_ddr_mem t_ddrmem;
2258f520bb22SYouMin Chen 	struct tag_soc_info t_socinfo;
2259f520bb22SYouMin Chen 	u64 cs_cap[2];
2260f520bb22SYouMin Chen 	u32 cs_pst = 0;
2261f520bb22SYouMin Chen 
2262f520bb22SYouMin Chen 	cs_cap[0] = sdram_get_cs_cap(cap_info, 0, dram_type);
2263f520bb22SYouMin Chen 	cs_cap[1] = sdram_get_cs_cap(cap_info, 1, dram_type);
2264f520bb22SYouMin Chen 
2265f520bb22SYouMin Chen 	memset(&t_serial, 0, sizeof(struct tag_serial));
2266f520bb22SYouMin Chen 
2267f520bb22SYouMin Chen 	t_serial.version = 0;
2268f520bb22SYouMin Chen 	t_serial.enable = 1;
2269f520bb22SYouMin Chen 	t_serial.addr = CONFIG_DEBUG_UART_BASE;
2270f520bb22SYouMin Chen 	t_serial.baudrate = CONFIG_BAUDRATE;
2271f520bb22SYouMin Chen 	t_serial.m_mode = SERIAL_M_MODE_M0;
2272f520bb22SYouMin Chen 	t_serial.id = 2;
2273f520bb22SYouMin Chen 
2274f520bb22SYouMin Chen 	atags_destroy();
2275f520bb22SYouMin Chen 	atags_set_tag(ATAG_SERIAL,  &t_serial);
2276f520bb22SYouMin Chen 
2277f520bb22SYouMin Chen 	memset(&t_ddrmem, 0, sizeof(struct tag_ddr_mem));
2278f520bb22SYouMin Chen 	if (cap_info->row_3_4) {
2279f520bb22SYouMin Chen 		cs_cap[0] =  cs_cap[0] * 3 / 4;
2280f520bb22SYouMin Chen 		cs_cap[1] =  cs_cap[1] * 3 / 4;
2281f520bb22SYouMin Chen 	}
2282f520bb22SYouMin Chen 	t_ddrmem.version = 0;
2283f520bb22SYouMin Chen 	t_ddrmem.bank[0] = CONFIG_SYS_SDRAM_BASE;
2284f520bb22SYouMin Chen 	if (cs_cap[1]) {
2285f520bb22SYouMin Chen 		cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) +
2286f520bb22SYouMin Chen 			6 + 2;
2287f520bb22SYouMin Chen 	}
2288f520bb22SYouMin Chen 
2289f520bb22SYouMin Chen 	if (cs_cap[1] && cs_pst > 27) {
2290f520bb22SYouMin Chen 		t_ddrmem.count = 2;
2291f520bb22SYouMin Chen 		t_ddrmem.bank[1] = 1 << cs_pst;
2292f520bb22SYouMin Chen 		t_ddrmem.bank[2] = cs_cap[0];
2293f520bb22SYouMin Chen 		t_ddrmem.bank[3] = cs_cap[1];
2294f520bb22SYouMin Chen 	} else {
2295f520bb22SYouMin Chen 		t_ddrmem.count = 1;
2296f520bb22SYouMin Chen 		t_ddrmem.bank[1] = (u64)cs_cap[0] + (u64)cs_cap[1];
2297f520bb22SYouMin Chen 	}
2298f520bb22SYouMin Chen 
2299f520bb22SYouMin Chen 	atags_set_tag(ATAG_DDR_MEM,  &t_ddrmem);
2300f520bb22SYouMin Chen 
2301f520bb22SYouMin Chen 	memset(&t_socinfo, 0, sizeof(struct tag_soc_info));
2302f520bb22SYouMin Chen 	t_socinfo.version = 0;
2303f520bb22SYouMin Chen 	t_socinfo.name = 0x1126;
2304f520bb22SYouMin Chen }
2305f520bb22SYouMin Chen 
2306f520bb22SYouMin Chen static void print_ddr_info(struct rv1126_sdram_params *sdram_params)
2307f520bb22SYouMin Chen {
2308f520bb22SYouMin Chen 	u32 split;
2309f520bb22SYouMin Chen 
2310f520bb22SYouMin Chen 	if ((readl(DDR_GRF_BASE_ADDR + DDR_GRF_SPLIT_CON) &
2311f520bb22SYouMin Chen 	     (1 << SPLIT_BYPASS_OFFSET)) != 0)
2312f520bb22SYouMin Chen 		split = 0;
2313f520bb22SYouMin Chen 	else
2314f520bb22SYouMin Chen 		split = readl(DDR_GRF_BASE_ADDR + DDR_GRF_SPLIT_CON) &
2315f520bb22SYouMin Chen 			SPLIT_SIZE_MASK;
2316f520bb22SYouMin Chen 
2317f520bb22SYouMin Chen 	sdram_print_ddr_info(&sdram_params->ch.cap_info,
2318f520bb22SYouMin Chen 			     &sdram_params->base, split);
2319f520bb22SYouMin Chen }
2320f520bb22SYouMin Chen 
2321f520bb22SYouMin Chen static int sdram_init_(struct dram_info *dram,
2322f520bb22SYouMin Chen 		       struct rv1126_sdram_params *sdram_params, u32 post_init)
2323f520bb22SYouMin Chen {
2324f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2325f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
2326f520bb22SYouMin Chen 	u32 ddr4_vref;
2327f520bb22SYouMin Chen 	u32 mr_tmp;
2328f520bb22SYouMin Chen 
2329f520bb22SYouMin Chen 	rkclk_configure_ddr(dram, sdram_params);
2330f520bb22SYouMin Chen 
2331f520bb22SYouMin Chen 	rkclk_ddr_reset(dram, 1, 1, 1, 1);
2332f520bb22SYouMin Chen 	udelay(10);
2333f520bb22SYouMin Chen 
2334f520bb22SYouMin Chen 	rkclk_ddr_reset(dram, 1, 1, 1, 0);
2335f520bb22SYouMin Chen 	phy_cfg(dram, sdram_params);
2336f520bb22SYouMin Chen 
2337f520bb22SYouMin Chen 	rkclk_ddr_reset(dram, 1, 1, 0, 0);
2338f520bb22SYouMin Chen 	phy_pll_set(dram, sdram_params->base.ddr_freq * MHZ, 1);
2339f520bb22SYouMin Chen 
2340f520bb22SYouMin Chen 	rkclk_ddr_reset(dram, 1, 0, 0, 0);
2341f520bb22SYouMin Chen 	pctl_cfg(dram->pctl, &sdram_params->pctl_regs,
2342f520bb22SYouMin Chen 		 dram->sr_idle, dram->pd_idle);
2343f520bb22SYouMin Chen 
234422b43223SZhihuan He 	if (sdram_params->ch.cap_info.bw == 2) {
2345e8885e24SCanYang He 		/* 32bit interface use pageclose */
2346e8885e24SCanYang He 		setbits_le32(pctl_base + DDR_PCTL2_SCHED, 1 << 2);
234722b43223SZhihuan He 		/* pageclose = 1, pageclose_timer = 0 will err in lp4 328MHz */
234822b43223SZhihuan He 		clrsetbits_le32(pctl_base + DDR_PCTL2_SCHED1, 0xff, 0x1 << 0);
234922b43223SZhihuan He 	} else {
2350e8885e24SCanYang He 		clrbits_le32(pctl_base + DDR_PCTL2_SCHED, 1 << 2);
235122b43223SZhihuan He 	}
2352e8885e24SCanYang He 
2353ee5f0829STang Yun ping #ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT
2354ee5f0829STang Yun ping 	u32 tmp, trefi;
2355ee5f0829STang Yun ping 
2356ee5f0829STang Yun ping 	tmp = readl(pctl_base + DDR_PCTL2_RFSHTMG);
2357ee5f0829STang Yun ping 	trefi = (tmp >> 16) & 0xfff;
2358ee5f0829STang Yun ping 	writel((tmp & 0xf000ffff) | (trefi / 2) << 16,
2359ee5f0829STang Yun ping 	       pctl_base + DDR_PCTL2_RFSHTMG);
2360ee5f0829STang Yun ping #endif
2361ee5f0829STang Yun ping 
2362f520bb22SYouMin Chen 	/* set frequency_mode */
2363f520bb22SYouMin Chen 	setbits_le32(pctl_base + DDR_PCTL2_MSTR, 0x1 << 29);
2364f520bb22SYouMin Chen 	/* set target_frequency to Frequency 0 */
2365f520bb22SYouMin Chen 	clrsetbits_le32(pctl_base + DDR_PCTL2_MSTR2, 0x3, 0);
2366f520bb22SYouMin Chen 
2367f520bb22SYouMin Chen 	set_ds_odt(dram, sdram_params, 0);
2368f520bb22SYouMin Chen 	sdram_params->ch.cap_info.ddrconfig = calculate_ddrconfig(sdram_params);
2369f520bb22SYouMin Chen 	set_ctl_address_map(dram, sdram_params);
2370f520bb22SYouMin Chen 
2371f520bb22SYouMin Chen 	setbits_le32(pctl_base + DDR_PCTL2_DFIMISC, (1 << 5) | (1 << 4));
2372f520bb22SYouMin Chen 
2373f520bb22SYouMin Chen 	rkclk_ddr_reset(dram, 0, 0, 0, 0);
2374f520bb22SYouMin Chen 
2375f520bb22SYouMin Chen 	while ((readl(pctl_base + DDR_PCTL2_STAT) & 0x7) == 0)
2376f520bb22SYouMin Chen 		continue;
2377f520bb22SYouMin Chen 
2378f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == LPDDR3) {
2379f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 11, lp3_odt_value, LPDDR3);
2380f520bb22SYouMin Chen 	} else if (sdram_params->base.dramtype == LPDDR4) {
2381f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + DDR_PCTL2_INIT6);
2382f520bb22SYouMin Chen 		/* MR11 */
2383f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 11,
2384f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
2385f520bb22SYouMin Chen 			      LPDDR4);
2386f520bb22SYouMin Chen 		/* MR12 */
2387f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 12,
2388f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR12_SHIFT & PCTL2_MR_MASK,
2389f520bb22SYouMin Chen 			      LPDDR4);
2390f520bb22SYouMin Chen 
2391f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + DDR_PCTL2_INIT7);
2392f520bb22SYouMin Chen 		/* MR22 */
2393f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 22,
2394f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
2395f520bb22SYouMin Chen 			      LPDDR4);
2396f520bb22SYouMin Chen 		/* MR14 */
2397f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 14,
2398f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
2399f520bb22SYouMin Chen 			      LPDDR4);
2400f520bb22SYouMin Chen 	}
2401f520bb22SYouMin Chen 
2402f520bb22SYouMin Chen 	if (data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING) != 0) {
2403f520bb22SYouMin Chen 		if (post_init != 0)
2404f520bb22SYouMin Chen 			printascii("DTT cs0 error\n");
2405f520bb22SYouMin Chen 		return -1;
2406f520bb22SYouMin Chen 	}
2407f520bb22SYouMin Chen 
2408f520bb22SYouMin Chen 	if (post_init != 0 && sdram_params->ch.cap_info.rank == 2) {
2409f520bb22SYouMin Chen 		if (data_training(dram, 1, sdram_params, 0,
2410f520bb22SYouMin Chen 				  READ_GATE_TRAINING) != 0) {
2411f520bb22SYouMin Chen 			printascii("DTT cs1 error\n");
2412f520bb22SYouMin Chen 			return -1;
2413f520bb22SYouMin Chen 		}
2414f520bb22SYouMin Chen 	}
2415f520bb22SYouMin Chen 
2416f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4) {
2417f520bb22SYouMin Chen 		ddr4_vref = readl(PHY_REG(phy_base, 0x105)) * 39;
2418f520bb22SYouMin Chen 		pctl_write_vrefdq(dram->pctl, 0x3, ddr4_vref,
2419f520bb22SYouMin Chen 				  sdram_params->base.dramtype);
2420f520bb22SYouMin Chen 	}
2421f520bb22SYouMin Chen 
2422f520bb22SYouMin Chen 	dram_all_config(dram, sdram_params);
2423f520bb22SYouMin Chen 	enable_low_power(dram, sdram_params);
2424f520bb22SYouMin Chen 
2425f520bb22SYouMin Chen 	return 0;
2426f520bb22SYouMin Chen }
2427f520bb22SYouMin Chen 
2428f520bb22SYouMin Chen static u64 dram_detect_cap(struct dram_info *dram,
2429f520bb22SYouMin Chen 			   struct rv1126_sdram_params *sdram_params,
2430f520bb22SYouMin Chen 			   unsigned char channel)
2431f520bb22SYouMin Chen {
2432f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2433f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2434f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
2435f520bb22SYouMin Chen 	u32 mr8;
2436f520bb22SYouMin Chen 
2437f520bb22SYouMin Chen 	u32 bktmp;
2438f520bb22SYouMin Chen 	u32 coltmp;
2439f520bb22SYouMin Chen 	u32 rowtmp;
2440f520bb22SYouMin Chen 	u32 cs;
2441f520bb22SYouMin Chen 	u32 dram_type = sdram_params->base.dramtype;
2442f520bb22SYouMin Chen 	u32 pwrctl;
24439d5c314bSWesley Yao 	u32 i, dq_map;
24449d5c314bSWesley Yao 	u32 byte1 = 0, byte0 = 0;
2445f520bb22SYouMin Chen 
24469d5c314bSWesley Yao 	cap_info->bw = dram_type == DDR3 ? 0 : 1;
2447f520bb22SYouMin Chen 	if (dram_type != LPDDR4) {
2448f520bb22SYouMin Chen 		if (dram_type != DDR4) {
2449f520bb22SYouMin Chen 			coltmp = 12;
2450f520bb22SYouMin Chen 			bktmp = 3;
2451f520bb22SYouMin Chen 			if (dram_type == LPDDR2)
2452f520bb22SYouMin Chen 				rowtmp = 15;
2453f520bb22SYouMin Chen 			else
2454f520bb22SYouMin Chen 				rowtmp = 16;
2455f520bb22SYouMin Chen 
2456f520bb22SYouMin Chen 			if (sdram_detect_col(cap_info, coltmp) != 0)
2457f520bb22SYouMin Chen 				goto cap_err;
2458f520bb22SYouMin Chen 
2459f520bb22SYouMin Chen 			sdram_detect_bank(cap_info, coltmp, bktmp);
2460f520bb22SYouMin Chen 			sdram_detect_dbw(cap_info, dram_type);
2461f520bb22SYouMin Chen 		} else {
2462f520bb22SYouMin Chen 			coltmp = 10;
2463f520bb22SYouMin Chen 			bktmp = 4;
2464f520bb22SYouMin Chen 			rowtmp = 17;
2465f520bb22SYouMin Chen 
2466f520bb22SYouMin Chen 			cap_info->col = 10;
2467f520bb22SYouMin Chen 			cap_info->bk = 2;
2468f520bb22SYouMin Chen 			sdram_detect_bg(cap_info, coltmp);
2469f520bb22SYouMin Chen 		}
2470f520bb22SYouMin Chen 
2471f520bb22SYouMin Chen 		if (sdram_detect_row(cap_info, coltmp, bktmp, rowtmp) != 0)
2472f520bb22SYouMin Chen 			goto cap_err;
2473f520bb22SYouMin Chen 
2474f520bb22SYouMin Chen 		sdram_detect_row_3_4(cap_info, coltmp, bktmp);
2475f520bb22SYouMin Chen 	} else {
2476f520bb22SYouMin Chen 		mr8 = (read_mr(dram, 1, 8, dram_type) >> 2) & 0xf;
2477f520bb22SYouMin Chen 		cap_info->col = 10;
2478f520bb22SYouMin Chen 		cap_info->bk = 3;
2479f520bb22SYouMin Chen 		cap_info->cs0_row = 14 + (mr8 + 1) / 2;
2480f520bb22SYouMin Chen 		if (mr8 % 2)
2481f520bb22SYouMin Chen 			cap_info->row_3_4 = 1;
2482f520bb22SYouMin Chen 		else
2483f520bb22SYouMin Chen 			cap_info->row_3_4 = 0;
2484f520bb22SYouMin Chen 		cap_info->dbw = 1;
2485f520bb22SYouMin Chen 		cap_info->bw = 2;
2486f520bb22SYouMin Chen 	}
2487f520bb22SYouMin Chen 
2488f520bb22SYouMin Chen 	pwrctl = readl(pctl_base + DDR_PCTL2_PWRCTL);
2489f520bb22SYouMin Chen 	writel(0, pctl_base + DDR_PCTL2_PWRCTL);
2490f520bb22SYouMin Chen 
2491f520bb22SYouMin Chen 	if (data_training(dram, 1, sdram_params, 0, READ_GATE_TRAINING) == 0)
2492f520bb22SYouMin Chen 		cs = 1;
2493f520bb22SYouMin Chen 	else
2494f520bb22SYouMin Chen 		cs = 0;
2495f520bb22SYouMin Chen 	cap_info->rank = cs + 1;
2496f520bb22SYouMin Chen 
2497f520bb22SYouMin Chen 	if (dram_type != LPDDR4) {
2498f520bb22SYouMin Chen 		setbits_le32(PHY_REG(phy_base, 0xf), 0xf);
2499f520bb22SYouMin Chen 
2500f520bb22SYouMin Chen 		if (data_training(dram, 0, sdram_params, 0,
25019d5c314bSWesley Yao 				  READ_GATE_TRAINING) == 0) {
2502f520bb22SYouMin Chen 			cap_info->bw = 2;
25039d5c314bSWesley Yao 		} else {
25049d5c314bSWesley Yao 			dq_map = readl(PHY_REG(phy_base, 0x4f));
25059d5c314bSWesley Yao 			for (i = 0; i < 4; i++) {
25069d5c314bSWesley Yao 				if (((dq_map >> (i * 2)) & 0x3) == 0)
25079d5c314bSWesley Yao 					byte0 = i;
25089d5c314bSWesley Yao 				if (((dq_map >> (i * 2)) & 0x3) == 1)
25099d5c314bSWesley Yao 					byte1 = i;
25109d5c314bSWesley Yao 			}
25119d5c314bSWesley Yao 			clrsetbits_le32(PHY_REG(phy_base, 0xf), PHY_DQ_WIDTH_MASK,
25129d5c314bSWesley Yao 					BIT(byte0) | BIT(byte1));
25139d5c314bSWesley Yao 			if (data_training(dram, 0, sdram_params, 0,
25149d5c314bSWesley Yao 					  READ_GATE_TRAINING) == 0)
2515f520bb22SYouMin Chen 				cap_info->bw = 1;
25169d5c314bSWesley Yao 			else
25179d5c314bSWesley Yao 				cap_info->bw = 0;
25189d5c314bSWesley Yao 		}
25193993b0c7SWesley Yao 		if (cap_info->bw > 0)
25203993b0c7SWesley Yao 			cap_info->dbw = 1;
2521f520bb22SYouMin Chen 	}
2522f520bb22SYouMin Chen 
2523f520bb22SYouMin Chen 	writel(pwrctl, pctl_base + DDR_PCTL2_PWRCTL);
2524f520bb22SYouMin Chen 
2525f520bb22SYouMin Chen 	cap_info->cs0_high16bit_row = cap_info->cs0_row;
2526f520bb22SYouMin Chen 	if (cs) {
2527f520bb22SYouMin Chen 		cap_info->cs1_row = cap_info->cs0_row;
2528f520bb22SYouMin Chen 		cap_info->cs1_high16bit_row = cap_info->cs0_row;
2529f520bb22SYouMin Chen 	} else {
2530f520bb22SYouMin Chen 		cap_info->cs1_row = 0;
2531f520bb22SYouMin Chen 		cap_info->cs1_high16bit_row = 0;
2532f520bb22SYouMin Chen 	}
2533f520bb22SYouMin Chen 
2534f520bb22SYouMin Chen 	return 0;
2535f520bb22SYouMin Chen cap_err:
2536f520bb22SYouMin Chen 	return -1;
2537f520bb22SYouMin Chen }
2538f520bb22SYouMin Chen 
2539f520bb22SYouMin Chen static int dram_detect_cs1_row(struct dram_info *dram,
2540f520bb22SYouMin Chen 			       struct rv1126_sdram_params *sdram_params,
2541f520bb22SYouMin Chen 			       unsigned char channel)
2542f520bb22SYouMin Chen {
2543f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2544f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2545f520bb22SYouMin Chen 	u32 ret = 0;
2546f520bb22SYouMin Chen 	void __iomem *test_addr;
2547f520bb22SYouMin Chen 	u32 row, bktmp, coltmp, bw;
2548f520bb22SYouMin Chen 	u64 cs0_cap;
2549f520bb22SYouMin Chen 	u32 byte_mask;
2550f520bb22SYouMin Chen 	u32 cs_pst;
2551f520bb22SYouMin Chen 	u32 cs_add = 0;
2552f520bb22SYouMin Chen 	u32 max_row;
2553f520bb22SYouMin Chen 
2554f520bb22SYouMin Chen 	if (cap_info->rank == 2) {
2555f520bb22SYouMin Chen 		cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) +
2556f520bb22SYouMin Chen 			6 + 2;
2557f520bb22SYouMin Chen 		if (cs_pst < 28)
2558f520bb22SYouMin Chen 			cs_add = 1;
2559f520bb22SYouMin Chen 
2560f520bb22SYouMin Chen 		cs0_cap = 1 << cs_pst;
2561f520bb22SYouMin Chen 
2562f520bb22SYouMin Chen 		if (sdram_params->base.dramtype == DDR4) {
2563f520bb22SYouMin Chen 			if (cap_info->dbw == 0)
2564f520bb22SYouMin Chen 				bktmp = cap_info->bk + 2;
2565f520bb22SYouMin Chen 			else
2566f520bb22SYouMin Chen 				bktmp = cap_info->bk + 1;
2567f520bb22SYouMin Chen 		} else {
2568f520bb22SYouMin Chen 			bktmp = cap_info->bk;
2569f520bb22SYouMin Chen 		}
2570f520bb22SYouMin Chen 		bw = cap_info->bw;
2571f520bb22SYouMin Chen 		coltmp = cap_info->col;
2572f520bb22SYouMin Chen 
2573f520bb22SYouMin Chen 		if (bw == 2)
2574f520bb22SYouMin Chen 			byte_mask = 0xFFFF;
2575f520bb22SYouMin Chen 		else
2576f520bb22SYouMin Chen 			byte_mask = 0xFF;
2577f520bb22SYouMin Chen 
2578f520bb22SYouMin Chen 		max_row = (cs_pst == 31) ? 30 : 31;
2579f520bb22SYouMin Chen 
2580f520bb22SYouMin Chen 		max_row = max_row - bktmp - coltmp - bw - cs_add + 1;
2581f520bb22SYouMin Chen 
2582f520bb22SYouMin Chen 		row = (cap_info->cs0_row > max_row) ? max_row :
2583f520bb22SYouMin Chen 			cap_info->cs0_row;
2584f520bb22SYouMin Chen 
2585f520bb22SYouMin Chen 		for (; row > 12; row--) {
2586f520bb22SYouMin Chen 			test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
2587f520bb22SYouMin Chen 				    (u32)cs0_cap +
2588f520bb22SYouMin Chen 				    (1ul << (row + bktmp + coltmp +
2589f520bb22SYouMin Chen 					     cs_add + bw - 1ul)));
2590f520bb22SYouMin Chen 
2591f520bb22SYouMin Chen 			writel(0, CONFIG_SYS_SDRAM_BASE + (u32)cs0_cap);
2592f520bb22SYouMin Chen 			writel(PATTERN, test_addr);
2593f520bb22SYouMin Chen 
2594f520bb22SYouMin Chen 			if (((readl(test_addr) & byte_mask) ==
2595f520bb22SYouMin Chen 			     (PATTERN & byte_mask)) &&
2596f520bb22SYouMin Chen 			    ((readl(CONFIG_SYS_SDRAM_BASE + (u32)cs0_cap) &
2597f520bb22SYouMin Chen 			      byte_mask) == 0)) {
2598f520bb22SYouMin Chen 				ret = row;
2599f520bb22SYouMin Chen 				break;
2600f520bb22SYouMin Chen 			}
2601f520bb22SYouMin Chen 		}
2602f520bb22SYouMin Chen 	}
2603f520bb22SYouMin Chen 
2604f520bb22SYouMin Chen 	return ret;
2605f520bb22SYouMin Chen }
2606f520bb22SYouMin Chen 
2607f520bb22SYouMin Chen /* return: 0 = success, other = fail */
2608f520bb22SYouMin Chen static int sdram_init_detect(struct dram_info *dram,
2609f520bb22SYouMin Chen 			     struct rv1126_sdram_params *sdram_params)
2610f520bb22SYouMin Chen {
2611f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2612f520bb22SYouMin Chen 	u32 ret;
2613f520bb22SYouMin Chen 	u32 sys_reg = 0;
2614f520bb22SYouMin Chen 	u32 sys_reg3 = 0;
26151040f70aSTang Yun ping 	struct sdram_head_info_index_v2 *index =
26161040f70aSTang Yun ping 		(struct sdram_head_info_index_v2 *)common_info;
26171040f70aSTang Yun ping 	struct dq_map_info *map_info;
2618f520bb22SYouMin Chen 
26191040f70aSTang Yun ping 	map_info = (struct dq_map_info *)((void *)common_info +
26201040f70aSTang Yun ping 		index->dq_map_index.offset * 4);
26211040f70aSTang Yun ping 
26221040f70aSTang Yun ping 	if (sdram_init_(dram, sdram_params, 0)) {
26231040f70aSTang Yun ping 		if (sdram_params->base.dramtype == DDR3) {
26241040f70aSTang Yun ping 			clrsetbits_le32(&map_info->byte_map[0], 0xff << 24,
26251040f70aSTang Yun ping 					((0x1 << 6) | (0x3 << 4) | (0x2 << 2) |
26261040f70aSTang Yun ping 					(0x0 << 0)) << 24);
26271040f70aSTang Yun ping 			if (sdram_init_(dram, sdram_params, 0))
2628f520bb22SYouMin Chen 				return -1;
26291040f70aSTang Yun ping 		} else {
26301040f70aSTang Yun ping 			return -1;
26311040f70aSTang Yun ping 		}
26321040f70aSTang Yun ping 	}
2633f520bb22SYouMin Chen 
2634f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR3) {
2635f520bb22SYouMin Chen 		writel(PATTERN, CONFIG_SYS_SDRAM_BASE);
2636f520bb22SYouMin Chen 		if (readl(CONFIG_SYS_SDRAM_BASE) != PATTERN)
2637f520bb22SYouMin Chen 			return -1;
2638f520bb22SYouMin Chen 	}
2639f520bb22SYouMin Chen 
2640f520bb22SYouMin Chen 	if (dram_detect_cap(dram, sdram_params, 0) != 0)
2641f520bb22SYouMin Chen 		return -1;
2642f520bb22SYouMin Chen 
2643f520bb22SYouMin Chen 	pctl_remodify_sdram_params(&sdram_params->pctl_regs, cap_info,
2644f520bb22SYouMin Chen 				   sdram_params->base.dramtype);
2645f520bb22SYouMin Chen 	ret = sdram_init_(dram, sdram_params, 1);
2646f520bb22SYouMin Chen 	if (ret != 0)
2647f520bb22SYouMin Chen 		goto out;
2648f520bb22SYouMin Chen 
2649f520bb22SYouMin Chen 	cap_info->cs1_row =
2650f520bb22SYouMin Chen 		dram_detect_cs1_row(dram, sdram_params, 0);
2651f520bb22SYouMin Chen 	if (cap_info->cs1_row) {
2652f520bb22SYouMin Chen 		sys_reg = readl(&dram->pmugrf->os_reg[2]);
2653f520bb22SYouMin Chen 		sys_reg3 = readl(&dram->pmugrf->os_reg[3]);
2654f520bb22SYouMin Chen 		SYS_REG_ENC_CS1_ROW(cap_info->cs1_row,
2655f520bb22SYouMin Chen 				    sys_reg, sys_reg3, 0);
2656f520bb22SYouMin Chen 		writel(sys_reg, &dram->pmugrf->os_reg[2]);
2657f520bb22SYouMin Chen 		writel(sys_reg3, &dram->pmugrf->os_reg[3]);
2658f520bb22SYouMin Chen 	}
2659f520bb22SYouMin Chen 
2660f520bb22SYouMin Chen 	sdram_detect_high_row(cap_info);
2661f520bb22SYouMin Chen 
2662f520bb22SYouMin Chen out:
2663f520bb22SYouMin Chen 	return ret;
2664f520bb22SYouMin Chen }
2665f520bb22SYouMin Chen 
2666f520bb22SYouMin Chen struct rv1126_sdram_params *get_default_sdram_config(u32 freq_mhz)
2667f520bb22SYouMin Chen {
2668f520bb22SYouMin Chen 	u32 i;
2669f520bb22SYouMin Chen 	u32 offset = 0;
2670f520bb22SYouMin Chen 	struct ddr2_3_4_lp2_3_info *ddr_info;
2671f520bb22SYouMin Chen 
2672f520bb22SYouMin Chen 	if (!freq_mhz) {
2673f520bb22SYouMin Chen 		ddr_info = get_ddr_drv_odt_info(sdram_configs[0].base.dramtype);
2674f520bb22SYouMin Chen 		if (ddr_info)
2675f520bb22SYouMin Chen 			freq_mhz =
2676f520bb22SYouMin Chen 				(ddr_info->ddr_freq0_1 >> DDR_FREQ_F0_SHIFT) &
2677f520bb22SYouMin Chen 				DDR_FREQ_MASK;
2678f520bb22SYouMin Chen 		else
2679f520bb22SYouMin Chen 			freq_mhz = 0;
2680f520bb22SYouMin Chen 	}
2681f520bb22SYouMin Chen 
2682f520bb22SYouMin Chen 	for (i = 0; i < ARRAY_SIZE(sdram_configs); i++) {
2683f520bb22SYouMin Chen 		if (sdram_configs[i].base.ddr_freq == 0 ||
2684f520bb22SYouMin Chen 		    freq_mhz < sdram_configs[i].base.ddr_freq)
2685f520bb22SYouMin Chen 			break;
2686f520bb22SYouMin Chen 	}
2687f520bb22SYouMin Chen 	offset = i == 0 ? 0 : i - 1;
2688f520bb22SYouMin Chen 
2689f520bb22SYouMin Chen 	return &sdram_configs[offset];
2690f520bb22SYouMin Chen }
2691f520bb22SYouMin Chen 
2692f520bb22SYouMin Chen static const u16 pctl_need_update_reg[] = {
2693f520bb22SYouMin Chen 	DDR_PCTL2_RFSHTMG,
2694f520bb22SYouMin Chen 	DDR_PCTL2_INIT3,
2695f520bb22SYouMin Chen 	DDR_PCTL2_INIT4,
2696f520bb22SYouMin Chen 	DDR_PCTL2_INIT6,
2697f520bb22SYouMin Chen 	DDR_PCTL2_INIT7,
2698f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG0,
2699f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG1,
2700f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG2,
2701f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG3,
2702f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG4,
2703f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG5,
2704f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG6,
2705f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG7,
2706f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG8,
2707f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG9,
2708f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG12,
2709f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG13,
2710f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG14,
2711f520bb22SYouMin Chen 	DDR_PCTL2_ZQCTL0,
2712f520bb22SYouMin Chen 	DDR_PCTL2_DFITMG0,
2713f520bb22SYouMin Chen 	DDR_PCTL2_ODTCFG
2714f520bb22SYouMin Chen };
2715f520bb22SYouMin Chen 
2716f520bb22SYouMin Chen static const u16 phy_need_update_reg[] = {
2717f520bb22SYouMin Chen 	0x14,
2718f520bb22SYouMin Chen 	0x18,
2719f520bb22SYouMin Chen 	0x1c
2720f520bb22SYouMin Chen };
2721f520bb22SYouMin Chen 
2722f520bb22SYouMin Chen static void pre_set_rate(struct dram_info *dram,
2723f520bb22SYouMin Chen 			 struct rv1126_sdram_params *sdram_params,
2724f520bb22SYouMin Chen 			 u32 dst_fsp, u32 dst_fsp_lp4)
2725f520bb22SYouMin Chen {
2726f520bb22SYouMin Chen 	u32 i, j, find;
2727f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2728f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
2729f520bb22SYouMin Chen 	u32 phy_offset;
2730f520bb22SYouMin Chen 	u32 mr_tmp;
2731f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
2732f520bb22SYouMin Chen 
2733f520bb22SYouMin Chen 	sw_set_req(dram);
2734f520bb22SYouMin Chen 	/* pctl timing update */
2735f520bb22SYouMin Chen 	for (i = 0, find = 0; i < ARRAY_SIZE(pctl_need_update_reg); i++) {
2736f520bb22SYouMin Chen 		for (j = find; sdram_params->pctl_regs.pctl[j][0] != 0xFFFFFFFF;
2737f520bb22SYouMin Chen 		     j++) {
2738f520bb22SYouMin Chen 			if (sdram_params->pctl_regs.pctl[j][0] ==
2739f520bb22SYouMin Chen 			    pctl_need_update_reg[i]) {
2740f520bb22SYouMin Chen 				writel(sdram_params->pctl_regs.pctl[j][1],
2741f520bb22SYouMin Chen 				       pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2742f520bb22SYouMin Chen 				       pctl_need_update_reg[i]);
2743f520bb22SYouMin Chen 				find = j;
2744f520bb22SYouMin Chen 				break;
2745f520bb22SYouMin Chen 			}
2746f520bb22SYouMin Chen 		}
2747f520bb22SYouMin Chen 	}
2748ee5f0829STang Yun ping 
2749ee5f0829STang Yun ping #ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT
2750ee5f0829STang Yun ping 	u32 tmp, trefi;
2751ee5f0829STang Yun ping 
2752ee5f0829STang Yun ping 	tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_RFSHTMG);
2753ee5f0829STang Yun ping 	trefi = (tmp >> 16) & 0xfff;
2754ee5f0829STang Yun ping 	writel((tmp & 0xf000ffff) | (trefi / 2) << 16,
2755ee5f0829STang Yun ping 	       pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_RFSHTMG);
2756ee5f0829STang Yun ping #endif
2757ee5f0829STang Yun ping 
2758f520bb22SYouMin Chen 	sw_set_ack(dram);
2759f520bb22SYouMin Chen 
2760f520bb22SYouMin Chen 	/* phy timing update */
2761f520bb22SYouMin Chen 	if (dst_fsp == 0)
2762f520bb22SYouMin Chen 		phy_offset = 0;
2763f520bb22SYouMin Chen 	else
2764f520bb22SYouMin Chen 		phy_offset = PHY_REG(0, 0x387 - 5 + (dst_fsp - 1) * 3);
2765f520bb22SYouMin Chen 	/* cl cwl al update */
2766f520bb22SYouMin Chen 	for (i = 0, find = 0; i < ARRAY_SIZE(phy_need_update_reg); i++) {
2767f520bb22SYouMin Chen 		for (j = find; sdram_params->phy_regs.phy[j][0] != 0xFFFFFFFF;
2768f520bb22SYouMin Chen 		     j++) {
2769f520bb22SYouMin Chen 			if (sdram_params->phy_regs.phy[j][0] ==
2770f520bb22SYouMin Chen 			    phy_need_update_reg[i]) {
2771f520bb22SYouMin Chen 				writel(sdram_params->phy_regs.phy[j][1],
2772f520bb22SYouMin Chen 				       phy_base + phy_offset +
2773f520bb22SYouMin Chen 				       phy_need_update_reg[i]);
2774f520bb22SYouMin Chen 				find = j;
2775f520bb22SYouMin Chen 				break;
2776f520bb22SYouMin Chen 			}
2777f520bb22SYouMin Chen 		}
2778f520bb22SYouMin Chen 	}
2779f520bb22SYouMin Chen 
2780f520bb22SYouMin Chen 	set_ds_odt(dram, sdram_params, dst_fsp);
2781f520bb22SYouMin Chen 	if (dramtype == LPDDR4) {
2782f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2783f520bb22SYouMin Chen 			       DDR_PCTL2_INIT4);
2784f520bb22SYouMin Chen 		/* MR13 */
2785f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 13,
2786f520bb22SYouMin Chen 			      ((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
2787f520bb22SYouMin Chen 			       PCTL2_MR_MASK) & (~(BIT(7) | BIT(6)))) |
2788f520bb22SYouMin Chen 			      ((0x2 << 6) >> dst_fsp_lp4), dramtype);
2789f520bb22SYouMin Chen 		writel(((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
2790f520bb22SYouMin Chen 				      PCTL2_MR_MASK) & (~(BIT(7) | BIT(6)))) |
2791f520bb22SYouMin Chen 				      ((0x2 << 6) >> dst_fsp_lp4),
2792f520bb22SYouMin Chen 				       PHY_REG(phy_base, 0x1b));
2793f520bb22SYouMin Chen 		/* MR3 */
2794f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 3,
2795f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT &
2796f520bb22SYouMin Chen 			      PCTL2_MR_MASK,
2797f520bb22SYouMin Chen 			      dramtype);
2798f520bb22SYouMin Chen 		writel(mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT & PCTL2_MR_MASK,
2799f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x19));
2800f520bb22SYouMin Chen 
2801f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2802f520bb22SYouMin Chen 			       DDR_PCTL2_INIT3);
2803f520bb22SYouMin Chen 		/* MR1 */
2804f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 1,
2805f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR234_MR1_SHIFT &
2806f520bb22SYouMin Chen 			      PCTL2_MR_MASK,
2807f520bb22SYouMin Chen 			      dramtype);
2808f520bb22SYouMin Chen 		writel(mr_tmp >> PCTL2_LPDDR234_MR1_SHIFT & PCTL2_MR_MASK,
2809f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x17));
2810f520bb22SYouMin Chen 		/* MR2 */
2811f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 2, mr_tmp & PCTL2_MR_MASK,
2812f520bb22SYouMin Chen 			      dramtype);
2813f520bb22SYouMin Chen 		writel(mr_tmp & PCTL2_MR_MASK,
2814f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x18));
2815f520bb22SYouMin Chen 
2816f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2817f520bb22SYouMin Chen 			       DDR_PCTL2_INIT6);
2818f520bb22SYouMin Chen 		/* MR11 */
2819f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 11,
2820f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
2821f520bb22SYouMin Chen 			      dramtype);
2822f520bb22SYouMin Chen 		writel(mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
2823f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x1a));
2824f520bb22SYouMin Chen 		/* MR12 */
2825f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 12,
2826f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR12_SHIFT & PCTL2_MR_MASK,
2827f520bb22SYouMin Chen 			      dramtype);
2828f520bb22SYouMin Chen 
2829f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2830f520bb22SYouMin Chen 			       DDR_PCTL2_INIT7);
2831f520bb22SYouMin Chen 		/* MR22 */
2832f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 22,
2833f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
2834f520bb22SYouMin Chen 			      dramtype);
2835f520bb22SYouMin Chen 		writel(mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
2836f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x1d));
2837f520bb22SYouMin Chen 		/* MR14 */
2838f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 14,
2839f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
2840f520bb22SYouMin Chen 			      dramtype);
2841f520bb22SYouMin Chen 		writel(mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
2842f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x1c));
2843f520bb22SYouMin Chen 	}
2844f520bb22SYouMin Chen 
2845f520bb22SYouMin Chen 	update_noc_timing(dram, sdram_params);
2846f520bb22SYouMin Chen }
2847f520bb22SYouMin Chen 
2848f520bb22SYouMin Chen static void save_fsp_param(struct dram_info *dram, u32 dst_fsp,
2849f520bb22SYouMin Chen 			   struct rv1126_sdram_params *sdram_params)
2850f520bb22SYouMin Chen {
2851f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2852f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
2853f520bb22SYouMin Chen 	struct rv1126_fsp_param *p_fsp_param = &fsp_param[dst_fsp];
2854f520bb22SYouMin Chen 	u32 temp, temp1;
2855f520bb22SYouMin Chen 	struct ddr2_3_4_lp2_3_info *ddr_info;
2856f520bb22SYouMin Chen 
2857f520bb22SYouMin Chen 	ddr_info = get_ddr_drv_odt_info(sdram_params->base.dramtype);
2858f520bb22SYouMin Chen 
2859f520bb22SYouMin Chen 	p_fsp_param->freq_mhz = sdram_params->base.ddr_freq;
2860f520bb22SYouMin Chen 
2861f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4) {
2862f520bb22SYouMin Chen 		p_fsp_param->rd_odt_up_en = 0;
2863f520bb22SYouMin Chen 		p_fsp_param->rd_odt_down_en = 1;
2864f520bb22SYouMin Chen 	} else {
2865f520bb22SYouMin Chen 		p_fsp_param->rd_odt_up_en =
2866f520bb22SYouMin Chen 			ODT_INFO_PULLUP_EN(ddr_info->odt_info);
2867f520bb22SYouMin Chen 		p_fsp_param->rd_odt_down_en =
2868f520bb22SYouMin Chen 			ODT_INFO_PULLDOWN_EN(ddr_info->odt_info);
2869f520bb22SYouMin Chen 	}
2870f520bb22SYouMin Chen 
2871f520bb22SYouMin Chen 	if (p_fsp_param->rd_odt_up_en)
2872f520bb22SYouMin Chen 		p_fsp_param->rd_odt = readl(PHY_REG(phy_base, 0x111));
2873f520bb22SYouMin Chen 	else if (p_fsp_param->rd_odt_down_en)
2874f520bb22SYouMin Chen 		p_fsp_param->rd_odt = readl(PHY_REG(phy_base, 0x110));
2875f520bb22SYouMin Chen 	else
2876f520bb22SYouMin Chen 		p_fsp_param->rd_odt = 0;
2877f520bb22SYouMin Chen 	p_fsp_param->wr_dq_drv = readl(PHY_REG(phy_base, 0x112));
2878f520bb22SYouMin Chen 	p_fsp_param->wr_ca_drv = readl(PHY_REG(phy_base, 0x100));
2879f520bb22SYouMin Chen 	p_fsp_param->wr_ckcs_drv = readl(PHY_REG(phy_base, 0x102));
2880f520bb22SYouMin Chen 	p_fsp_param->vref_inner = readl(PHY_REG(phy_base, 0x128));
2881f520bb22SYouMin Chen 	p_fsp_param->vref_out = readl(PHY_REG(phy_base, 0x105));
2882f520bb22SYouMin Chen 
2883f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR3) {
2884f520bb22SYouMin Chen 		temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2885f520bb22SYouMin Chen 			     DDR_PCTL2_INIT3);
2886f520bb22SYouMin Chen 		temp = (temp >> PCTL2_DDR34_MR1_SHIFT) & PCTL2_MR_MASK;
28878e4f57b9SYouMin Chen 		p_fsp_param->ds_pdds = temp & DDR3_DS_MASK;
28888e4f57b9SYouMin Chen 		p_fsp_param->dq_odt = temp & DDR3_RTT_NOM_MASK;
2889f520bb22SYouMin Chen 		p_fsp_param->ca_odt = p_fsp_param->dq_odt;
2890f520bb22SYouMin Chen 	} else if (sdram_params->base.dramtype == DDR4) {
2891f520bb22SYouMin Chen 		temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2892f520bb22SYouMin Chen 			     DDR_PCTL2_INIT3);
2893f520bb22SYouMin Chen 		temp = (temp >> PCTL2_DDR34_MR1_SHIFT) & PCTL2_MR_MASK;
28948e4f57b9SYouMin Chen 		p_fsp_param->ds_pdds = temp & DDR4_DS_MASK;
28958e4f57b9SYouMin Chen 		p_fsp_param->dq_odt = temp & DDR4_RTT_NOM_MASK;
2896f520bb22SYouMin Chen 		p_fsp_param->ca_odt = p_fsp_param->dq_odt;
2897f520bb22SYouMin Chen 	} else if (sdram_params->base.dramtype == LPDDR3) {
2898f520bb22SYouMin Chen 		temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2899f520bb22SYouMin Chen 			     DDR_PCTL2_INIT4);
2900f520bb22SYouMin Chen 		temp = (temp >> PCTL2_LPDDR234_MR3_SHIFT) & PCTL2_MR_MASK;
2901f520bb22SYouMin Chen 		p_fsp_param->ds_pdds = temp & 0xf;
2902f520bb22SYouMin Chen 
2903f520bb22SYouMin Chen 		p_fsp_param->dq_odt = lp3_odt_value;
2904f520bb22SYouMin Chen 		p_fsp_param->ca_odt = p_fsp_param->dq_odt;
2905f520bb22SYouMin Chen 	} else if (sdram_params->base.dramtype == LPDDR4) {
2906f520bb22SYouMin Chen 		temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2907f520bb22SYouMin Chen 			     DDR_PCTL2_INIT4);
2908f520bb22SYouMin Chen 		temp = (temp >> PCTL2_LPDDR234_MR3_SHIFT) & PCTL2_MR_MASK;
29098e4f57b9SYouMin Chen 		p_fsp_param->ds_pdds = temp & LPDDR4_PDDS_MASK;
2910f520bb22SYouMin Chen 
2911f520bb22SYouMin Chen 		temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2912f520bb22SYouMin Chen 			     DDR_PCTL2_INIT6);
2913f520bb22SYouMin Chen 		temp = (temp >> PCTL2_LPDDR4_MR11_SHIFT) & PCTL2_MR_MASK;
29148e4f57b9SYouMin Chen 		p_fsp_param->dq_odt = temp & LPDDR4_DQODT_MASK;
29158e4f57b9SYouMin Chen 		p_fsp_param->ca_odt = temp & LPDDR4_CAODT_MASK;
2916f520bb22SYouMin Chen 
2917f520bb22SYouMin Chen 		temp = MAX(readl(PHY_REG(phy_base, 0x3ae)),
2918f520bb22SYouMin Chen 			   readl(PHY_REG(phy_base, 0x3ce)));
2919f520bb22SYouMin Chen 		temp1 = MIN(readl(PHY_REG(phy_base, 0x3be)),
2920f520bb22SYouMin Chen 			    readl(PHY_REG(phy_base, 0x3de)));
2921f520bb22SYouMin Chen 		p_fsp_param->vref_ca[0] = (temp + temp1) / 2;
2922f520bb22SYouMin Chen 		temp = MAX(readl(PHY_REG(phy_base, 0x3af)),
2923f520bb22SYouMin Chen 			   readl(PHY_REG(phy_base, 0x3cf)));
2924f520bb22SYouMin Chen 		temp1 = MIN(readl(PHY_REG(phy_base, 0x3bf)),
2925f520bb22SYouMin Chen 			    readl(PHY_REG(phy_base, 0x3df)));
2926f520bb22SYouMin Chen 		p_fsp_param->vref_ca[1] = (temp + temp1) / 2;
2927f520bb22SYouMin Chen 		p_fsp_param->vref_ca[0] |=
2928f520bb22SYouMin Chen 			(readl(PHY_REG(phy_base, 0x1e)) & BIT(6));
2929f520bb22SYouMin Chen 		p_fsp_param->vref_ca[1] |=
2930f520bb22SYouMin Chen 			(readl(PHY_REG(phy_base, 0x1e)) & BIT(6));
2931f520bb22SYouMin Chen 
2932f520bb22SYouMin Chen 		p_fsp_param->lp4_drv_pd_en = (readl(PHY_REG(phy_base, 0x114)) >>
2933f520bb22SYouMin Chen 					      3) & 0x1;
2934f520bb22SYouMin Chen 	}
2935f520bb22SYouMin Chen 
2936f520bb22SYouMin Chen 	p_fsp_param->noc_timings.ddrtiminga0 =
2937f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.ddrtiminga0;
2938f520bb22SYouMin Chen 	p_fsp_param->noc_timings.ddrtimingb0 =
2939f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.ddrtimingb0;
2940f520bb22SYouMin Chen 	p_fsp_param->noc_timings.ddrtimingc0 =
2941f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.ddrtimingc0;
2942f520bb22SYouMin Chen 	p_fsp_param->noc_timings.devtodev0 =
2943f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.devtodev0;
2944f520bb22SYouMin Chen 	p_fsp_param->noc_timings.ddrmode =
2945f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.ddrmode;
2946f520bb22SYouMin Chen 	p_fsp_param->noc_timings.ddr4timing =
2947f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.ddr4timing;
2948f520bb22SYouMin Chen 	p_fsp_param->noc_timings.agingx0 =
2949f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.agingx0;
2950f520bb22SYouMin Chen 	p_fsp_param->noc_timings.aging0 =
2951f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.aging0;
2952f520bb22SYouMin Chen 	p_fsp_param->noc_timings.aging1 =
2953f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.aging1;
2954f520bb22SYouMin Chen 	p_fsp_param->noc_timings.aging2 =
2955f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.aging2;
2956f520bb22SYouMin Chen 	p_fsp_param->noc_timings.aging3 =
2957f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.aging3;
2958f520bb22SYouMin Chen 
2959f520bb22SYouMin Chen 	p_fsp_param->flag = FSP_FLAG;
2960f520bb22SYouMin Chen }
2961f520bb22SYouMin Chen 
2962958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT
2963f520bb22SYouMin Chen static void copy_fsp_param_to_ddr(void)
2964f520bb22SYouMin Chen {
2965f520bb22SYouMin Chen 	memcpy((void *)FSP_PARAM_STORE_ADDR, (void *)&fsp_param,
2966f520bb22SYouMin Chen 	       sizeof(fsp_param));
2967f520bb22SYouMin Chen }
2968d3f5f12cSTang Yun ping #endif
2969f520bb22SYouMin Chen 
2970e2dc1cc0SWesley Yao static void pctl_modify_trfc(struct ddr_pctl_regs *pctl_regs,
2971e2dc1cc0SWesley Yao 			     struct sdram_cap_info *cap_info, u32 dram_type,
2972e2dc1cc0SWesley Yao 			     u32 freq)
2973e2dc1cc0SWesley Yao {
2974e2dc1cc0SWesley Yao 	u64 cs0_cap;
2975e2dc1cc0SWesley Yao 	u32 die_cap;
2976e2dc1cc0SWesley Yao 	u32 trfc_ns, trfc4_ns;
2977e2dc1cc0SWesley Yao 	u32 trfc, txsnr;
2978e2dc1cc0SWesley Yao 	u32 txs_abort_fast = 0;
2979e2dc1cc0SWesley Yao 	u32 tmp;
2980e2dc1cc0SWesley Yao 
2981e2dc1cc0SWesley Yao 	cs0_cap = sdram_get_cs_cap(cap_info, 0, dram_type);
2982e2dc1cc0SWesley Yao 	die_cap = (u32)(cs0_cap >> (20 + (cap_info->bw - cap_info->dbw)));
2983e2dc1cc0SWesley Yao 
2984e2dc1cc0SWesley Yao 	switch (dram_type) {
2985e2dc1cc0SWesley Yao 	case DDR3:
2986e2dc1cc0SWesley Yao 		if (die_cap <= DIE_CAP_512MBIT)
2987e2dc1cc0SWesley Yao 			trfc_ns = 90;
2988e2dc1cc0SWesley Yao 		else if (die_cap <= DIE_CAP_1GBIT)
2989e2dc1cc0SWesley Yao 			trfc_ns = 110;
2990e2dc1cc0SWesley Yao 		else if (die_cap <= DIE_CAP_2GBIT)
2991e2dc1cc0SWesley Yao 			trfc_ns = 160;
2992e2dc1cc0SWesley Yao 		else if (die_cap <= DIE_CAP_4GBIT)
2993e2dc1cc0SWesley Yao 			trfc_ns = 260;
2994e2dc1cc0SWesley Yao 		else
2995e2dc1cc0SWesley Yao 			trfc_ns = 350;
2996e2dc1cc0SWesley Yao 		txsnr = MAX(5, ((trfc_ns + 10) * freq + 999) / 1000);
2997e2dc1cc0SWesley Yao 		break;
2998e2dc1cc0SWesley Yao 
2999e2dc1cc0SWesley Yao 	case DDR4:
3000e2dc1cc0SWesley Yao 		if (die_cap <= DIE_CAP_2GBIT) {
3001e2dc1cc0SWesley Yao 			trfc_ns = 160;
3002e2dc1cc0SWesley Yao 			trfc4_ns = 90;
3003e2dc1cc0SWesley Yao 		} else if (die_cap <= DIE_CAP_4GBIT) {
3004e2dc1cc0SWesley Yao 			trfc_ns = 260;
3005e2dc1cc0SWesley Yao 			trfc4_ns = 110;
3006e2dc1cc0SWesley Yao 		} else if (die_cap <= DIE_CAP_8GBIT) {
3007e2dc1cc0SWesley Yao 			trfc_ns = 350;
3008e2dc1cc0SWesley Yao 			trfc4_ns = 160;
3009e2dc1cc0SWesley Yao 		} else {
3010e2dc1cc0SWesley Yao 			trfc_ns = 550;
3011e2dc1cc0SWesley Yao 			trfc4_ns = 260;
3012e2dc1cc0SWesley Yao 		}
3013e2dc1cc0SWesley Yao 		txsnr = ((trfc_ns + 10) * freq + 999) / 1000;
3014e2dc1cc0SWesley Yao 		txs_abort_fast = ((trfc4_ns + 10) * freq + 999) / 1000;
3015e2dc1cc0SWesley Yao 		break;
3016e2dc1cc0SWesley Yao 
3017e2dc1cc0SWesley Yao 	case LPDDR3:
3018e2dc1cc0SWesley Yao 		if (die_cap <= DIE_CAP_4GBIT)
3019e2dc1cc0SWesley Yao 			trfc_ns = 130;
3020e2dc1cc0SWesley Yao 		else
3021e2dc1cc0SWesley Yao 			trfc_ns = 210;
3022e2dc1cc0SWesley Yao 		txsnr = MAX(2, ((trfc_ns + 10) * freq + 999) / 1000);
3023e2dc1cc0SWesley Yao 		break;
3024e2dc1cc0SWesley Yao 
3025e2dc1cc0SWesley Yao 	case LPDDR4:
3026e2dc1cc0SWesley Yao 	case LPDDR4X:
3027e2dc1cc0SWesley Yao 		if (die_cap <= DIE_CAP_4GBIT)
3028e2dc1cc0SWesley Yao 			trfc_ns = 130;
3029e2dc1cc0SWesley Yao 		else if (die_cap <= DIE_CAP_8GBIT)
3030e2dc1cc0SWesley Yao 			trfc_ns = 180;
3031e2dc1cc0SWesley Yao 		else if (die_cap <= DIE_CAP_16GBIT)
3032e2dc1cc0SWesley Yao 			trfc_ns = 280;
3033e2dc1cc0SWesley Yao 		else
3034e2dc1cc0SWesley Yao 			trfc_ns = 380;
3035e2dc1cc0SWesley Yao 		txsnr = MAX(2, ((trfc_ns + 10) * freq + 999) / 1000);
3036e2dc1cc0SWesley Yao 		break;
3037e2dc1cc0SWesley Yao 
3038e2dc1cc0SWesley Yao 	default:
3039e2dc1cc0SWesley Yao 		return;
3040e2dc1cc0SWesley Yao 	}
3041e2dc1cc0SWesley Yao 	trfc = (trfc_ns * freq + 999) / 1000;
3042e2dc1cc0SWesley Yao 
3043e2dc1cc0SWesley Yao 	for (int i = 0; pctl_regs->pctl[i][0] != 0xffffffff; i++) {
3044e2dc1cc0SWesley Yao 		switch (pctl_regs->pctl[i][0]) {
3045e2dc1cc0SWesley Yao 		case DDR_PCTL2_RFSHTMG:
3046e2dc1cc0SWesley Yao 			tmp = pctl_regs->pctl[i][1];
3047e2dc1cc0SWesley Yao 			/* t_rfc_min */
3048e2dc1cc0SWesley Yao 			tmp &= ~((u32)0x3ff);
3049e2dc1cc0SWesley Yao 			tmp |= ((trfc + 1) / 2) & 0x3ff;
3050e2dc1cc0SWesley Yao 			pctl_regs->pctl[i][1] = tmp;
3051e2dc1cc0SWesley Yao 			break;
3052e2dc1cc0SWesley Yao 
3053e2dc1cc0SWesley Yao 		case DDR_PCTL2_DRAMTMG8:
3054e2dc1cc0SWesley Yao 			if (dram_type == DDR3 || dram_type == DDR4) {
3055e2dc1cc0SWesley Yao 				tmp = pctl_regs->pctl[i][1];
3056e2dc1cc0SWesley Yao 				/* t_xs_x32 */
3057e2dc1cc0SWesley Yao 				tmp &= ~((u32)0x7f);
3058e2dc1cc0SWesley Yao 				tmp |= ((txsnr + 63) / 64) & 0x7f;
3059e2dc1cc0SWesley Yao 
3060e2dc1cc0SWesley Yao 				if (dram_type == DDR4) {
3061e2dc1cc0SWesley Yao 					/* t_xs_abort_x32 */
3062e2dc1cc0SWesley Yao 					tmp &= ~((u32)(0x7f << 16));
3063e2dc1cc0SWesley Yao 					tmp |= (((txs_abort_fast + 63) / 64) & 0x7f) << 16;
3064e2dc1cc0SWesley Yao 					/* t_xs_fast_x32 */
3065e2dc1cc0SWesley Yao 					tmp &= ~((u32)(0x7f << 24));
3066e2dc1cc0SWesley Yao 					tmp |= (((txs_abort_fast + 63) / 64) & 0x7f) << 24;
3067e2dc1cc0SWesley Yao 				}
3068e2dc1cc0SWesley Yao 
3069e2dc1cc0SWesley Yao 				pctl_regs->pctl[i][1] = tmp;
3070e2dc1cc0SWesley Yao 			}
3071e2dc1cc0SWesley Yao 			break;
3072e2dc1cc0SWesley Yao 
3073e2dc1cc0SWesley Yao 		case DDR_PCTL2_DRAMTMG14:
3074e2dc1cc0SWesley Yao 			if (dram_type == LPDDR3 ||
3075e2dc1cc0SWesley Yao 			    dram_type == LPDDR4 || dram_type == LPDDR4X) {
3076e2dc1cc0SWesley Yao 				tmp = pctl_regs->pctl[i][1];
3077e2dc1cc0SWesley Yao 				/* t_xsr */
3078e2dc1cc0SWesley Yao 				tmp &= ~((u32)0xfff);
3079e2dc1cc0SWesley Yao 				tmp |= ((txsnr + 1) / 2) & 0xfff;
3080e2dc1cc0SWesley Yao 				pctl_regs->pctl[i][1] = tmp;
3081e2dc1cc0SWesley Yao 			}
3082e2dc1cc0SWesley Yao 			break;
3083e2dc1cc0SWesley Yao 
3084e2dc1cc0SWesley Yao 		default:
3085e2dc1cc0SWesley Yao 			break;
3086e2dc1cc0SWesley Yao 		}
3087e2dc1cc0SWesley Yao 	}
3088e2dc1cc0SWesley Yao }
3089e2dc1cc0SWesley Yao 
3090f520bb22SYouMin Chen void ddr_set_rate(struct dram_info *dram,
3091f520bb22SYouMin Chen 		  struct rv1126_sdram_params *sdram_params,
3092f520bb22SYouMin Chen 		  u32 freq, u32 cur_freq, u32 dst_fsp,
3093f520bb22SYouMin Chen 		  u32 dst_fsp_lp4, u32 training_en)
3094f520bb22SYouMin Chen {
3095f520bb22SYouMin Chen 	u32 dest_dll_off, cur_init3, dst_init3, cur_fsp, cur_dll_off;
3096f520bb22SYouMin Chen 	u32 mr_tmp;
3097f520bb22SYouMin Chen 	u32 lp_stat;
3098f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
3099f520bb22SYouMin Chen 	struct rv1126_sdram_params *sdram_params_new;
3100f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
3101f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
3102f520bb22SYouMin Chen 
3103f520bb22SYouMin Chen 	lp_stat = low_power_update(dram, 0);
3104f520bb22SYouMin Chen 	sdram_params_new = get_default_sdram_config(freq);
3105f520bb22SYouMin Chen 	sdram_params_new->ch.cap_info.rank = sdram_params->ch.cap_info.rank;
310638b16f08SYouMin Chen 	sdram_params_new->ch.cap_info.bw = sdram_params->ch.cap_info.bw;
3107f520bb22SYouMin Chen 
3108e2dc1cc0SWesley Yao 	pctl_modify_trfc(&sdram_params_new->pctl_regs,
3109e2dc1cc0SWesley Yao 			 &sdram_params->ch.cap_info, dramtype, freq);
3110f520bb22SYouMin Chen 	pre_set_rate(dram, sdram_params_new, dst_fsp, dst_fsp_lp4);
3111f520bb22SYouMin Chen 
3112f520bb22SYouMin Chen 	while ((readl(pctl_base + DDR_PCTL2_STAT) &
3113f520bb22SYouMin Chen 			 PCTL2_OPERATING_MODE_MASK) ==
3114f520bb22SYouMin Chen 			 PCTL2_OPERATING_MODE_SR)
3115f520bb22SYouMin Chen 		continue;
3116f520bb22SYouMin Chen 
3117f520bb22SYouMin Chen 	dest_dll_off = 0;
3118f520bb22SYouMin Chen 	dst_init3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3119f520bb22SYouMin Chen 			  DDR_PCTL2_INIT3);
3120f520bb22SYouMin Chen 	if ((dramtype == DDR3 && (dst_init3 & 1)) ||
3121f520bb22SYouMin Chen 	    (dramtype == DDR4 && !(dst_init3 & 1)))
3122f520bb22SYouMin Chen 		dest_dll_off = 1;
3123f520bb22SYouMin Chen 
3124f520bb22SYouMin Chen 	cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
3125f520bb22SYouMin Chen 	cur_init3 = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
3126f520bb22SYouMin Chen 			  DDR_PCTL2_INIT3);
3127f520bb22SYouMin Chen 	cur_init3 &= PCTL2_MR_MASK;
3128f520bb22SYouMin Chen 	cur_dll_off = 1;
3129f520bb22SYouMin Chen 	if ((dramtype == DDR3 && !(cur_init3 & 1)) ||
3130f520bb22SYouMin Chen 	    (dramtype == DDR4 && (cur_init3 & 1)))
3131f520bb22SYouMin Chen 		cur_dll_off = 0;
3132f520bb22SYouMin Chen 
3133f520bb22SYouMin Chen 	if (!cur_dll_off) {
3134f520bb22SYouMin Chen 		if (dramtype == DDR3)
3135f520bb22SYouMin Chen 			cur_init3 |= 1;
3136f520bb22SYouMin Chen 		else
3137f520bb22SYouMin Chen 			cur_init3 &= ~1;
3138f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 2, 1, cur_init3, dramtype);
3139f520bb22SYouMin Chen 	}
3140f520bb22SYouMin Chen 
3141f520bb22SYouMin Chen 	setbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3,
3142f520bb22SYouMin Chen 		     PCTL2_DIS_AUTO_REFRESH);
3143f520bb22SYouMin Chen 	update_refresh_reg(dram);
3144f520bb22SYouMin Chen 
3145f4f57f8eSTang Yun ping 	enter_sr(dram, 1);
3146f520bb22SYouMin Chen 
3147f520bb22SYouMin Chen 	writel(PMUGRF_CON_DDRPHY_BUFFEREN_MASK |
3148f520bb22SYouMin Chen 	       PMUGRF_CON_DDRPHY_BUFFEREN_EN,
3149df8389e3STang Yun ping 	       &dram->pmugrf->soc_con[0]);
3150f520bb22SYouMin Chen 	sw_set_req(dram);
3151f520bb22SYouMin Chen 	clrbits_le32(pctl_base + DDR_PCTL2_DFIMISC,
3152f520bb22SYouMin Chen 		     PCTL2_DFI_INIT_COMPLETE_EN);
3153f520bb22SYouMin Chen 	sw_set_ack(dram);
3154f520bb22SYouMin Chen 
3155f520bb22SYouMin Chen 	sw_set_req(dram);
3156f520bb22SYouMin Chen 	if ((dramtype == DDR3 || dramtype == DDR4) && dest_dll_off)
3157f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_MSTR, PCTL2_DLL_OFF_MODE);
3158f520bb22SYouMin Chen 	else
3159f520bb22SYouMin Chen 		clrbits_le32(pctl_base + DDR_PCTL2_MSTR, PCTL2_DLL_OFF_MODE);
3160f520bb22SYouMin Chen 
3161f520bb22SYouMin Chen 	setbits_le32(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + DDR_PCTL2_ZQCTL0,
3162f520bb22SYouMin Chen 		     PCTL2_DIS_SRX_ZQCL);
3163f520bb22SYouMin Chen 	setbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_ZQCTL0,
3164f520bb22SYouMin Chen 		     PCTL2_DIS_SRX_ZQCL);
3165f520bb22SYouMin Chen 	sw_set_ack(dram);
3166f520bb22SYouMin Chen 
3167f520bb22SYouMin Chen 	writel(DDR_MSCH_EN_MASK | (0x1 << DDR_MSCH_EN_SHIFT),
3168df8389e3STang Yun ping 	       &dram->cru->clkgate_con[21]);
3169f520bb22SYouMin Chen 	writel(CLK_DDR_UPCTL_EN_MASK | ACLK_DDR_UPCTL_EN_MASK |
3170f520bb22SYouMin Chen 					(0x1 << CLK_DDR_UPCTL_EN_SHIFT) |
3171f520bb22SYouMin Chen 					(0x1 << ACLK_DDR_UPCTL_EN_SHIFT),
3172f520bb22SYouMin Chen 			BUS_SGRF_BASE_ADDR + SGRF_SOC_CON12);
3173f520bb22SYouMin Chen 
3174f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET | DIGITAL_DERESET);
3175f520bb22SYouMin Chen 	rkclk_set_dpll(dram, freq * MHz / 2);
3176f520bb22SYouMin Chen 	phy_pll_set(dram, freq * MHz, 0);
3177f520bb22SYouMin Chen 	phy_pll_set(dram, freq * MHz, 1);
3178f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET | DIGITAL_DERESET);
3179f520bb22SYouMin Chen 
3180f520bb22SYouMin Chen 	writel(PMUGRF_CON_DDRPHY_BUFFEREN_MASK |
3181f520bb22SYouMin Chen 			PMUGRF_CON_DDRPHY_BUFFEREN_DIS,
3182df8389e3STang Yun ping 			&dram->pmugrf->soc_con[0]);
3183f520bb22SYouMin Chen 	writel(DDR_MSCH_EN_MASK | (0x0 << DDR_MSCH_EN_SHIFT),
3184df8389e3STang Yun ping 	       &dram->cru->clkgate_con[21]);
3185f520bb22SYouMin Chen 	writel(CLK_DDR_UPCTL_EN_MASK | ACLK_DDR_UPCTL_EN_MASK |
3186f520bb22SYouMin Chen 					(0x0 << CLK_DDR_UPCTL_EN_SHIFT) |
3187f520bb22SYouMin Chen 					(0x0 << ACLK_DDR_UPCTL_EN_SHIFT),
3188f520bb22SYouMin Chen 			BUS_SGRF_BASE_ADDR + SGRF_SOC_CON12);
3189f520bb22SYouMin Chen 	while ((readl(pctl_base + DDR_PCTL2_DFISTAT) &
3190f520bb22SYouMin Chen 	       PCTL2_DFI_INIT_COMPLETE) != PCTL2_DFI_INIT_COMPLETE)
3191f520bb22SYouMin Chen 		continue;
3192f520bb22SYouMin Chen 
3193f520bb22SYouMin Chen 	sw_set_req(dram);
3194f520bb22SYouMin Chen 	setbits_le32(pctl_base + DDR_PCTL2_MSTR, 0x1 << 29);
3195f520bb22SYouMin Chen 	clrsetbits_le32(pctl_base + DDR_PCTL2_MSTR2, 0x3, dst_fsp);
3196f520bb22SYouMin Chen 	sw_set_ack(dram);
3197f520bb22SYouMin Chen 	update_refresh_reg(dram);
3198f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0xc), 0x3 << 2, dst_fsp << 2);
3199f520bb22SYouMin Chen 
3200f4f57f8eSTang Yun ping 	enter_sr(dram, 0);
3201f520bb22SYouMin Chen 
3202f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
3203f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
3204f520bb22SYouMin Chen 
3205f520bb22SYouMin Chen 	mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_INIT4);
3206f520bb22SYouMin Chen 	if (dramtype == LPDDR3) {
3207f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 1,
3208f520bb22SYouMin Chen 			      (dst_init3 >> PCTL2_LPDDR234_MR1_SHIFT) &
3209f520bb22SYouMin Chen 			      PCTL2_MR_MASK,
3210f520bb22SYouMin Chen 			      dramtype);
3211f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 2, dst_init3 & PCTL2_MR_MASK,
3212f520bb22SYouMin Chen 			      dramtype);
3213f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 3,
3214f520bb22SYouMin Chen 			      (mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT) &
3215f520bb22SYouMin Chen 			      PCTL2_MR_MASK,
3216f520bb22SYouMin Chen 			      dramtype);
3217f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 11, lp3_odt_value, dramtype);
3218f520bb22SYouMin Chen 	} else if ((dramtype == DDR3) || (dramtype == DDR4)) {
3219f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 1, dst_init3 & PCTL2_MR_MASK,
3220f520bb22SYouMin Chen 			      dramtype);
3221f520bb22SYouMin Chen 		if (!dest_dll_off) {
3222f520bb22SYouMin Chen 			pctl_write_mr(dram->pctl, 3, 0,
3223f520bb22SYouMin Chen 				      ((dst_init3 >> PCTL2_DDR34_MR0_SHIFT) &
3224f520bb22SYouMin Chen 				      PCTL2_MR_MASK) | DDR3_DLL_RESET,
3225f520bb22SYouMin Chen 				      dramtype);
3226f520bb22SYouMin Chen 			udelay(2);
3227f520bb22SYouMin Chen 		}
3228f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 0,
3229f520bb22SYouMin Chen 			      (dst_init3 >> PCTL2_DDR34_MR0_SHIFT &
3230f520bb22SYouMin Chen 			       PCTL2_MR_MASK) & (~DDR3_DLL_RESET),
3231f520bb22SYouMin Chen 			      dramtype);
3232f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 2,
3233f520bb22SYouMin Chen 			      ((mr_tmp >> PCTL2_DDR34_MR2_SHIFT) &
3234f520bb22SYouMin Chen 			       PCTL2_MR_MASK), dramtype);
3235f520bb22SYouMin Chen 		if (dramtype == DDR4) {
3236f520bb22SYouMin Chen 			pctl_write_mr(dram->pctl, 3, 3, mr_tmp & PCTL2_MR_MASK,
3237f520bb22SYouMin Chen 				      dramtype);
3238f520bb22SYouMin Chen 			mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3239f520bb22SYouMin Chen 				       DDR_PCTL2_INIT6);
3240f520bb22SYouMin Chen 			pctl_write_mr(dram->pctl, 3, 4,
3241f520bb22SYouMin Chen 				      (mr_tmp >> PCTL2_DDR4_MR4_SHIFT) &
3242f520bb22SYouMin Chen 				       PCTL2_MR_MASK,
3243f520bb22SYouMin Chen 				      dramtype);
3244f520bb22SYouMin Chen 			pctl_write_mr(dram->pctl, 3, 5,
3245f520bb22SYouMin Chen 				      mr_tmp >> PCTL2_DDR4_MR5_SHIFT &
3246f520bb22SYouMin Chen 				      PCTL2_MR_MASK,
3247f520bb22SYouMin Chen 				      dramtype);
3248f520bb22SYouMin Chen 
3249f520bb22SYouMin Chen 			mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3250f520bb22SYouMin Chen 				       DDR_PCTL2_INIT7);
3251f520bb22SYouMin Chen 			pctl_write_mr(dram->pctl, 3, 6,
3252f520bb22SYouMin Chen 				      mr_tmp >> PCTL2_DDR4_MR6_SHIFT &
3253f520bb22SYouMin Chen 				      PCTL2_MR_MASK,
3254f520bb22SYouMin Chen 				      dramtype);
3255f520bb22SYouMin Chen 		}
3256f520bb22SYouMin Chen 	} else if (dramtype == LPDDR4) {
3257f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 13,
3258f520bb22SYouMin Chen 			      ((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
3259f520bb22SYouMin Chen 			       PCTL2_MR_MASK) & (~(BIT(7)))) |
3260f520bb22SYouMin Chen 			      dst_fsp_lp4 << 7, dramtype);
3261f520bb22SYouMin Chen 	}
3262f4f57f8eSTang Yun ping 	clrbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3,
3263f4f57f8eSTang Yun ping 		     PCTL2_DIS_AUTO_REFRESH);
3264f4f57f8eSTang Yun ping 	update_refresh_reg(dram);
3265f520bb22SYouMin Chen 
3266f520bb22SYouMin Chen 	/* training */
3267f520bb22SYouMin Chen 	high_freq_training(dram, sdram_params_new, dst_fsp);
3268f520bb22SYouMin Chen 	low_power_update(dram, lp_stat);
3269f520bb22SYouMin Chen 
3270f520bb22SYouMin Chen 	save_fsp_param(dram, dst_fsp, sdram_params_new);
3271f520bb22SYouMin Chen }
3272f520bb22SYouMin Chen 
3273f520bb22SYouMin Chen static void ddr_set_rate_for_fsp(struct dram_info *dram,
3274f520bb22SYouMin Chen 				 struct rv1126_sdram_params *sdram_params)
3275f520bb22SYouMin Chen {
3276f520bb22SYouMin Chen 	struct ddr2_3_4_lp2_3_info *ddr_info;
3277d3f5f12cSTang Yun ping 	u32 f0;
3278f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
3279958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT
3280d3f5f12cSTang Yun ping 	u32 f1, f2, f3;
3281d3f5f12cSTang Yun ping #endif
3282f520bb22SYouMin Chen 
3283f520bb22SYouMin Chen 	ddr_info = get_ddr_drv_odt_info(dramtype);
3284f520bb22SYouMin Chen 	if (!ddr_info)
3285f520bb22SYouMin Chen 		return;
3286f520bb22SYouMin Chen 
3287d3f5f12cSTang Yun ping 	f0 = (ddr_info->ddr_freq0_1 >> DDR_FREQ_F0_SHIFT) &
3288d3f5f12cSTang Yun ping 	     DDR_FREQ_MASK;
3289d3f5f12cSTang Yun ping 
3290958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT
3291f520bb22SYouMin Chen 	memset((void *)FSP_PARAM_STORE_ADDR, 0, sizeof(fsp_param));
3292f520bb22SYouMin Chen 	memset((void *)&fsp_param, 0, sizeof(fsp_param));
3293f520bb22SYouMin Chen 
3294f520bb22SYouMin Chen 	f1 = (ddr_info->ddr_freq0_1 >> DDR_FREQ_F1_SHIFT) &
3295f520bb22SYouMin Chen 	     DDR_FREQ_MASK;
3296f520bb22SYouMin Chen 	f2 = (ddr_info->ddr_freq2_3 >> DDR_FREQ_F2_SHIFT) &
3297f520bb22SYouMin Chen 	     DDR_FREQ_MASK;
3298f520bb22SYouMin Chen 	f3 = (ddr_info->ddr_freq2_3 >> DDR_FREQ_F3_SHIFT) &
3299f520bb22SYouMin Chen 	     DDR_FREQ_MASK;
3300d3f5f12cSTang Yun ping #endif
3301f520bb22SYouMin Chen 
3302f520bb22SYouMin Chen 	if (get_wrlvl_val(dram, sdram_params))
3303f520bb22SYouMin Chen 		printascii("get wrlvl value fail\n");
3304d3f5f12cSTang Yun ping 
3305958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT
3306f876ce9bSTang Yun ping 	printascii("change to: ");
3307f520bb22SYouMin Chen 	printdec(f1);
3308f520bb22SYouMin Chen 	printascii("MHz\n");
3309f520bb22SYouMin Chen 	ddr_set_rate(&dram_info, sdram_params, f1,
3310f520bb22SYouMin Chen 		     sdram_params->base.ddr_freq, 1, 1, 1);
3311f876ce9bSTang Yun ping 	printascii("change to: ");
3312f520bb22SYouMin Chen 	printdec(f2);
3313f520bb22SYouMin Chen 	printascii("MHz\n");
3314f520bb22SYouMin Chen 	ddr_set_rate(&dram_info, sdram_params, f2, f1, 2, 0, 1);
3315f876ce9bSTang Yun ping 	printascii("change to: ");
3316f520bb22SYouMin Chen 	printdec(f3);
3317f520bb22SYouMin Chen 	printascii("MHz\n");
3318f520bb22SYouMin Chen 	ddr_set_rate(&dram_info, sdram_params, f3, f2, 3, 1, 1);
3319d3f5f12cSTang Yun ping #endif
3320f876ce9bSTang Yun ping 	printascii("change to: ");
3321f520bb22SYouMin Chen 	printdec(f0);
3322f876ce9bSTang Yun ping 	printascii("MHz(final freq)\n");
3323958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT
3324f520bb22SYouMin Chen 	ddr_set_rate(&dram_info, sdram_params, f0, f3, 0, 0, 1);
3325d3f5f12cSTang Yun ping #else
3326d3f5f12cSTang Yun ping 	ddr_set_rate(&dram_info, sdram_params, f0, sdram_params->base.ddr_freq, 1, 1, 1);
3327d3f5f12cSTang Yun ping #endif
3328f520bb22SYouMin Chen }
3329f520bb22SYouMin Chen 
3330f520bb22SYouMin Chen int get_uart_config(void)
3331f520bb22SYouMin Chen {
3332f520bb22SYouMin Chen 	struct sdram_head_info_index_v2 *index =
3333f520bb22SYouMin Chen 		(struct sdram_head_info_index_v2 *)common_info;
3334f520bb22SYouMin Chen 	struct global_info *gbl_info;
3335f520bb22SYouMin Chen 
3336f520bb22SYouMin Chen 	gbl_info = (struct global_info *)((void *)common_info +
3337f520bb22SYouMin Chen 		index->global_index.offset * 4);
3338f520bb22SYouMin Chen 
3339f520bb22SYouMin Chen 	return gbl_info->uart_info;
3340f520bb22SYouMin Chen }
3341f520bb22SYouMin Chen 
3342f520bb22SYouMin Chen /* return: 0 = success, other = fail */
3343f520bb22SYouMin Chen int sdram_init(void)
3344f520bb22SYouMin Chen {
3345f520bb22SYouMin Chen 	struct rv1126_sdram_params *sdram_params;
3346f520bb22SYouMin Chen 	int ret = 0;
3347f520bb22SYouMin Chen 	struct sdram_head_info_index_v2 *index =
3348f520bb22SYouMin Chen 		(struct sdram_head_info_index_v2 *)common_info;
3349f520bb22SYouMin Chen 	struct global_info *gbl_info;
3350f520bb22SYouMin Chen 
3351f520bb22SYouMin Chen 	dram_info.phy = (void *)DDR_PHY_BASE_ADDR;
3352f520bb22SYouMin Chen 	dram_info.pctl = (void *)UPCTL2_BASE_ADDR;
3353f520bb22SYouMin Chen 	dram_info.grf = (void *)GRF_BASE_ADDR;
3354f520bb22SYouMin Chen 	dram_info.cru = (void *)CRU_BASE_ADDR;
3355f520bb22SYouMin Chen 	dram_info.msch = (void *)SERVER_MSCH_BASE_ADDR;
3356f520bb22SYouMin Chen 	dram_info.ddrgrf = (void *)DDR_GRF_BASE_ADDR;
3357f520bb22SYouMin Chen 	dram_info.pmugrf = (void *)PMU_GRF_BASE_ADDR;
3358f520bb22SYouMin Chen 
3359ee5f0829STang Yun ping #ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT
3360ee5f0829STang Yun ping 	printascii("extended temp support\n");
3361ee5f0829STang Yun ping #endif
3362f520bb22SYouMin Chen 	if (index->version_info != 2 ||
3363f520bb22SYouMin Chen 	    (index->global_index.size != sizeof(struct global_info) / 4) ||
3364f520bb22SYouMin Chen 	    (index->ddr3_index.size !=
3365f520bb22SYouMin Chen 		sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
3366f520bb22SYouMin Chen 	    (index->ddr4_index.size !=
3367f520bb22SYouMin Chen 		sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
3368f520bb22SYouMin Chen 	    (index->lp3_index.size !=
3369f520bb22SYouMin Chen 		sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
3370f520bb22SYouMin Chen 	    (index->lp4_index.size != (sizeof(struct lp4_info) / 4)) ||
3371f520bb22SYouMin Chen 	    index->global_index.offset == 0 ||
3372f520bb22SYouMin Chen 	    index->ddr3_index.offset == 0 ||
3373f520bb22SYouMin Chen 	    index->ddr4_index.offset == 0 ||
3374f520bb22SYouMin Chen 	    index->lp3_index.offset == 0 ||
3375f520bb22SYouMin Chen 	    index->lp4_index.offset == 0) {
3376f520bb22SYouMin Chen 		printascii("common info error\n");
3377f520bb22SYouMin Chen 		goto error;
3378f520bb22SYouMin Chen 	}
3379f520bb22SYouMin Chen 
3380f520bb22SYouMin Chen 	gbl_info = (struct global_info *)((void *)common_info +
3381f520bb22SYouMin Chen 		index->global_index.offset * 4);
3382f520bb22SYouMin Chen 
3383f520bb22SYouMin Chen 	dram_info.sr_idle = SR_INFO(gbl_info->sr_pd_info);
3384f520bb22SYouMin Chen 	dram_info.pd_idle = PD_INFO(gbl_info->sr_pd_info);
3385f520bb22SYouMin Chen 
3386f520bb22SYouMin Chen 	sdram_params = &sdram_configs[0];
3387f520bb22SYouMin Chen 
3388f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR3 ||
3389f520bb22SYouMin Chen 	    sdram_params->base.dramtype == DDR4) {
3390f520bb22SYouMin Chen 		if (DDR_2T_INFO(gbl_info->info_2t))
3391f520bb22SYouMin Chen 			sdram_params->pctl_regs.pctl[0][1] |= 0x1 << 10;
3392f520bb22SYouMin Chen 		else
3393f520bb22SYouMin Chen 			sdram_params->pctl_regs.pctl[0][1] &=
3394f520bb22SYouMin Chen 				~(0x1 << 10);
3395f520bb22SYouMin Chen 	}
3396f520bb22SYouMin Chen 	ret = sdram_init_detect(&dram_info, sdram_params);
3397f520bb22SYouMin Chen 	if (ret) {
3398f520bb22SYouMin Chen 		sdram_print_dram_type(sdram_params->base.dramtype);
3399f520bb22SYouMin Chen 		printascii(", ");
3400f520bb22SYouMin Chen 		printdec(sdram_params->base.ddr_freq);
3401f520bb22SYouMin Chen 		printascii("MHz\n");
3402f520bb22SYouMin Chen 		goto error;
3403f520bb22SYouMin Chen 	}
3404f520bb22SYouMin Chen 	print_ddr_info(sdram_params);
3405c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL)
3406c71eeac4SWesley Yao 	init_rw_trn_result_struct(&rw_trn_result, dram_info.phy,
3407c71eeac4SWesley Yao 				  (u8)sdram_params->ch.cap_info.rank);
3408c71eeac4SWesley Yao #endif
3409f520bb22SYouMin Chen 
3410f520bb22SYouMin Chen 	ddr_set_rate_for_fsp(&dram_info, sdram_params);
3411958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT
3412f520bb22SYouMin Chen 	copy_fsp_param_to_ddr();
3413d3f5f12cSTang Yun ping #endif
3414f520bb22SYouMin Chen 
3415f520bb22SYouMin Chen 	ddr_set_atags(&dram_info, sdram_params);
3416c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL)
3417c71eeac4SWesley Yao 	save_rw_trn_result_to_ddr(&rw_trn_result);
3418c71eeac4SWesley Yao #endif
3419f520bb22SYouMin Chen 
3420f520bb22SYouMin Chen 	printascii("out\n");
3421f520bb22SYouMin Chen 
3422f520bb22SYouMin Chen 	return ret;
3423f520bb22SYouMin Chen error:
3424f520bb22SYouMin Chen 	printascii("error\n");
3425f520bb22SYouMin Chen 	return (-1);
3426f520bb22SYouMin Chen }
3427f520bb22SYouMin Chen #endif /* CONFIG_TPL_BUILD */
3428