xref: /rk3399_rockchip-uboot/drivers/ram/rockchip/sdram_rv1126.c (revision c0a4decf1890f4d80ec5b5a3605ac54a3f74696a)
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 
28dfa73e58SWesley Yao /* #define DDR4_READ_GATE_PREAMBLE_MODE */
29dfa73e58SWesley Yao #ifndef DDR4_READ_GATE_PREAMBLE_MODE
30dfa73e58SWesley Yao /* DDR4 read gate normal mode conflicts with 1nCK preamble */
31dfa73e58SWesley Yao #define DDR4_READ_GATE_2NCK_PREAMBLE
32dfa73e58SWesley Yao #endif
33dfa73e58SWesley Yao 
34f520bb22SYouMin Chen #define SKEW_RX_SIGNAL			(0)
35f520bb22SYouMin Chen #define SKEW_TX_SIGNAL			(1)
36f520bb22SYouMin Chen #define SKEW_CA_SIGNAL			(2)
37f520bb22SYouMin Chen 
38f520bb22SYouMin Chen #define DESKEW_MDF_ABS_VAL		(0)
39f520bb22SYouMin Chen #define DESKEW_MDF_DIFF_VAL		(1)
40f520bb22SYouMin Chen 
41f520bb22SYouMin Chen #ifdef CONFIG_TPL_BUILD
42f520bb22SYouMin Chen #ifndef CONFIG_TPL_TINY_FRAMEWORK
43f520bb22SYouMin Chen #error please defined CONFIG_TPL_TINY_FRAMEWORK for RV1126 !!!
44f520bb22SYouMin Chen #endif
45f520bb22SYouMin Chen #endif
46f520bb22SYouMin Chen 
47f520bb22SYouMin Chen #ifdef CONFIG_TPL_BUILD
48f520bb22SYouMin Chen 
49f520bb22SYouMin Chen struct dram_info {
50f520bb22SYouMin Chen 	void __iomem *pctl;
51f520bb22SYouMin Chen 	void __iomem *phy;
52f520bb22SYouMin Chen 	struct rv1126_cru *cru;
53f520bb22SYouMin Chen 	struct msch_regs *msch;
54f520bb22SYouMin Chen 	struct rv1126_ddrgrf *ddrgrf;
55f520bb22SYouMin Chen 	struct rv1126_grf *grf;
56f520bb22SYouMin Chen 	struct ram_info info;
57f520bb22SYouMin Chen 	struct rv1126_pmugrf *pmugrf;
58f520bb22SYouMin Chen 	u32 sr_idle;
59f520bb22SYouMin Chen 	u32 pd_idle;
60f520bb22SYouMin Chen };
61f520bb22SYouMin Chen 
62f520bb22SYouMin Chen #define GRF_BASE_ADDR			0xfe000000
63f520bb22SYouMin Chen #define PMU_GRF_BASE_ADDR		0xfe020000
64f520bb22SYouMin Chen #define DDR_GRF_BASE_ADDR		0xfe030000
65f520bb22SYouMin Chen #define BUS_SGRF_BASE_ADDR		0xfe0a0000
66f520bb22SYouMin Chen #define SERVER_MSCH_BASE_ADDR		0xfe800000
67f520bb22SYouMin Chen #define CRU_BASE_ADDR			0xff490000
68f520bb22SYouMin Chen #define DDR_PHY_BASE_ADDR		0xff4a0000
69f520bb22SYouMin Chen #define UPCTL2_BASE_ADDR		0xffa50000
70f520bb22SYouMin Chen 
71f627cf25SZhihuan He #define SGRF_SOC_CON2			0x8
72f520bb22SYouMin Chen #define SGRF_SOC_CON12			0x30
73f520bb22SYouMin Chen #define SGRF_SOC_CON13			0x34
74f520bb22SYouMin Chen 
75f520bb22SYouMin Chen struct dram_info dram_info;
76f520bb22SYouMin Chen 
77970fa5d8STang Yun ping #if (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 3)
78f520bb22SYouMin Chen struct rv1126_sdram_params sdram_configs[] = {
79112c8ab5SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-328.inc"
80f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-396.inc"
81f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-528.inc"
82f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-664.inc"
83f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-784.inc"
84f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-924.inc"
8505431850SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-1056.inc"
86f520bb22SYouMin Chen };
87970fa5d8STang Yun ping #elif (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 0)
88f520bb22SYouMin Chen struct rv1126_sdram_params sdram_configs[] = {
89112c8ab5SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-328.inc"
90f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-396.inc"
91f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-528.inc"
92f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-664.inc"
93f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-784.inc"
94f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-924.inc"
95f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-1056.inc"
96f520bb22SYouMin Chen };
97970fa5d8STang Yun ping #elif (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 6)
98f520bb22SYouMin Chen struct rv1126_sdram_params sdram_configs[] = {
99112c8ab5SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-328.inc"
100f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-396.inc"
101f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-528.inc"
102f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-664.inc"
103f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-784.inc"
104f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-924.inc"
10505431850SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-1056.inc"
106f520bb22SYouMin Chen };
1079ebc0521SWesley Yao #elif (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 7) || (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 8)
108f520bb22SYouMin Chen struct rv1126_sdram_params sdram_configs[] = {
109112c8ab5SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-328.inc"
110f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-396.inc"
111f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-528.inc"
112f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-664.inc"
113f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-784.inc"
114f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-924.inc"
115f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-1056.inc"
116f520bb22SYouMin Chen };
117f520bb22SYouMin Chen #endif
118f520bb22SYouMin Chen 
119f520bb22SYouMin Chen u32 common_info[] = {
120f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-loader_params.inc"
121f520bb22SYouMin Chen };
122f520bb22SYouMin Chen 
123c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL)
124c71eeac4SWesley Yao static struct rw_trn_result rw_trn_result;
125c71eeac4SWesley Yao #endif
126c71eeac4SWesley Yao 
127f520bb22SYouMin Chen static struct rv1126_fsp_param fsp_param[MAX_IDX];
128f520bb22SYouMin Chen 
129f520bb22SYouMin Chen static u8 lp3_odt_value;
130f520bb22SYouMin Chen 
131d5bb9a92STang Yun ping static s8 wrlvl_result[2][4];
132f520bb22SYouMin Chen 
133f520bb22SYouMin Chen /* DDR configuration 0-9 */
134f520bb22SYouMin Chen u16 ddr_cfg_2_rbc[] = {
135f520bb22SYouMin Chen 	((0 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 3), /* 0 */
136f520bb22SYouMin Chen 	((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 2), /* 1 */
137f520bb22SYouMin Chen 	((1 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 3), /* 2 */
138f520bb22SYouMin Chen 	((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 1), /* 3 */
139f520bb22SYouMin Chen 	((0 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 4), /* 4 */
140f520bb22SYouMin Chen 	((0 << 8) | (3 << 5) | (1 << 4) | (1 << 3) | 1), /* 5 */
141f520bb22SYouMin Chen 	((0 << 8) | (3 << 5) | (1 << 4) | (1 << 3) | 2), /* 6 */
142f520bb22SYouMin Chen 	((0 << 8) | (2 << 5) | (1 << 4) | (1 << 3) | 3), /* 7 */
143f520bb22SYouMin Chen 	((1 << 8) | (3 << 5) | (0 << 4) | (0 << 3) | 2), /* 8 */
144f520bb22SYouMin Chen 	((1 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 2) /* 9 */
145f520bb22SYouMin Chen };
146f520bb22SYouMin Chen 
147f520bb22SYouMin Chen /* DDR configuration 10-21 */
148f520bb22SYouMin Chen u8 ddr4_cfg_2_rbc[] = {
149f520bb22SYouMin Chen 	((0 << 7) | (3 << 4) | (0 << 3) | (2 << 1) | 0), /* 10 */
150f520bb22SYouMin Chen 	((1 << 7) | (2 << 4) | (0 << 3) | (2 << 1) | 0), /* 11 */
151f520bb22SYouMin Chen 	((0 << 7) | (4 << 4) | (0 << 3) | (1 << 1) | 0), /* 12 */
152f520bb22SYouMin Chen 	((1 << 7) | (3 << 4) | (0 << 3) | (1 << 1) | 0), /* 13 */
153f520bb22SYouMin Chen 	((0 << 7) | (4 << 4) | (0 << 3) | (2 << 1) | 1), /* 14 */
154f520bb22SYouMin Chen 	((1 << 7) | (3 << 4) | (0 << 3) | (2 << 1) | 1), /* 15 */
155f520bb22SYouMin Chen 	((1 << 7) | (4 << 4) | (0 << 3) | (1 << 1) | 1), /* 16 */
156f520bb22SYouMin Chen 	((0 << 7) | (2 << 4) | (1 << 3) | (2 << 1) | 0), /* 17 */
157f520bb22SYouMin Chen 	((0 << 7) | (3 << 4) | (1 << 3) | (1 << 1) | 0), /* 18 */
158f520bb22SYouMin Chen 	((0 << 7) | (3 << 4) | (1 << 3) | (2 << 1) | 1), /* 19 */
159f520bb22SYouMin Chen 	((0 << 7) | (4 << 4) | (1 << 3) | (1 << 1) | 1), /* 20 */
160f520bb22SYouMin Chen 	((1 << 7) | (4 << 4) | (0 << 3) | (0 << 1) | 0) /* 21 */
161f520bb22SYouMin Chen };
162f520bb22SYouMin Chen 
163f520bb22SYouMin Chen /* DDR configuration 22-28 */
164f520bb22SYouMin Chen u16 ddr_cfg_2_rbc_p2[] = {
165f520bb22SYouMin Chen 	((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 0), /* 22 */
166f520bb22SYouMin Chen 	((0 << 8) | (4 << 5) | (0 << 4) | (1 << 3) | 2), /* 23 */
167f520bb22SYouMin Chen 	((1 << 8) | (3 << 5) | (0 << 4) | (0 << 3) | 3), /* 24 */
168f520bb22SYouMin Chen 	((0 << 8) | (3 << 5) | (1 << 4) | (0 << 3) | 3), /* 25 */
169f520bb22SYouMin Chen 	((0 << 8) | (4 << 5) | (1 << 4) | (0 << 3) | 2), /* 26 */
170f520bb22SYouMin Chen 	((1 << 8) | (4 << 5) | (0 << 4) | (0 << 3) | 2), /* 27 */
171f520bb22SYouMin Chen 	((0 << 8) | (4 << 5) | (0 << 4) | (0 << 3) | 3) /* 28 */
172f520bb22SYouMin Chen };
173f520bb22SYouMin Chen 
174f520bb22SYouMin Chen u8 d4_rbc_2_d3_rbc[][2] = {
175f520bb22SYouMin Chen 	{10, 0},
176f520bb22SYouMin Chen 	{11, 2},
177f520bb22SYouMin Chen 	{12, 23},
178f520bb22SYouMin Chen 	{13, 1},
179f520bb22SYouMin Chen 	{14, 28},
180f520bb22SYouMin Chen 	{15, 24},
181f520bb22SYouMin Chen 	{16, 27},
182f520bb22SYouMin Chen 	{17, 7},
183f520bb22SYouMin Chen 	{18, 6},
184f520bb22SYouMin Chen 	{19, 25},
185f520bb22SYouMin Chen 	{20, 26},
186f520bb22SYouMin Chen 	{21, 3}
187f520bb22SYouMin Chen };
188f520bb22SYouMin Chen 
189a4bbeaccSWesley Yao u32 addrmap[29][9] = {
190f520bb22SYouMin Chen 	{24, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
191f520bb22SYouMin Chen 		0x08080808, 0x00000f0f, 0x3f3f}, /* 0 */
192f520bb22SYouMin Chen 	{23, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
193f520bb22SYouMin Chen 		0x07070707, 0x00000f0f, 0x3f3f}, /* 1 */
194f520bb22SYouMin Chen 	{23, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
195f520bb22SYouMin Chen 		0x0f080808, 0x00000f0f, 0x3f3f}, /* 2 */
196f520bb22SYouMin Chen 	{22, 0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x06060606,
197f520bb22SYouMin Chen 		0x06060606, 0x00000f0f, 0x3f3f}, /* 3 */
198f520bb22SYouMin Chen 	{24, 0x000a0a0a, 0x00000000, 0x00000000, 0x00000000, 0x09090909,
199f520bb22SYouMin Chen 		0x0f090909, 0x00000f0f, 0x3f3f}, /* 4 */
200f520bb22SYouMin Chen 	{6, 0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x07070707,
201f520bb22SYouMin Chen 		0x07070707, 0x00000f0f, 0x3f3f}, /* 5 */
202f520bb22SYouMin Chen 	{7, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x08080808,
203f520bb22SYouMin Chen 		0x08080808, 0x00000f0f, 0x3f3f}, /* 6 */
204f520bb22SYouMin Chen 	{8, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x09090909,
205f520bb22SYouMin Chen 		0x0f090909, 0x00000f0f, 0x3f3f}, /* 7 */
206f520bb22SYouMin Chen 	{22, 0x001f0808, 0x00000000, 0x00000000, 0x00001f1f, 0x06060606,
207f520bb22SYouMin Chen 		0x06060606, 0x00000f0f, 0x3f3f}, /* 8 */
208f520bb22SYouMin Chen 	{23, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
209f520bb22SYouMin Chen 		0x0f070707, 0x00000f0f, 0x3f3f}, /* 9 */
210f520bb22SYouMin Chen 
211f520bb22SYouMin Chen 	{24, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
212f520bb22SYouMin Chen 		0x08080808, 0x00000f0f, 0x0801}, /* 10 */
213f520bb22SYouMin Chen 	{23, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
214f520bb22SYouMin Chen 		0x0f080808, 0x00000f0f, 0x0801}, /* 11 */
215f520bb22SYouMin Chen 	{24, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
216f520bb22SYouMin Chen 		0x07070707, 0x00000f07, 0x0700}, /* 12 */
217f520bb22SYouMin Chen 	{23, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
218f520bb22SYouMin Chen 		0x07070707, 0x00000f0f, 0x0700}, /* 13 */
219f520bb22SYouMin Chen 	{24, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
220f520bb22SYouMin Chen 		0x07070707, 0x00000f07, 0x3f01}, /* 14 */
221f520bb22SYouMin Chen 	{23, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
222f520bb22SYouMin Chen 		0x07070707, 0x00000f0f, 0x3f01}, /* 15 */
223f520bb22SYouMin Chen 	{23, 0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x06060606,
224f520bb22SYouMin Chen 		0x06060606, 0x00000f06, 0x3f00}, /* 16 */
225f520bb22SYouMin Chen 	{8, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x09090909,
226f520bb22SYouMin Chen 		0x0f090909, 0x00000f0f, 0x0801}, /* 17 */
227f520bb22SYouMin Chen 	{7, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x08080808,
228f520bb22SYouMin Chen 		0x08080808, 0x00000f0f, 0x0700}, /* 18 */
229f520bb22SYouMin Chen 	{7, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
230f520bb22SYouMin Chen 		0x08080808, 0x00000f0f, 0x3f01}, /* 19 */
231f520bb22SYouMin Chen 
232f520bb22SYouMin Chen 	{6, 0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
233f520bb22SYouMin Chen 		0x07070707, 0x00000f07, 0x3f00}, /* 20 */
234f520bb22SYouMin Chen 	{23, 0x003f0909, 0x00000006, 0x1f1f0000, 0x00001f1f, 0x06060606,
235f520bb22SYouMin Chen 		0x06060606, 0x00000f06, 0x0600}, /* 21 */
236f520bb22SYouMin Chen 	{21, 0x00060606, 0x00000000, 0x1f1f0000, 0x00001f1f, 0x05050505,
237a4bbeaccSWesley Yao 		0x05050505, 0x00000f0f, 0x3f3f}, /* 22 */
238a4bbeaccSWesley Yao 
239a4bbeaccSWesley Yao 	{24, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
240a4bbeaccSWesley Yao 		0x07070707, 0x00000f07, 0x3f3f}, /* 23 */
241a4bbeaccSWesley Yao 	{23, 0x003f0909, 0x00000000, 0x00000000, 0x00001f00, 0x07070707,
242a4bbeaccSWesley Yao 		0x07070707, 0x00000f0f, 0x3f3f}, /* 24 */
243a4bbeaccSWesley Yao 	{7, 0x003f0909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
244a4bbeaccSWesley Yao 		0x08080808, 0x00000f0f, 0x3f3f}, /* 25 */
245a4bbeaccSWesley Yao 	{6, 0x003f0808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
246a4bbeaccSWesley Yao 		0x07070707, 0x00000f07, 0x3f3f}, /* 26 */
247a4bbeaccSWesley Yao 	{23, 0x003f0808, 0x00000000, 0x00000000, 0x00001f1f, 0x06060606,
248a4bbeaccSWesley Yao 		0x06060606, 0x00000f06, 0x3f3f}, /* 27 */
249a4bbeaccSWesley Yao 	{24, 0x003f0909, 0x00000000, 0x00000000, 0x00001f00, 0x07070707,
250a4bbeaccSWesley Yao 		0x07070707, 0x00000f07, 0x3f3f} /* 28 */
251f520bb22SYouMin Chen };
252f520bb22SYouMin Chen 
253f520bb22SYouMin Chen static u8 dq_sel[22][3] = {
254f520bb22SYouMin Chen 	{0x0, 0x17, 0x22},
255f520bb22SYouMin Chen 	{0x1, 0x18, 0x23},
256f520bb22SYouMin Chen 	{0x2, 0x19, 0x24},
257f520bb22SYouMin Chen 	{0x3, 0x1a, 0x25},
258f520bb22SYouMin Chen 	{0x4, 0x1b, 0x26},
259f520bb22SYouMin Chen 	{0x5, 0x1c, 0x27},
260f520bb22SYouMin Chen 	{0x6, 0x1d, 0x28},
261f520bb22SYouMin Chen 	{0x7, 0x1e, 0x29},
262f520bb22SYouMin Chen 	{0x8, 0x16, 0x21},
263f520bb22SYouMin Chen 	{0x9, 0x1f, 0x2a},
264f520bb22SYouMin Chen 	{0xa, 0x20, 0x2b},
265f520bb22SYouMin Chen 	{0x10, 0x1, 0xc},
266f520bb22SYouMin Chen 	{0x11, 0x2, 0xd},
267f520bb22SYouMin Chen 	{0x12, 0x3, 0xe},
268f520bb22SYouMin Chen 	{0x13, 0x4, 0xf},
269f520bb22SYouMin Chen 	{0x14, 0x5, 0x10},
270f520bb22SYouMin Chen 	{0x15, 0x6, 0x11},
271f520bb22SYouMin Chen 	{0x16, 0x7, 0x12},
272f520bb22SYouMin Chen 	{0x17, 0x8, 0x13},
273f520bb22SYouMin Chen 	{0x18, 0x0, 0xb},
274f520bb22SYouMin Chen 	{0x19, 0x9, 0x14},
275f520bb22SYouMin Chen 	{0x1a, 0xa, 0x15}
276f520bb22SYouMin Chen };
277f520bb22SYouMin Chen 
278f520bb22SYouMin Chen static u16 grp_addr[4] = {
279f520bb22SYouMin Chen 	ADD_GROUP_CS0_A,
280f520bb22SYouMin Chen 	ADD_GROUP_CS0_B,
281f520bb22SYouMin Chen 	ADD_GROUP_CS1_A,
282f520bb22SYouMin Chen 	ADD_GROUP_CS1_B
283f520bb22SYouMin Chen };
284f520bb22SYouMin Chen 
285f520bb22SYouMin Chen static u8 wrlvl_result_offset[2][4] = {
286f520bb22SYouMin Chen 	{0xa0 + 0x26, 0xa0 + 0x27, 0xd0 + 0x26, 0xd0 + 0x27},
287f520bb22SYouMin Chen 	{0xa0 + 0x28, 0xa0 + 0x29, 0xd0 + 0x28, 0xd0 + 0x29},
288f520bb22SYouMin Chen };
289f520bb22SYouMin Chen 
290f520bb22SYouMin Chen static u16 dqs_dq_skew_adr[16] = {
291f520bb22SYouMin Chen 	0x170 + 0,	/* SKEW_UPDATE_RX_CS0_DQS0 */
292f520bb22SYouMin Chen 	0x170 + 0xb,	/* SKEW_UPDATE_RX_CS0_DQS1 */
293f520bb22SYouMin Chen 	0x1d0 + 0,	/* SKEW_UPDATE_RX_CS0_DQS2 */
294f520bb22SYouMin Chen 	0x1d0 + 0xb,	/* SKEW_UPDATE_RX_CS0_DQS3 */
295f520bb22SYouMin Chen 	0x1a0 + 0,	/* SKEW_UPDATE_RX_CS1_DQS0 */
296f520bb22SYouMin Chen 	0x1a0 + 0xb,	/* SKEW_UPDATE_RX_CS1_DQS1 */
297f520bb22SYouMin Chen 	0x200 + 0,	/* SKEW_UPDATE_RX_CS1_DQS2 */
298f520bb22SYouMin Chen 	0x200 + 0xb,	/* SKEW_UPDATE_RX_CS1_DQS3 */
299f520bb22SYouMin Chen 	0x170 + 0x16,	/* SKEW_UPDATE_TX_CS0_DQS0 */
300f520bb22SYouMin Chen 	0x170 + 0x21,	/* SKEW_UPDATE_TX_CS0_DQS1 */
301f520bb22SYouMin Chen 	0x1d0 + 0x16,	/* SKEW_UPDATE_TX_CS0_DQS2 */
302f520bb22SYouMin Chen 	0x1d0 + 0x21,	/* SKEW_UPDATE_TX_CS0_DQS3 */
303f520bb22SYouMin Chen 	0x1a0 + 0x16,	/* SKEW_UPDATE_TX_CS1_DQS0 */
304f520bb22SYouMin Chen 	0x1a0 + 0x21,	/* SKEW_UPDATE_TX_CS1_DQS1 */
305f520bb22SYouMin Chen 	0x200 + 0x16,	/* SKEW_UPDATE_TX_CS1_DQS2 */
306f520bb22SYouMin Chen 	0x200 + 0x21,	/* SKEW_UPDATE_TX_CS1_DQS3 */
307f520bb22SYouMin Chen };
308f520bb22SYouMin Chen 
rkclk_ddr_reset(struct dram_info * dram,u32 ctl_srstn,u32 ctl_psrstn,u32 phy_srstn,u32 phy_psrstn)309f520bb22SYouMin Chen static void rkclk_ddr_reset(struct dram_info *dram,
310f520bb22SYouMin Chen 			    u32 ctl_srstn, u32 ctl_psrstn,
311f520bb22SYouMin Chen 			    u32 phy_srstn, u32 phy_psrstn)
312f520bb22SYouMin Chen {
313f520bb22SYouMin Chen 	writel(UPCTL2_SRSTN_REQ(ctl_srstn) | UPCTL2_PSRSTN_REQ(ctl_psrstn) |
314f520bb22SYouMin Chen 	       UPCTL2_ASRSTN_REQ(ctl_srstn),
315f520bb22SYouMin Chen 	       BUS_SGRF_BASE_ADDR + SGRF_SOC_CON13);
316f520bb22SYouMin Chen 
317f520bb22SYouMin Chen 	writel(DDRPHY_SRSTN_REQ(phy_srstn) | DDRPHY_PSRSTN_REQ(phy_psrstn),
318f520bb22SYouMin Chen 	       &dram->cru->softrst_con[12]);
319f520bb22SYouMin Chen }
320f520bb22SYouMin Chen 
rkclk_set_dpll(struct dram_info * dram,unsigned int hz)321f520bb22SYouMin Chen static void rkclk_set_dpll(struct dram_info *dram, unsigned int hz)
322f520bb22SYouMin Chen {
323f520bb22SYouMin Chen 	unsigned int refdiv, postdiv1, postdiv2, fbdiv;
324f520bb22SYouMin Chen 	int delay = 1000;
325f520bb22SYouMin Chen 	u32 mhz = hz / MHz;
3260367dfefSZhihuan He 	struct global_info *gbl_info;
3270367dfefSZhihuan He 	struct sdram_head_info_index_v2 *index =
3280367dfefSZhihuan He 		(struct sdram_head_info_index_v2 *)common_info;
3290367dfefSZhihuan He 	u32 ssmod_info;
3300367dfefSZhihuan He 	u32 dsmpd = 1;
331f520bb22SYouMin Chen 
3320367dfefSZhihuan He 	gbl_info = (struct global_info *)((void *)common_info +
3330367dfefSZhihuan He 		    index->global_index.offset * 4);
3340367dfefSZhihuan He 	ssmod_info = gbl_info->info_2t;
335f520bb22SYouMin Chen 	refdiv = 1;
336f520bb22SYouMin Chen 	if (mhz <= 100) {
337f520bb22SYouMin Chen 		postdiv1 = 6;
338f520bb22SYouMin Chen 		postdiv2 = 4;
339f520bb22SYouMin Chen 	} else if (mhz <= 150) {
340f520bb22SYouMin Chen 		postdiv1 = 4;
341f520bb22SYouMin Chen 		postdiv2 = 4;
342f520bb22SYouMin Chen 	} else if (mhz <= 200) {
343f520bb22SYouMin Chen 		postdiv1 = 6;
344f520bb22SYouMin Chen 		postdiv2 = 2;
345f520bb22SYouMin Chen 	} else if (mhz <= 300) {
346f520bb22SYouMin Chen 		postdiv1 = 4;
347f520bb22SYouMin Chen 		postdiv2 = 2;
348f520bb22SYouMin Chen 	} else if (mhz <= 400) {
349f520bb22SYouMin Chen 		postdiv1 = 6;
350f520bb22SYouMin Chen 		postdiv2 = 1;
351f520bb22SYouMin Chen 	} else {
352f520bb22SYouMin Chen 		postdiv1 = 4;
353f520bb22SYouMin Chen 		postdiv2 = 1;
354f520bb22SYouMin Chen 	}
355f520bb22SYouMin Chen 	fbdiv = (mhz * refdiv * postdiv1 * postdiv2) / 24;
356f520bb22SYouMin Chen 
357f520bb22SYouMin Chen 	writel(DPLL_MODE(CLOCK_FROM_XIN_OSC), &dram->cru->mode);
358f520bb22SYouMin Chen 
359f520bb22SYouMin Chen 	writel(0x1f000000, &dram->cru->clksel_con[64]);
360f520bb22SYouMin Chen 	writel(POSTDIV1(postdiv1) | FBDIV(fbdiv), &dram->cru->pll[1].con0);
3610367dfefSZhihuan He 	/* enable ssmod */
3620367dfefSZhihuan He 	if (PLL_SSMOD_SPREAD(ssmod_info)) {
3630367dfefSZhihuan He 		dsmpd = 0;
3640367dfefSZhihuan He 		clrsetbits_le32(&dram->cru->pll[1].con2,
3650367dfefSZhihuan He 				0xffffff << 0, 0x0 << 0);
3660367dfefSZhihuan He 		writel(SSMOD_SPREAD(PLL_SSMOD_SPREAD(ssmod_info)) |
3670367dfefSZhihuan He 		       SSMOD_DIVVAL(PLL_SSMOD_DIV(ssmod_info)) |
3680367dfefSZhihuan He 		       SSMOD_DOWNSPREAD(PLL_SSMOD_DOWNSPREAD(ssmod_info)) |
3690367dfefSZhihuan He 		       SSMOD_RESET(0) |
3700367dfefSZhihuan He 		       SSMOD_DIS_SSCG(0) |
3710367dfefSZhihuan He 		       SSMOD_BP(0),
3720367dfefSZhihuan He 		       &dram->cru->pll[1].con3);
3730367dfefSZhihuan He 	}
3740367dfefSZhihuan He 	writel(DSMPD(dsmpd) | POSTDIV2(postdiv2) | REFDIV(refdiv),
375f520bb22SYouMin Chen 	       &dram->cru->pll[1].con1);
376f520bb22SYouMin Chen 
377f520bb22SYouMin Chen 	while (delay > 0) {
378f520bb22SYouMin Chen 		udelay(1);
379f520bb22SYouMin Chen 		if (LOCK(readl(&dram->cru->pll[1].con1)))
380f520bb22SYouMin Chen 			break;
381f520bb22SYouMin Chen 		delay--;
382f520bb22SYouMin Chen 	}
383a6422204SWesley Yao 	if (delay <= 0)
384a6422204SWesley Yao 		printascii("ERROR: DPLL lock timeout!\n");
385f520bb22SYouMin Chen 
386f520bb22SYouMin Chen 	writel(DPLL_MODE(CLOCK_FROM_PLL), &dram->cru->mode);
387f520bb22SYouMin Chen }
388f520bb22SYouMin Chen 
rkclk_configure_ddr(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)389f520bb22SYouMin Chen static void rkclk_configure_ddr(struct dram_info *dram,
390f520bb22SYouMin Chen 				struct rv1126_sdram_params *sdram_params)
391f520bb22SYouMin Chen {
3925d4a323cSTang Yun ping 	/* for ddr phy need freq / 2 */
393f520bb22SYouMin Chen 	rkclk_set_dpll(dram, sdram_params->base.ddr_freq * MHZ / 2);
394f520bb22SYouMin Chen }
395f520bb22SYouMin Chen 
396f520bb22SYouMin Chen static unsigned int
calculate_ddrconfig(struct rv1126_sdram_params * sdram_params)397f520bb22SYouMin Chen 	calculate_ddrconfig(struct rv1126_sdram_params *sdram_params)
398f520bb22SYouMin Chen {
399f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
400f520bb22SYouMin Chen 	u32 cs, bw, die_bw, col, row, bank;
401f520bb22SYouMin Chen 	u32 cs1_row;
402f520bb22SYouMin Chen 	u32 i, tmp;
403f520bb22SYouMin Chen 	u32 ddrconf = -1;
404f520bb22SYouMin Chen 	u32 row_3_4;
405f520bb22SYouMin Chen 
406f520bb22SYouMin Chen 	cs = cap_info->rank;
407f520bb22SYouMin Chen 	bw = cap_info->bw;
408f520bb22SYouMin Chen 	die_bw = cap_info->dbw;
409f520bb22SYouMin Chen 	col = cap_info->col;
410f520bb22SYouMin Chen 	row = cap_info->cs0_row;
411f520bb22SYouMin Chen 	cs1_row = cap_info->cs1_row;
412f520bb22SYouMin Chen 	bank = cap_info->bk;
413f520bb22SYouMin Chen 	row_3_4 = cap_info->row_3_4;
414f520bb22SYouMin Chen 
415f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4) {
416f520bb22SYouMin Chen 		if (cs == 2 && row == cs1_row && !row_3_4) {
417f520bb22SYouMin Chen 			tmp = ((row - 13) << 4) | (1 << 3) | (bw << 1) |
418f520bb22SYouMin Chen 			      die_bw;
419f520bb22SYouMin Chen 			for (i = 17; i < 21; i++) {
420f520bb22SYouMin Chen 				if (((tmp & 0xf) ==
421f520bb22SYouMin Chen 				     (ddr4_cfg_2_rbc[i - 10] & 0xf)) &&
422f520bb22SYouMin Chen 				    ((tmp & 0x70) <=
423f520bb22SYouMin Chen 				     (ddr4_cfg_2_rbc[i - 10] & 0x70))) {
424f520bb22SYouMin Chen 					ddrconf = i;
425f520bb22SYouMin Chen 					goto out;
426f520bb22SYouMin Chen 				}
427f520bb22SYouMin Chen 			}
428f520bb22SYouMin Chen 		}
429f520bb22SYouMin Chen 
430f520bb22SYouMin Chen 		tmp = ((cs - 1) << 7) | ((row - 13) << 4) | (bw << 1) | die_bw;
431f520bb22SYouMin Chen 		for (i = 10; i < 21; i++) {
432f520bb22SYouMin Chen 			if (((tmp & 0xf) == (ddr4_cfg_2_rbc[i - 10] & 0xf)) &&
433f520bb22SYouMin Chen 			    ((tmp & 0x70) <= (ddr4_cfg_2_rbc[i - 10] & 0x70)) &&
434f520bb22SYouMin Chen 			    ((tmp & 0x80) <= (ddr4_cfg_2_rbc[i - 10] & 0x80))) {
435f520bb22SYouMin Chen 				ddrconf = i;
436f520bb22SYouMin Chen 				goto out;
437f520bb22SYouMin Chen 			}
438f520bb22SYouMin Chen 		}
439f520bb22SYouMin Chen 	} else {
440f520bb22SYouMin Chen 		if (cs == 2 && row == cs1_row && bank == 3) {
441f520bb22SYouMin Chen 			for (i = 5; i < 8; i++) {
442f520bb22SYouMin Chen 				if (((bw + col - 10) == (ddr_cfg_2_rbc[i] &
443f520bb22SYouMin Chen 							 0x7)) &&
444f520bb22SYouMin Chen 				    ((row - 13) << 5) <= (ddr_cfg_2_rbc[i] &
445f520bb22SYouMin Chen 							  (0x7 << 5))) {
446f520bb22SYouMin Chen 					ddrconf = i;
447f520bb22SYouMin Chen 					goto out;
448f520bb22SYouMin Chen 				}
449f520bb22SYouMin Chen 			}
450f520bb22SYouMin Chen 		}
451f520bb22SYouMin Chen 
452f520bb22SYouMin Chen 		tmp = ((cs - 1) << 8) | ((row - 13) << 5) |
453f520bb22SYouMin Chen 		      ((bw + col - 10) << 0);
454f520bb22SYouMin Chen 		if (bank == 3)
455f520bb22SYouMin Chen 			tmp |= (1 << 3);
456f520bb22SYouMin Chen 
457f520bb22SYouMin Chen 		for (i = 0; i < 9; i++)
458f520bb22SYouMin Chen 			if (((tmp & 0x1f) == (ddr_cfg_2_rbc[i] & 0x1f)) &&
459f520bb22SYouMin Chen 			    ((tmp & (7 << 5)) <=
460f520bb22SYouMin Chen 			     (ddr_cfg_2_rbc[i] & (7 << 5))) &&
461f520bb22SYouMin Chen 			    ((tmp & (1 << 8)) <=
462f520bb22SYouMin Chen 			     (ddr_cfg_2_rbc[i] & (1 << 8)))) {
463f520bb22SYouMin Chen 				ddrconf = i;
464f520bb22SYouMin Chen 				goto out;
465f520bb22SYouMin Chen 			}
4669d5c314bSWesley Yao 
4679d5c314bSWesley Yao 		for (i = 0; i < 7; i++)
4689d5c314bSWesley Yao 			if (((tmp & 0x1f) == (ddr_cfg_2_rbc_p2[i] & 0x1f)) &&
4699d5c314bSWesley Yao 			    ((tmp & (7 << 5)) <=
4709d5c314bSWesley Yao 			     (ddr_cfg_2_rbc_p2[i] & (7 << 5))) &&
4719d5c314bSWesley Yao 			    ((tmp & (1 << 8)) <=
4729d5c314bSWesley Yao 			     (ddr_cfg_2_rbc_p2[i] & (1 << 8)))) {
4739d5c314bSWesley Yao 				ddrconf = i + 22;
4749d5c314bSWesley Yao 				goto out;
4759d5c314bSWesley Yao 			}
4769d5c314bSWesley Yao 
477f520bb22SYouMin Chen 		if (cs == 1 && bank == 3 && row <= 17 &&
478f520bb22SYouMin Chen 		    (col + bw) == 12)
479f520bb22SYouMin Chen 			ddrconf = 23;
480f520bb22SYouMin Chen 	}
481f520bb22SYouMin Chen 
482f520bb22SYouMin Chen out:
483f520bb22SYouMin Chen 	if (ddrconf > 28)
484f520bb22SYouMin Chen 		printascii("calculate ddrconfig error\n");
485f520bb22SYouMin Chen 
486f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4) {
487f520bb22SYouMin Chen 		for (i = 0; i < ARRAY_SIZE(d4_rbc_2_d3_rbc) ; i++) {
488f520bb22SYouMin Chen 			if (ddrconf == d4_rbc_2_d3_rbc[i][0]) {
489f520bb22SYouMin Chen 				if (ddrconf == 21 && row > 16)
490f520bb22SYouMin Chen 					printascii("warn:ddrconf21 row > 16\n");
491f520bb22SYouMin Chen 				else
492f520bb22SYouMin Chen 					ddrconf = d4_rbc_2_d3_rbc[i][1];
493f520bb22SYouMin Chen 				break;
494f520bb22SYouMin Chen 			}
495f520bb22SYouMin Chen 		}
496f520bb22SYouMin Chen 	}
497f520bb22SYouMin Chen 
498f520bb22SYouMin Chen 	return ddrconf;
499f520bb22SYouMin Chen }
500f520bb22SYouMin Chen 
sw_set_req(struct dram_info * dram)501f520bb22SYouMin Chen static void sw_set_req(struct dram_info *dram)
502f520bb22SYouMin Chen {
503f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
504f520bb22SYouMin Chen 
505f520bb22SYouMin Chen 	/* clear sw_done=0 */
506f520bb22SYouMin Chen 	writel(PCTL2_SW_DONE_CLEAR, pctl_base + DDR_PCTL2_SWCTL);
507f520bb22SYouMin Chen }
508f520bb22SYouMin Chen 
sw_set_ack(struct dram_info * dram)509f520bb22SYouMin Chen static void sw_set_ack(struct dram_info *dram)
510f520bb22SYouMin Chen {
511f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
512f520bb22SYouMin Chen 
513f520bb22SYouMin Chen 	/* set sw_done=1 */
514f520bb22SYouMin Chen 	writel(PCTL2_SW_DONE, pctl_base + DDR_PCTL2_SWCTL);
515f520bb22SYouMin Chen 	while (1) {
516f520bb22SYouMin Chen 		/* wait programming done */
517f520bb22SYouMin Chen 		if (readl(pctl_base + DDR_PCTL2_SWSTAT) &
518f520bb22SYouMin Chen 				PCTL2_SW_DONE_ACK)
519f520bb22SYouMin Chen 			break;
520f520bb22SYouMin Chen 	}
521f520bb22SYouMin Chen }
522f520bb22SYouMin Chen 
set_ctl_address_map(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)523f520bb22SYouMin Chen static void set_ctl_address_map(struct dram_info *dram,
524f520bb22SYouMin Chen 				struct rv1126_sdram_params *sdram_params)
525f520bb22SYouMin Chen {
526f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
527f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
528f520bb22SYouMin Chen 	u32 ddrconf = cap_info->ddrconfig;
529f520bb22SYouMin Chen 	u32 i, row;
530f520bb22SYouMin Chen 
531f520bb22SYouMin Chen 	row = cap_info->cs0_row;
532f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4) {
533f520bb22SYouMin Chen 		for (i = 0; i < ARRAY_SIZE(d4_rbc_2_d3_rbc) ; i++) {
534f520bb22SYouMin Chen 			if (ddrconf == d4_rbc_2_d3_rbc[i][1]) {
535f520bb22SYouMin Chen 				ddrconf = d4_rbc_2_d3_rbc[i][0];
536f520bb22SYouMin Chen 				break;
537f520bb22SYouMin Chen 			}
538f520bb22SYouMin Chen 		}
539f520bb22SYouMin Chen 	}
540f520bb22SYouMin Chen 
541d49e7c34SWesley Yao 	if (ddrconf >= ARRAY_SIZE(addrmap)) {
542f520bb22SYouMin Chen 		printascii("set ctl address map fail\n");
543f520bb22SYouMin Chen 		return;
544f520bb22SYouMin Chen 	}
545f520bb22SYouMin Chen 
546f520bb22SYouMin Chen 	sdram_copy_to_reg((u32 *)(pctl_base + DDR_PCTL2_ADDRMAP0),
5471ad4a306SWesley Yao 			  &addrmap[ddrconf][0], ARRAY_SIZE(addrmap[ddrconf]) * 4);
548f520bb22SYouMin Chen 
549f520bb22SYouMin Chen 	/* unused row set to 0xf */
550f520bb22SYouMin Chen 	for (i = 17; i >= row; i--)
551f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6 +
552f520bb22SYouMin Chen 			((i - 12) * 8 / 32) * 4,
553f520bb22SYouMin Chen 			0xf << ((i - 12) * 8 % 32));
554f520bb22SYouMin Chen 
555f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == LPDDR3 && cap_info->row_3_4)
556f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6, 1 << 31);
557f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4 && cap_info->bw == 0x1)
558f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_PCCFG, 1 << 8);
559f520bb22SYouMin Chen 
560f520bb22SYouMin Chen 	if (cap_info->rank == 1)
561f520bb22SYouMin Chen 		clrsetbits_le32(pctl_base + DDR_PCTL2_ADDRMAP0, 0x1f, 0x1f);
562f520bb22SYouMin Chen }
563f520bb22SYouMin Chen 
phy_pll_set(struct dram_info * dram,u32 freq,u32 wait)564f520bb22SYouMin Chen static void phy_pll_set(struct dram_info *dram, u32 freq, u32 wait)
565f520bb22SYouMin Chen {
566f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
567f520bb22SYouMin Chen 	u32 fbdiv, prediv, postdiv, postdiv_en;
568a6422204SWesley Yao 	int delay = 1000;
569f520bb22SYouMin Chen 
570f520bb22SYouMin Chen 	if (wait) {
571f520bb22SYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x53), PHY_PD_DISB);
572a6422204SWesley Yao 		while (!(readl(PHY_REG(phy_base, 0x90)) & PHY_PLL_LOCK)) {
573a6422204SWesley Yao 			udelay(1);
574a6422204SWesley Yao 			if (delay-- <= 0) {
575a6422204SWesley Yao 				printascii("ERROR: phy pll lock timeout!\n");
576a6422204SWesley Yao 				while (1)
577a6422204SWesley Yao 					;
578a6422204SWesley Yao 			}
579a6422204SWesley Yao 		}
580f520bb22SYouMin Chen 	} else {
581f520bb22SYouMin Chen 		freq /= MHz;
582f520bb22SYouMin Chen 		prediv = 1;
583f520bb22SYouMin Chen 		if (freq <= 200) {
584f520bb22SYouMin Chen 			fbdiv = 16;
585f520bb22SYouMin Chen 			postdiv = 2;
586f520bb22SYouMin Chen 			postdiv_en = 1;
587f520bb22SYouMin Chen 		} else if (freq <= 456) {
588f520bb22SYouMin Chen 			fbdiv = 8;
589f520bb22SYouMin Chen 			postdiv = 1;
590f520bb22SYouMin Chen 			postdiv_en = 1;
591f520bb22SYouMin Chen 		} else {
592f520bb22SYouMin Chen 			fbdiv = 4;
593f520bb22SYouMin Chen 			postdiv = 0;
594f520bb22SYouMin Chen 			postdiv_en = 0;
595f520bb22SYouMin Chen 		}
596f520bb22SYouMin Chen 		writel(fbdiv & 0xff, PHY_REG(phy_base, 0x50));
597f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x51), PHY_PBDIV_BIT9_MASK,
598f520bb22SYouMin Chen 				(fbdiv >> 8) & 1);
599f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x51), PHY_POSTDIV_EN_MASK,
600f520bb22SYouMin Chen 				postdiv_en << PHY_POSTDIV_EN_SHIFT);
601f520bb22SYouMin Chen 
602f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x52),
603f520bb22SYouMin Chen 				PHY_PREDIV_MASK << PHY_PREDIV_SHIFT, prediv);
604f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x53),
605f520bb22SYouMin Chen 				PHY_POSTDIV_MASK << PHY_POSTDIV_SHIFT,
606f520bb22SYouMin Chen 				postdiv << PHY_POSTDIV_SHIFT);
607f520bb22SYouMin Chen 	}
608f520bb22SYouMin Chen }
609f520bb22SYouMin Chen 
610f520bb22SYouMin Chen static const u16 d3_phy_drv_2_ohm[][2] = {
61170fee8b3STang Yun ping 	{PHY_DDR3_RON_455ohm, 455},
61270fee8b3STang Yun ping 	{PHY_DDR3_RON_230ohm, 230},
61370fee8b3STang Yun ping 	{PHY_DDR3_RON_153ohm, 153},
61470fee8b3STang Yun ping 	{PHY_DDR3_RON_115ohm, 115},
61570fee8b3STang Yun ping 	{PHY_DDR3_RON_91ohm, 91},
61670fee8b3STang Yun ping 	{PHY_DDR3_RON_76ohm, 76},
61770fee8b3STang Yun ping 	{PHY_DDR3_RON_65ohm, 65},
61870fee8b3STang Yun ping 	{PHY_DDR3_RON_57ohm, 57},
619f520bb22SYouMin Chen 	{PHY_DDR3_RON_51ohm, 51},
620f520bb22SYouMin Chen 	{PHY_DDR3_RON_46ohm, 46},
62170fee8b3STang Yun ping 	{PHY_DDR3_RON_41ohm, 41},
62270fee8b3STang Yun ping 	{PHY_DDR3_RON_38ohm, 38},
62370fee8b3STang Yun ping 	{PHY_DDR3_RON_35ohm, 35},
624f520bb22SYouMin Chen 	{PHY_DDR3_RON_32ohm, 32},
625f520bb22SYouMin Chen 	{PHY_DDR3_RON_30ohm, 30},
626f520bb22SYouMin Chen 	{PHY_DDR3_RON_28ohm, 28},
627f520bb22SYouMin Chen 	{PHY_DDR3_RON_27ohm, 27},
628f520bb22SYouMin Chen 	{PHY_DDR3_RON_25ohm, 25},
629f520bb22SYouMin Chen 	{PHY_DDR3_RON_24ohm, 24},
630f520bb22SYouMin Chen 	{PHY_DDR3_RON_23ohm, 23},
63170fee8b3STang Yun ping 	{PHY_DDR3_RON_22ohm, 22},
63270fee8b3STang Yun ping 	{PHY_DDR3_RON_21ohm, 21},
63370fee8b3STang Yun ping 	{PHY_DDR3_RON_20ohm, 20}
634f520bb22SYouMin Chen };
635f520bb22SYouMin Chen 
636f520bb22SYouMin Chen static u16 d3_phy_odt_2_ohm[][2] = {
637f520bb22SYouMin Chen 	{PHY_DDR3_RTT_DISABLE, 0},
63870fee8b3STang Yun ping 	{PHY_DDR3_RTT_561ohm, 561},
63970fee8b3STang Yun ping 	{PHY_DDR3_RTT_282ohm, 282},
64070fee8b3STang Yun ping 	{PHY_DDR3_RTT_188ohm, 188},
64170fee8b3STang Yun ping 	{PHY_DDR3_RTT_141ohm, 141},
64270fee8b3STang Yun ping 	{PHY_DDR3_RTT_113ohm, 113},
64370fee8b3STang Yun ping 	{PHY_DDR3_RTT_94ohm, 94},
64470fee8b3STang Yun ping 	{PHY_DDR3_RTT_81ohm, 81},
64570fee8b3STang Yun ping 	{PHY_DDR3_RTT_72ohm, 72},
646f520bb22SYouMin Chen 	{PHY_DDR3_RTT_64ohm, 64},
64770fee8b3STang Yun ping 	{PHY_DDR3_RTT_58ohm, 58},
64870fee8b3STang Yun ping 	{PHY_DDR3_RTT_52ohm, 52},
649f520bb22SYouMin Chen 	{PHY_DDR3_RTT_48ohm, 48},
650f520bb22SYouMin Chen 	{PHY_DDR3_RTT_44ohm, 44},
65170fee8b3STang Yun ping 	{PHY_DDR3_RTT_41ohm, 41},
65270fee8b3STang Yun ping 	{PHY_DDR3_RTT_38ohm, 38},
65370fee8b3STang Yun ping 	{PHY_DDR3_RTT_37ohm, 37},
65470fee8b3STang Yun ping 	{PHY_DDR3_RTT_34ohm, 34},
65570fee8b3STang Yun ping 	{PHY_DDR3_RTT_32ohm, 32},
65670fee8b3STang Yun ping 	{PHY_DDR3_RTT_31ohm, 31},
65770fee8b3STang Yun ping 	{PHY_DDR3_RTT_29ohm, 29},
65870fee8b3STang Yun ping 	{PHY_DDR3_RTT_28ohm, 28},
65970fee8b3STang Yun ping 	{PHY_DDR3_RTT_27ohm, 27},
66070fee8b3STang Yun ping 	{PHY_DDR3_RTT_25ohm, 25}
661f520bb22SYouMin Chen };
662f520bb22SYouMin Chen 
663f520bb22SYouMin Chen static u16 d4lp3_phy_drv_2_ohm[][2] = {
66470fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_482ohm, 482},
66570fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_244ohm, 244},
66670fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_162ohm, 162},
66770fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_122ohm, 122},
66870fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_97ohm, 97},
669f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_81ohm, 81},
67070fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_69ohm, 69},
67170fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_61ohm, 61},
67270fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_54ohm, 54},
67370fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_48ohm, 48},
674f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_44ohm, 44},
67570fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_40ohm, 40},
67670fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_37ohm, 37},
677f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_34ohm, 34},
678f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_32ohm, 32},
679f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_30ohm, 30},
680f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_28ohm, 28},
681f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_27ohm, 27},
68270fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_25ohm, 25},
68370fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_24ohm, 24},
68470fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_23ohm, 23},
68570fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_22ohm, 22},
68670fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RON_21ohm, 21}
687f520bb22SYouMin Chen };
688f520bb22SYouMin Chen 
689f520bb22SYouMin Chen static u16 d4lp3_phy_odt_2_ohm[][2] = {
690f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_DISABLE, 0},
69170fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_586ohm, 586},
69270fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_294ohm, 294},
69370fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_196ohm, 196},
69470fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_148ohm, 148},
69570fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_118ohm, 118},
696f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_99ohm, 99},
69770fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_85ohm, 58},
698f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_76ohm, 76},
69970fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_67ohm, 67},
70070fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_60ohm, 60},
701f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_55ohm, 55},
70270fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_50ohm, 50},
70370fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_46ohm, 46},
70470fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_43ohm, 43},
70570fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_40ohm, 40},
70670fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_38ohm, 38},
70770fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_36ohm, 36},
70870fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_34ohm, 34},
70970fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_32ohm, 32},
71070fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_31ohm, 31},
71170fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_29ohm, 29},
71270fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_28ohm, 28},
71370fee8b3STang Yun ping 	{PHY_DDR4_LPDDR3_RTT_27ohm, 27}
714f520bb22SYouMin Chen };
715f520bb22SYouMin Chen 
716f520bb22SYouMin Chen static u16 lp4_phy_drv_2_ohm[][2] = {
71770fee8b3STang Yun ping 	{PHY_LPDDR4_RON_501ohm, 501},
71870fee8b3STang Yun ping 	{PHY_LPDDR4_RON_253ohm, 253},
71970fee8b3STang Yun ping 	{PHY_LPDDR4_RON_168ohm, 168},
72070fee8b3STang Yun ping 	{PHY_LPDDR4_RON_126ohm, 126},
721f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_101ohm, 101},
72270fee8b3STang Yun ping 	{PHY_LPDDR4_RON_84ohm, 84},
72370fee8b3STang Yun ping 	{PHY_LPDDR4_RON_72ohm, 72},
72470fee8b3STang Yun ping 	{PHY_LPDDR4_RON_63ohm, 63},
72570fee8b3STang Yun ping 	{PHY_LPDDR4_RON_56ohm, 56},
72670fee8b3STang Yun ping 	{PHY_LPDDR4_RON_50ohm, 50},
72770fee8b3STang Yun ping 	{PHY_LPDDR4_RON_46ohm, 46},
72870fee8b3STang Yun ping 	{PHY_LPDDR4_RON_42ohm, 42},
729f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_38ohm, 38},
730f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_36ohm, 36},
73170fee8b3STang Yun ping 	{PHY_LPDDR4_RON_33ohm, 33},
73270fee8b3STang Yun ping 	{PHY_LPDDR4_RON_31ohm, 31},
733f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_29ohm, 29},
734f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_28ohm, 28},
73570fee8b3STang Yun ping 	{PHY_LPDDR4_RON_26ohm, 26},
73670fee8b3STang Yun ping 	{PHY_LPDDR4_RON_25ohm, 25},
73770fee8b3STang Yun ping 	{PHY_LPDDR4_RON_24ohm, 24},
73870fee8b3STang Yun ping 	{PHY_LPDDR4_RON_23ohm, 23},
73970fee8b3STang Yun ping 	{PHY_LPDDR4_RON_22ohm, 22}
740f520bb22SYouMin Chen };
741f520bb22SYouMin Chen 
742f520bb22SYouMin Chen static u16 lp4_phy_odt_2_ohm[][2] = {
743f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_DISABLE, 0},
74470fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_604ohm, 604},
74570fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_303ohm, 303},
746f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_202ohm, 202},
74770fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_152ohm, 152},
74870fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_122ohm, 122},
749f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_101ohm, 101},
75070fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_87ohm,	87},
751f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_78ohm, 78},
75270fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_69ohm, 69},
75370fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_62ohm, 62},
754f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_56ohm, 56},
75570fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_52ohm, 52},
756f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_48ohm, 48},
75770fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_44ohm, 44},
75870fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_41ohm, 41},
75970fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_39ohm, 39},
76070fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_37ohm, 37},
76170fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_35ohm, 35},
76270fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_33ohm, 33},
76370fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_32ohm, 32},
76470fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_30ohm, 30},
76570fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_29ohm, 29},
76670fee8b3STang Yun ping 	{PHY_LPDDR4_RTT_27ohm, 27}
767f520bb22SYouMin Chen };
768f520bb22SYouMin Chen 
lp4_odt_calc(u32 odt_ohm)769f520bb22SYouMin Chen static u32 lp4_odt_calc(u32 odt_ohm)
770f520bb22SYouMin Chen {
771f520bb22SYouMin Chen 	u32 odt;
772f520bb22SYouMin Chen 
773f520bb22SYouMin Chen 	if (odt_ohm == 0)
774f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_DIS;
775f520bb22SYouMin Chen 	else if (odt_ohm <= 40)
776f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_40;
777f520bb22SYouMin Chen 	else if (odt_ohm <= 48)
778f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_48;
779f520bb22SYouMin Chen 	else if (odt_ohm <= 60)
780f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_60;
781f520bb22SYouMin Chen 	else if (odt_ohm <= 80)
782f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_80;
783f520bb22SYouMin Chen 	else if (odt_ohm <= 120)
784f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_120;
785f520bb22SYouMin Chen 	else
786f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_240;
787f520bb22SYouMin Chen 
788f520bb22SYouMin Chen 	return odt;
789f520bb22SYouMin Chen }
790f520bb22SYouMin Chen 
get_ddr_drv_odt_info(u32 dramtype)791f520bb22SYouMin Chen static void *get_ddr_drv_odt_info(u32 dramtype)
792f520bb22SYouMin Chen {
793f520bb22SYouMin Chen 	struct sdram_head_info_index_v2 *index =
794f520bb22SYouMin Chen 		(struct sdram_head_info_index_v2 *)common_info;
795f520bb22SYouMin Chen 	void *ddr_info = 0;
796f520bb22SYouMin Chen 
797f520bb22SYouMin Chen 	if (dramtype == DDR4)
798f520bb22SYouMin Chen 		ddr_info = (void *)common_info + index->ddr4_index.offset * 4;
799f520bb22SYouMin Chen 	else if (dramtype == DDR3)
800f520bb22SYouMin Chen 		ddr_info = (void *)common_info + index->ddr3_index.offset * 4;
801f520bb22SYouMin Chen 	else if (dramtype == LPDDR3)
802f520bb22SYouMin Chen 		ddr_info = (void *)common_info + index->lp3_index.offset * 4;
803f520bb22SYouMin Chen 	else if (dramtype == LPDDR4)
804f520bb22SYouMin Chen 		ddr_info = (void *)common_info + index->lp4_index.offset * 4;
805c2a03d5dSZhihuan He 	else if (dramtype == LPDDR4X)
806c2a03d5dSZhihuan He 		ddr_info = (void *)common_info + index->lp4x_index.offset * 4;
807f520bb22SYouMin Chen 	else
808f520bb22SYouMin Chen 		printascii("unsupported dram type\n");
809f520bb22SYouMin Chen 	return ddr_info;
810f520bb22SYouMin Chen }
811f520bb22SYouMin Chen 
set_lp4_vref(struct dram_info * dram,struct lp4_info * lp4_info,u32 freq_mhz,u32 dst_fsp,u32 dramtype)812f520bb22SYouMin Chen static void set_lp4_vref(struct dram_info *dram, struct lp4_info *lp4_info,
813c2a03d5dSZhihuan He 			 u32 freq_mhz, u32 dst_fsp, u32 dramtype)
814f520bb22SYouMin Chen {
815f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
816f520bb22SYouMin Chen 	u32 ca_vref, dq_vref;
817f520bb22SYouMin Chen 
818f520bb22SYouMin Chen 	if (freq_mhz <= LP4_CA_ODT_EN_FREQ(lp4_info->ca_odten_freq))
819f520bb22SYouMin Chen 		ca_vref = LP4_CA_VREF(lp4_info->vref_when_odtoff);
820f520bb22SYouMin Chen 	else
821f520bb22SYouMin Chen 		ca_vref = LP4_CA_VREF(lp4_info->vref_when_odten);
822f520bb22SYouMin Chen 
823f520bb22SYouMin Chen 	if (freq_mhz <= LP4_DQ_ODT_EN_FREQ(lp4_info->dq_odten_freq))
824f520bb22SYouMin Chen 		dq_vref = LP4_DQ_VREF(lp4_info->vref_when_odtoff);
825f520bb22SYouMin Chen 	else
826f520bb22SYouMin Chen 		dq_vref = LP4_DQ_VREF(lp4_info->vref_when_odten);
827f520bb22SYouMin Chen 
828c2a03d5dSZhihuan He 	if (dramtype == LPDDR4) {
829f520bb22SYouMin Chen 		if (ca_vref < 100)
830f520bb22SYouMin Chen 			ca_vref = 100;
831f520bb22SYouMin Chen 		if (ca_vref > 420)
832f520bb22SYouMin Chen 			ca_vref = 420;
833f520bb22SYouMin Chen 
834f520bb22SYouMin Chen 		if (ca_vref <= 300)
835f520bb22SYouMin Chen 			ca_vref = (0 << 6) | (ca_vref - 100) / 4;
836f520bb22SYouMin Chen 		else
837f520bb22SYouMin Chen 			ca_vref = (1 << 6) | (ca_vref - 220) / 4;
838f520bb22SYouMin Chen 
839f520bb22SYouMin Chen 		if (dq_vref < 100)
840f520bb22SYouMin Chen 			dq_vref = 100;
841f520bb22SYouMin Chen 		if (dq_vref > 420)
842f520bb22SYouMin Chen 			dq_vref = 420;
843f520bb22SYouMin Chen 
844f520bb22SYouMin Chen 		if (dq_vref <= 300)
845f520bb22SYouMin Chen 			dq_vref = (0 << 6) | (dq_vref - 100) / 4;
846f520bb22SYouMin Chen 		else
847f520bb22SYouMin Chen 			dq_vref = (1 << 6) | (dq_vref - 220) / 4;
848c2a03d5dSZhihuan He 	} else {
849c2a03d5dSZhihuan He 		ca_vref = ca_vref * 11 / 6;
850c2a03d5dSZhihuan He 		if (ca_vref < 150)
851c2a03d5dSZhihuan He 			ca_vref = 150;
852c2a03d5dSZhihuan He 		if (ca_vref > 629)
853c2a03d5dSZhihuan He 			ca_vref = 629;
854f520bb22SYouMin Chen 
855c2a03d5dSZhihuan He 		if (ca_vref <= 449)
856c2a03d5dSZhihuan He 			ca_vref = (0 << 6) | (ca_vref - 150) / 4;
857c2a03d5dSZhihuan He 		else
858c2a03d5dSZhihuan He 			ca_vref = (1 << 6) | (ca_vref - 329) / 4;
859c2a03d5dSZhihuan He 
860c2a03d5dSZhihuan He 		if (dq_vref < 150)
861c2a03d5dSZhihuan He 			dq_vref = 150;
862c2a03d5dSZhihuan He 		if (dq_vref > 629)
863c2a03d5dSZhihuan He 			dq_vref = 629;
864c2a03d5dSZhihuan He 
865c2a03d5dSZhihuan He 		if (dq_vref <= 449)
866c2a03d5dSZhihuan He 			dq_vref = (0 << 6) | (dq_vref - 150) / 6;
867c2a03d5dSZhihuan He 		else
868c2a03d5dSZhihuan He 			dq_vref = (1 << 6) | (dq_vref - 329) / 6;
869c2a03d5dSZhihuan He 	}
870f520bb22SYouMin Chen 	sw_set_req(dram);
871f520bb22SYouMin Chen 	clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
872f520bb22SYouMin Chen 			DDR_PCTL2_INIT6,
873f520bb22SYouMin Chen 			PCTL2_MR_MASK << PCTL2_LPDDR4_MR12_SHIFT,
874f520bb22SYouMin Chen 			ca_vref << PCTL2_LPDDR4_MR12_SHIFT);
875f520bb22SYouMin Chen 
876f520bb22SYouMin Chen 	clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
877f520bb22SYouMin Chen 			DDR_PCTL2_INIT7,
878f520bb22SYouMin Chen 			PCTL2_MR_MASK << PCTL2_LPDDR4_MR14_SHIFT,
879f520bb22SYouMin Chen 			dq_vref << PCTL2_LPDDR4_MR14_SHIFT);
880f520bb22SYouMin Chen 	sw_set_ack(dram);
881f520bb22SYouMin Chen }
882f520bb22SYouMin Chen 
set_ds_odt(struct dram_info * dram,struct rv1126_sdram_params * sdram_params,u32 dst_fsp)883f520bb22SYouMin Chen static void set_ds_odt(struct dram_info *dram,
884f520bb22SYouMin Chen 		       struct rv1126_sdram_params *sdram_params, u32 dst_fsp)
885f520bb22SYouMin Chen {
886f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
887f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
888f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
889f520bb22SYouMin Chen 	struct ddr2_3_4_lp2_3_info *ddr_info;
890f520bb22SYouMin Chen 	struct lp4_info *lp4_info;
891f520bb22SYouMin Chen 	u32 i, j, tmp;
892f520bb22SYouMin Chen 	const u16 (*p_drv)[2];
893f520bb22SYouMin Chen 	const u16 (*p_odt)[2];
894f520bb22SYouMin Chen 	u32 drv_info, sr_info;
895f520bb22SYouMin Chen 	u32 phy_dq_drv_ohm, phy_clk_drv_ohm, phy_ca_drv_ohm, dram_drv_ohm;
896f520bb22SYouMin Chen 	u32 phy_odt_ohm, dram_odt_ohm;
897f520bb22SYouMin Chen 	u32 lp4_pu_cal, phy_lp4_drv_pd_en;
898f520bb22SYouMin Chen 	u32 phy_odt_up_en, phy_odt_dn_en;
899f520bb22SYouMin Chen 	u32 sr_dq, sr_clk;
900f520bb22SYouMin Chen 	u32 freq = sdram_params->base.ddr_freq;
901f520bb22SYouMin Chen 	u32 mr1_mr3, mr11, mr22, vref_out, vref_inner;
902f520bb22SYouMin Chen 	u32 phy_clk_drv = 0, phy_odt = 0, phy_ca_drv = 0, dram_caodt_ohm = 0;
903f520bb22SYouMin Chen 	u32 phy_dq_drv = 0;
904f520bb22SYouMin Chen 	u32 phy_odt_up = 0, phy_odt_dn = 0;
905f520bb22SYouMin Chen 
906f520bb22SYouMin Chen 	ddr_info = get_ddr_drv_odt_info(dramtype);
907f520bb22SYouMin Chen 	lp4_info = (void *)ddr_info;
908f520bb22SYouMin Chen 
909f520bb22SYouMin Chen 	if (!ddr_info)
910f520bb22SYouMin Chen 		return;
911f520bb22SYouMin Chen 
912f520bb22SYouMin Chen 	/* dram odt en freq control phy drv, dram odt and phy sr */
913f520bb22SYouMin Chen 	if (freq <= DRAMODT_EN_FREQ(ddr_info->odten_freq)) {
914f520bb22SYouMin Chen 		drv_info = ddr_info->drv_when_odtoff;
915f520bb22SYouMin Chen 		dram_odt_ohm = 0;
916f520bb22SYouMin Chen 		sr_info = ddr_info->sr_when_odtoff;
917f520bb22SYouMin Chen 		phy_lp4_drv_pd_en =
918f520bb22SYouMin Chen 			PHY_LP4_DRV_PULLDOWN_EN_ODTOFF(lp4_info->odt_info);
919f520bb22SYouMin Chen 	} else {
920f520bb22SYouMin Chen 		drv_info = ddr_info->drv_when_odten;
921f520bb22SYouMin Chen 		dram_odt_ohm = ODT_INFO_DRAM_ODT(ddr_info->odt_info);
922f520bb22SYouMin Chen 		sr_info = ddr_info->sr_when_odten;
923f520bb22SYouMin Chen 		phy_lp4_drv_pd_en =
924f520bb22SYouMin Chen 			PHY_LP4_DRV_PULLDOWN_EN_ODTEN(lp4_info->odt_info);
925f520bb22SYouMin Chen 	}
926f520bb22SYouMin Chen 	phy_dq_drv_ohm =
927f520bb22SYouMin Chen 		DRV_INFO_PHY_DQ_DRV(drv_info);
928f520bb22SYouMin Chen 	phy_clk_drv_ohm =
929f520bb22SYouMin Chen 		DRV_INFO_PHY_CLK_DRV(drv_info);
930f520bb22SYouMin Chen 	phy_ca_drv_ohm =
931f520bb22SYouMin Chen 		DRV_INFO_PHY_CA_DRV(drv_info);
932f520bb22SYouMin Chen 
933f520bb22SYouMin Chen 	sr_dq = DQ_SR_INFO(sr_info);
934f520bb22SYouMin Chen 	sr_clk = CLK_SR_INFO(sr_info);
935f520bb22SYouMin Chen 
936f520bb22SYouMin Chen 	/* phy odt en freq control dram drv and phy odt */
937f520bb22SYouMin Chen 	if (freq <= PHYODT_EN_FREQ(ddr_info->odten_freq)) {
938f520bb22SYouMin Chen 		dram_drv_ohm = DRV_INFO_DRAM_DQ_DRV(ddr_info->drv_when_odtoff);
939f520bb22SYouMin Chen 		lp4_pu_cal = LP4_DRV_PU_CAL_ODTOFF(lp4_info->odt_info);
940f520bb22SYouMin Chen 		phy_odt_ohm = 0;
941f520bb22SYouMin Chen 		phy_odt_up_en = 0;
942f520bb22SYouMin Chen 		phy_odt_dn_en = 0;
943f520bb22SYouMin Chen 	} else {
944f520bb22SYouMin Chen 		dram_drv_ohm =
945f520bb22SYouMin Chen 			DRV_INFO_DRAM_DQ_DRV(ddr_info->drv_when_odten);
946f520bb22SYouMin Chen 		phy_odt_ohm = ODT_INFO_PHY_ODT(ddr_info->odt_info);
947f520bb22SYouMin Chen 		phy_odt_up_en =
948f520bb22SYouMin Chen 			ODT_INFO_PULLUP_EN(ddr_info->odt_info);
949f520bb22SYouMin Chen 		phy_odt_dn_en =
950f520bb22SYouMin Chen 			ODT_INFO_PULLDOWN_EN(ddr_info->odt_info);
951f520bb22SYouMin Chen 		lp4_pu_cal = LP4_DRV_PU_CAL_ODTEN(lp4_info->odt_info);
952f520bb22SYouMin Chen 	}
953f520bb22SYouMin Chen 
954c2a03d5dSZhihuan He 	if (dramtype == LPDDR4 || dramtype == LPDDR4X) {
955f520bb22SYouMin Chen 		if (phy_odt_ohm) {
956f520bb22SYouMin Chen 			phy_odt_up_en = 0;
957f520bb22SYouMin Chen 			phy_odt_dn_en = 1;
958f520bb22SYouMin Chen 		}
959f520bb22SYouMin Chen 		if (freq <= LP4_CA_ODT_EN_FREQ(lp4_info->ca_odten_freq))
960f520bb22SYouMin Chen 			dram_caodt_ohm = 0;
961f520bb22SYouMin Chen 		else
962f520bb22SYouMin Chen 			dram_caodt_ohm =
963f520bb22SYouMin Chen 				ODT_INFO_LP4_CA_ODT(lp4_info->odt_info);
964f520bb22SYouMin Chen 	}
965f520bb22SYouMin Chen 
966f520bb22SYouMin Chen 	if (dramtype == DDR3) {
967f520bb22SYouMin Chen 		p_drv = d3_phy_drv_2_ohm;
968f520bb22SYouMin Chen 		p_odt = d3_phy_odt_2_ohm;
969c2a03d5dSZhihuan He 	} else if (dramtype == LPDDR4 || dramtype == LPDDR4X) {
970f520bb22SYouMin Chen 		p_drv = lp4_phy_drv_2_ohm;
971f520bb22SYouMin Chen 		p_odt = lp4_phy_odt_2_ohm;
972f520bb22SYouMin Chen 	} else {
973f520bb22SYouMin Chen 		p_drv = d4lp3_phy_drv_2_ohm;
974f520bb22SYouMin Chen 		p_odt = d4lp3_phy_odt_2_ohm;
975f520bb22SYouMin Chen 	}
976f520bb22SYouMin Chen 
977f520bb22SYouMin Chen 	for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
978f520bb22SYouMin Chen 		if (phy_dq_drv_ohm <= *(*(p_drv + i) + 1)) {
979f520bb22SYouMin Chen 			phy_dq_drv = **(p_drv + i);
980f520bb22SYouMin Chen 			break;
981f520bb22SYouMin Chen 		}
982f520bb22SYouMin Chen 		if (i == 0)
983f520bb22SYouMin Chen 			break;
984f520bb22SYouMin Chen 	}
985f520bb22SYouMin Chen 	for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
986f520bb22SYouMin Chen 		if (phy_clk_drv_ohm <= *(*(p_drv + i) + 1)) {
987f520bb22SYouMin Chen 			phy_clk_drv = **(p_drv + i);
988f520bb22SYouMin Chen 			break;
989f520bb22SYouMin Chen 		}
990f520bb22SYouMin Chen 		if (i == 0)
991f520bb22SYouMin Chen 			break;
992f520bb22SYouMin Chen 	}
993f520bb22SYouMin Chen 	for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
994f520bb22SYouMin Chen 		if (phy_ca_drv_ohm <= *(*(p_drv + i) + 1)) {
995f520bb22SYouMin Chen 			phy_ca_drv = **(p_drv + i);
996f520bb22SYouMin Chen 			break;
997f520bb22SYouMin Chen 		}
998f520bb22SYouMin Chen 		if (i == 0)
999f520bb22SYouMin Chen 			break;
1000f520bb22SYouMin Chen 	}
1001f520bb22SYouMin Chen 	if (!phy_odt_ohm)
1002f520bb22SYouMin Chen 		phy_odt = 0;
1003f520bb22SYouMin Chen 	else
1004f520bb22SYouMin Chen 		for (i = ARRAY_SIZE(d4lp3_phy_odt_2_ohm) - 1; ; i--) {
1005f520bb22SYouMin Chen 			if (phy_odt_ohm <= *(*(p_odt + i) + 1)) {
1006f520bb22SYouMin Chen 				phy_odt = **(p_odt + i);
1007f520bb22SYouMin Chen 				break;
1008f520bb22SYouMin Chen 			}
1009f520bb22SYouMin Chen 			if (i == 0)
1010f520bb22SYouMin Chen 				break;
1011f520bb22SYouMin Chen 		}
1012f520bb22SYouMin Chen 
1013c2a03d5dSZhihuan He 	if (dramtype != LPDDR4 && dramtype != LPDDR4X) {
1014f520bb22SYouMin Chen 		if (!phy_odt_ohm || (phy_odt_up_en && phy_odt_dn_en))
1015f520bb22SYouMin Chen 			vref_inner = 0x80;
1016f520bb22SYouMin Chen 		else if (phy_odt_up_en)
1017f520bb22SYouMin Chen 			vref_inner = (2 * dram_drv_ohm + phy_odt_ohm) * 128 /
1018f520bb22SYouMin Chen 				     (dram_drv_ohm + phy_odt_ohm);
1019f520bb22SYouMin Chen 		else
1020f520bb22SYouMin Chen 			vref_inner = phy_odt_ohm * 128 /
1021f520bb22SYouMin Chen 				(phy_odt_ohm + dram_drv_ohm);
1022f520bb22SYouMin Chen 
1023f520bb22SYouMin Chen 		if (dramtype != DDR3 && dram_odt_ohm)
1024f520bb22SYouMin Chen 			vref_out = (2 * phy_dq_drv_ohm + dram_odt_ohm) * 128 /
1025f520bb22SYouMin Chen 				   (phy_dq_drv_ohm + dram_odt_ohm);
1026f520bb22SYouMin Chen 		else
1027f520bb22SYouMin Chen 			vref_out = 0x80;
1028f520bb22SYouMin Chen 	} else {
1029c2a03d5dSZhihuan He 		/* for lp4 and lp4x*/
1030f520bb22SYouMin Chen 		if (phy_odt_ohm)
1031f520bb22SYouMin Chen 			vref_inner =
1032f520bb22SYouMin Chen 				(PHY_LP4_DQ_VREF(lp4_info->vref_when_odten) *
1033f520bb22SYouMin Chen 				 256) / 1000;
1034f520bb22SYouMin Chen 		else
1035f520bb22SYouMin Chen 			vref_inner =
1036f520bb22SYouMin Chen 				(PHY_LP4_DQ_VREF(lp4_info->vref_when_odtoff) *
1037f520bb22SYouMin Chen 				 256) / 1000;
1038f520bb22SYouMin Chen 
1039f520bb22SYouMin Chen 		vref_out = 0x80;
1040f520bb22SYouMin Chen 	}
1041f520bb22SYouMin Chen 
1042f520bb22SYouMin Chen 	/* default ZQCALIB bypass mode */
1043f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x100), 0x1f, phy_ca_drv);
1044f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x101), 0x1f, phy_ca_drv);
1045f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x102), 0x1f, phy_clk_drv);
1046f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x103), 0x1f, phy_clk_drv);
1047c2a03d5dSZhihuan He 	if (dramtype == LPDDR4 || dramtype == LPDDR4X) {
1048a5033de0STang Yun ping 		clrsetbits_le32(PHY_REG(phy_base, 0x107), 0x1f, phy_clk_drv);
1049a5033de0STang Yun ping 		clrsetbits_le32(PHY_REG(phy_base, 0x108), 0x1f, phy_clk_drv);
1050a5033de0STang Yun ping 	} else {
1051a5033de0STang Yun ping 		clrsetbits_le32(PHY_REG(phy_base, 0x107), 0x1f, phy_ca_drv);
1052a5033de0STang Yun ping 		clrsetbits_le32(PHY_REG(phy_base, 0x108), 0x1f, phy_ca_drv);
1053a5033de0STang Yun ping 	}
1054f520bb22SYouMin Chen 	/* clk / cmd slew rate */
1055f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x106), 0x1f, sr_clk);
1056f520bb22SYouMin Chen 
1057f520bb22SYouMin Chen 	phy_lp4_drv_pd_en = (~phy_lp4_drv_pd_en) & 1;
1058f520bb22SYouMin Chen 	if (phy_odt_up_en)
1059f520bb22SYouMin Chen 		phy_odt_up = phy_odt;
1060f520bb22SYouMin Chen 	if (phy_odt_dn_en)
1061f520bb22SYouMin Chen 		phy_odt_dn = phy_odt;
1062f520bb22SYouMin Chen 
1063f520bb22SYouMin Chen 	for (i = 0; i < 4; i++) {
1064f520bb22SYouMin Chen 		j = 0x110 + i * 0x10;
1065f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, j + 1), 0x1f, phy_odt_up);
1066f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, j), 0x1f, phy_odt_dn);
1067f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, j + 2), 0x1f, phy_dq_drv);
1068f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, j + 3), 0x1f, phy_dq_drv);
1069f520bb22SYouMin Chen 		writel(vref_inner, PHY_REG(phy_base, 0x118 + i * 0x10));
1070f520bb22SYouMin Chen 
1071f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x114 + i * 0x10),
1072f520bb22SYouMin Chen 				1 << 3, phy_lp4_drv_pd_en << 3);
107306a17b4aSWesley Yao 		if (dramtype == LPDDR4 || dramtype == LPDDR4X)
107406a17b4aSWesley Yao 			clrbits_le32(PHY_REG(phy_base, 0x114 + i * 0x10), BIT(5));
1075f520bb22SYouMin Chen 		/* dq slew rate */
1076f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x117 + i * 0x10),
1077f520bb22SYouMin Chen 				0x1f, sr_dq);
1078f520bb22SYouMin Chen 	}
1079f520bb22SYouMin Chen 
1080f520bb22SYouMin Chen 	/* reg_rx_vref_value_update */
1081f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
1082f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
1083f520bb22SYouMin Chen 
1084f520bb22SYouMin Chen 	/* RAM VREF */
1085f520bb22SYouMin Chen 	writel(vref_out, PHY_REG(phy_base, 0x105));
1086d3f5f12cSTang Yun ping 	if (dramtype == LPDDR3)
1087d3f5f12cSTang Yun ping 		udelay(100);
1088f520bb22SYouMin Chen 
1089c2a03d5dSZhihuan He 	if (dramtype == LPDDR4 || dramtype == LPDDR4X)
1090c2a03d5dSZhihuan He 		set_lp4_vref(dram, lp4_info, freq, dst_fsp, dramtype);
1091f520bb22SYouMin Chen 
1092f520bb22SYouMin Chen 	if (dramtype == DDR3 || dramtype == DDR4) {
1093f520bb22SYouMin Chen 		mr1_mr3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1094f520bb22SYouMin Chen 				DDR_PCTL2_INIT3);
1095f520bb22SYouMin Chen 		mr1_mr3 = mr1_mr3 >> PCTL2_DDR34_MR1_SHIFT & PCTL2_MR_MASK;
1096f520bb22SYouMin Chen 	} else {
1097f520bb22SYouMin Chen 		mr1_mr3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1098f520bb22SYouMin Chen 				DDR_PCTL2_INIT4);
1099f520bb22SYouMin Chen 		mr1_mr3 = mr1_mr3 >> PCTL2_LPDDR234_MR3_SHIFT & PCTL2_MR_MASK;
1100f520bb22SYouMin Chen 	}
1101f520bb22SYouMin Chen 
1102f520bb22SYouMin Chen 	if (dramtype == DDR3) {
1103f520bb22SYouMin Chen 		mr1_mr3 &= ~(DDR3_DS_MASK | DDR3_RTT_NOM_MASK);
1104f520bb22SYouMin Chen 		if (dram_drv_ohm == 34)
1105f520bb22SYouMin Chen 			mr1_mr3 |= DDR3_DS_34;
1106f520bb22SYouMin Chen 
1107f520bb22SYouMin Chen 		if (dram_odt_ohm == 0)
1108f520bb22SYouMin Chen 			mr1_mr3 |= DDR3_RTT_NOM_DIS;
1109f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 40)
1110f520bb22SYouMin Chen 			mr1_mr3 |= DDR3_RTT_NOM_40;
1111f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 60)
1112f520bb22SYouMin Chen 			mr1_mr3 |= DDR3_RTT_NOM_60;
1113f520bb22SYouMin Chen 		else
1114f520bb22SYouMin Chen 			mr1_mr3 |= DDR3_RTT_NOM_120;
1115f520bb22SYouMin Chen 
1116f520bb22SYouMin Chen 	} else if (dramtype == DDR4) {
1117f520bb22SYouMin Chen 		mr1_mr3 &= ~(DDR4_DS_MASK | DDR4_RTT_NOM_MASK);
1118f520bb22SYouMin Chen 		if (dram_drv_ohm == 48)
1119f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_DS_48;
1120f520bb22SYouMin Chen 
1121f520bb22SYouMin Chen 		if (dram_odt_ohm == 0)
1122f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_DIS;
1123f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 34)
1124f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_34;
1125f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 40)
1126f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_40;
1127f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 48)
1128f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_48;
1129f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 60)
1130f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_60;
1131f520bb22SYouMin Chen 		else
1132f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_120;
1133f520bb22SYouMin Chen 
1134f520bb22SYouMin Chen 	} else if (dramtype == LPDDR3) {
1135f520bb22SYouMin Chen 		if (dram_drv_ohm <= 34)
1136f520bb22SYouMin Chen 			mr1_mr3 |= LPDDR3_DS_34;
1137f520bb22SYouMin Chen 		else if (dram_drv_ohm <= 40)
1138f520bb22SYouMin Chen 			mr1_mr3 |= LPDDR3_DS_40;
1139f520bb22SYouMin Chen 		else if (dram_drv_ohm <= 48)
1140f520bb22SYouMin Chen 			mr1_mr3 |= LPDDR3_DS_48;
1141f520bb22SYouMin Chen 		else if (dram_drv_ohm <= 60)
1142f520bb22SYouMin Chen 			mr1_mr3 |= LPDDR3_DS_60;
1143f520bb22SYouMin Chen 		else if (dram_drv_ohm <= 80)
1144f520bb22SYouMin Chen 			mr1_mr3 |= LPDDR3_DS_80;
1145f520bb22SYouMin Chen 
1146f520bb22SYouMin Chen 		if (dram_odt_ohm == 0)
1147f520bb22SYouMin Chen 			lp3_odt_value = LPDDR3_ODT_DIS;
1148f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 60)
1149f520bb22SYouMin Chen 			lp3_odt_value = LPDDR3_ODT_60;
1150f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 120)
1151f520bb22SYouMin Chen 			lp3_odt_value = LPDDR3_ODT_120;
1152f520bb22SYouMin Chen 		else
1153f520bb22SYouMin Chen 			lp3_odt_value = LPDDR3_ODT_240;
1154c2a03d5dSZhihuan He 	} else {/* for lpddr4 and lpddr4x */
1155f520bb22SYouMin Chen 		/* MR3 for lp4 PU-CAL and PDDS */
1156f520bb22SYouMin Chen 		mr1_mr3 &= ~(LPDDR4_PDDS_MASK | LPDDR4_PU_CAL_MASK);
1157f520bb22SYouMin Chen 		mr1_mr3 |= lp4_pu_cal;
1158f520bb22SYouMin Chen 
1159f520bb22SYouMin Chen 		tmp = lp4_odt_calc(dram_drv_ohm);
1160f520bb22SYouMin Chen 		if (!tmp)
1161f520bb22SYouMin Chen 			tmp = LPDDR4_PDDS_240;
1162f520bb22SYouMin Chen 		mr1_mr3 |= (tmp << LPDDR4_PDDS_SHIFT);
1163f520bb22SYouMin Chen 
1164f520bb22SYouMin Chen 		/* MR11 for lp4 ca odt, dq odt set */
1165f520bb22SYouMin Chen 		mr11 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1166f520bb22SYouMin Chen 			     DDR_PCTL2_INIT6);
1167f520bb22SYouMin Chen 		mr11 = mr11 >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK;
1168f520bb22SYouMin Chen 
1169f520bb22SYouMin Chen 		mr11 &= ~(LPDDR4_DQODT_MASK | LPDDR4_CAODT_MASK);
1170f520bb22SYouMin Chen 
1171f520bb22SYouMin Chen 		tmp = lp4_odt_calc(dram_odt_ohm);
1172f520bb22SYouMin Chen 		mr11 |= (tmp << LPDDR4_DQODT_SHIFT);
1173f520bb22SYouMin Chen 
1174f520bb22SYouMin Chen 		tmp = lp4_odt_calc(dram_caodt_ohm);
1175f520bb22SYouMin Chen 		mr11 |= (tmp << LPDDR4_CAODT_SHIFT);
1176f520bb22SYouMin Chen 		sw_set_req(dram);
1177f520bb22SYouMin Chen 		clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1178f520bb22SYouMin Chen 				DDR_PCTL2_INIT6,
1179f520bb22SYouMin Chen 				PCTL2_MR_MASK << PCTL2_LPDDR4_MR11_SHIFT,
1180f520bb22SYouMin Chen 				mr11 << PCTL2_LPDDR4_MR11_SHIFT);
1181f520bb22SYouMin Chen 		sw_set_ack(dram);
1182f520bb22SYouMin Chen 
1183f520bb22SYouMin Chen 		/* MR22 for soc odt/odt-ck/odt-cs/odt-ca */
1184f520bb22SYouMin Chen 		mr22 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1185f520bb22SYouMin Chen 			     DDR_PCTL2_INIT7);
1186f520bb22SYouMin Chen 		mr22 = mr22 >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK;
1187f520bb22SYouMin Chen 		mr22 &= ~LPDDR4_SOC_ODT_MASK;
1188f520bb22SYouMin Chen 
1189f520bb22SYouMin Chen 		tmp = lp4_odt_calc(phy_odt_ohm);
1190f520bb22SYouMin Chen 		mr22 |= tmp;
1191f520bb22SYouMin Chen 		mr22 = mr22 |
1192f520bb22SYouMin Chen 		       (LP4_ODTE_CK_EN(lp4_info->cs_drv_ca_odt_info) <<
1193f520bb22SYouMin Chen 			LPDDR4_ODTE_CK_SHIFT) |
1194f520bb22SYouMin Chen 		       (LP4_ODTE_CS_EN(lp4_info->cs_drv_ca_odt_info) <<
1195f520bb22SYouMin Chen 			LPDDR4_ODTE_CS_SHIFT) |
1196f520bb22SYouMin Chen 		       (LP4_ODTD_CA_EN(lp4_info->cs_drv_ca_odt_info) <<
1197f520bb22SYouMin Chen 			LPDDR4_ODTD_CA_SHIFT);
1198f520bb22SYouMin Chen 
1199f520bb22SYouMin Chen 		sw_set_req(dram);
1200f520bb22SYouMin Chen 		clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1201f520bb22SYouMin Chen 				DDR_PCTL2_INIT7,
1202f520bb22SYouMin Chen 				PCTL2_MR_MASK << PCTL2_LPDDR4_MR22_SHIFT,
1203f520bb22SYouMin Chen 				mr22 << PCTL2_LPDDR4_MR22_SHIFT);
1204f520bb22SYouMin Chen 		sw_set_ack(dram);
1205f520bb22SYouMin Chen 	}
1206f520bb22SYouMin Chen 
1207f520bb22SYouMin Chen 	if (dramtype == DDR4 || dramtype == DDR3) {
1208f520bb22SYouMin Chen 		sw_set_req(dram);
1209f520bb22SYouMin Chen 		clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1210f520bb22SYouMin Chen 				DDR_PCTL2_INIT3,
1211f520bb22SYouMin Chen 				PCTL2_MR_MASK << PCTL2_DDR34_MR1_SHIFT,
1212f520bb22SYouMin Chen 				mr1_mr3 << PCTL2_DDR34_MR1_SHIFT);
1213f520bb22SYouMin Chen 		sw_set_ack(dram);
1214f520bb22SYouMin Chen 	} else {
1215f520bb22SYouMin Chen 		sw_set_req(dram);
1216f520bb22SYouMin Chen 		clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1217f520bb22SYouMin Chen 				DDR_PCTL2_INIT4,
1218f520bb22SYouMin Chen 				PCTL2_MR_MASK << PCTL2_LPDDR234_MR3_SHIFT,
1219f520bb22SYouMin Chen 				mr1_mr3 << PCTL2_LPDDR234_MR3_SHIFT);
1220f520bb22SYouMin Chen 		sw_set_ack(dram);
1221f520bb22SYouMin Chen 	}
1222f520bb22SYouMin Chen }
1223f520bb22SYouMin Chen 
sdram_cmd_dq_path_remap(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)1224f520bb22SYouMin Chen static int sdram_cmd_dq_path_remap(struct dram_info *dram,
1225f520bb22SYouMin Chen 				   struct rv1126_sdram_params *sdram_params)
1226f520bb22SYouMin Chen {
1227f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1228f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
1229f520bb22SYouMin Chen 	struct sdram_head_info_index_v2 *index =
1230f520bb22SYouMin Chen 		(struct sdram_head_info_index_v2 *)common_info;
1231f520bb22SYouMin Chen 	struct dq_map_info *map_info;
1232f520bb22SYouMin Chen 
1233f520bb22SYouMin Chen 	map_info = (struct dq_map_info *)((void *)common_info +
1234f520bb22SYouMin Chen 		index->dq_map_index.offset * 4);
1235f520bb22SYouMin Chen 
1236c2a03d5dSZhihuan He 	if (dramtype == LPDDR4X)
1237c2a03d5dSZhihuan He 		dramtype = LPDDR4;
1238c2a03d5dSZhihuan He 
1239f520bb22SYouMin Chen 	if (dramtype <= LPDDR4)
1240f520bb22SYouMin Chen 		writel((map_info->byte_map[dramtype / 4] >>
1241f520bb22SYouMin Chen 			((dramtype % 4) * 8)) & 0xff,
1242f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x4f));
1243f520bb22SYouMin Chen 
1244f520bb22SYouMin Chen 	return 0;
1245f520bb22SYouMin Chen }
1246f520bb22SYouMin Chen 
phy_cfg(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)1247f520bb22SYouMin Chen static void phy_cfg(struct dram_info *dram,
1248f520bb22SYouMin Chen 		    struct rv1126_sdram_params *sdram_params)
1249f520bb22SYouMin Chen {
1250f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
1251f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1252f520bb22SYouMin Chen 	u32 i, dq_map, tmp;
1253f520bb22SYouMin Chen 	u32 byte1 = 0, byte0 = 0;
1254f520bb22SYouMin Chen 
1255f520bb22SYouMin Chen 	sdram_cmd_dq_path_remap(dram, sdram_params);
1256f520bb22SYouMin Chen 
1257f520bb22SYouMin Chen 	phy_pll_set(dram, sdram_params->base.ddr_freq * MHZ, 0);
1258f520bb22SYouMin Chen 	for (i = 0; sdram_params->phy_regs.phy[i][0] != 0xFFFFFFFF; i++) {
1259f520bb22SYouMin Chen 		writel(sdram_params->phy_regs.phy[i][1],
1260f520bb22SYouMin Chen 		       phy_base + sdram_params->phy_regs.phy[i][0]);
1261f520bb22SYouMin Chen 	}
1262f520bb22SYouMin Chen 
1263f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x62), BIT(5));
1264f520bb22SYouMin Chen 	dq_map = readl(PHY_REG(phy_base, 0x4f));
1265f520bb22SYouMin Chen 	for (i = 0; i < 4; i++) {
12660d2a0f8fSWesley Yao 		if (((dq_map >> (i * 2)) & 0x3) == 0) {
1267f520bb22SYouMin Chen 			byte0 = i;
12680d2a0f8fSWesley Yao 			break;
12690d2a0f8fSWesley Yao 		}
12700d2a0f8fSWesley Yao 	}
12710d2a0f8fSWesley Yao 	for (i = 0; i < 4; i++) {
12720d2a0f8fSWesley Yao 		if (((dq_map >> (i * 2)) & 0x3) == 1) {
1273f520bb22SYouMin Chen 			byte1 = i;
12740d2a0f8fSWesley Yao 			break;
12750d2a0f8fSWesley Yao 		}
1276f520bb22SYouMin Chen 	}
1277f520bb22SYouMin Chen 
1278f520bb22SYouMin Chen 	tmp = readl(PHY_REG(phy_base, 0xf)) & (~PHY_DQ_WIDTH_MASK);
1279f520bb22SYouMin Chen 	if (cap_info->bw == 2)
1280f520bb22SYouMin Chen 		tmp |= 0xf;
1281f520bb22SYouMin Chen 	else if (cap_info->bw == 1)
1282f520bb22SYouMin Chen 		tmp |= ((1 << byte0) | (1 << byte1));
1283f520bb22SYouMin Chen 	else
1284f520bb22SYouMin Chen 		tmp |= (1 << byte0);
1285f520bb22SYouMin Chen 
1286f520bb22SYouMin Chen 	writel(tmp, PHY_REG(phy_base, 0xf));
1287f520bb22SYouMin Chen 
1288f520bb22SYouMin Chen 	/* lpddr4 odt control by phy, enable cs0 odt */
1289c2a03d5dSZhihuan He 	if (sdram_params->base.dramtype == LPDDR4 ||
1290c2a03d5dSZhihuan He 	    sdram_params->base.dramtype == LPDDR4X)
1291f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x20), 0x7 << 4,
1292f520bb22SYouMin Chen 				(1 << 6) | (1 << 4));
1293f520bb22SYouMin Chen 	/* for ca training ca vref choose range1 */
1294f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x1e), BIT(6));
1295f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x1f), BIT(6));
1296f520bb22SYouMin Chen 	/* for wr training PHY_0x7c[5], choose range0 */
1297f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x7c), BIT(5));
1298f520bb22SYouMin Chen }
1299f520bb22SYouMin Chen 
update_refresh_reg(struct dram_info * dram)1300f520bb22SYouMin Chen static int update_refresh_reg(struct dram_info *dram)
1301f520bb22SYouMin Chen {
1302f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1303f520bb22SYouMin Chen 	u32 ret;
1304f520bb22SYouMin Chen 
1305f520bb22SYouMin Chen 	ret = readl(pctl_base + DDR_PCTL2_RFSHCTL3) ^ (1 << 1);
1306f520bb22SYouMin Chen 	writel(ret, pctl_base + DDR_PCTL2_RFSHCTL3);
1307f520bb22SYouMin Chen 
1308f520bb22SYouMin Chen 	return 0;
1309f520bb22SYouMin Chen }
1310f520bb22SYouMin Chen 
1311f520bb22SYouMin Chen /*
1312f520bb22SYouMin Chen  * rank = 1: cs0
1313f520bb22SYouMin Chen  * rank = 2: cs1
1314f520bb22SYouMin Chen  */
read_mr(struct dram_info * dram,u32 rank,u32 byte,u32 mr_num,u32 dramtype)131568a0f633SWesley Yao u32 read_mr(struct dram_info *dram, u32 rank, u32 byte, u32 mr_num, u32 dramtype)
1316f520bb22SYouMin Chen {
1317f520bb22SYouMin Chen 	u32 ret;
1318f520bb22SYouMin Chen 	u32 i, temp;
1319f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
132068a0f633SWesley Yao 	struct sdram_head_info_index_v2 *index;
1321f520bb22SYouMin Chen 	struct dq_map_info *map_info;
1322f520bb22SYouMin Chen 
1323f520bb22SYouMin Chen 	pctl_read_mr(pctl_base, rank, mr_num);
1324f520bb22SYouMin Chen 
132568a0f633SWesley Yao 	if (dramtype != LPDDR4 && dramtype != LPDDR4X) {
132668a0f633SWesley Yao 		temp = (readl(&dram->ddrgrf->ddr_grf_status[0]) >> (byte * 8)) & 0xff;
132768a0f633SWesley Yao 
132868a0f633SWesley Yao 		if (byte == 0) {
132968a0f633SWesley Yao 			index = (struct sdram_head_info_index_v2 *)common_info;
133068a0f633SWesley Yao 			map_info = (struct dq_map_info *)((void *)common_info +
133168a0f633SWesley Yao 							  index->dq_map_index.offset * 4);
1332181bc465SWesley Yao 			ret = 0;
1333181bc465SWesley Yao 			for (i = 0; i < 8; i++)
133468a0f633SWesley Yao 				ret |= ((temp >> i) & 0x1) <<
133568a0f633SWesley Yao 				       ((map_info->lp3_dq0_7_map >> (i * 4)) & 0xf);
1336f520bb22SYouMin Chen 		} else {
133768a0f633SWesley Yao 			ret = temp;
133868a0f633SWesley Yao 		}
133968a0f633SWesley Yao 	} else {
134068a0f633SWesley Yao 		ret = (readl(&dram->ddrgrf->ddr_grf_status[1]) >> (byte * 8)) & 0xff;
1341f520bb22SYouMin Chen 	}
1342f520bb22SYouMin Chen 
1343181bc465SWesley Yao 	return ret;
1344f520bb22SYouMin Chen }
1345f520bb22SYouMin Chen 
enter_sr(struct dram_info * dram,u32 en)1346f4f57f8eSTang Yun ping static void enter_sr(struct dram_info *dram, u32 en)
1347f4f57f8eSTang Yun ping {
1348f4f57f8eSTang Yun ping 	void __iomem *pctl_base = dram->pctl;
1349f4f57f8eSTang Yun ping 
1350f4f57f8eSTang Yun ping 	if (en) {
1351f4f57f8eSTang Yun ping 		setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, PCTL2_SELFREF_SW);
1352f4f57f8eSTang Yun ping 		while (1) {
1353f4f57f8eSTang Yun ping 			if (((readl(pctl_base + DDR_PCTL2_STAT) &
1354f4f57f8eSTang Yun ping 			      PCTL2_SELFREF_TYPE_MASK) ==
1355f4f57f8eSTang Yun ping 			     PCTL2_SELFREF_TYPE_SR_NOT_AUTO) &&
1356f4f57f8eSTang Yun ping 			    ((readl(pctl_base + DDR_PCTL2_STAT) &
1357f4f57f8eSTang Yun ping 			      PCTL2_OPERATING_MODE_MASK) ==
1358f4f57f8eSTang Yun ping 			     PCTL2_OPERATING_MODE_SR))
1359f4f57f8eSTang Yun ping 				break;
1360f4f57f8eSTang Yun ping 		}
1361f4f57f8eSTang Yun ping 	} else {
1362f4f57f8eSTang Yun ping 		clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, PCTL2_SELFREF_SW);
1363f4f57f8eSTang Yun ping 		while ((readl(pctl_base + DDR_PCTL2_STAT) &
1364f4f57f8eSTang Yun ping 		       PCTL2_OPERATING_MODE_MASK) == PCTL2_OPERATING_MODE_SR)
1365f4f57f8eSTang Yun ping 			continue;
1366f4f57f8eSTang Yun ping 	}
1367f4f57f8eSTang Yun ping }
1368f4f57f8eSTang Yun ping 
record_dq_prebit(struct dram_info * dram)1369f520bb22SYouMin Chen void record_dq_prebit(struct dram_info *dram)
1370f520bb22SYouMin Chen {
1371f520bb22SYouMin Chen 	u32 group, i, tmp;
1372f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1373f520bb22SYouMin Chen 
1374f520bb22SYouMin Chen 	for (group = 0; group < 4; group++) {
1375f520bb22SYouMin Chen 		for (i = 0; i < ARRAY_SIZE(dq_sel); i++) {
1376f520bb22SYouMin Chen 			/* l_loop_invdelaysel */
1377f520bb22SYouMin Chen 			writel(dq_sel[i][0], PHY_REG(phy_base,
1378f520bb22SYouMin Chen 						     grp_addr[group] + 0x2c));
1379f520bb22SYouMin Chen 			tmp = readl(PHY_REG(phy_base, grp_addr[group] + 0x2e));
1380f520bb22SYouMin Chen 			writel(tmp, PHY_REG(phy_base,
1381f520bb22SYouMin Chen 					    grp_addr[group] + dq_sel[i][1]));
1382f520bb22SYouMin Chen 
1383f520bb22SYouMin Chen 			/* r_loop_invdelaysel */
1384f520bb22SYouMin Chen 			writel(dq_sel[i][0], PHY_REG(phy_base,
1385f520bb22SYouMin Chen 						     grp_addr[group] + 0x2d));
1386f520bb22SYouMin Chen 			tmp = readl(PHY_REG(phy_base, grp_addr[group] + 0x2f));
1387f520bb22SYouMin Chen 			writel(tmp, PHY_REG(phy_base,
1388f520bb22SYouMin Chen 					    grp_addr[group] + dq_sel[i][2]));
1389f520bb22SYouMin Chen 		}
1390f520bb22SYouMin Chen 	}
1391f520bb22SYouMin Chen }
1392f520bb22SYouMin Chen 
update_dq_rx_prebit(struct dram_info * dram)1393f520bb22SYouMin Chen static void update_dq_rx_prebit(struct dram_info *dram)
1394f520bb22SYouMin Chen {
1395f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1396f520bb22SYouMin Chen 
1397f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x70), BIT(1) | BIT(6) | BIT(4),
1398f520bb22SYouMin Chen 			BIT(4));
1399f520bb22SYouMin Chen 	udelay(1);
1400f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x70), BIT(4));
1401f520bb22SYouMin Chen }
1402f520bb22SYouMin Chen 
update_dq_tx_prebit(struct dram_info * dram)1403f520bb22SYouMin Chen static void update_dq_tx_prebit(struct dram_info *dram)
1404f520bb22SYouMin Chen {
1405f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1406f520bb22SYouMin Chen 
1407f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
1408f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x2), BIT(3));
1409f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0xc), BIT(6));
1410f520bb22SYouMin Chen 	udelay(1);
1411f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0xc), BIT(6));
1412f520bb22SYouMin Chen }
1413f520bb22SYouMin Chen 
update_ca_prebit(struct dram_info * dram)1414f520bb22SYouMin Chen static void update_ca_prebit(struct dram_info *dram)
1415f520bb22SYouMin Chen {
1416f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1417f520bb22SYouMin Chen 
1418f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x25), BIT(2));
1419f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x22), BIT(6));
1420f520bb22SYouMin Chen 	udelay(1);
1421f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x22), BIT(6));
1422f520bb22SYouMin Chen }
1423f520bb22SYouMin Chen 
1424f520bb22SYouMin Chen /*
1425f520bb22SYouMin Chen  * dir: 0: de-skew = delta_*
1426f520bb22SYouMin Chen  *	1: de-skew = reg val - delta_*
1427f520bb22SYouMin Chen  * delta_dir: value for differential signal: clk/
1428f520bb22SYouMin Chen  * delta_sig: value for single signal: ca/cmd
1429f520bb22SYouMin Chen  */
modify_ca_deskew(struct dram_info * dram,u32 dir,int delta_dif,int delta_sig,u32 cs,u32 dramtype)1430f520bb22SYouMin Chen static void modify_ca_deskew(struct dram_info *dram, u32 dir, int delta_dif,
1431f520bb22SYouMin Chen 			     int delta_sig, u32 cs, u32 dramtype)
1432f520bb22SYouMin Chen {
1433f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1434f520bb22SYouMin Chen 	u32 i, cs_en, tmp;
1435f4f57f8eSTang Yun ping 	u32 dfi_lp_stat = 0;
1436f520bb22SYouMin Chen 
1437f520bb22SYouMin Chen 	if (cs == 0)
1438f520bb22SYouMin Chen 		cs_en = 1;
1439f520bb22SYouMin Chen 	else if (cs == 2)
1440f520bb22SYouMin Chen 		cs_en = 2;
1441f520bb22SYouMin Chen 	else
1442f520bb22SYouMin Chen 		cs_en = 3;
1443f520bb22SYouMin Chen 
1444c2a03d5dSZhihuan He 	if ((dramtype == LPDDR4 || dramtype == LPDDR4X) &&
1445f4f57f8eSTang Yun ping 	    ((readl(PHY_REG(phy_base, 0x60)) & BIT(5)) == 0)) {
1446f4f57f8eSTang Yun ping 		dfi_lp_stat = 1;
1447f4f57f8eSTang Yun ping 		setbits_le32(PHY_REG(phy_base, 0x60), BIT(5));
1448f4f57f8eSTang Yun ping 	}
1449f4f57f8eSTang Yun ping 	enter_sr(dram, 1);
1450f4f57f8eSTang Yun ping 
1451f520bb22SYouMin Chen 	for (i = 0; i < 0x20; i++) {
1452f520bb22SYouMin Chen 		if (dir == DESKEW_MDF_ABS_VAL)
1453f520bb22SYouMin Chen 			tmp = delta_sig;
1454f520bb22SYouMin Chen 		else
1455f520bb22SYouMin Chen 			tmp = readl(PHY_REG(phy_base, 0x150 + i)) +
1456f520bb22SYouMin Chen 			      delta_sig;
1457f520bb22SYouMin Chen 		writel(tmp, PHY_REG(phy_base, 0x150 + i));
1458f520bb22SYouMin Chen 	}
1459f520bb22SYouMin Chen 
1460f520bb22SYouMin Chen 	if (dir == DESKEW_MDF_ABS_VAL)
1461f520bb22SYouMin Chen 		tmp = delta_dif;
1462f520bb22SYouMin Chen 	else
1463f520bb22SYouMin Chen 		tmp = readl(PHY_REG(phy_base, 0x150 + 0x17)) -
1464f520bb22SYouMin Chen 		       delta_sig + delta_dif;
1465f520bb22SYouMin Chen 	writel(tmp, PHY_REG(phy_base, 0x150 + 0x17));
1466f520bb22SYouMin Chen 	writel(tmp, PHY_REG(phy_base, 0x150 + 0x18));
1467c2a03d5dSZhihuan He 	if (dramtype == LPDDR4 || dramtype == LPDDR4X) {
1468f520bb22SYouMin Chen 		writel(tmp, PHY_REG(phy_base, 0x150 + 0x4));
1469f520bb22SYouMin Chen 		writel(tmp, PHY_REG(phy_base, 0x150 + 0xa));
1470f520bb22SYouMin Chen 
1471f520bb22SYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x10), cs_en << 6);
1472f520bb22SYouMin Chen 		update_ca_prebit(dram);
1473f520bb22SYouMin Chen 	}
1474f4f57f8eSTang Yun ping 	enter_sr(dram, 0);
1475f4f57f8eSTang Yun ping 
1476f4f57f8eSTang Yun ping 	if (dfi_lp_stat)
1477f4f57f8eSTang Yun ping 		clrbits_le32(PHY_REG(phy_base, 0x60), BIT(5));
1478f4f57f8eSTang Yun ping 
1479f520bb22SYouMin Chen }
1480f520bb22SYouMin Chen 
get_min_value(struct dram_info * dram,u32 signal,u32 rank)1481f520bb22SYouMin Chen static u32 get_min_value(struct dram_info *dram, u32 signal, u32 rank)
1482f520bb22SYouMin Chen {
1483f520bb22SYouMin Chen 	u32 i, j, offset = 0;
1484f520bb22SYouMin Chen 	u32 min = 0x3f;
1485f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1486f520bb22SYouMin Chen 	u32 byte_en;
1487f520bb22SYouMin Chen 
1488f520bb22SYouMin Chen 	if (signal == SKEW_TX_SIGNAL)
1489f520bb22SYouMin Chen 		offset = 8;
1490f520bb22SYouMin Chen 
1491f520bb22SYouMin Chen 	if (signal == SKEW_CA_SIGNAL) {
1492f520bb22SYouMin Chen 		for (i = 0; i < 0x20; i++)
1493f520bb22SYouMin Chen 			min = MIN(min, readl(PHY_REG(phy_base, 0x150  + i)));
1494f520bb22SYouMin Chen 	} else {
1495f520bb22SYouMin Chen 		byte_en = readl(PHY_REG(phy_base, 0xf)) & 0xf;
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 < 11; i++)
1500f520bb22SYouMin Chen 				min = MIN(min,
1501f520bb22SYouMin Chen 					  readl(PHY_REG(phy_base,
1502f520bb22SYouMin Chen 							dqs_dq_skew_adr[j] +
1503f520bb22SYouMin Chen 							i)));
1504f520bb22SYouMin Chen 		}
1505f520bb22SYouMin Chen 	}
1506f520bb22SYouMin Chen 
1507f520bb22SYouMin Chen 	return min;
1508f520bb22SYouMin Chen }
1509f520bb22SYouMin Chen 
low_power_update(struct dram_info * dram,u32 en)1510f520bb22SYouMin Chen static u32 low_power_update(struct dram_info *dram, u32 en)
1511f520bb22SYouMin Chen {
1512f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1513f520bb22SYouMin Chen 	u32 lp_stat = 0;
1514f520bb22SYouMin Chen 
1515f520bb22SYouMin Chen 	if (en) {
1516f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, en & 0xf);
1517f520bb22SYouMin Chen 	} else {
1518f520bb22SYouMin Chen 		lp_stat = readl(pctl_base + DDR_PCTL2_PWRCTL) & 0xf;
1519f520bb22SYouMin Chen 		clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 0xf);
1520f520bb22SYouMin Chen 	}
1521f520bb22SYouMin Chen 
1522f520bb22SYouMin Chen 	return lp_stat;
1523f520bb22SYouMin Chen }
1524f520bb22SYouMin Chen 
1525f520bb22SYouMin Chen /*
1526f520bb22SYouMin Chen  * signal:
1527f520bb22SYouMin Chen  * dir: 0: de-skew = delta_*
1528f520bb22SYouMin Chen  *	1: de-skew = reg val - delta_*
1529f520bb22SYouMin Chen  * delta_dir: value for differential signal: dqs
1530f520bb22SYouMin Chen  * delta_sig: value for single signal: dq/dm
1531f520bb22SYouMin Chen  */
modify_dq_deskew(struct dram_info * dram,u32 signal,u32 dir,int delta_dif,int delta_sig,u32 rank)1532f520bb22SYouMin Chen static void modify_dq_deskew(struct dram_info *dram, u32 signal, u32 dir,
1533f520bb22SYouMin Chen 			     int delta_dif, int delta_sig, u32 rank)
1534f520bb22SYouMin Chen {
1535f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1536f520bb22SYouMin Chen 	u32 i, j, tmp, offset;
1537f520bb22SYouMin Chen 	u32 byte_en;
1538f520bb22SYouMin Chen 
1539f520bb22SYouMin Chen 	byte_en = readl(PHY_REG(phy_base, 0xf)) & 0xf;
1540f520bb22SYouMin Chen 
1541f520bb22SYouMin Chen 	if (signal == SKEW_RX_SIGNAL)
1542f520bb22SYouMin Chen 		offset = 0;
1543f520bb22SYouMin Chen 	else
1544f520bb22SYouMin Chen 		offset = 8;
1545f520bb22SYouMin Chen 
1546f520bb22SYouMin Chen 	for (j = offset; j < (offset + rank * 4); j++) {
1547f520bb22SYouMin Chen 		if (!((byte_en >> (j % 4)) & 1))
1548f520bb22SYouMin Chen 			continue;
1549f520bb22SYouMin Chen 		for (i = 0; i < 0x9; i++) {
1550f520bb22SYouMin Chen 			if (dir == DESKEW_MDF_ABS_VAL)
1551f520bb22SYouMin Chen 				tmp = delta_sig;
1552f520bb22SYouMin Chen 			else
1553f520bb22SYouMin Chen 				tmp = delta_sig + readl(PHY_REG(phy_base,
1554f520bb22SYouMin Chen 							dqs_dq_skew_adr[j] +
1555f520bb22SYouMin Chen 							i));
1556f520bb22SYouMin Chen 			writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + i));
1557f520bb22SYouMin Chen 		}
1558f520bb22SYouMin Chen 		if (dir == DESKEW_MDF_ABS_VAL)
1559f520bb22SYouMin Chen 			tmp = delta_dif;
1560f520bb22SYouMin Chen 		else
1561f520bb22SYouMin Chen 			tmp = delta_dif + readl(PHY_REG(phy_base,
1562f520bb22SYouMin Chen 						dqs_dq_skew_adr[j] + 9));
1563f520bb22SYouMin Chen 		writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + 9));
1564f520bb22SYouMin Chen 		writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + 0xa));
1565f520bb22SYouMin Chen 	}
1566f520bb22SYouMin Chen 	if (signal == SKEW_RX_SIGNAL)
1567f520bb22SYouMin Chen 		update_dq_rx_prebit(dram);
1568f520bb22SYouMin Chen 	else
1569f520bb22SYouMin Chen 		update_dq_tx_prebit(dram);
1570f520bb22SYouMin Chen }
1571f520bb22SYouMin Chen 
data_training_rg(struct dram_info * dram,u32 cs,u32 dramtype)1572f520bb22SYouMin Chen static int data_training_rg(struct dram_info *dram, u32 cs, u32 dramtype)
1573f520bb22SYouMin Chen {
1574f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1575f520bb22SYouMin Chen 	u32 ret;
1576f520bb22SYouMin Chen 	u32 dis_auto_zq = 0;
1577f520bb22SYouMin Chen 	u32 odt_val_up, odt_val_dn;
1578f520bb22SYouMin Chen 	u32 i, j;
1579dfa73e58SWesley Yao #if defined(DDR4_READ_GATE_2NCK_PREAMBLE)
1580dfa73e58SWesley Yao 	void __iomem *pctl_base = dram->pctl;
1581dfa73e58SWesley Yao 	u32 mr4_d4 = 0;
1582dfa73e58SWesley Yao #endif
1583f520bb22SYouMin Chen 
1584f520bb22SYouMin Chen 	odt_val_dn = readl(PHY_REG(phy_base, 0x110));
1585f520bb22SYouMin Chen 	odt_val_up = readl(PHY_REG(phy_base, 0x111));
1586f520bb22SYouMin Chen 
1587c2a03d5dSZhihuan He 	if (dramtype != LPDDR4 || dramtype != LPDDR4X) {
1588f520bb22SYouMin Chen 		for (i = 0; i < 4; i++) {
1589f520bb22SYouMin Chen 			j = 0x110 + i * 0x10;
159070fee8b3STang Yun ping 			writel(PHY_DDR4_LPDDR3_RTT_294ohm,
1591f520bb22SYouMin Chen 			       PHY_REG(phy_base, j));
1592f520bb22SYouMin Chen 			writel(PHY_DDR4_LPDDR3_RTT_DISABLE,
1593f520bb22SYouMin Chen 			       PHY_REG(phy_base, j + 0x1));
1594f520bb22SYouMin Chen 		}
1595f520bb22SYouMin Chen 	}
1596f520bb22SYouMin Chen 	dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
1597f520bb22SYouMin Chen 	/* use normal read mode for data training */
1598f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0xc), BIT(1));
1599f520bb22SYouMin Chen 
1600dfa73e58SWesley Yao 	if (dramtype == DDR4) {
1601dfa73e58SWesley Yao #if defined(DDR4_READ_GATE_PREAMBLE_MODE)
16022c5208e2STang Yun ping 		setbits_le32(PHY_REG(phy_base, 0xc), BIT(1));
1603dfa73e58SWesley Yao #elif defined(DDR4_READ_GATE_2NCK_PREAMBLE)
1604dfa73e58SWesley Yao 		mr4_d4 = readl(pctl_base + DDR_PCTL2_INIT6) >> PCTL2_DDR4_MR4_SHIFT & PCTL2_MR_MASK;
1605dfa73e58SWesley Yao 		/* 2nCK Read Preamble */
1606dfa73e58SWesley Yao 		pctl_write_mr(pctl_base, BIT(cs), 4, mr4_d4 | BIT(11), DDR4);
1607dfa73e58SWesley Yao #endif
1608dfa73e58SWesley Yao 	}
1609f520bb22SYouMin Chen 
1610f520bb22SYouMin Chen 	/* choose training cs */
1611f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs));
1612f520bb22SYouMin Chen 	/* enable gate training */
1613f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1);
1614f520bb22SYouMin Chen 	udelay(50);
1615f520bb22SYouMin Chen 	ret = readl(PHY_REG(phy_base, 0x91));
1616f520bb22SYouMin Chen 	/* disable gate training */
1617f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0);
1618f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 2), 0x30);
1619f520bb22SYouMin Chen 	pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
1620f520bb22SYouMin Chen 
1621dfa73e58SWesley Yao #if defined(DDR4_READ_GATE_2NCK_PREAMBLE)
1622dfa73e58SWesley Yao 	if (dramtype == DDR4) {
1623dfa73e58SWesley Yao 		pctl_write_mr(pctl_base, BIT(cs), 4, mr4_d4, DDR4);
1624dfa73e58SWesley Yao 	}
1625dfa73e58SWesley Yao #endif
1626dfa73e58SWesley Yao 
16279080840aSWesley Yao 	ret = (ret & 0x2f) ^ (readl(PHY_REG(phy_base, 0xf)) & 0xf);
1628f520bb22SYouMin Chen 
1629c2a03d5dSZhihuan He 	if (dramtype != LPDDR4 || dramtype != LPDDR4X) {
1630f520bb22SYouMin Chen 		for (i = 0; i < 4; i++) {
1631f520bb22SYouMin Chen 			j = 0x110 + i * 0x10;
1632f520bb22SYouMin Chen 			writel(odt_val_dn, PHY_REG(phy_base, j));
1633f520bb22SYouMin Chen 			writel(odt_val_up, PHY_REG(phy_base, j + 0x1));
1634f520bb22SYouMin Chen 		}
1635f520bb22SYouMin Chen 	}
1636f520bb22SYouMin Chen 	return ret;
1637f520bb22SYouMin Chen }
1638f520bb22SYouMin Chen 
data_training_wl(struct dram_info * dram,u32 cs,u32 dramtype,u32 rank)1639f520bb22SYouMin Chen static int data_training_wl(struct dram_info *dram, u32 cs, u32 dramtype,
1640f520bb22SYouMin Chen 			    u32 rank)
1641f520bb22SYouMin Chen {
1642f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1643f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1644f520bb22SYouMin Chen 	u32 dis_auto_zq = 0;
1645f520bb22SYouMin Chen 	u32 tmp;
1646f520bb22SYouMin Chen 	u32 cur_fsp;
1647f520bb22SYouMin Chen 	u32 timeout_us = 1000;
1648f520bb22SYouMin Chen 
1649f520bb22SYouMin Chen 	dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
1650f520bb22SYouMin Chen 
1651f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x7a), 0x1);
1652f520bb22SYouMin Chen 
1653f520bb22SYouMin Chen 	cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
1654f520bb22SYouMin Chen 	tmp = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + DDR_PCTL2_INIT3) &
1655f520bb22SYouMin Chen 	      0xffff;
1656f520bb22SYouMin Chen 	writel(tmp & 0xff, PHY_REG(phy_base, 0x3));
1657f520bb22SYouMin Chen 
1658f520bb22SYouMin Chen 	/* disable another cs's output */
1659f520bb22SYouMin Chen 	if ((dramtype == DDR3 || dramtype == DDR4) && rank == 2)
1660f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, (cs + 1) & 1, 1, tmp | (1 << 12),
1661f520bb22SYouMin Chen 			      dramtype);
1662f520bb22SYouMin Chen 	if (dramtype == DDR3 || dramtype == DDR4)
1663f520bb22SYouMin Chen 		writel(0x40 | ((tmp >> 8) & 0x3f), PHY_REG(phy_base, 0x4));
1664f520bb22SYouMin Chen 	else
1665f520bb22SYouMin Chen 		writel(0x80 | ((tmp >> 8) & 0x3f), PHY_REG(phy_base, 0x4));
1666f520bb22SYouMin Chen 
1667f520bb22SYouMin Chen 	/* choose cs */
1668f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
1669f520bb22SYouMin Chen 			((0x2 >> cs) << 6) | (0 << 2));
1670f520bb22SYouMin Chen 	/* enable write leveling */
1671f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
1672f520bb22SYouMin Chen 			((0x2 >> cs) << 6) | (1 << 2));
1673f520bb22SYouMin Chen 
1674f520bb22SYouMin Chen 	while (1) {
1675f520bb22SYouMin Chen 		if ((readl(PHY_REG(phy_base, 0x92)) & 0xf) ==
1676f520bb22SYouMin Chen 		    (readl(PHY_REG(phy_base, 0xf)) & 0xf))
1677f520bb22SYouMin Chen 			break;
1678f520bb22SYouMin Chen 
1679f520bb22SYouMin Chen 		udelay(1);
1680f520bb22SYouMin Chen 		if (timeout_us-- == 0) {
1681f520bb22SYouMin Chen 			printascii("error: write leveling timeout\n");
1682f520bb22SYouMin Chen 			while (1)
1683f520bb22SYouMin Chen 				;
1684f520bb22SYouMin Chen 		}
1685f520bb22SYouMin Chen 	}
1686f520bb22SYouMin Chen 
1687f520bb22SYouMin Chen 	/* disable write leveling */
1688f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
1689f520bb22SYouMin Chen 			((0x2 >> cs) << 6) | (0 << 2));
1690f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x3 << 6, 0 << 6);
1691f520bb22SYouMin Chen 
1692f520bb22SYouMin Chen 	/* enable another cs's output */
1693f520bb22SYouMin Chen 	if ((dramtype == DDR3 || dramtype == DDR4) && rank == 2)
1694f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, (cs + 1) & 1, 1, tmp & ~(1 << 12),
1695f520bb22SYouMin Chen 			      dramtype);
1696f520bb22SYouMin Chen 
1697f520bb22SYouMin Chen 	pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
1698f520bb22SYouMin Chen 
1699f520bb22SYouMin Chen 	return 0;
1700f520bb22SYouMin Chen }
1701f520bb22SYouMin Chen 
1702f520bb22SYouMin Chen char pattern[32] = {
1703f520bb22SYouMin Chen 	0xaa, 0x55, 0xaa, 0x55, 0x55, 0xaa, 0x55, 0xaa,
1704f520bb22SYouMin Chen 	0x55, 0xaa, 0x55, 0xaa, 0xaa, 0x55, 0xaa, 0x55,
1705f520bb22SYouMin Chen 	0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55,
1706f520bb22SYouMin Chen 	0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa
1707f520bb22SYouMin Chen };
1708f520bb22SYouMin Chen 
data_training_rd(struct dram_info * dram,u32 cs,u32 dramtype,u32 mhz)1709f520bb22SYouMin Chen static int data_training_rd(struct dram_info *dram, u32 cs, u32 dramtype,
1710f520bb22SYouMin Chen 			    u32 mhz)
1711f520bb22SYouMin Chen {
1712f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1713f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1714f520bb22SYouMin Chen 	u32 trefi_1x, trfc_1x;
1715f520bb22SYouMin Chen 	u32 dis_auto_zq = 0;
1716f520bb22SYouMin Chen 	u32 timeout_us = 1000;
1717f520bb22SYouMin Chen 	u32 dqs_default;
1718f520bb22SYouMin Chen 	u32 cur_fsp;
171948c0a787SYouMin Chen 	u32 vref_inner;
1720f520bb22SYouMin Chen 	u32 i;
1721f520bb22SYouMin Chen 	struct sdram_head_info_index_v2 *index =
1722f520bb22SYouMin Chen 		(struct sdram_head_info_index_v2 *)common_info;
1723f520bb22SYouMin Chen 	struct dq_map_info *map_info;
1724f520bb22SYouMin Chen 
172548c0a787SYouMin Chen 	vref_inner = readl(PHY_REG(phy_base, 0x128)) & 0xff;
172648c0a787SYouMin Chen 	if (dramtype == DDR3 && vref_inner == 0x80) {
172748c0a787SYouMin Chen 		for (i = 0; i < 4; i++)
172848c0a787SYouMin Chen 			writel(vref_inner - 0xa,
172948c0a787SYouMin Chen 			       PHY_REG(phy_base, 0x118 + i * 0x10));
173048c0a787SYouMin Chen 
173148c0a787SYouMin Chen 		/* reg_rx_vref_value_update */
173248c0a787SYouMin Chen 		setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
173348c0a787SYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
173448c0a787SYouMin Chen 	}
173548c0a787SYouMin Chen 
1736f520bb22SYouMin Chen 	map_info = (struct dq_map_info *)((void *)common_info +
1737f520bb22SYouMin Chen 		index->dq_map_index.offset * 4);
1738f520bb22SYouMin Chen 	/* only 1cs a time, 0:cs0 1 cs1 */
1739f520bb22SYouMin Chen 	if (cs > 1)
1740f520bb22SYouMin Chen 		return -1;
1741f520bb22SYouMin Chen 
1742f520bb22SYouMin Chen 	dqs_default = 0xf;
1743f520bb22SYouMin Chen 	dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
1744f520bb22SYouMin Chen 
1745f520bb22SYouMin Chen 	cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
1746f520bb22SYouMin Chen 	/* config refresh timing */
1747f520bb22SYouMin Chen 	trefi_1x = ((readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1748f520bb22SYouMin Chen 			   DDR_PCTL2_RFSHTMG) >> 16) & 0xfff) * 32;
1749f520bb22SYouMin Chen 	trfc_1x = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1750f520bb22SYouMin Chen 			DDR_PCTL2_RFSHTMG) & 0x3ff;
1751f520bb22SYouMin Chen 	/* reg_phy_trefi[7:0] and reg_phy_trefi[13:8] */
1752f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x6e), 0xff, trefi_1x & 0xff);
1753f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x6f), 0x3f, (trefi_1x >> 8) & 0x3f);
1754f520bb22SYouMin Chen 	/* reg_phy_trfc */
1755f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x57), 0xff, trfc_1x);
1756f520bb22SYouMin Chen 	/* reg_max_refi_cnt */
1757f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x61), 0xf << 4, 0x8 << 4);
1758f520bb22SYouMin Chen 
1759f520bb22SYouMin Chen 	/* choose training cs */
1760f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x71), 0x3 << 6, (0x2 >> cs) << 6);
1761f520bb22SYouMin Chen 
1762f520bb22SYouMin Chen 	/* set dq map for ddr4 */
1763f520bb22SYouMin Chen 	if (dramtype == DDR4) {
1764f520bb22SYouMin Chen 		setbits_le32(PHY_REG(phy_base, 0x70), BIT(7));
1765f520bb22SYouMin Chen 		for (i = 0; i < 4; i++) {
1766f520bb22SYouMin Chen 			writel((map_info->ddr4_dq_map[cs * 2] >>
1767f520bb22SYouMin Chen 				((i % 4) * 8)) & 0xff,
1768f520bb22SYouMin Chen 				PHY_REG(phy_base, 0x238 + i));
1769f520bb22SYouMin Chen 			writel((map_info->ddr4_dq_map[cs * 2 + 1] >>
1770f520bb22SYouMin Chen 				((i % 4) * 8)) & 0xff,
1771f520bb22SYouMin Chen 				PHY_REG(phy_base, 0x2b8 + i));
1772f520bb22SYouMin Chen 		}
1773f520bb22SYouMin Chen 	}
1774f520bb22SYouMin Chen 
1775f520bb22SYouMin Chen 	/* cha_l reg_l_rd_train_dqs_default[5:0] */
1776f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x230), 0x3f, dqs_default);
1777f520bb22SYouMin Chen 	/* cha_h reg_h_rd_train_dqs_default[5:0] */
1778f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x234), 0x3f, dqs_default);
1779f520bb22SYouMin Chen 	/* chb_l reg_l_rd_train_dqs_default[5:0] */
1780f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x2b0), 0x3f, dqs_default);
1781f520bb22SYouMin Chen 	/* chb_h reg_h_rd_train_dqs_default[5:0] */
1782f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x2b4), 0x3f, dqs_default);
1783f520bb22SYouMin Chen 
1784f520bb22SYouMin Chen 	/* Choose the read train auto mode */
1785f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x70), 0x3, 0x1);
1786f520bb22SYouMin Chen 	/* Enable the auto train of the read train */
1787f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x70), 0x3, 0x3);
1788f520bb22SYouMin Chen 
1789f520bb22SYouMin Chen 	/* Wait the train done. */
1790f520bb22SYouMin Chen 	while (1) {
1791f520bb22SYouMin Chen 		if ((readl(PHY_REG(phy_base, 0x93)) >> 7) & 0x1)
1792f520bb22SYouMin Chen 			break;
1793f520bb22SYouMin Chen 
1794f520bb22SYouMin Chen 		udelay(1);
1795f520bb22SYouMin Chen 		if (timeout_us-- == 0) {
1796f520bb22SYouMin Chen 			printascii("error: read training timeout\n");
1797f520bb22SYouMin Chen 			return -1;
1798f520bb22SYouMin Chen 		}
1799f520bb22SYouMin Chen 	}
1800f520bb22SYouMin Chen 
1801f520bb22SYouMin Chen 	/* Check the read train state */
1802f520bb22SYouMin Chen 	if ((readl(PHY_REG(phy_base, 0x240)) & 0x3) ||
1803f520bb22SYouMin Chen 	    (readl(PHY_REG(phy_base, 0x2c0)) & 0x3)) {
1804f520bb22SYouMin Chen 		printascii("error: read training error\n");
1805f520bb22SYouMin Chen 		return -1;
1806f520bb22SYouMin Chen 	}
1807f520bb22SYouMin Chen 
1808f520bb22SYouMin Chen 	/* Exit the Read Training by setting */
1809f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x70), BIT(1));
1810f520bb22SYouMin Chen 
1811f520bb22SYouMin Chen 	pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
1812f520bb22SYouMin Chen 
181348c0a787SYouMin Chen 	if (dramtype == DDR3 && vref_inner == 0x80) {
181448c0a787SYouMin Chen 		for (i = 0; i < 4; i++)
181548c0a787SYouMin Chen 			writel(vref_inner,
181648c0a787SYouMin Chen 			       PHY_REG(phy_base, 0x118 + i * 0x10));
181748c0a787SYouMin Chen 
181848c0a787SYouMin Chen 		/* reg_rx_vref_value_update */
181948c0a787SYouMin Chen 		setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
182048c0a787SYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
182148c0a787SYouMin Chen 	}
182248c0a787SYouMin Chen 
1823f520bb22SYouMin Chen 	return 0;
1824f520bb22SYouMin Chen }
1825f520bb22SYouMin Chen 
data_training_wr(struct dram_info * dram,u32 cs,u32 dramtype,u32 mhz,u32 dst_fsp)1826f520bb22SYouMin Chen static int data_training_wr(struct dram_info *dram, u32 cs, u32 dramtype,
1827f520bb22SYouMin Chen 			    u32 mhz, u32 dst_fsp)
1828f520bb22SYouMin Chen {
1829f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1830f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1831f520bb22SYouMin Chen 	u32 trefi_1x, trfc_1x;
1832f520bb22SYouMin Chen 	u32 dis_auto_zq = 0;
1833f520bb22SYouMin Chen 	u32 timeout_us = 1000;
1834f520bb22SYouMin Chen 	u32 cur_fsp;
1835f520bb22SYouMin Chen 	u32 mr_tmp, cl, cwl, phy_fsp, offset = 0;
1836f520bb22SYouMin Chen 
1837f520bb22SYouMin Chen 	if (dramtype == LPDDR3 && mhz <= 400) {
1838f520bb22SYouMin Chen 		phy_fsp = (readl(PHY_REG(phy_base, 0xc)) >> 0x2) & 0x3;
1839f520bb22SYouMin Chen 		offset = (phy_fsp == 0) ? 0x5 : 0x387 + (phy_fsp - 1) * 3;
1840f520bb22SYouMin Chen 		cl = readl(PHY_REG(phy_base, offset));
1841f520bb22SYouMin Chen 		cwl = readl(PHY_REG(phy_base, offset + 2));
1842f520bb22SYouMin Chen 
1843f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, offset), 0x1f, 0x8);
1844f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, offset + 2), 0x1f, 0x4);
1845f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 2, 0x6, dramtype);
1846f520bb22SYouMin Chen 	}
1847f520bb22SYouMin Chen 
1848f520bb22SYouMin Chen 	dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
1849f520bb22SYouMin Chen 
1850f520bb22SYouMin Chen 	/* PHY_0x7b[7:0] reg_train_col_addr[7:0] */
1851f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7b), 0xff, 0x0);
1852f520bb22SYouMin Chen 	/* PHY_0x7c[4:2] reg_train_ba_addr[2:0] */
1853f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x7 << 2, 0x0 << 2);
1854f520bb22SYouMin Chen 	/* PHY_0x7c[1:0] reg_train_col_addr[9:8] */
1855f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x3, 0x0);
1856f520bb22SYouMin Chen 	/* PHY_0x7d[7:0] reg_train_row_addr[7:0] */
1857f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7d), 0xff, 0x0);
1858f520bb22SYouMin Chen 	/* PHY_0x7e[7:0] reg_train_row_addr[15:8] */
1859f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7e), 0xff, 0x0);
1860f520bb22SYouMin Chen 
1861f520bb22SYouMin Chen 	/* PHY_0x71[3] wrtrain_check_data_value_random_gen */
1862f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x71), BIT(3));
1863f520bb22SYouMin Chen 
1864f520bb22SYouMin Chen 	/* config refresh timing */
1865f520bb22SYouMin Chen 	cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
1866f520bb22SYouMin Chen 	trefi_1x = ((readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1867f520bb22SYouMin Chen 			   DDR_PCTL2_RFSHTMG) >> 16) & 0xfff) * 32;
1868f520bb22SYouMin Chen 	trfc_1x = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1869f520bb22SYouMin Chen 			DDR_PCTL2_RFSHTMG) & 0x3ff;
1870f520bb22SYouMin Chen 	/* reg_phy_trefi[7:0] and reg_phy_trefi[13:8] */
1871f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x6e), 0xff, trefi_1x & 0xff);
1872f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x6f), 0x3f, (trefi_1x >> 8) & 0x3f);
1873f520bb22SYouMin Chen 	/* reg_phy_trfc */
1874f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x57), 0xff, trfc_1x);
1875f520bb22SYouMin Chen 	/* reg_max_refi_cnt */
1876f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x61), 0xf << 4, 0x8 << 4);
1877f520bb22SYouMin Chen 
1878f520bb22SYouMin Chen 	/* choose training cs */
1879f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x3 << 6, (0x2 >> cs) << 6);
1880f520bb22SYouMin Chen 
1881f520bb22SYouMin Chen 	/* PHY_0x7a [4] reg_wr_train_dqs_default_bypass */
1882f520bb22SYouMin Chen 	/* 0: Use the write-leveling value. */
1883f520bb22SYouMin Chen 	/* 1: use reg0x233 0x237 0x2b3 0x2b7 */
1884f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x7a), BIT(4));
1885f520bb22SYouMin Chen 
1886f520bb22SYouMin Chen 	/* PHY_0x7a [0] reg_dq_wr_train_auto */
1887f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x7a), 0x1);
1888f520bb22SYouMin Chen 
1889f520bb22SYouMin Chen 	/* PHY_0x7a [1] reg_dq_wr_train_en */
1890f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
1891f520bb22SYouMin Chen 
1892e1652d39SZhihuan He 	send_a_refresh(dram->pctl, 0x3);
1893f520bb22SYouMin Chen 
1894f520bb22SYouMin Chen 	while (1) {
1895f520bb22SYouMin Chen 		if ((readl(PHY_REG(phy_base, 0x92)) >> 7) & 0x1)
1896f520bb22SYouMin Chen 			break;
1897f520bb22SYouMin Chen 
1898f520bb22SYouMin Chen 		udelay(1);
1899f520bb22SYouMin Chen 		if (timeout_us-- == 0) {
1900f520bb22SYouMin Chen 			printascii("error: write training timeout\n");
1901f520bb22SYouMin Chen 			while (1)
1902f520bb22SYouMin Chen 				;
1903f520bb22SYouMin Chen 		}
1904f520bb22SYouMin Chen 	}
1905f520bb22SYouMin Chen 
1906f520bb22SYouMin Chen 	/* Check the write train state */
1907f520bb22SYouMin Chen 	if ((readl(PHY_REG(phy_base, 0x90)) >> 5) & 0x7) {
1908f520bb22SYouMin Chen 		printascii("error: write training error\n");
1909f520bb22SYouMin Chen 		return -1;
1910f520bb22SYouMin Chen 	}
1911f520bb22SYouMin Chen 
1912f520bb22SYouMin Chen 	/* PHY_0x7a [1] reg_dq_wr_train_en */
1913f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
1914f520bb22SYouMin Chen 
1915f520bb22SYouMin Chen 	pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
1916f520bb22SYouMin Chen 
1917c2a03d5dSZhihuan He 	/* save LPDDR4/LPDDR4X write vref to fsp_param for dfs */
1918c2a03d5dSZhihuan He 	if (dramtype == LPDDR4 || dramtype == LPDDR4X) {
1919f520bb22SYouMin Chen 		fsp_param[dst_fsp].vref_dq[cs] =
1920f520bb22SYouMin Chen 			((readl(PHY_REG(phy_base, 0x384)) & 0x3f) +
1921f520bb22SYouMin Chen 			 (readl(PHY_REG(phy_base, 0x385)) & 0x3f)) / 2;
1922f520bb22SYouMin Chen 		/* add range info */
1923f520bb22SYouMin Chen 		fsp_param[dst_fsp].vref_dq[cs] |=
1924f520bb22SYouMin Chen 			((readl(PHY_REG(phy_base, 0x7c)) & BIT(5)) << 1);
1925f520bb22SYouMin Chen 	}
1926f520bb22SYouMin Chen 
1927f520bb22SYouMin Chen 	if (dramtype == LPDDR3 && mhz <= 400) {
1928f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, offset), 0x1f, cl);
1929f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, offset + 2), 0x1f, cwl);
1930f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1931f520bb22SYouMin Chen 			       DDR_PCTL2_INIT3);
1932f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 2, mr_tmp & PCTL2_MR_MASK,
1933f520bb22SYouMin Chen 			      dramtype);
1934f520bb22SYouMin Chen 	}
1935f520bb22SYouMin Chen 
1936f520bb22SYouMin Chen 	return 0;
1937f520bb22SYouMin Chen }
1938f520bb22SYouMin Chen 
data_training(struct dram_info * dram,u32 cs,struct rv1126_sdram_params * sdram_params,u32 dst_fsp,u32 training_flag)1939f520bb22SYouMin Chen static int data_training(struct dram_info *dram, u32 cs,
1940f520bb22SYouMin Chen 			 struct rv1126_sdram_params *sdram_params, u32 dst_fsp,
1941f520bb22SYouMin Chen 			 u32 training_flag)
1942f520bb22SYouMin Chen {
1943f520bb22SYouMin Chen 	u32 ret = 0;
1944f520bb22SYouMin Chen 
1945f520bb22SYouMin Chen 	if (training_flag == FULL_TRAINING)
1946f520bb22SYouMin Chen 		training_flag = READ_GATE_TRAINING | WRITE_LEVELING |
1947f520bb22SYouMin Chen 				WRITE_TRAINING | READ_TRAINING;
1948f520bb22SYouMin Chen 
1949f520bb22SYouMin Chen 	if ((training_flag & WRITE_LEVELING) == WRITE_LEVELING) {
1950f520bb22SYouMin Chen 		ret = data_training_wl(dram, cs,
1951f520bb22SYouMin Chen 				       sdram_params->base.dramtype,
1952f520bb22SYouMin Chen 				       sdram_params->ch.cap_info.rank);
1953f520bb22SYouMin Chen 		if (ret != 0)
1954f520bb22SYouMin Chen 			goto out;
1955f520bb22SYouMin Chen 	}
1956f520bb22SYouMin Chen 
1957f520bb22SYouMin Chen 	if ((training_flag & READ_GATE_TRAINING) == READ_GATE_TRAINING) {
1958f520bb22SYouMin Chen 		ret = data_training_rg(dram, cs,
1959f520bb22SYouMin Chen 				       sdram_params->base.dramtype);
1960f520bb22SYouMin Chen 		if (ret != 0)
1961f520bb22SYouMin Chen 			goto out;
1962f520bb22SYouMin Chen 	}
1963f520bb22SYouMin Chen 
1964f520bb22SYouMin Chen 	if ((training_flag & READ_TRAINING) == READ_TRAINING) {
1965f520bb22SYouMin Chen 		ret = data_training_rd(dram, cs,
1966f520bb22SYouMin Chen 				       sdram_params->base.dramtype,
1967f520bb22SYouMin Chen 				       sdram_params->base.ddr_freq);
1968f520bb22SYouMin Chen 		if (ret != 0)
1969f520bb22SYouMin Chen 			goto out;
1970f520bb22SYouMin Chen 	}
1971f520bb22SYouMin Chen 
1972f520bb22SYouMin Chen 	if ((training_flag & WRITE_TRAINING) == WRITE_TRAINING) {
1973f520bb22SYouMin Chen 		ret = data_training_wr(dram, cs,
1974f520bb22SYouMin Chen 				       sdram_params->base.dramtype,
1975f520bb22SYouMin Chen 				       sdram_params->base.ddr_freq, dst_fsp);
1976f520bb22SYouMin Chen 		if (ret != 0)
1977f520bb22SYouMin Chen 			goto out;
1978f520bb22SYouMin Chen 	}
1979f520bb22SYouMin Chen 
1980f520bb22SYouMin Chen out:
1981f520bb22SYouMin Chen 	return ret;
1982f520bb22SYouMin Chen }
1983f520bb22SYouMin Chen 
get_wrlvl_val(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)1984f520bb22SYouMin Chen static int get_wrlvl_val(struct dram_info *dram,
1985f520bb22SYouMin Chen 			 struct rv1126_sdram_params *sdram_params)
1986f520bb22SYouMin Chen {
198721372cf0SWesley Yao 	int i, j, clk_skew;
1988f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1989f520bb22SYouMin Chen 	u32 lp_stat;
1990f520bb22SYouMin Chen 	int ret;
1991f520bb22SYouMin Chen 
1992f520bb22SYouMin Chen 	lp_stat = low_power_update(dram, 0);
1993f520bb22SYouMin Chen 
1994d5bb9a92STang Yun ping 	clk_skew = 0x1f;
1995d5bb9a92STang Yun ping 	modify_ca_deskew(dram, DESKEW_MDF_ABS_VAL, clk_skew, clk_skew, 3,
1996d5bb9a92STang Yun ping 			 sdram_params->base.dramtype);
1997f520bb22SYouMin Chen 
1998f520bb22SYouMin Chen 	ret = data_training(dram, 0, sdram_params, 0, WRITE_LEVELING);
1999f520bb22SYouMin Chen 	if (sdram_params->ch.cap_info.rank == 2)
2000f520bb22SYouMin Chen 		ret |= data_training(dram, 1, sdram_params, 0, WRITE_LEVELING);
2001f520bb22SYouMin Chen 
2002f520bb22SYouMin Chen 	for (j = 0; j < 2; j++)
2003f520bb22SYouMin Chen 		for (i = 0; i < 4; i++)
2004f520bb22SYouMin Chen 			wrlvl_result[j][i] =
200521372cf0SWesley Yao 				(readl(PHY_REG(phy_base, wrlvl_result_offset[j][i])) & 0x3f) -
2006f520bb22SYouMin Chen 				clk_skew;
2007f520bb22SYouMin Chen 
2008f520bb22SYouMin Chen 	low_power_update(dram, lp_stat);
2009f520bb22SYouMin Chen 
2010f520bb22SYouMin Chen 	return ret;
2011f520bb22SYouMin Chen }
2012f520bb22SYouMin Chen 
2013c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL)
init_rw_trn_result_struct(struct rw_trn_result * result,void __iomem * phy_base,u8 cs_num)2014c71eeac4SWesley Yao static void init_rw_trn_result_struct(struct rw_trn_result *result,
2015c71eeac4SWesley Yao 				      void __iomem *phy_base, u8 cs_num)
2016c71eeac4SWesley Yao {
2017c71eeac4SWesley Yao 	int i;
2018c71eeac4SWesley Yao 
2019c71eeac4SWesley Yao 	result->cs_num = cs_num;
2020c71eeac4SWesley Yao 	result->byte_en = readb(PHY_REG(dram_info.phy, 0xf)) &
2021c71eeac4SWesley Yao 			  PHY_DQ_WIDTH_MASK;
2022c71eeac4SWesley Yao 	for (i = 0; i < FSP_NUM; i++)
2023c71eeac4SWesley Yao 		result->fsp_mhz[i] = 0;
2024c71eeac4SWesley Yao }
2025c71eeac4SWesley Yao 
save_rw_trn_min_max(void __iomem * phy_base,struct cs_rw_trn_result * rd_result,struct cs_rw_trn_result * wr_result,u8 byte_en)2026c71eeac4SWesley Yao static void save_rw_trn_min_max(void __iomem *phy_base,
2027c71eeac4SWesley Yao 				struct cs_rw_trn_result *rd_result,
2028c71eeac4SWesley Yao 				struct cs_rw_trn_result *wr_result,
2029c71eeac4SWesley Yao 				u8 byte_en)
2030c71eeac4SWesley Yao {
2031c71eeac4SWesley Yao 	u16 phy_ofs;
2032c71eeac4SWesley Yao 	u8 dqs;
2033c71eeac4SWesley Yao 	u8 dq;
2034c71eeac4SWesley Yao 
20358889aef0SWesley Yao 	for (dqs = 0; dqs < BYTE_NUM; dqs++) {
20368889aef0SWesley Yao 		if ((byte_en & BIT(dqs)) == 0)
20378889aef0SWesley Yao 			continue;
20388889aef0SWesley Yao 
2039c71eeac4SWesley Yao 		/* Channel A or B (low or high 16 bit) */
2040c71eeac4SWesley Yao 		phy_ofs = dqs < 2 ? 0x230 : 0x2b0;
2041c71eeac4SWesley Yao 		/* low or high 8 bit */
2042c71eeac4SWesley Yao 		phy_ofs += (dqs & 0x1) == 0 ? 0 : 0x9;
2043c71eeac4SWesley Yao 		for (dq = 0; dq < 8; dq++) {
2044c71eeac4SWesley Yao 			rd_result->dqs[dqs].dq_min[dq] =
2045c71eeac4SWesley Yao 				readb(PHY_REG(phy_base, phy_ofs + 0x15 + dq));
2046c71eeac4SWesley Yao 			rd_result->dqs[dqs].dq_max[dq] =
2047c71eeac4SWesley Yao 				readb(PHY_REG(phy_base, phy_ofs + 0x27 + dq));
2048c71eeac4SWesley Yao 			wr_result->dqs[dqs].dq_min[dq] =
2049c71eeac4SWesley Yao 				readb(PHY_REG(phy_base, phy_ofs + 0x3d + dq));
2050c71eeac4SWesley Yao 			wr_result->dqs[dqs].dq_max[dq] =
2051c71eeac4SWesley Yao 				readb(PHY_REG(phy_base, phy_ofs + 0x4f + dq));
2052c71eeac4SWesley Yao 		}
2053c71eeac4SWesley Yao 	}
2054c71eeac4SWesley Yao }
2055c71eeac4SWesley Yao 
save_rw_trn_deskew(void __iomem * phy_base,struct fsp_rw_trn_result * result,u8 cs_num,int min_val,bool rw)2056c71eeac4SWesley Yao static void save_rw_trn_deskew(void __iomem *phy_base,
2057c71eeac4SWesley Yao 			       struct fsp_rw_trn_result *result, u8 cs_num,
2058c71eeac4SWesley Yao 			       int min_val, bool rw)
2059c71eeac4SWesley Yao {
2060c71eeac4SWesley Yao 	u16 phy_ofs;
2061c71eeac4SWesley Yao 	u8 cs;
2062c71eeac4SWesley Yao 	u8 dq;
2063c71eeac4SWesley Yao 
2064c71eeac4SWesley Yao 	result->min_val = min_val;
2065c71eeac4SWesley Yao 
2066c71eeac4SWesley Yao 	for (cs = 0; cs < cs_num; cs++) {
2067c71eeac4SWesley Yao 		phy_ofs = cs == 0 ? 0x170 : 0x1a0;
2068c71eeac4SWesley Yao 		phy_ofs += rw == SKEW_RX_SIGNAL ? 0x1 : 0x17;
2069c71eeac4SWesley Yao 		for (dq = 0; dq < 8; dq++) {
2070c71eeac4SWesley Yao 			result->cs[cs].dqs[0].dq_deskew[dq] =
2071c71eeac4SWesley Yao 				readb(PHY_REG(phy_base, phy_ofs + dq));
2072c71eeac4SWesley Yao 			result->cs[cs].dqs[1].dq_deskew[dq] =
2073c71eeac4SWesley Yao 				readb(PHY_REG(phy_base, phy_ofs + 0xb + dq));
2074c71eeac4SWesley Yao 			result->cs[cs].dqs[2].dq_deskew[dq] =
2075c71eeac4SWesley Yao 				readb(PHY_REG(phy_base, phy_ofs + 0x60 + dq));
2076c71eeac4SWesley Yao 			result->cs[cs].dqs[3].dq_deskew[dq] =
2077c71eeac4SWesley Yao 				readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0xb + dq));
2078c71eeac4SWesley Yao 		}
2079c71eeac4SWesley Yao 
2080c71eeac4SWesley Yao 		result->cs[cs].dqs[0].dqs_deskew =
2081c71eeac4SWesley Yao 			readb(PHY_REG(phy_base, phy_ofs + 0x8));
2082c71eeac4SWesley Yao 		result->cs[cs].dqs[1].dqs_deskew =
2083c71eeac4SWesley Yao 			readb(PHY_REG(phy_base, phy_ofs + 0xb + 0x8));
2084c71eeac4SWesley Yao 		result->cs[cs].dqs[2].dqs_deskew =
2085c71eeac4SWesley Yao 			readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0x8));
2086c71eeac4SWesley Yao 		result->cs[cs].dqs[3].dqs_deskew =
2087c71eeac4SWesley Yao 			readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0xb + 0x8));
2088c71eeac4SWesley Yao 	}
2089c71eeac4SWesley Yao }
2090c71eeac4SWesley Yao 
save_rw_trn_result_to_ddr(struct rw_trn_result * result)2091c71eeac4SWesley Yao static void save_rw_trn_result_to_ddr(struct rw_trn_result *result)
2092c71eeac4SWesley Yao {
20937a110f3aSWesley Yao 	result->flag = DDR_DQ_EYE_FLAG;
2094c71eeac4SWesley Yao 	memcpy((void *)(RW_TRN_RESULT_ADDR), result, sizeof(*result));
2095c71eeac4SWesley Yao }
2096c71eeac4SWesley Yao #endif
2097c71eeac4SWesley Yao 
high_freq_training(struct dram_info * dram,struct rv1126_sdram_params * sdram_params,u32 fsp)2098f520bb22SYouMin Chen static int high_freq_training(struct dram_info *dram,
2099f520bb22SYouMin Chen 			      struct rv1126_sdram_params *sdram_params,
2100f520bb22SYouMin Chen 			      u32 fsp)
2101f520bb22SYouMin Chen {
2102f520bb22SYouMin Chen 	u32 i, j;
2103f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
2104f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
2105f520bb22SYouMin Chen 	int min_val;
2106d5bb9a92STang Yun ping 	int dqs_skew, clk_skew, ca_skew;
210782ad70b5SWesley Yao 	u8 byte_en;
2108f520bb22SYouMin Chen 	int ret;
2109f520bb22SYouMin Chen 
211082ad70b5SWesley Yao 	byte_en = readl(PHY_REG(phy_base, 0xf)) & PHY_DQ_WIDTH_MASK;
2111f520bb22SYouMin Chen 	dqs_skew = 0;
211282ad70b5SWesley Yao 	for (j = 0; j < sdram_params->ch.cap_info.rank; j++) {
211382ad70b5SWesley Yao 		for (i = 0; i < ARRAY_SIZE(wrlvl_result[0]); i++) {
211482ad70b5SWesley Yao 			if ((byte_en & BIT(i)) != 0)
2115f520bb22SYouMin Chen 				dqs_skew += wrlvl_result[j][i];
211682ad70b5SWesley Yao 		}
211782ad70b5SWesley Yao 	}
211821372cf0SWesley Yao 	dqs_skew = dqs_skew /
211921372cf0SWesley Yao 		   (int)(sdram_params->ch.cap_info.rank * (1 << sdram_params->ch.cap_info.bw));
2120f520bb22SYouMin Chen 
2121f520bb22SYouMin Chen 	clk_skew = 0x20 - dqs_skew;
2122f520bb22SYouMin Chen 	dqs_skew = 0x20;
2123f520bb22SYouMin Chen 
2124c2a03d5dSZhihuan He 	if (dramtype == LPDDR4 || dramtype == LPDDR4X) {
2125e90784abSZhihuan He 		min_val = 0xff;
2126e90784abSZhihuan He 		for (j = 0; j < sdram_params->ch.cap_info.rank; j++)
21271911c183SWesley Yao 			for (i = 0; i < ARRAY_SIZE(wrlvl_result[0]); i++) {
21281911c183SWesley Yao 				if ((byte_en & BIT(i)) != 0)
2129e90784abSZhihuan He 					min_val = MIN(wrlvl_result[j][i], min_val);
21301911c183SWesley Yao 			}
2131e90784abSZhihuan He 
2132e90784abSZhihuan He 		if (min_val < 0) {
2133e90784abSZhihuan He 			clk_skew = -min_val;
2134e90784abSZhihuan He 			ca_skew = -min_val;
2135e90784abSZhihuan He 		} else {
2136f520bb22SYouMin Chen 			clk_skew = 0;
2137f520bb22SYouMin Chen 			ca_skew = 0;
2138e90784abSZhihuan He 		}
2139f520bb22SYouMin Chen 	} else if (dramtype == LPDDR3) {
2140f520bb22SYouMin Chen 		ca_skew = clk_skew - 4;
2141f520bb22SYouMin Chen 	} else {
2142f520bb22SYouMin Chen 		ca_skew = clk_skew;
2143f520bb22SYouMin Chen 	}
2144f520bb22SYouMin Chen 	modify_ca_deskew(dram, DESKEW_MDF_ABS_VAL, clk_skew, ca_skew, 3,
2145f520bb22SYouMin Chen 			 dramtype);
2146f520bb22SYouMin Chen 
2147f520bb22SYouMin Chen 	writel(wrlvl_result[0][0] + clk_skew, PHY_REG(phy_base, 0x233));
2148f520bb22SYouMin Chen 	writel(wrlvl_result[0][1] + clk_skew, PHY_REG(phy_base, 0x237));
2149f520bb22SYouMin Chen 	writel(wrlvl_result[0][2] + clk_skew, PHY_REG(phy_base, 0x2b3));
2150f520bb22SYouMin Chen 	writel(wrlvl_result[0][3] + clk_skew, PHY_REG(phy_base, 0x2b7));
2151f520bb22SYouMin Chen 	ret = data_training(dram, 0, sdram_params, fsp, READ_GATE_TRAINING |
2152f520bb22SYouMin Chen 			    READ_TRAINING | WRITE_TRAINING);
2153c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL)
2154c71eeac4SWesley Yao 	rw_trn_result.fsp_mhz[fsp] = (u16)sdram_params->base.ddr_freq;
2155c71eeac4SWesley Yao 	save_rw_trn_min_max(phy_base, &rw_trn_result.rd_fsp[fsp].cs[0],
2156c71eeac4SWesley Yao 			    &rw_trn_result.wr_fsp[fsp].cs[0],
2157c71eeac4SWesley Yao 			    rw_trn_result.byte_en);
2158c71eeac4SWesley Yao #endif
2159f520bb22SYouMin Chen 	if (sdram_params->ch.cap_info.rank == 2) {
2160f520bb22SYouMin Chen 		writel(wrlvl_result[1][0] + clk_skew, PHY_REG(phy_base, 0x233));
2161f520bb22SYouMin Chen 		writel(wrlvl_result[1][1] + clk_skew, PHY_REG(phy_base, 0x237));
2162f520bb22SYouMin Chen 		writel(wrlvl_result[1][2] + clk_skew, PHY_REG(phy_base, 0x2b3));
2163f520bb22SYouMin Chen 		writel(wrlvl_result[1][3] + clk_skew, PHY_REG(phy_base, 0x2b7));
2164f520bb22SYouMin Chen 		ret |= data_training(dram, 1, sdram_params, fsp,
2165f520bb22SYouMin Chen 				     READ_GATE_TRAINING | READ_TRAINING |
2166f520bb22SYouMin Chen 				     WRITE_TRAINING);
2167c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL)
2168c71eeac4SWesley Yao 		save_rw_trn_min_max(phy_base, &rw_trn_result.rd_fsp[fsp].cs[1],
2169c71eeac4SWesley Yao 				    &rw_trn_result.wr_fsp[fsp].cs[1],
2170c71eeac4SWesley Yao 				    rw_trn_result.byte_en);
2171c71eeac4SWesley Yao #endif
2172f520bb22SYouMin Chen 	}
2173f520bb22SYouMin Chen 	if (ret)
2174f520bb22SYouMin Chen 		goto out;
2175f520bb22SYouMin Chen 
2176f520bb22SYouMin Chen 	record_dq_prebit(dram);
2177f520bb22SYouMin Chen 
2178f520bb22SYouMin Chen 	min_val = get_min_value(dram, SKEW_RX_SIGNAL,
2179f520bb22SYouMin Chen 				sdram_params->ch.cap_info.rank) * -1;
2180f520bb22SYouMin Chen 	modify_dq_deskew(dram, SKEW_RX_SIGNAL, DESKEW_MDF_DIFF_VAL,
2181f520bb22SYouMin Chen 			 min_val, min_val, sdram_params->ch.cap_info.rank);
2182c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL)
2183c71eeac4SWesley Yao 	save_rw_trn_deskew(phy_base, &rw_trn_result.rd_fsp[fsp],
2184c71eeac4SWesley Yao 			   rw_trn_result.cs_num, (u8)(min_val * (-1)),
2185c71eeac4SWesley Yao 			   SKEW_RX_SIGNAL);
2186c71eeac4SWesley Yao #endif
2187f520bb22SYouMin Chen 
2188f520bb22SYouMin Chen 	min_val = MIN(get_min_value(dram, SKEW_TX_SIGNAL,
2189f520bb22SYouMin Chen 				    sdram_params->ch.cap_info.rank),
2190f520bb22SYouMin Chen 		      get_min_value(dram, SKEW_CA_SIGNAL,
2191f520bb22SYouMin Chen 				    sdram_params->ch.cap_info.rank)) * -1;
2192f520bb22SYouMin Chen 
2193f520bb22SYouMin Chen 	/* clk = 0, rx all skew -7, tx - min_value */
2194f520bb22SYouMin Chen 	modify_ca_deskew(dram, DESKEW_MDF_DIFF_VAL, min_val, min_val, 3,
2195f520bb22SYouMin Chen 			 dramtype);
2196f520bb22SYouMin Chen 
2197f520bb22SYouMin Chen 	modify_dq_deskew(dram, SKEW_TX_SIGNAL, DESKEW_MDF_DIFF_VAL,
2198f520bb22SYouMin Chen 			 min_val, min_val, sdram_params->ch.cap_info.rank);
2199c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL)
2200c71eeac4SWesley Yao 	save_rw_trn_deskew(phy_base, &rw_trn_result.wr_fsp[fsp],
2201c71eeac4SWesley Yao 			   rw_trn_result.cs_num, (u8)(min_val * (-1)),
2202c71eeac4SWesley Yao 			   SKEW_TX_SIGNAL);
2203c71eeac4SWesley Yao #endif
2204f520bb22SYouMin Chen 
2205f520bb22SYouMin Chen 	ret = data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING);
2206f520bb22SYouMin Chen 	if (sdram_params->ch.cap_info.rank == 2)
2207f520bb22SYouMin Chen 		ret |= data_training(dram, 1, sdram_params, 0,
2208f520bb22SYouMin Chen 				     READ_GATE_TRAINING);
2209f520bb22SYouMin Chen out:
2210f520bb22SYouMin Chen 	return ret;
2211f520bb22SYouMin Chen }
2212f520bb22SYouMin Chen 
set_ddrconfig(struct dram_info * dram,u32 ddrconfig)2213f520bb22SYouMin Chen static void set_ddrconfig(struct dram_info *dram, u32 ddrconfig)
2214f520bb22SYouMin Chen {
2215f520bb22SYouMin Chen 	writel(ddrconfig, &dram->msch->deviceconf);
2216f520bb22SYouMin Chen 	clrsetbits_le32(&dram->grf->noc_con0, 0x3 << 0, 0 << 0);
2217f520bb22SYouMin Chen }
2218f520bb22SYouMin Chen 
update_noc_timing(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)2219f520bb22SYouMin Chen static void update_noc_timing(struct dram_info *dram,
2220f520bb22SYouMin Chen 			      struct rv1126_sdram_params *sdram_params)
2221f520bb22SYouMin Chen {
222238b16f08SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
222338b16f08SYouMin Chen 	u32 bw, bl;
222438b16f08SYouMin Chen 
222538b16f08SYouMin Chen 	bw = 8 << sdram_params->ch.cap_info.bw;
222638b16f08SYouMin Chen 	bl = ((readl(pctl_base + DDR_PCTL2_MSTR) >> 16) & 0xf) * 2;
222738b16f08SYouMin Chen 
222838b16f08SYouMin Chen 	/* update the noc timing related to data bus width */
22299d5c314bSWesley Yao 	if ((bw / 8 * bl) <= 16)
223038b16f08SYouMin Chen 		sdram_params->ch.noc_timings.ddrmode.b.burstsize = 0;
223138b16f08SYouMin Chen 	else if ((bw / 8 * bl) == 32)
223238b16f08SYouMin Chen 		sdram_params->ch.noc_timings.ddrmode.b.burstsize = 1;
223338b16f08SYouMin Chen 	else if ((bw / 8 * bl) == 64)
223438b16f08SYouMin Chen 		sdram_params->ch.noc_timings.ddrmode.b.burstsize = 2;
223538b16f08SYouMin Chen 	else
223638b16f08SYouMin Chen 		sdram_params->ch.noc_timings.ddrmode.b.burstsize = 3;
223738b16f08SYouMin Chen 
223838b16f08SYouMin Chen 	sdram_params->ch.noc_timings.ddrtimingc0.b.burstpenalty =
2239da1862e9SYouMin Chen 		(bl * bw / 8) > 16 ? (bl / 4) : (16 / (bl * bw / 8)) * bl / 4;
224038b16f08SYouMin Chen 
2241c2a03d5dSZhihuan He 	if (sdram_params->base.dramtype == LPDDR4 ||
2242c2a03d5dSZhihuan He 	    sdram_params->base.dramtype == LPDDR4X) {
224338b16f08SYouMin Chen 		sdram_params->ch.noc_timings.ddrmode.b.mwrsize =
224438b16f08SYouMin Chen 			(bw == 16) ? 0x1 : 0x2;
224538b16f08SYouMin Chen 		sdram_params->ch.noc_timings.ddrtimingc0.b.wrtomwr =
224638b16f08SYouMin Chen 			3 * sdram_params->ch.noc_timings.ddrtimingc0.b.burstpenalty;
224738b16f08SYouMin Chen 	}
224838b16f08SYouMin Chen 
2249f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.ddrtiminga0.d32,
2250f520bb22SYouMin Chen 	       &dram->msch->ddrtiminga0);
2251f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.ddrtimingb0.d32,
2252f520bb22SYouMin Chen 	       &dram->msch->ddrtimingb0);
2253f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.ddrtimingc0.d32,
2254f520bb22SYouMin Chen 	       &dram->msch->ddrtimingc0);
2255f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.devtodev0.d32,
2256f520bb22SYouMin Chen 	       &dram->msch->devtodev0);
2257f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.ddrmode.d32, &dram->msch->ddrmode);
2258f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.ddr4timing.d32,
2259f520bb22SYouMin Chen 	       &dram->msch->ddr4timing);
2260f520bb22SYouMin Chen }
2261f520bb22SYouMin Chen 
split_setup(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)2262f627cf25SZhihuan He static int split_setup(struct dram_info *dram,
2263f627cf25SZhihuan He 		       struct rv1126_sdram_params *sdram_params)
2264f627cf25SZhihuan He {
2265f627cf25SZhihuan He 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2266f627cf25SZhihuan He 	u32 dramtype = sdram_params->base.dramtype;
2267f627cf25SZhihuan He 	u32 split_size, split_mode;
2268f627cf25SZhihuan He 	u64 cs_cap[2], cap;
2269f627cf25SZhihuan He 
2270f627cf25SZhihuan He 	cs_cap[0] = sdram_get_cs_cap(cap_info, 0, dramtype);
2271f627cf25SZhihuan He 	cs_cap[1] = sdram_get_cs_cap(cap_info, 1, dramtype);
22724d64c723SZhihuan He 
22734d64c723SZhihuan He 	/* The ddr split only support 1 rank and less than 4GB capacity. */
22744d64c723SZhihuan He 	if ((cs_cap[1]) || (cs_cap[0] >= 0x100000000ULL))
22754d64c723SZhihuan He 		goto out;
22764d64c723SZhihuan He 
2277f627cf25SZhihuan He 	/* only support the larger cap is in low 16bit */
2278f627cf25SZhihuan He 	if (cap_info->cs0_high16bit_row < cap_info->cs0_row) {
2279f627cf25SZhihuan He 		cap = cs_cap[0] / (1 << (cap_info->cs0_row -
2280f627cf25SZhihuan He 		cap_info->cs0_high16bit_row));
2281f627cf25SZhihuan He 	} else if ((cap_info->cs1_high16bit_row < cap_info->cs1_row) &&
2282f627cf25SZhihuan He 		   (cap_info->rank == 2)) {
2283f627cf25SZhihuan He 		if (!cap_info->cs1_high16bit_row)
2284f627cf25SZhihuan He 			cap = cs_cap[0];
2285f627cf25SZhihuan He 		else
2286f627cf25SZhihuan He 			cap = cs_cap[0] + cs_cap[1] / (1 << (cap_info->cs1_row -
2287f627cf25SZhihuan He 				cap_info->cs1_high16bit_row));
2288f627cf25SZhihuan He 	} else {
2289f627cf25SZhihuan He 		goto out;
2290f627cf25SZhihuan He 	}
2291f627cf25SZhihuan He 	split_size = (u32)(cap >> 24) & SPLIT_SIZE_MASK;
2292f627cf25SZhihuan He 	if (cap_info->bw == 2)
2293f627cf25SZhihuan He 		split_mode = SPLIT_MODE_32_L16_VALID;
2294f627cf25SZhihuan He 	else
2295f627cf25SZhihuan He 		split_mode = SPLIT_MODE_16_L8_VALID;
2296f627cf25SZhihuan He 
2297f627cf25SZhihuan He 	rk_clrsetreg(&dram->ddrgrf->grf_ddrsplit_con,
2298f627cf25SZhihuan He 		     (SPLIT_MODE_MASK << SPLIT_MODE_OFFSET) |
2299f627cf25SZhihuan He 		     (SPLIT_BYPASS_MASK << SPLIT_BYPASS_OFFSET) |
2300f627cf25SZhihuan He 		     (SPLIT_SIZE_MASK << SPLIT_SIZE_OFFSET),
2301f627cf25SZhihuan He 		     (split_mode << SPLIT_MODE_OFFSET) |
2302f627cf25SZhihuan He 		     (0x0 << SPLIT_BYPASS_OFFSET) |
2303f627cf25SZhihuan He 		     (split_size << SPLIT_SIZE_OFFSET));
2304f627cf25SZhihuan He 
2305f627cf25SZhihuan He 	rk_clrsetreg(BUS_SGRF_BASE_ADDR + SGRF_SOC_CON2,
2306f627cf25SZhihuan He 		     MSCH_AXI_BYPASS_ALL_MASK << MSCH_AXI_BYPASS_ALL_SHIFT,
2307f627cf25SZhihuan He 		     0x0 << MSCH_AXI_BYPASS_ALL_SHIFT);
2308f627cf25SZhihuan He 
2309f627cf25SZhihuan He out:
2310f627cf25SZhihuan He 	return 0;
2311f627cf25SZhihuan He }
2312f627cf25SZhihuan He 
split_bypass(struct dram_info * dram)2313f627cf25SZhihuan He static void split_bypass(struct dram_info *dram)
2314f627cf25SZhihuan He {
2315f627cf25SZhihuan He 	if ((readl(&dram->ddrgrf->grf_ddrsplit_con) &
2316f627cf25SZhihuan He 	     (1 << SPLIT_BYPASS_OFFSET)) != 0)
2317f627cf25SZhihuan He 		return;
2318f627cf25SZhihuan He 
2319f627cf25SZhihuan He 	/* bypass split */
2320f627cf25SZhihuan He 	rk_clrsetreg(&dram->ddrgrf->grf_ddrsplit_con,
2321f627cf25SZhihuan He 		     (SPLIT_BYPASS_MASK << SPLIT_BYPASS_OFFSET) |
2322f627cf25SZhihuan He 		     (SPLIT_SIZE_MASK << SPLIT_SIZE_OFFSET),
2323f627cf25SZhihuan He 		     (0x1 << SPLIT_BYPASS_OFFSET) |
2324f627cf25SZhihuan He 		     (0x0 << SPLIT_SIZE_OFFSET));
2325f627cf25SZhihuan He }
2326f627cf25SZhihuan He 
dram_all_config(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)2327f520bb22SYouMin Chen static void dram_all_config(struct dram_info *dram,
2328f520bb22SYouMin Chen 			    struct rv1126_sdram_params *sdram_params)
2329f520bb22SYouMin Chen {
2330f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2331f520bb22SYouMin Chen 	u32 dram_type = sdram_params->base.dramtype;
2332f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2333f520bb22SYouMin Chen 	u32 sys_reg2 = 0;
2334f520bb22SYouMin Chen 	u32 sys_reg3 = 0;
2335f520bb22SYouMin Chen 	u64 cs_cap[2];
2336f520bb22SYouMin Chen 	u32 cs_pst;
2337f520bb22SYouMin Chen 
2338f520bb22SYouMin Chen 	set_ddrconfig(dram, cap_info->ddrconfig);
2339f520bb22SYouMin Chen 	sdram_org_config(cap_info, &sdram_params->base, &sys_reg2,
2340f520bb22SYouMin Chen 			 &sys_reg3, 0);
2341f520bb22SYouMin Chen 	writel(sys_reg2, &dram->pmugrf->os_reg[2]);
2342f520bb22SYouMin Chen 	writel(sys_reg3, &dram->pmugrf->os_reg[3]);
2343f520bb22SYouMin Chen 
2344f520bb22SYouMin Chen 	cs_cap[0] = sdram_get_cs_cap(cap_info, 0, dram_type);
2345f520bb22SYouMin Chen 	cs_cap[1] = sdram_get_cs_cap(cap_info, 1, dram_type);
2346f520bb22SYouMin Chen 
2347f520bb22SYouMin Chen 	if (cap_info->rank == 2) {
2348f520bb22SYouMin Chen 		cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) +
2349f520bb22SYouMin Chen 			6 + 2;
2350f520bb22SYouMin Chen 		if (cs_pst > 28)
2351bf922fc8SWesley Yao 			cs_cap[0] = 1llu << cs_pst;
2352f520bb22SYouMin Chen 	}
2353f520bb22SYouMin Chen 
2354f520bb22SYouMin Chen 	writel(((((cs_cap[1] >> 20) / 64) & 0xff) << 8) |
2355f520bb22SYouMin Chen 			(((cs_cap[0] >> 20) / 64) & 0xff),
2356f520bb22SYouMin Chen 			&dram->msch->devicesize);
2357f520bb22SYouMin Chen 	update_noc_timing(dram, sdram_params);
2358f520bb22SYouMin Chen }
2359f520bb22SYouMin Chen 
enable_low_power(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)2360f520bb22SYouMin Chen static void enable_low_power(struct dram_info *dram,
2361f520bb22SYouMin Chen 			     struct rv1126_sdram_params *sdram_params)
2362f520bb22SYouMin Chen {
2363f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2364f520bb22SYouMin Chen 	u32 grf_lp_con;
2365f520bb22SYouMin Chen 
2366f520bb22SYouMin Chen 	writel(0x1f1f0617, &dram->ddrgrf->ddr_grf_con[1]);
2367f520bb22SYouMin Chen 
2368f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4)
2369f520bb22SYouMin Chen 		grf_lp_con = (0x7 << 16) | (1 << 1);
2370f520bb22SYouMin Chen 	else if (sdram_params->base.dramtype == DDR3)
2371f520bb22SYouMin Chen 		grf_lp_con = (0x7 << 16) | (1 << 0);
2372f520bb22SYouMin Chen 	else
2373f520bb22SYouMin Chen 		grf_lp_con = (0x7 << 16) | (1 << 2);
2374f520bb22SYouMin Chen 
2375f520bb22SYouMin Chen 	/* en lpckdis_en */
2376f520bb22SYouMin Chen 	grf_lp_con = grf_lp_con | (0x1 << (9 + 16)) | (0x1 << 9);
2377f520bb22SYouMin Chen 	writel(grf_lp_con, &dram->ddrgrf->ddr_grf_lp_con);
2378f520bb22SYouMin Chen 
2379f520bb22SYouMin Chen 	/* enable sr, pd */
2380f520bb22SYouMin Chen 	if (dram->pd_idle == 0)
2381f520bb22SYouMin Chen 		clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
2382f520bb22SYouMin Chen 	else
2383f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
2384f520bb22SYouMin Chen 	if (dram->sr_idle == 0)
2385f520bb22SYouMin Chen 		clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
2386f520bb22SYouMin Chen 	else
2387f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
2388f520bb22SYouMin Chen 	setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 3));
2389f520bb22SYouMin Chen }
2390f520bb22SYouMin Chen 
ddr_set_atags(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)2391f520bb22SYouMin Chen static void ddr_set_atags(struct dram_info *dram,
2392f520bb22SYouMin Chen 			  struct rv1126_sdram_params *sdram_params)
2393f520bb22SYouMin Chen {
2394f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2395f520bb22SYouMin Chen 	u32 dram_type = sdram_params->base.dramtype;
2396f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2397f520bb22SYouMin Chen 	struct tag_serial t_serial;
2398f520bb22SYouMin Chen 	struct tag_ddr_mem t_ddrmem;
2399f520bb22SYouMin Chen 	struct tag_soc_info t_socinfo;
2400f520bb22SYouMin Chen 	u64 cs_cap[2];
2401f520bb22SYouMin Chen 	u32 cs_pst = 0;
2402f627cf25SZhihuan He 	u32 split, split_size;
2403f627cf25SZhihuan He 	u64 reduce_cap = 0;
2404f520bb22SYouMin Chen 
2405f520bb22SYouMin Chen 	cs_cap[0] = sdram_get_cs_cap(cap_info, 0, dram_type);
2406f520bb22SYouMin Chen 	cs_cap[1] = sdram_get_cs_cap(cap_info, 1, dram_type);
2407f520bb22SYouMin Chen 
2408f520bb22SYouMin Chen 	memset(&t_serial, 0, sizeof(struct tag_serial));
2409f520bb22SYouMin Chen 
2410f520bb22SYouMin Chen 	t_serial.version = 0;
2411f520bb22SYouMin Chen 	t_serial.enable = 1;
2412f520bb22SYouMin Chen 	t_serial.addr = CONFIG_DEBUG_UART_BASE;
2413f520bb22SYouMin Chen 	t_serial.baudrate = CONFIG_BAUDRATE;
2414f520bb22SYouMin Chen 	t_serial.m_mode = SERIAL_M_MODE_M0;
2415f520bb22SYouMin Chen 	t_serial.id = 2;
2416f520bb22SYouMin Chen 
2417f520bb22SYouMin Chen 	atags_destroy();
2418f520bb22SYouMin Chen 	atags_set_tag(ATAG_SERIAL, &t_serial);
2419f520bb22SYouMin Chen 
2420f627cf25SZhihuan He 	split = readl(&dram->ddrgrf->grf_ddrsplit_con);
2421f520bb22SYouMin Chen 	memset(&t_ddrmem, 0, sizeof(struct tag_ddr_mem));
2422f520bb22SYouMin Chen 	if (cap_info->row_3_4) {
2423f520bb22SYouMin Chen 		cs_cap[0] =  cs_cap[0] * 3 / 4;
2424f520bb22SYouMin Chen 		cs_cap[1] =  cs_cap[1] * 3 / 4;
2425f627cf25SZhihuan He 	} else if (!(split & (1 << SPLIT_BYPASS_OFFSET))) {
2426f627cf25SZhihuan He 		split_size = (split >> SPLIT_SIZE_OFFSET) & SPLIT_SIZE_MASK;
2427f627cf25SZhihuan He 		reduce_cap = (cs_cap[0] + cs_cap[1] - (split_size << 24)) / 2;
2428f520bb22SYouMin Chen 	}
2429f520bb22SYouMin Chen 	t_ddrmem.version = 0;
2430f520bb22SYouMin Chen 	t_ddrmem.bank[0] = CONFIG_SYS_SDRAM_BASE;
2431f520bb22SYouMin Chen 	if (cs_cap[1]) {
2432f520bb22SYouMin Chen 		cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) +
2433f520bb22SYouMin Chen 			6 + 2;
2434f520bb22SYouMin Chen 	}
2435f520bb22SYouMin Chen 
2436f520bb22SYouMin Chen 	if (cs_cap[1] && cs_pst > 27) {
2437f520bb22SYouMin Chen 		t_ddrmem.count = 2;
2438f520bb22SYouMin Chen 		t_ddrmem.bank[1] = 1 << cs_pst;
2439f520bb22SYouMin Chen 		t_ddrmem.bank[2] = cs_cap[0];
2440f627cf25SZhihuan He 		t_ddrmem.bank[3] = cs_cap[1] - reduce_cap;
2441f520bb22SYouMin Chen 	} else {
2442f520bb22SYouMin Chen 		t_ddrmem.count = 1;
2443f627cf25SZhihuan He 		t_ddrmem.bank[1] = (u64)cs_cap[0] + (u64)cs_cap[1] - reduce_cap;
2444f520bb22SYouMin Chen 	}
2445f520bb22SYouMin Chen 
2446f520bb22SYouMin Chen 	atags_set_tag(ATAG_DDR_MEM, &t_ddrmem);
2447f520bb22SYouMin Chen 
2448f520bb22SYouMin Chen 	memset(&t_socinfo, 0, sizeof(struct tag_soc_info));
2449b579a1b7SWesley Yao 	t_socinfo.version = 0x1;
2450f520bb22SYouMin Chen 	t_socinfo.name = 0x1126;
2451b579a1b7SWesley Yao 	t_socinfo.flags = SOC_FLAGS_TDBT;
2452b579a1b7SWesley Yao 	atags_set_tag(ATAG_SOC_INFO, &t_socinfo);
2453f520bb22SYouMin Chen }
2454f520bb22SYouMin Chen 
print_ddr_info(struct rv1126_sdram_params * sdram_params)2455f520bb22SYouMin Chen static void print_ddr_info(struct rv1126_sdram_params *sdram_params)
2456f520bb22SYouMin Chen {
2457f520bb22SYouMin Chen 	u32 split;
2458f520bb22SYouMin Chen 
2459f520bb22SYouMin Chen 	if ((readl(DDR_GRF_BASE_ADDR + DDR_GRF_SPLIT_CON) &
2460f520bb22SYouMin Chen 	     (1 << SPLIT_BYPASS_OFFSET)) != 0)
2461f520bb22SYouMin Chen 		split = 0;
2462f520bb22SYouMin Chen 	else
2463f520bb22SYouMin Chen 		split = readl(DDR_GRF_BASE_ADDR + DDR_GRF_SPLIT_CON) &
2464f520bb22SYouMin Chen 			SPLIT_SIZE_MASK;
2465f520bb22SYouMin Chen 
2466f520bb22SYouMin Chen 	sdram_print_ddr_info(&sdram_params->ch.cap_info,
2467f520bb22SYouMin Chen 			     &sdram_params->base, split);
2468f520bb22SYouMin Chen }
2469f520bb22SYouMin Chen 
check_lp4_rzqi_value(struct dram_info * dram,u32 cs,u32 byte,u32 zq,u32 dramtype)247023817349SWesley Yao static int check_lp4_rzqi_value(struct dram_info *dram, u32 cs, u32 byte, u32 zq, u32 dramtype)
247123817349SWesley Yao {
247223817349SWesley Yao 	u32 rzqi;
247323817349SWesley Yao 
247423817349SWesley Yao 	rzqi = (read_mr(dram, BIT(cs), byte, 0, dramtype) >> 3) & 0x3;
247523817349SWesley Yao 	if (rzqi == 0x1 || rzqi == 0x2) {
247623817349SWesley Yao 		printascii("WARNING: ZQ");
247723817349SWesley Yao 		printdec(zq);
247823817349SWesley Yao 		printascii(" may ");
247923817349SWesley Yao 		if (rzqi == 0x1)
248023817349SWesley Yao 			printascii("connect to VSSQ or float!\n");
248123817349SWesley Yao 		else
248223817349SWesley Yao 			printascii("short to VDDQ!\n");
248323817349SWesley Yao 
248423817349SWesley Yao 		return -1;
248523817349SWesley Yao 	}
248623817349SWesley Yao 
248723817349SWesley Yao 	return 0;
248823817349SWesley Yao }
248923817349SWesley Yao 
check_lp4_rzqi(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)249023817349SWesley Yao static int check_lp4_rzqi(struct dram_info *dram, struct rv1126_sdram_params *sdram_params)
249123817349SWesley Yao {
249223817349SWesley Yao 	u32 cs, byte;
249323817349SWesley Yao 	u32 dramtype = sdram_params->base.dramtype;
249423817349SWesley Yao 	struct sdram_cap_info *cap_info;
249523817349SWesley Yao 	int ret = 0;
249623817349SWesley Yao 
249723817349SWesley Yao 	if (dramtype != LPDDR4 && dramtype != LPDDR4X)
249823817349SWesley Yao 		return 0;
249923817349SWesley Yao 
250023817349SWesley Yao 	cap_info = &sdram_params->ch.cap_info;
250123817349SWesley Yao 	if (cap_info->dbw == 0) {
250223817349SWesley Yao 		cs = cap_info->rank - 1;
250323817349SWesley Yao 		for (byte = 0; byte < 2; byte++) {
250423817349SWesley Yao 			if (check_lp4_rzqi_value(dram, cs, byte, byte, dramtype))
250523817349SWesley Yao 				ret = -1;
250623817349SWesley Yao 		}
250723817349SWesley Yao 	} else {
250823817349SWesley Yao 		byte = 0;
250923817349SWesley Yao 		for (cs = 0; cs < cap_info->rank; cs++) {
251023817349SWesley Yao 			if (check_lp4_rzqi_value(dram, cs, byte, cs, dramtype))
251123817349SWesley Yao 				ret = -1;
251223817349SWesley Yao 		}
251323817349SWesley Yao 	}
251423817349SWesley Yao 
251523817349SWesley Yao 	return ret;
251623817349SWesley Yao }
251723817349SWesley Yao 
modify_ddr34_bw_byte_map(u8 rg_result,struct rv1126_sdram_params * sdram_params)2518f71f1edbSWesley Yao int modify_ddr34_bw_byte_map(u8 rg_result, struct rv1126_sdram_params *sdram_params)
25190d2a0f8fSWesley Yao {
25200d2a0f8fSWesley Yao 	struct sdram_head_info_index_v2 *index = (struct sdram_head_info_index_v2 *)common_info;
25210d2a0f8fSWesley Yao 	struct dq_map_info *map_info = (struct dq_map_info *)
25220d2a0f8fSWesley Yao 				       ((void *)common_info + index->dq_map_index.offset * 4);
25230d2a0f8fSWesley Yao 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
25240d2a0f8fSWesley Yao 	u32 dramtype = sdram_params->base.dramtype;
25250d2a0f8fSWesley Yao 	u32 byte_map = 0;
25260d2a0f8fSWesley Yao 	u32 byte = 0;
25270d2a0f8fSWesley Yao 	u32 byte_map_shift;
25280d2a0f8fSWesley Yao 	int i;
25290d2a0f8fSWesley Yao 
25300d2a0f8fSWesley Yao 	if (dramtype == DDR3)
25310d2a0f8fSWesley Yao 		byte_map_shift = 24;
25320d2a0f8fSWesley Yao 	else if (dramtype == DDR4)
25330d2a0f8fSWesley Yao 		byte_map_shift = 0;
25340d2a0f8fSWesley Yao 	else
25350d2a0f8fSWesley Yao 		return -1;
25360d2a0f8fSWesley Yao 
25370d2a0f8fSWesley Yao 	for (i = 0; i < 4; i++) {
25380d2a0f8fSWesley Yao 		if ((rg_result & BIT(i)) == 0) {
25390d2a0f8fSWesley Yao 			byte_map |= byte << (i * 2);
25400d2a0f8fSWesley Yao 			byte++;
25410d2a0f8fSWesley Yao 		}
25420d2a0f8fSWesley Yao 	}
25430d2a0f8fSWesley Yao 	if (byte != 1 && byte != 2 && byte != 4) {
25440d2a0f8fSWesley Yao 		printascii("DTT result is abnormal: ");
25450d2a0f8fSWesley Yao 		printdec(byte);
25460d2a0f8fSWesley Yao 		printascii("byte\n");
25470d2a0f8fSWesley Yao 		return -1;
25480d2a0f8fSWesley Yao 	}
25490d2a0f8fSWesley Yao 	cap_info->bw = byte / 2;
25500d2a0f8fSWesley Yao 	for (i = 0; i < 4; i++) {
25510d2a0f8fSWesley Yao 		if ((rg_result & BIT(i)) != 0) {
25520d2a0f8fSWesley Yao 			byte_map |= byte << (i * 2);
25530d2a0f8fSWesley Yao 			byte++;
25540d2a0f8fSWesley Yao 		}
25550d2a0f8fSWesley Yao 	}
25560d2a0f8fSWesley Yao 
25570d2a0f8fSWesley Yao 	if ((u8)byte_map != (u8)(map_info->byte_map[0] >> byte_map_shift)) {
25580d2a0f8fSWesley Yao 		clrsetbits_le32(&map_info->byte_map[0],
25590d2a0f8fSWesley Yao 				0xff << byte_map_shift, byte_map << byte_map_shift);
25600d2a0f8fSWesley Yao 		pctl_remodify_sdram_params(&sdram_params->pctl_regs, cap_info, dramtype);
25610d2a0f8fSWesley Yao 		return 1;
25620d2a0f8fSWesley Yao 	}
25630d2a0f8fSWesley Yao 
25640d2a0f8fSWesley Yao 	return 0;
25650d2a0f8fSWesley Yao }
25660d2a0f8fSWesley Yao 
sdram_init_(struct dram_info * dram,struct rv1126_sdram_params * sdram_params,u32 post_init)25671b8bda11SWesley Yao int sdram_init_(struct dram_info *dram, struct rv1126_sdram_params *sdram_params, u32 post_init)
2568f520bb22SYouMin Chen {
2569f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2570f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
2571f520bb22SYouMin Chen 	u32 ddr4_vref;
25720d2a0f8fSWesley Yao 	u32 mr_tmp, tmp;
25739363e6afSWesley Yao 	int delay = 3000;
2574f520bb22SYouMin Chen 
2575f520bb22SYouMin Chen 	rkclk_configure_ddr(dram, sdram_params);
2576f520bb22SYouMin Chen 
2577f520bb22SYouMin Chen 	rkclk_ddr_reset(dram, 1, 1, 1, 1);
2578f520bb22SYouMin Chen 	udelay(10);
2579f520bb22SYouMin Chen 
2580f520bb22SYouMin Chen 	rkclk_ddr_reset(dram, 1, 1, 1, 0);
2581f520bb22SYouMin Chen 	phy_cfg(dram, sdram_params);
2582f520bb22SYouMin Chen 
2583f520bb22SYouMin Chen 	rkclk_ddr_reset(dram, 1, 1, 0, 0);
2584f520bb22SYouMin Chen 	phy_pll_set(dram, sdram_params->base.ddr_freq * MHZ, 1);
2585f520bb22SYouMin Chen 
2586f520bb22SYouMin Chen 	rkclk_ddr_reset(dram, 1, 0, 0, 0);
2587f520bb22SYouMin Chen 	pctl_cfg(dram->pctl, &sdram_params->pctl_regs,
2588f520bb22SYouMin Chen 		 dram->sr_idle, dram->pd_idle);
2589f520bb22SYouMin Chen 
259022b43223SZhihuan He 	if (sdram_params->ch.cap_info.bw == 2) {
2591e8885e24SCanYang He 		/* 32bit interface use pageclose */
2592e8885e24SCanYang He 		setbits_le32(pctl_base + DDR_PCTL2_SCHED, 1 << 2);
259322b43223SZhihuan He 		/* pageclose = 1, pageclose_timer = 0 will err in lp4 328MHz */
259422b43223SZhihuan He 		clrsetbits_le32(pctl_base + DDR_PCTL2_SCHED1, 0xff, 0x1 << 0);
259522b43223SZhihuan He 	} else {
2596e8885e24SCanYang He 		clrbits_le32(pctl_base + DDR_PCTL2_SCHED, 1 << 2);
259722b43223SZhihuan He 	}
2598e8885e24SCanYang He 
2599ee5f0829STang Yun ping #ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT
26000d2a0f8fSWesley Yao 	u32 trefi;
2601ee5f0829STang Yun ping 
2602ee5f0829STang Yun ping 	tmp = readl(pctl_base + DDR_PCTL2_RFSHTMG);
2603ee5f0829STang Yun ping 	trefi = (tmp >> 16) & 0xfff;
2604ee5f0829STang Yun ping 	writel((tmp & 0xf000ffff) | (trefi / 2) << 16,
2605ee5f0829STang Yun ping 	       pctl_base + DDR_PCTL2_RFSHTMG);
2606ee5f0829STang Yun ping #endif
2607ee5f0829STang Yun ping 
2608f520bb22SYouMin Chen 	/* set frequency_mode */
2609f520bb22SYouMin Chen 	setbits_le32(pctl_base + DDR_PCTL2_MSTR, 0x1 << 29);
2610f520bb22SYouMin Chen 	/* set target_frequency to Frequency 0 */
2611f520bb22SYouMin Chen 	clrsetbits_le32(pctl_base + DDR_PCTL2_MSTR2, 0x3, 0);
2612f520bb22SYouMin Chen 
2613f520bb22SYouMin Chen 	set_ds_odt(dram, sdram_params, 0);
2614f520bb22SYouMin Chen 	sdram_params->ch.cap_info.ddrconfig = calculate_ddrconfig(sdram_params);
2615f520bb22SYouMin Chen 	set_ctl_address_map(dram, sdram_params);
2616f520bb22SYouMin Chen 
2617f520bb22SYouMin Chen 	setbits_le32(pctl_base + DDR_PCTL2_DFIMISC, (1 << 5) | (1 << 4));
2618f520bb22SYouMin Chen 
2619f520bb22SYouMin Chen 	rkclk_ddr_reset(dram, 0, 0, 0, 0);
2620f520bb22SYouMin Chen 
2621a6422204SWesley Yao 	while ((readl(pctl_base + DDR_PCTL2_STAT) & 0x7) == 0) {
2622a6422204SWesley Yao 		udelay(1);
2623a6422204SWesley Yao 		if (delay-- <= 0) {
2624a6422204SWesley Yao 			printascii("ERROR: Cannot wait dfi_init_done!\n");
2625a6422204SWesley Yao 			while (1)
2626a6422204SWesley Yao 				;
2627a6422204SWesley Yao 		}
2628a6422204SWesley Yao 	}
2629f520bb22SYouMin Chen 
2630f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == LPDDR3) {
2631f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 11, lp3_odt_value, LPDDR3);
2632c2a03d5dSZhihuan He 	} else if (sdram_params->base.dramtype == LPDDR4 ||
2633c2a03d5dSZhihuan He 		   sdram_params->base.dramtype == LPDDR4X) {
2634f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + DDR_PCTL2_INIT6);
2635f520bb22SYouMin Chen 		/* MR11 */
2636f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 11,
2637f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
2638f520bb22SYouMin Chen 			      LPDDR4);
2639f520bb22SYouMin Chen 		/* MR12 */
2640f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 12,
2641f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR12_SHIFT & PCTL2_MR_MASK,
2642f520bb22SYouMin Chen 			      LPDDR4);
2643f520bb22SYouMin Chen 
2644f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + DDR_PCTL2_INIT7);
2645f520bb22SYouMin Chen 		/* MR22 */
2646f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 22,
2647f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
2648f520bb22SYouMin Chen 			      LPDDR4);
2649df9ee7ebSWesley Yao 	} else if (sdram_params->base.dramtype == DDR4) {
2650df9ee7ebSWesley Yao 		mr_tmp = readl(pctl_base + DDR_PCTL2_INIT7) >> PCTL2_DDR4_MR6_SHIFT & PCTL2_MR_MASK;
2651df9ee7ebSWesley Yao 		pctl_write_mr(dram->pctl, 0x3, 6, mr_tmp | BIT(7), DDR4);
2652df9ee7ebSWesley Yao 		pctl_write_mr(dram->pctl, 0x3, 6, mr_tmp | BIT(7), DDR4);
2653df9ee7ebSWesley Yao 		pctl_write_mr(dram->pctl, 0x3, 6, mr_tmp, DDR4);
2654f520bb22SYouMin Chen 	}
2655f520bb22SYouMin Chen 
26560d2a0f8fSWesley Yao 	if (sdram_params->base.dramtype == DDR3 && post_init == 0)
26570d2a0f8fSWesley Yao 		setbits_le32(PHY_REG(phy_base, 0xf), 0xf);
26580d2a0f8fSWesley Yao 	tmp = data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING) & 0xf;
26590d2a0f8fSWesley Yao 
26600d2a0f8fSWesley Yao 	if (tmp != 0) {
26610d2a0f8fSWesley Yao 		if (post_init != 0) {
2662f520bb22SYouMin Chen 			printascii("DTT cs0 error\n");
2663f520bb22SYouMin Chen 			return -1;
2664f520bb22SYouMin Chen 		}
26650d2a0f8fSWesley Yao 		if (sdram_params->base.dramtype != DDR3 || tmp == 0xf)
26660d2a0f8fSWesley Yao 			return -1;
26670d2a0f8fSWesley Yao 	}
26680d2a0f8fSWesley Yao 
26690d2a0f8fSWesley Yao 	if (sdram_params->base.dramtype == DDR3 && post_init == 0) {
26700d2a0f8fSWesley Yao 		if (modify_ddr34_bw_byte_map((u8)tmp, sdram_params) != 0)
26710d2a0f8fSWesley Yao 			return -1;
26720d2a0f8fSWesley Yao 	}
2673f520bb22SYouMin Chen 
2674c2a03d5dSZhihuan He 	if (sdram_params->base.dramtype == LPDDR4) {
267568a0f633SWesley Yao 		mr_tmp = read_mr(dram, 1, 0, 14, LPDDR4);
2676c2a03d5dSZhihuan He 
2677c2a03d5dSZhihuan He 		if (mr_tmp != 0x4d)
2678c2a03d5dSZhihuan He 			return -1;
2679c2a03d5dSZhihuan He 	}
2680c2a03d5dSZhihuan He 
2681c2a03d5dSZhihuan He 	if (sdram_params->base.dramtype == LPDDR4 ||
2682c2a03d5dSZhihuan He 	    sdram_params->base.dramtype == LPDDR4X) {
2683c2a03d5dSZhihuan He 		mr_tmp = readl(pctl_base + DDR_PCTL2_INIT7);
2684c2a03d5dSZhihuan He 		/* MR14 */
2685c2a03d5dSZhihuan He 		pctl_write_mr(dram->pctl, 3, 14,
2686c2a03d5dSZhihuan He 			      mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
2687c2a03d5dSZhihuan He 			      LPDDR4);
2688c2a03d5dSZhihuan He 	}
2689f520bb22SYouMin Chen 	if (post_init != 0 && sdram_params->ch.cap_info.rank == 2) {
2690f520bb22SYouMin Chen 		if (data_training(dram, 1, sdram_params, 0,
2691f520bb22SYouMin Chen 				  READ_GATE_TRAINING) != 0) {
2692f520bb22SYouMin Chen 			printascii("DTT cs1 error\n");
2693f520bb22SYouMin Chen 			return -1;
2694f520bb22SYouMin Chen 		}
2695f520bb22SYouMin Chen 	}
2696f520bb22SYouMin Chen 
2697f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4) {
2698f520bb22SYouMin Chen 		ddr4_vref = readl(PHY_REG(phy_base, 0x105)) * 39;
2699f520bb22SYouMin Chen 		pctl_write_vrefdq(dram->pctl, 0x3, ddr4_vref,
2700f520bb22SYouMin Chen 				  sdram_params->base.dramtype);
2701f520bb22SYouMin Chen 	}
2702f520bb22SYouMin Chen 
2703f520bb22SYouMin Chen 	dram_all_config(dram, sdram_params);
2704f520bb22SYouMin Chen 	enable_low_power(dram, sdram_params);
2705f520bb22SYouMin Chen 
2706f520bb22SYouMin Chen 	return 0;
2707f520bb22SYouMin Chen }
2708f520bb22SYouMin Chen 
dram_detect_cap(struct dram_info * dram,struct rv1126_sdram_params * sdram_params,unsigned char channel)2709f520bb22SYouMin Chen static u64 dram_detect_cap(struct dram_info *dram,
2710f520bb22SYouMin Chen 			   struct rv1126_sdram_params *sdram_params,
2711f520bb22SYouMin Chen 			   unsigned char channel)
2712f520bb22SYouMin Chen {
2713f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2714f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2715f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
2716f520bb22SYouMin Chen 	u32 mr8;
2717f520bb22SYouMin Chen 
2718f520bb22SYouMin Chen 	u32 bktmp;
2719f520bb22SYouMin Chen 	u32 coltmp;
2720f520bb22SYouMin Chen 	u32 rowtmp;
2721f520bb22SYouMin Chen 	u32 cs;
2722f520bb22SYouMin Chen 	u32 dram_type = sdram_params->base.dramtype;
2723f520bb22SYouMin Chen 	u32 pwrctl;
27249d5c314bSWesley Yao 	u32 i, dq_map;
27259d5c314bSWesley Yao 	u32 byte1 = 0, byte0 = 0;
2726f520bb22SYouMin Chen 
2727c2a03d5dSZhihuan He 	if (dram_type != LPDDR4 && dram_type != LPDDR4X) {
2728f520bb22SYouMin Chen 		if (dram_type != DDR4) {
27290d2a0f8fSWesley Yao 			if (dram_type == DDR3)
27300d2a0f8fSWesley Yao 				coltmp = 11;
27310d2a0f8fSWesley Yao 			else
2732f520bb22SYouMin Chen 				coltmp = 12;
2733f520bb22SYouMin Chen 			bktmp = 3;
2734f520bb22SYouMin Chen 			if (dram_type == LPDDR2)
2735f520bb22SYouMin Chen 				rowtmp = 15;
2736f520bb22SYouMin Chen 			else
2737f520bb22SYouMin Chen 				rowtmp = 16;
2738f520bb22SYouMin Chen 
2739f520bb22SYouMin Chen 			if (sdram_detect_col(cap_info, coltmp) != 0)
2740f520bb22SYouMin Chen 				goto cap_err;
2741f520bb22SYouMin Chen 
2742e1652d39SZhihuan He 			sdram_detect_bank(cap_info, pctl_base, coltmp, bktmp);
2743d393fbb5SWesley Yao 			if (dram_type != LPDDR3)
2744f520bb22SYouMin Chen 				sdram_detect_dbw(cap_info, dram_type);
2745f520bb22SYouMin Chen 		} else {
2746f520bb22SYouMin Chen 			coltmp = 10;
2747f520bb22SYouMin Chen 			bktmp = 4;
2748f520bb22SYouMin Chen 			rowtmp = 17;
2749f520bb22SYouMin Chen 
2750f520bb22SYouMin Chen 			cap_info->col = 10;
2751f520bb22SYouMin Chen 			cap_info->bk = 2;
2752e1652d39SZhihuan He 			sdram_detect_bg(cap_info, pctl_base, coltmp);
2753f520bb22SYouMin Chen 		}
2754f520bb22SYouMin Chen 
2755f520bb22SYouMin Chen 		if (sdram_detect_row(cap_info, coltmp, bktmp, rowtmp) != 0)
2756f520bb22SYouMin Chen 			goto cap_err;
2757f520bb22SYouMin Chen 
2758f520bb22SYouMin Chen 		sdram_detect_row_3_4(cap_info, coltmp, bktmp);
2759f520bb22SYouMin Chen 	} else {
2760f520bb22SYouMin Chen 		cap_info->col = 10;
2761f520bb22SYouMin Chen 		cap_info->bk = 3;
276268a0f633SWesley Yao 		mr8 = read_mr(dram, 1, 0, 8, dram_type);
2763e8897b95SWesley Yao 		cap_info->dbw = ((mr8 >> 6) & 0x3) == 0 ? 1 : 0;
2764e8897b95SWesley Yao 		mr8 = (mr8 >> 2) & 0xf;
2765e8897b95SWesley Yao 		if (mr8 >= 0 && mr8 <= 6) {
2766f520bb22SYouMin Chen 			cap_info->cs0_row = 14 + (mr8 + 1) / 2;
2767e8897b95SWesley Yao 		} else if (mr8 == 0xc) {
2768e8897b95SWesley Yao 			cap_info->cs0_row = 13;
2769e8897b95SWesley Yao 		} else {
2770e8897b95SWesley Yao 			printascii("Cap ERR: Fail to get cap of LPDDR4/X from MR8\n");
2771e8897b95SWesley Yao 			goto cap_err;
2772e8897b95SWesley Yao 		}
2773e8897b95SWesley Yao 		if (cap_info->dbw == 0)
2774e8897b95SWesley Yao 			cap_info->cs0_row++;
2775e8897b95SWesley Yao 		cap_info->row_3_4 = mr8 % 2 == 1 ? 1 : 0;
2776e8897b95SWesley Yao 		if (cap_info->cs0_row >= 17) {
2777e8897b95SWesley Yao 			printascii("Cap ERR: ");
2778e8897b95SWesley Yao 			printascii("RV1126 LPDDR4/X cannot support row >= 17\n");
2779e8897b95SWesley Yao 			goto cap_err;
2780e8897b95SWesley Yao 			// cap_info->cs0_row = 16;
2781e8897b95SWesley Yao 			// cap_info->row_3_4 = 0;
2782e8897b95SWesley Yao 		}
2783f520bb22SYouMin Chen 	}
2784f520bb22SYouMin Chen 
2785f520bb22SYouMin Chen 	pwrctl = readl(pctl_base + DDR_PCTL2_PWRCTL);
2786f520bb22SYouMin Chen 	writel(0, pctl_base + DDR_PCTL2_PWRCTL);
2787f520bb22SYouMin Chen 
2788f520bb22SYouMin Chen 	if (data_training(dram, 1, sdram_params, 0, READ_GATE_TRAINING) == 0)
2789f520bb22SYouMin Chen 		cs = 1;
2790f520bb22SYouMin Chen 	else
2791f520bb22SYouMin Chen 		cs = 0;
2792f520bb22SYouMin Chen 	cap_info->rank = cs + 1;
2793f520bb22SYouMin Chen 
2794f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0xf), 0xf);
2795f520bb22SYouMin Chen 
27960d2a0f8fSWesley Yao 	if (dram_type != DDR3) {
27970d2a0f8fSWesley Yao 		if ((data_training_rg(dram, 0, dram_type) & 0xf) == 0) {
2798f520bb22SYouMin Chen 			cap_info->bw = 2;
27999d5c314bSWesley Yao 		} else {
28009d5c314bSWesley Yao 			dq_map = readl(PHY_REG(phy_base, 0x4f));
28019d5c314bSWesley Yao 			for (i = 0; i < 4; i++) {
28029d5c314bSWesley Yao 				if (((dq_map >> (i * 2)) & 0x3) == 0)
28039d5c314bSWesley Yao 					byte0 = i;
28049d5c314bSWesley Yao 				if (((dq_map >> (i * 2)) & 0x3) == 1)
28059d5c314bSWesley Yao 					byte1 = i;
28069d5c314bSWesley Yao 			}
28079d5c314bSWesley Yao 			clrsetbits_le32(PHY_REG(phy_base, 0xf), PHY_DQ_WIDTH_MASK,
28089d5c314bSWesley Yao 					BIT(byte0) | BIT(byte1));
28094a3d9628SWesley Yao 			if (data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING) == 0)
2810f520bb22SYouMin Chen 				cap_info->bw = 1;
28119d5c314bSWesley Yao 			else
28129d5c314bSWesley Yao 				cap_info->bw = 0;
28139d5c314bSWesley Yao 		}
28149080840aSWesley Yao 	}
2815f520bb22SYouMin Chen 
2816f520bb22SYouMin Chen 	writel(pwrctl, pctl_base + DDR_PCTL2_PWRCTL);
2817f520bb22SYouMin Chen 
2818f520bb22SYouMin Chen 	cap_info->cs0_high16bit_row = cap_info->cs0_row;
2819f520bb22SYouMin Chen 	if (cs) {
2820f520bb22SYouMin Chen 		cap_info->cs1_row = cap_info->cs0_row;
2821f520bb22SYouMin Chen 		cap_info->cs1_high16bit_row = cap_info->cs0_row;
2822f520bb22SYouMin Chen 	} else {
2823f520bb22SYouMin Chen 		cap_info->cs1_row = 0;
2824f520bb22SYouMin Chen 		cap_info->cs1_high16bit_row = 0;
2825f520bb22SYouMin Chen 	}
2826f520bb22SYouMin Chen 
2827d393fbb5SWesley Yao 	if (dram_type == LPDDR3)
2828d393fbb5SWesley Yao 		sdram_detect_dbw(cap_info, dram_type);
2829d393fbb5SWesley Yao 
2830f520bb22SYouMin Chen 	return 0;
2831f520bb22SYouMin Chen cap_err:
2832f520bb22SYouMin Chen 	return -1;
2833f520bb22SYouMin Chen }
2834f520bb22SYouMin Chen 
dram_detect_cs1_row(struct dram_info * dram,struct rv1126_sdram_params * sdram_params,unsigned char channel)2835f520bb22SYouMin Chen static int dram_detect_cs1_row(struct dram_info *dram,
2836f520bb22SYouMin Chen 			       struct rv1126_sdram_params *sdram_params,
2837f520bb22SYouMin Chen 			       unsigned char channel)
2838f520bb22SYouMin Chen {
2839f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2840f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2841f520bb22SYouMin Chen 	u32 ret = 0;
2842f520bb22SYouMin Chen 	void __iomem *test_addr;
2843f520bb22SYouMin Chen 	u32 row, bktmp, coltmp, bw;
2844f520bb22SYouMin Chen 	u64 cs0_cap;
2845f520bb22SYouMin Chen 	u32 byte_mask;
2846f520bb22SYouMin Chen 	u32 cs_pst;
2847f520bb22SYouMin Chen 	u32 cs_add = 0;
2848f520bb22SYouMin Chen 	u32 max_row;
2849f520bb22SYouMin Chen 
2850f520bb22SYouMin Chen 	if (cap_info->rank == 2) {
2851f520bb22SYouMin Chen 		cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) +
2852f520bb22SYouMin Chen 			6 + 2;
2853f520bb22SYouMin Chen 		if (cs_pst < 28)
2854f520bb22SYouMin Chen 			cs_add = 1;
2855f520bb22SYouMin Chen 
2856f520bb22SYouMin Chen 		cs0_cap = 1 << cs_pst;
2857f520bb22SYouMin Chen 
2858f520bb22SYouMin Chen 		if (sdram_params->base.dramtype == DDR4) {
2859f520bb22SYouMin Chen 			if (cap_info->dbw == 0)
2860f520bb22SYouMin Chen 				bktmp = cap_info->bk + 2;
2861f520bb22SYouMin Chen 			else
2862f520bb22SYouMin Chen 				bktmp = cap_info->bk + 1;
2863f520bb22SYouMin Chen 		} else {
2864f520bb22SYouMin Chen 			bktmp = cap_info->bk;
2865f520bb22SYouMin Chen 		}
2866f520bb22SYouMin Chen 		bw = cap_info->bw;
2867f520bb22SYouMin Chen 		coltmp = cap_info->col;
2868f520bb22SYouMin Chen 
2869f520bb22SYouMin Chen 		if (bw == 2)
2870f520bb22SYouMin Chen 			byte_mask = 0xFFFF;
2871f520bb22SYouMin Chen 		else
2872f520bb22SYouMin Chen 			byte_mask = 0xFF;
2873f520bb22SYouMin Chen 
2874f520bb22SYouMin Chen 		max_row = (cs_pst == 31) ? 30 : 31;
2875f520bb22SYouMin Chen 
2876f520bb22SYouMin Chen 		max_row = max_row - bktmp - coltmp - bw - cs_add + 1;
2877f520bb22SYouMin Chen 
2878f520bb22SYouMin Chen 		row = (cap_info->cs0_row > max_row) ? max_row :
2879f520bb22SYouMin Chen 			cap_info->cs0_row;
2880f520bb22SYouMin Chen 
2881f520bb22SYouMin Chen 		for (; row > 12; row--) {
2882f520bb22SYouMin Chen 			test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
2883f520bb22SYouMin Chen 				    (u32)cs0_cap +
2884f520bb22SYouMin Chen 				    (1ul << (row + bktmp + coltmp +
2885f520bb22SYouMin Chen 					     cs_add + bw - 1ul)));
2886f520bb22SYouMin Chen 
2887f520bb22SYouMin Chen 			writel(0, CONFIG_SYS_SDRAM_BASE + (u32)cs0_cap);
2888f520bb22SYouMin Chen 			writel(PATTERN, test_addr);
2889f520bb22SYouMin Chen 
2890f520bb22SYouMin Chen 			if (((readl(test_addr) & byte_mask) ==
2891f520bb22SYouMin Chen 			     (PATTERN & byte_mask)) &&
2892f520bb22SYouMin Chen 			    ((readl(CONFIG_SYS_SDRAM_BASE + (u32)cs0_cap) &
2893f520bb22SYouMin Chen 			      byte_mask) == 0)) {
2894f520bb22SYouMin Chen 				ret = row;
2895f520bb22SYouMin Chen 				break;
2896f520bb22SYouMin Chen 			}
2897f520bb22SYouMin Chen 		}
2898f520bb22SYouMin Chen 	}
2899f520bb22SYouMin Chen 
2900f520bb22SYouMin Chen 	return ret;
2901f520bb22SYouMin Chen }
2902f520bb22SYouMin Chen 
2903f520bb22SYouMin Chen /* return: 0 = success, other = fail */
sdram_init_detect(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)2904f520bb22SYouMin Chen static int sdram_init_detect(struct dram_info *dram,
2905f520bb22SYouMin Chen 			     struct rv1126_sdram_params *sdram_params)
2906f520bb22SYouMin Chen {
2907f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2908f520bb22SYouMin Chen 	u32 ret;
2909f520bb22SYouMin Chen 	u32 sys_reg = 0;
2910f520bb22SYouMin Chen 	u32 sys_reg3 = 0;
29111040f70aSTang Yun ping 
29121040f70aSTang Yun ping 	if (sdram_init_(dram, sdram_params, 0)) {
29131040f70aSTang Yun ping 		if (sdram_params->base.dramtype == DDR3) {
29141040f70aSTang Yun ping 			if (sdram_init_(dram, sdram_params, 0))
2915f520bb22SYouMin Chen 				return -1;
29161040f70aSTang Yun ping 		} else {
29171040f70aSTang Yun ping 			return -1;
29181040f70aSTang Yun ping 		}
29191040f70aSTang Yun ping 	}
2920f520bb22SYouMin Chen 
2921f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR3) {
2922f520bb22SYouMin Chen 		writel(PATTERN, CONFIG_SYS_SDRAM_BASE);
2923f520bb22SYouMin Chen 		if (readl(CONFIG_SYS_SDRAM_BASE) != PATTERN)
2924f520bb22SYouMin Chen 			return -1;
2925f520bb22SYouMin Chen 	}
2926f520bb22SYouMin Chen 
2927f627cf25SZhihuan He 	split_bypass(dram);
2928f520bb22SYouMin Chen 	if (dram_detect_cap(dram, sdram_params, 0) != 0)
2929f520bb22SYouMin Chen 		return -1;
2930f520bb22SYouMin Chen 
2931f520bb22SYouMin Chen 	pctl_remodify_sdram_params(&sdram_params->pctl_regs, cap_info,
2932f520bb22SYouMin Chen 				   sdram_params->base.dramtype);
2933f520bb22SYouMin Chen 	ret = sdram_init_(dram, sdram_params, 1);
2934f520bb22SYouMin Chen 	if (ret != 0)
2935f520bb22SYouMin Chen 		goto out;
2936f520bb22SYouMin Chen 
2937f520bb22SYouMin Chen 	cap_info->cs1_row =
2938f520bb22SYouMin Chen 		dram_detect_cs1_row(dram, sdram_params, 0);
2939f520bb22SYouMin Chen 	if (cap_info->cs1_row) {
2940f520bb22SYouMin Chen 		sys_reg = readl(&dram->pmugrf->os_reg[2]);
2941f520bb22SYouMin Chen 		sys_reg3 = readl(&dram->pmugrf->os_reg[3]);
2942f520bb22SYouMin Chen 		SYS_REG_ENC_CS1_ROW(cap_info->cs1_row,
2943f520bb22SYouMin Chen 				    sys_reg, sys_reg3, 0);
2944f520bb22SYouMin Chen 		writel(sys_reg, &dram->pmugrf->os_reg[2]);
2945f520bb22SYouMin Chen 		writel(sys_reg3, &dram->pmugrf->os_reg[3]);
2946f520bb22SYouMin Chen 	}
2947f520bb22SYouMin Chen 
2948f627cf25SZhihuan He 	sdram_detect_high_row(cap_info, sdram_params->base.dramtype);
2949f627cf25SZhihuan He 	split_setup(dram, sdram_params);
2950f520bb22SYouMin Chen out:
2951f520bb22SYouMin Chen 	return ret;
2952f520bb22SYouMin Chen }
2953f520bb22SYouMin Chen 
get_default_sdram_config(u32 freq_mhz)2954f520bb22SYouMin Chen struct rv1126_sdram_params *get_default_sdram_config(u32 freq_mhz)
2955f520bb22SYouMin Chen {
2956f520bb22SYouMin Chen 	u32 i;
2957f520bb22SYouMin Chen 	u32 offset = 0;
2958f520bb22SYouMin Chen 	struct ddr2_3_4_lp2_3_info *ddr_info;
2959f520bb22SYouMin Chen 
2960f520bb22SYouMin Chen 	if (!freq_mhz) {
2961f520bb22SYouMin Chen 		ddr_info = get_ddr_drv_odt_info(sdram_configs[0].base.dramtype);
2962f520bb22SYouMin Chen 		if (ddr_info)
2963f520bb22SYouMin Chen 			freq_mhz =
2964f520bb22SYouMin Chen 				(ddr_info->ddr_freq0_1 >> DDR_FREQ_F0_SHIFT) &
2965f520bb22SYouMin Chen 				DDR_FREQ_MASK;
2966f520bb22SYouMin Chen 		else
2967f520bb22SYouMin Chen 			freq_mhz = 0;
2968f520bb22SYouMin Chen 	}
2969f520bb22SYouMin Chen 
2970f520bb22SYouMin Chen 	for (i = 0; i < ARRAY_SIZE(sdram_configs); i++) {
2971f520bb22SYouMin Chen 		if (sdram_configs[i].base.ddr_freq == 0 ||
2972f520bb22SYouMin Chen 		    freq_mhz < sdram_configs[i].base.ddr_freq)
2973f520bb22SYouMin Chen 			break;
2974f520bb22SYouMin Chen 	}
2975f520bb22SYouMin Chen 	offset = i == 0 ? 0 : i - 1;
2976f520bb22SYouMin Chen 
2977f520bb22SYouMin Chen 	return &sdram_configs[offset];
2978f520bb22SYouMin Chen }
2979f520bb22SYouMin Chen 
2980f520bb22SYouMin Chen static const u16 pctl_need_update_reg[] = {
2981f520bb22SYouMin Chen 	DDR_PCTL2_RFSHTMG,
2982f520bb22SYouMin Chen 	DDR_PCTL2_INIT3,
2983f520bb22SYouMin Chen 	DDR_PCTL2_INIT4,
2984f520bb22SYouMin Chen 	DDR_PCTL2_INIT6,
2985f520bb22SYouMin Chen 	DDR_PCTL2_INIT7,
2986f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG0,
2987f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG1,
2988f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG2,
2989f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG3,
2990f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG4,
2991f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG5,
2992f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG6,
2993f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG7,
2994f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG8,
2995f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG9,
2996f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG12,
2997f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG13,
2998f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG14,
2999f520bb22SYouMin Chen 	DDR_PCTL2_ZQCTL0,
3000f520bb22SYouMin Chen 	DDR_PCTL2_DFITMG0,
3001f520bb22SYouMin Chen 	DDR_PCTL2_ODTCFG
3002f520bb22SYouMin Chen };
3003f520bb22SYouMin Chen 
3004f520bb22SYouMin Chen static const u16 phy_need_update_reg[] = {
3005f520bb22SYouMin Chen 	0x14,
3006f520bb22SYouMin Chen 	0x18,
3007f520bb22SYouMin Chen 	0x1c
3008f520bb22SYouMin Chen };
3009f520bb22SYouMin Chen 
pre_set_rate(struct dram_info * dram,struct rv1126_sdram_params * sdram_params,u32 dst_fsp,u32 dst_fsp_lp4)3010f520bb22SYouMin Chen static void pre_set_rate(struct dram_info *dram,
3011f520bb22SYouMin Chen 			 struct rv1126_sdram_params *sdram_params,
3012f520bb22SYouMin Chen 			 u32 dst_fsp, u32 dst_fsp_lp4)
3013f520bb22SYouMin Chen {
3014f520bb22SYouMin Chen 	u32 i, j, find;
3015f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
3016f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
3017f520bb22SYouMin Chen 	u32 phy_offset;
3018f520bb22SYouMin Chen 	u32 mr_tmp;
3019f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
3020f520bb22SYouMin Chen 
3021f520bb22SYouMin Chen 	sw_set_req(dram);
30225d4a323cSTang Yun ping 	/* DDRCTL timing update */
3023f520bb22SYouMin Chen 	for (i = 0, find = 0; i < ARRAY_SIZE(pctl_need_update_reg); i++) {
3024f520bb22SYouMin Chen 		for (j = find; sdram_params->pctl_regs.pctl[j][0] != 0xFFFFFFFF;
3025f520bb22SYouMin Chen 		     j++) {
3026f520bb22SYouMin Chen 			if (sdram_params->pctl_regs.pctl[j][0] ==
3027f520bb22SYouMin Chen 			    pctl_need_update_reg[i]) {
3028f520bb22SYouMin Chen 				writel(sdram_params->pctl_regs.pctl[j][1],
3029f520bb22SYouMin Chen 				       pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3030f520bb22SYouMin Chen 				       pctl_need_update_reg[i]);
3031f520bb22SYouMin Chen 				find = j;
3032f520bb22SYouMin Chen 				break;
3033f520bb22SYouMin Chen 			}
3034f520bb22SYouMin Chen 		}
3035f520bb22SYouMin Chen 	}
3036ee5f0829STang Yun ping 
3037ee5f0829STang Yun ping #ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT
3038ee5f0829STang Yun ping 	u32 tmp, trefi;
3039ee5f0829STang Yun ping 
3040ee5f0829STang Yun ping 	tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_RFSHTMG);
3041ee5f0829STang Yun ping 	trefi = (tmp >> 16) & 0xfff;
3042ee5f0829STang Yun ping 	writel((tmp & 0xf000ffff) | (trefi / 2) << 16,
3043ee5f0829STang Yun ping 	       pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_RFSHTMG);
3044ee5f0829STang Yun ping #endif
3045ee5f0829STang Yun ping 
3046f520bb22SYouMin Chen 	sw_set_ack(dram);
3047f520bb22SYouMin Chen 
3048f520bb22SYouMin Chen 	/* phy timing update */
3049f520bb22SYouMin Chen 	if (dst_fsp == 0)
3050f520bb22SYouMin Chen 		phy_offset = 0;
3051f520bb22SYouMin Chen 	else
3052f520bb22SYouMin Chen 		phy_offset = PHY_REG(0, 0x387 - 5 + (dst_fsp - 1) * 3);
3053f520bb22SYouMin Chen 	/* cl cwl al update */
3054f520bb22SYouMin Chen 	for (i = 0, find = 0; i < ARRAY_SIZE(phy_need_update_reg); i++) {
3055f520bb22SYouMin Chen 		for (j = find; sdram_params->phy_regs.phy[j][0] != 0xFFFFFFFF;
3056f520bb22SYouMin Chen 		     j++) {
3057f520bb22SYouMin Chen 			if (sdram_params->phy_regs.phy[j][0] ==
3058f520bb22SYouMin Chen 			    phy_need_update_reg[i]) {
3059f520bb22SYouMin Chen 				writel(sdram_params->phy_regs.phy[j][1],
3060f520bb22SYouMin Chen 				       phy_base + phy_offset +
3061f520bb22SYouMin Chen 				       phy_need_update_reg[i]);
3062f520bb22SYouMin Chen 				find = j;
3063f520bb22SYouMin Chen 				break;
3064f520bb22SYouMin Chen 			}
3065f520bb22SYouMin Chen 		}
3066f520bb22SYouMin Chen 	}
3067f520bb22SYouMin Chen 
3068f520bb22SYouMin Chen 	set_ds_odt(dram, sdram_params, dst_fsp);
3069c2a03d5dSZhihuan He 	if (dramtype == LPDDR4 || dramtype == LPDDR4X) {
3070f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3071f520bb22SYouMin Chen 			       DDR_PCTL2_INIT4);
3072f520bb22SYouMin Chen 		/* MR13 */
3073f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 13,
3074f520bb22SYouMin Chen 			      ((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
3075f520bb22SYouMin Chen 			       PCTL2_MR_MASK) & (~(BIT(7) | BIT(6)))) |
3076f520bb22SYouMin Chen 			      ((0x2 << 6) >> dst_fsp_lp4), dramtype);
3077f520bb22SYouMin Chen 		writel(((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
3078f520bb22SYouMin Chen 				      PCTL2_MR_MASK) & (~(BIT(7) | BIT(6)))) |
3079f520bb22SYouMin Chen 				      ((0x2 << 6) >> dst_fsp_lp4),
3080f520bb22SYouMin Chen 				       PHY_REG(phy_base, 0x1b));
3081f520bb22SYouMin Chen 		/* MR3 */
3082f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 3,
3083f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT &
3084f520bb22SYouMin Chen 			      PCTL2_MR_MASK,
3085f520bb22SYouMin Chen 			      dramtype);
3086f520bb22SYouMin Chen 		writel(mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT & PCTL2_MR_MASK,
3087f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x19));
3088f520bb22SYouMin Chen 
3089f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3090f520bb22SYouMin Chen 			       DDR_PCTL2_INIT3);
3091f520bb22SYouMin Chen 		/* MR1 */
3092f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 1,
3093f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR234_MR1_SHIFT &
3094f520bb22SYouMin Chen 			      PCTL2_MR_MASK,
3095f520bb22SYouMin Chen 			      dramtype);
3096f520bb22SYouMin Chen 		writel(mr_tmp >> PCTL2_LPDDR234_MR1_SHIFT & PCTL2_MR_MASK,
3097f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x17));
3098f520bb22SYouMin Chen 		/* MR2 */
3099f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 2, mr_tmp & PCTL2_MR_MASK,
3100f520bb22SYouMin Chen 			      dramtype);
3101f520bb22SYouMin Chen 		writel(mr_tmp & PCTL2_MR_MASK,
3102f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x18));
3103f520bb22SYouMin Chen 
3104f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3105f520bb22SYouMin Chen 			       DDR_PCTL2_INIT6);
3106f520bb22SYouMin Chen 		/* MR11 */
3107f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 11,
3108f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
3109f520bb22SYouMin Chen 			      dramtype);
3110f520bb22SYouMin Chen 		writel(mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
3111f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x1a));
3112f520bb22SYouMin Chen 		/* MR12 */
3113f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 12,
3114f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR12_SHIFT & PCTL2_MR_MASK,
3115f520bb22SYouMin Chen 			      dramtype);
3116f520bb22SYouMin Chen 
3117f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3118f520bb22SYouMin Chen 			       DDR_PCTL2_INIT7);
3119f520bb22SYouMin Chen 		/* MR22 */
3120f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 22,
3121f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
3122f520bb22SYouMin Chen 			      dramtype);
3123f520bb22SYouMin Chen 		writel(mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
3124f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x1d));
3125f520bb22SYouMin Chen 		/* MR14 */
3126f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 14,
3127f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
3128f520bb22SYouMin Chen 			      dramtype);
3129f520bb22SYouMin Chen 		writel(mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
3130f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x1c));
3131f520bb22SYouMin Chen 	}
3132f520bb22SYouMin Chen 
3133f520bb22SYouMin Chen 	update_noc_timing(dram, sdram_params);
3134f520bb22SYouMin Chen }
3135f520bb22SYouMin Chen 
save_fsp_param(struct dram_info * dram,u32 dst_fsp,struct rv1126_sdram_params * sdram_params)3136f520bb22SYouMin Chen static void save_fsp_param(struct dram_info *dram, u32 dst_fsp,
3137f520bb22SYouMin Chen 			   struct rv1126_sdram_params *sdram_params)
3138f520bb22SYouMin Chen {
3139f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
3140f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
3141f520bb22SYouMin Chen 	struct rv1126_fsp_param *p_fsp_param = &fsp_param[dst_fsp];
3142f520bb22SYouMin Chen 	u32 temp, temp1;
3143f520bb22SYouMin Chen 	struct ddr2_3_4_lp2_3_info *ddr_info;
3144f520bb22SYouMin Chen 
3145f520bb22SYouMin Chen 	ddr_info = get_ddr_drv_odt_info(sdram_params->base.dramtype);
3146f520bb22SYouMin Chen 
3147f520bb22SYouMin Chen 	p_fsp_param->freq_mhz = sdram_params->base.ddr_freq;
3148f520bb22SYouMin Chen 
3149c2a03d5dSZhihuan He 	if (sdram_params->base.dramtype == LPDDR4 ||
3150c2a03d5dSZhihuan He 	    sdram_params->base.dramtype == LPDDR4X) {
3151f520bb22SYouMin Chen 		p_fsp_param->rd_odt_up_en = 0;
3152f520bb22SYouMin Chen 		p_fsp_param->rd_odt_down_en = 1;
3153f520bb22SYouMin Chen 	} else {
3154f520bb22SYouMin Chen 		p_fsp_param->rd_odt_up_en =
3155f520bb22SYouMin Chen 			ODT_INFO_PULLUP_EN(ddr_info->odt_info);
3156f520bb22SYouMin Chen 		p_fsp_param->rd_odt_down_en =
3157f520bb22SYouMin Chen 			ODT_INFO_PULLDOWN_EN(ddr_info->odt_info);
3158f520bb22SYouMin Chen 	}
3159f520bb22SYouMin Chen 
3160f520bb22SYouMin Chen 	if (p_fsp_param->rd_odt_up_en)
3161f520bb22SYouMin Chen 		p_fsp_param->rd_odt = readl(PHY_REG(phy_base, 0x111));
3162f520bb22SYouMin Chen 	else if (p_fsp_param->rd_odt_down_en)
3163f520bb22SYouMin Chen 		p_fsp_param->rd_odt = readl(PHY_REG(phy_base, 0x110));
3164f520bb22SYouMin Chen 	else
3165f520bb22SYouMin Chen 		p_fsp_param->rd_odt = 0;
3166f520bb22SYouMin Chen 	p_fsp_param->wr_dq_drv = readl(PHY_REG(phy_base, 0x112));
3167f520bb22SYouMin Chen 	p_fsp_param->wr_ca_drv = readl(PHY_REG(phy_base, 0x100));
3168f520bb22SYouMin Chen 	p_fsp_param->wr_ckcs_drv = readl(PHY_REG(phy_base, 0x102));
3169f520bb22SYouMin Chen 	p_fsp_param->vref_inner = readl(PHY_REG(phy_base, 0x128));
3170f520bb22SYouMin Chen 	p_fsp_param->vref_out = readl(PHY_REG(phy_base, 0x105));
3171f520bb22SYouMin Chen 
3172f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR3) {
3173f520bb22SYouMin Chen 		temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3174f520bb22SYouMin Chen 			     DDR_PCTL2_INIT3);
3175f520bb22SYouMin Chen 		temp = (temp >> PCTL2_DDR34_MR1_SHIFT) & PCTL2_MR_MASK;
31768e4f57b9SYouMin Chen 		p_fsp_param->ds_pdds = temp & DDR3_DS_MASK;
31778e4f57b9SYouMin Chen 		p_fsp_param->dq_odt = temp & DDR3_RTT_NOM_MASK;
3178f520bb22SYouMin Chen 		p_fsp_param->ca_odt = p_fsp_param->dq_odt;
3179f520bb22SYouMin Chen 	} else if (sdram_params->base.dramtype == DDR4) {
3180f520bb22SYouMin Chen 		temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3181f520bb22SYouMin Chen 			     DDR_PCTL2_INIT3);
3182f520bb22SYouMin Chen 		temp = (temp >> PCTL2_DDR34_MR1_SHIFT) & PCTL2_MR_MASK;
31838e4f57b9SYouMin Chen 		p_fsp_param->ds_pdds = temp & DDR4_DS_MASK;
31848e4f57b9SYouMin Chen 		p_fsp_param->dq_odt = temp & DDR4_RTT_NOM_MASK;
3185f520bb22SYouMin Chen 		p_fsp_param->ca_odt = p_fsp_param->dq_odt;
3186f520bb22SYouMin Chen 	} else if (sdram_params->base.dramtype == LPDDR3) {
3187f520bb22SYouMin Chen 		temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3188f520bb22SYouMin Chen 			     DDR_PCTL2_INIT4);
3189f520bb22SYouMin Chen 		temp = (temp >> PCTL2_LPDDR234_MR3_SHIFT) & PCTL2_MR_MASK;
3190f520bb22SYouMin Chen 		p_fsp_param->ds_pdds = temp & 0xf;
3191f520bb22SYouMin Chen 
3192f520bb22SYouMin Chen 		p_fsp_param->dq_odt = lp3_odt_value;
3193f520bb22SYouMin Chen 		p_fsp_param->ca_odt = p_fsp_param->dq_odt;
3194c2a03d5dSZhihuan He 	} else if (sdram_params->base.dramtype == LPDDR4 ||
3195c2a03d5dSZhihuan He 		   sdram_params->base.dramtype == LPDDR4X) {
3196f520bb22SYouMin Chen 		temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3197f520bb22SYouMin Chen 			     DDR_PCTL2_INIT4);
3198f520bb22SYouMin Chen 		temp = (temp >> PCTL2_LPDDR234_MR3_SHIFT) & PCTL2_MR_MASK;
31998e4f57b9SYouMin Chen 		p_fsp_param->ds_pdds = temp & LPDDR4_PDDS_MASK;
3200f520bb22SYouMin Chen 
3201f520bb22SYouMin Chen 		temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3202f520bb22SYouMin Chen 			     DDR_PCTL2_INIT6);
3203f520bb22SYouMin Chen 		temp = (temp >> PCTL2_LPDDR4_MR11_SHIFT) & PCTL2_MR_MASK;
32048e4f57b9SYouMin Chen 		p_fsp_param->dq_odt = temp & LPDDR4_DQODT_MASK;
32058e4f57b9SYouMin Chen 		p_fsp_param->ca_odt = temp & LPDDR4_CAODT_MASK;
3206f520bb22SYouMin Chen 
3207f520bb22SYouMin Chen 		temp = MAX(readl(PHY_REG(phy_base, 0x3ae)),
3208f520bb22SYouMin Chen 			   readl(PHY_REG(phy_base, 0x3ce)));
3209f520bb22SYouMin Chen 		temp1 = MIN(readl(PHY_REG(phy_base, 0x3be)),
3210f520bb22SYouMin Chen 			    readl(PHY_REG(phy_base, 0x3de)));
3211f520bb22SYouMin Chen 		p_fsp_param->vref_ca[0] = (temp + temp1) / 2;
3212f520bb22SYouMin Chen 		temp = MAX(readl(PHY_REG(phy_base, 0x3af)),
3213f520bb22SYouMin Chen 			   readl(PHY_REG(phy_base, 0x3cf)));
3214f520bb22SYouMin Chen 		temp1 = MIN(readl(PHY_REG(phy_base, 0x3bf)),
3215f520bb22SYouMin Chen 			    readl(PHY_REG(phy_base, 0x3df)));
3216f520bb22SYouMin Chen 		p_fsp_param->vref_ca[1] = (temp + temp1) / 2;
3217f520bb22SYouMin Chen 		p_fsp_param->vref_ca[0] |=
3218f520bb22SYouMin Chen 			(readl(PHY_REG(phy_base, 0x1e)) & BIT(6));
3219f520bb22SYouMin Chen 		p_fsp_param->vref_ca[1] |=
3220f520bb22SYouMin Chen 			(readl(PHY_REG(phy_base, 0x1e)) & BIT(6));
3221f520bb22SYouMin Chen 
3222f520bb22SYouMin Chen 		p_fsp_param->lp4_drv_pd_en = (readl(PHY_REG(phy_base, 0x114)) >>
3223f520bb22SYouMin Chen 					      3) & 0x1;
3224f520bb22SYouMin Chen 	}
3225f520bb22SYouMin Chen 
3226f520bb22SYouMin Chen 	p_fsp_param->noc_timings.ddrtiminga0 =
3227f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.ddrtiminga0;
3228f520bb22SYouMin Chen 	p_fsp_param->noc_timings.ddrtimingb0 =
3229f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.ddrtimingb0;
3230f520bb22SYouMin Chen 	p_fsp_param->noc_timings.ddrtimingc0 =
3231f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.ddrtimingc0;
3232f520bb22SYouMin Chen 	p_fsp_param->noc_timings.devtodev0 =
3233f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.devtodev0;
3234f520bb22SYouMin Chen 	p_fsp_param->noc_timings.ddrmode =
3235f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.ddrmode;
3236f520bb22SYouMin Chen 	p_fsp_param->noc_timings.ddr4timing =
3237f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.ddr4timing;
3238f520bb22SYouMin Chen 	p_fsp_param->noc_timings.agingx0 =
3239f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.agingx0;
3240f520bb22SYouMin Chen 	p_fsp_param->noc_timings.aging0 =
3241f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.aging0;
3242f520bb22SYouMin Chen 	p_fsp_param->noc_timings.aging1 =
3243f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.aging1;
3244f520bb22SYouMin Chen 	p_fsp_param->noc_timings.aging2 =
3245f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.aging2;
3246f520bb22SYouMin Chen 	p_fsp_param->noc_timings.aging3 =
3247f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.aging3;
3248f520bb22SYouMin Chen 
3249f520bb22SYouMin Chen 	p_fsp_param->flag = FSP_FLAG;
3250f520bb22SYouMin Chen }
3251f520bb22SYouMin Chen 
3252958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT
copy_fsp_param_to_ddr(void)3253f520bb22SYouMin Chen static void copy_fsp_param_to_ddr(void)
3254f520bb22SYouMin Chen {
3255f520bb22SYouMin Chen 	memcpy((void *)FSP_PARAM_STORE_ADDR, (void *)&fsp_param,
3256f520bb22SYouMin Chen 	       sizeof(fsp_param));
3257f520bb22SYouMin Chen }
3258d3f5f12cSTang Yun ping #endif
3259f520bb22SYouMin Chen 
pctl_modify_trfc(struct ddr_pctl_regs * pctl_regs,struct sdram_cap_info * cap_info,u32 dram_type,u32 freq)3260e2dc1cc0SWesley Yao static void pctl_modify_trfc(struct ddr_pctl_regs *pctl_regs,
3261e2dc1cc0SWesley Yao 			     struct sdram_cap_info *cap_info, u32 dram_type,
3262e2dc1cc0SWesley Yao 			     u32 freq)
3263e2dc1cc0SWesley Yao {
3264e2dc1cc0SWesley Yao 	u64 cs0_cap;
3265e2dc1cc0SWesley Yao 	u32 die_cap;
3266e2dc1cc0SWesley Yao 	u32 trfc_ns, trfc4_ns;
3267e2dc1cc0SWesley Yao 	u32 trfc, txsnr;
3268e2dc1cc0SWesley Yao 	u32 txs_abort_fast = 0;
3269e2dc1cc0SWesley Yao 	u32 tmp;
3270e2dc1cc0SWesley Yao 
3271e2dc1cc0SWesley Yao 	cs0_cap = sdram_get_cs_cap(cap_info, 0, dram_type);
3272e2dc1cc0SWesley Yao 	die_cap = (u32)(cs0_cap >> (20 + (cap_info->bw - cap_info->dbw)));
3273e2dc1cc0SWesley Yao 
3274e2dc1cc0SWesley Yao 	switch (dram_type) {
3275e2dc1cc0SWesley Yao 	case DDR3:
3276e2dc1cc0SWesley Yao 		if (die_cap <= DIE_CAP_512MBIT)
3277e2dc1cc0SWesley Yao 			trfc_ns = 90;
3278e2dc1cc0SWesley Yao 		else if (die_cap <= DIE_CAP_1GBIT)
3279e2dc1cc0SWesley Yao 			trfc_ns = 110;
3280e2dc1cc0SWesley Yao 		else if (die_cap <= DIE_CAP_2GBIT)
3281e2dc1cc0SWesley Yao 			trfc_ns = 160;
3282e2dc1cc0SWesley Yao 		else if (die_cap <= DIE_CAP_4GBIT)
3283e2dc1cc0SWesley Yao 			trfc_ns = 260;
3284e2dc1cc0SWesley Yao 		else
3285e2dc1cc0SWesley Yao 			trfc_ns = 350;
3286e2dc1cc0SWesley Yao 		txsnr = MAX(5, ((trfc_ns + 10) * freq + 999) / 1000);
3287e2dc1cc0SWesley Yao 		break;
3288e2dc1cc0SWesley Yao 
3289e2dc1cc0SWesley Yao 	case DDR4:
3290e2dc1cc0SWesley Yao 		if (die_cap <= DIE_CAP_2GBIT) {
3291e2dc1cc0SWesley Yao 			trfc_ns = 160;
3292e2dc1cc0SWesley Yao 			trfc4_ns = 90;
3293e2dc1cc0SWesley Yao 		} else if (die_cap <= DIE_CAP_4GBIT) {
3294e2dc1cc0SWesley Yao 			trfc_ns = 260;
3295e2dc1cc0SWesley Yao 			trfc4_ns = 110;
3296e2dc1cc0SWesley Yao 		} else if (die_cap <= DIE_CAP_8GBIT) {
3297e2dc1cc0SWesley Yao 			trfc_ns = 350;
3298e2dc1cc0SWesley Yao 			trfc4_ns = 160;
3299e2dc1cc0SWesley Yao 		} else {
3300e2dc1cc0SWesley Yao 			trfc_ns = 550;
3301e2dc1cc0SWesley Yao 			trfc4_ns = 260;
3302e2dc1cc0SWesley Yao 		}
3303e2dc1cc0SWesley Yao 		txsnr = ((trfc_ns + 10) * freq + 999) / 1000;
3304e2dc1cc0SWesley Yao 		txs_abort_fast = ((trfc4_ns + 10) * freq + 999) / 1000;
3305e2dc1cc0SWesley Yao 		break;
3306e2dc1cc0SWesley Yao 
3307e2dc1cc0SWesley Yao 	case LPDDR3:
3308e2dc1cc0SWesley Yao 		if (die_cap <= DIE_CAP_4GBIT)
3309e2dc1cc0SWesley Yao 			trfc_ns = 130;
3310e2dc1cc0SWesley Yao 		else
3311e2dc1cc0SWesley Yao 			trfc_ns = 210;
3312e2dc1cc0SWesley Yao 		txsnr = MAX(2, ((trfc_ns + 10) * freq + 999) / 1000);
3313e2dc1cc0SWesley Yao 		break;
3314e2dc1cc0SWesley Yao 
3315e2dc1cc0SWesley Yao 	case LPDDR4:
3316e2dc1cc0SWesley Yao 	case LPDDR4X:
3317957ed784SWesley Yao 		if (die_cap <= DIE_CAP_2GBIT)
3318e2dc1cc0SWesley Yao 			trfc_ns = 130;
3319957ed784SWesley Yao 		else if (die_cap <= DIE_CAP_4GBIT)
3320e2dc1cc0SWesley Yao 			trfc_ns = 180;
3321957ed784SWesley Yao 		else if (die_cap <= DIE_CAP_8GBIT)
3322e2dc1cc0SWesley Yao 			trfc_ns = 280;
3323e2dc1cc0SWesley Yao 		else
3324e2dc1cc0SWesley Yao 			trfc_ns = 380;
3325e2dc1cc0SWesley Yao 		txsnr = MAX(2, ((trfc_ns + 10) * freq + 999) / 1000);
3326e2dc1cc0SWesley Yao 		break;
3327e2dc1cc0SWesley Yao 
3328e2dc1cc0SWesley Yao 	default:
3329e2dc1cc0SWesley Yao 		return;
3330e2dc1cc0SWesley Yao 	}
3331e2dc1cc0SWesley Yao 	trfc = (trfc_ns * freq + 999) / 1000;
3332e2dc1cc0SWesley Yao 
3333e2dc1cc0SWesley Yao 	for (int i = 0; pctl_regs->pctl[i][0] != 0xffffffff; i++) {
3334e2dc1cc0SWesley Yao 		switch (pctl_regs->pctl[i][0]) {
3335e2dc1cc0SWesley Yao 		case DDR_PCTL2_RFSHTMG:
3336e2dc1cc0SWesley Yao 			tmp = pctl_regs->pctl[i][1];
3337e2dc1cc0SWesley Yao 			/* t_rfc_min */
3338e2dc1cc0SWesley Yao 			tmp &= ~((u32)0x3ff);
3339e2dc1cc0SWesley Yao 			tmp |= ((trfc + 1) / 2) & 0x3ff;
3340e2dc1cc0SWesley Yao 			pctl_regs->pctl[i][1] = tmp;
3341e2dc1cc0SWesley Yao 			break;
3342e2dc1cc0SWesley Yao 
3343e2dc1cc0SWesley Yao 		case DDR_PCTL2_DRAMTMG8:
3344e2dc1cc0SWesley Yao 			if (dram_type == DDR3 || dram_type == DDR4) {
3345e2dc1cc0SWesley Yao 				tmp = pctl_regs->pctl[i][1];
3346e2dc1cc0SWesley Yao 				/* t_xs_x32 */
3347e2dc1cc0SWesley Yao 				tmp &= ~((u32)0x7f);
334856f3e686SWesley Yao 				tmp |= ((txsnr + 63) / 64 + 1) & 0x7f;
3349e2dc1cc0SWesley Yao 
3350e2dc1cc0SWesley Yao 				if (dram_type == DDR4) {
3351e2dc1cc0SWesley Yao 					/* t_xs_abort_x32 */
3352e2dc1cc0SWesley Yao 					tmp &= ~((u32)(0x7f << 16));
335356f3e686SWesley Yao 					tmp |= (((txs_abort_fast + 63) / 64 + 1) & 0x7f) << 16;
3354e2dc1cc0SWesley Yao 					/* t_xs_fast_x32 */
3355e2dc1cc0SWesley Yao 					tmp &= ~((u32)(0x7f << 24));
335656f3e686SWesley Yao 					tmp |= (((txs_abort_fast + 63) / 64 + 1) & 0x7f) << 24;
3357e2dc1cc0SWesley Yao 				}
3358e2dc1cc0SWesley Yao 
3359e2dc1cc0SWesley Yao 				pctl_regs->pctl[i][1] = tmp;
3360e2dc1cc0SWesley Yao 			}
3361e2dc1cc0SWesley Yao 			break;
3362e2dc1cc0SWesley Yao 
3363e2dc1cc0SWesley Yao 		case DDR_PCTL2_DRAMTMG14:
3364e2dc1cc0SWesley Yao 			if (dram_type == LPDDR3 ||
3365e2dc1cc0SWesley Yao 			    dram_type == LPDDR4 || dram_type == LPDDR4X) {
3366e2dc1cc0SWesley Yao 				tmp = pctl_regs->pctl[i][1];
3367e2dc1cc0SWesley Yao 				/* t_xsr */
3368e2dc1cc0SWesley Yao 				tmp &= ~((u32)0xfff);
3369e2dc1cc0SWesley Yao 				tmp |= ((txsnr + 1) / 2) & 0xfff;
3370e2dc1cc0SWesley Yao 				pctl_regs->pctl[i][1] = tmp;
3371e2dc1cc0SWesley Yao 			}
3372e2dc1cc0SWesley Yao 			break;
3373e2dc1cc0SWesley Yao 
3374e2dc1cc0SWesley Yao 		default:
3375e2dc1cc0SWesley Yao 			break;
3376e2dc1cc0SWesley Yao 		}
3377e2dc1cc0SWesley Yao 	}
3378e2dc1cc0SWesley Yao }
3379e2dc1cc0SWesley Yao 
ddr_set_rate(struct dram_info * dram,struct rv1126_sdram_params * sdram_params,u32 freq,u32 cur_freq,u32 dst_fsp,u32 dst_fsp_lp4,u32 training_en)3380f520bb22SYouMin Chen void ddr_set_rate(struct dram_info *dram,
3381f520bb22SYouMin Chen 		  struct rv1126_sdram_params *sdram_params,
3382f520bb22SYouMin Chen 		  u32 freq, u32 cur_freq, u32 dst_fsp,
3383f520bb22SYouMin Chen 		  u32 dst_fsp_lp4, u32 training_en)
3384f520bb22SYouMin Chen {
3385f520bb22SYouMin Chen 	u32 dest_dll_off, cur_init3, dst_init3, cur_fsp, cur_dll_off;
3386f520bb22SYouMin Chen 	u32 mr_tmp;
3387f520bb22SYouMin Chen 	u32 lp_stat;
3388f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
3389f520bb22SYouMin Chen 	struct rv1126_sdram_params *sdram_params_new;
3390f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
3391f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
3392a6422204SWesley Yao 	int delay = 1000;
3393f520bb22SYouMin Chen 
3394f520bb22SYouMin Chen 	lp_stat = low_power_update(dram, 0);
3395f520bb22SYouMin Chen 	sdram_params_new = get_default_sdram_config(freq);
3396f520bb22SYouMin Chen 	sdram_params_new->ch.cap_info.rank = sdram_params->ch.cap_info.rank;
339738b16f08SYouMin Chen 	sdram_params_new->ch.cap_info.bw = sdram_params->ch.cap_info.bw;
3398f520bb22SYouMin Chen 
3399e2dc1cc0SWesley Yao 	pctl_modify_trfc(&sdram_params_new->pctl_regs,
3400e2dc1cc0SWesley Yao 			 &sdram_params->ch.cap_info, dramtype, freq);
3401f520bb22SYouMin Chen 	pre_set_rate(dram, sdram_params_new, dst_fsp, dst_fsp_lp4);
3402f520bb22SYouMin Chen 
3403f520bb22SYouMin Chen 	while ((readl(pctl_base + DDR_PCTL2_STAT) &
3404f520bb22SYouMin Chen 			 PCTL2_OPERATING_MODE_MASK) ==
3405f520bb22SYouMin Chen 			 PCTL2_OPERATING_MODE_SR)
3406f520bb22SYouMin Chen 		continue;
3407f520bb22SYouMin Chen 
3408f520bb22SYouMin Chen 	dest_dll_off = 0;
3409f520bb22SYouMin Chen 	dst_init3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3410f520bb22SYouMin Chen 			  DDR_PCTL2_INIT3);
3411f520bb22SYouMin Chen 	if ((dramtype == DDR3 && (dst_init3 & 1)) ||
3412f520bb22SYouMin Chen 	    (dramtype == DDR4 && !(dst_init3 & 1)))
3413f520bb22SYouMin Chen 		dest_dll_off = 1;
3414f520bb22SYouMin Chen 
3415f520bb22SYouMin Chen 	cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
3416f520bb22SYouMin Chen 	cur_init3 = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
3417f520bb22SYouMin Chen 			  DDR_PCTL2_INIT3);
3418f520bb22SYouMin Chen 	cur_init3 &= PCTL2_MR_MASK;
3419f520bb22SYouMin Chen 	cur_dll_off = 1;
3420f520bb22SYouMin Chen 	if ((dramtype == DDR3 && !(cur_init3 & 1)) ||
3421f520bb22SYouMin Chen 	    (dramtype == DDR4 && (cur_init3 & 1)))
3422f520bb22SYouMin Chen 		cur_dll_off = 0;
3423f520bb22SYouMin Chen 
3424f520bb22SYouMin Chen 	if (!cur_dll_off) {
3425f520bb22SYouMin Chen 		if (dramtype == DDR3)
3426f520bb22SYouMin Chen 			cur_init3 |= 1;
3427f520bb22SYouMin Chen 		else
3428f520bb22SYouMin Chen 			cur_init3 &= ~1;
3429f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 2, 1, cur_init3, dramtype);
3430f520bb22SYouMin Chen 	}
3431f520bb22SYouMin Chen 
3432f520bb22SYouMin Chen 	setbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3,
3433f520bb22SYouMin Chen 		     PCTL2_DIS_AUTO_REFRESH);
3434f520bb22SYouMin Chen 	update_refresh_reg(dram);
3435f520bb22SYouMin Chen 
3436f4f57f8eSTang Yun ping 	enter_sr(dram, 1);
3437f520bb22SYouMin Chen 
3438f520bb22SYouMin Chen 	writel(PMUGRF_CON_DDRPHY_BUFFEREN_MASK |
3439f520bb22SYouMin Chen 	       PMUGRF_CON_DDRPHY_BUFFEREN_EN,
3440df8389e3STang Yun ping 	       &dram->pmugrf->soc_con[0]);
3441f520bb22SYouMin Chen 	sw_set_req(dram);
3442f520bb22SYouMin Chen 	clrbits_le32(pctl_base + DDR_PCTL2_DFIMISC,
3443f520bb22SYouMin Chen 		     PCTL2_DFI_INIT_COMPLETE_EN);
3444f520bb22SYouMin Chen 	sw_set_ack(dram);
3445f520bb22SYouMin Chen 
3446f520bb22SYouMin Chen 	sw_set_req(dram);
3447f520bb22SYouMin Chen 	if ((dramtype == DDR3 || dramtype == DDR4) && dest_dll_off)
3448f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_MSTR, PCTL2_DLL_OFF_MODE);
3449f520bb22SYouMin Chen 	else
3450f520bb22SYouMin Chen 		clrbits_le32(pctl_base + DDR_PCTL2_MSTR, PCTL2_DLL_OFF_MODE);
3451f520bb22SYouMin Chen 
3452f520bb22SYouMin Chen 	setbits_le32(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + DDR_PCTL2_ZQCTL0,
3453f520bb22SYouMin Chen 		     PCTL2_DIS_SRX_ZQCL);
3454f520bb22SYouMin Chen 	setbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_ZQCTL0,
3455f520bb22SYouMin Chen 		     PCTL2_DIS_SRX_ZQCL);
3456f520bb22SYouMin Chen 	sw_set_ack(dram);
3457f520bb22SYouMin Chen 
3458f520bb22SYouMin Chen 	writel(DDR_MSCH_EN_MASK | (0x1 << DDR_MSCH_EN_SHIFT),
3459df8389e3STang Yun ping 	       &dram->cru->clkgate_con[21]);
3460f520bb22SYouMin Chen 	writel(CLK_DDR_UPCTL_EN_MASK | ACLK_DDR_UPCTL_EN_MASK |
3461f520bb22SYouMin Chen 					(0x1 << CLK_DDR_UPCTL_EN_SHIFT) |
3462f520bb22SYouMin Chen 					(0x1 << ACLK_DDR_UPCTL_EN_SHIFT),
3463f520bb22SYouMin Chen 			BUS_SGRF_BASE_ADDR + SGRF_SOC_CON12);
3464f520bb22SYouMin Chen 
3465f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET | DIGITAL_DERESET);
3466f520bb22SYouMin Chen 	rkclk_set_dpll(dram, freq * MHz / 2);
3467f520bb22SYouMin Chen 	phy_pll_set(dram, freq * MHz, 0);
3468f520bb22SYouMin Chen 	phy_pll_set(dram, freq * MHz, 1);
3469f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET | DIGITAL_DERESET);
3470f520bb22SYouMin Chen 
3471f520bb22SYouMin Chen 	writel(PMUGRF_CON_DDRPHY_BUFFEREN_MASK |
3472f520bb22SYouMin Chen 			PMUGRF_CON_DDRPHY_BUFFEREN_DIS,
3473df8389e3STang Yun ping 			&dram->pmugrf->soc_con[0]);
3474f520bb22SYouMin Chen 	writel(DDR_MSCH_EN_MASK | (0x0 << DDR_MSCH_EN_SHIFT),
3475df8389e3STang Yun ping 	       &dram->cru->clkgate_con[21]);
3476f520bb22SYouMin Chen 	writel(CLK_DDR_UPCTL_EN_MASK | ACLK_DDR_UPCTL_EN_MASK |
3477f520bb22SYouMin Chen 					(0x0 << CLK_DDR_UPCTL_EN_SHIFT) |
3478f520bb22SYouMin Chen 					(0x0 << ACLK_DDR_UPCTL_EN_SHIFT),
3479f520bb22SYouMin Chen 			BUS_SGRF_BASE_ADDR + SGRF_SOC_CON12);
3480f520bb22SYouMin Chen 	while ((readl(pctl_base + DDR_PCTL2_DFISTAT) &
3481a6422204SWesley Yao 	       PCTL2_DFI_INIT_COMPLETE) != PCTL2_DFI_INIT_COMPLETE) {
3482a6422204SWesley Yao 		udelay(1);
3483a6422204SWesley Yao 		if (delay-- <= 0) {
3484a6422204SWesley Yao 			printascii("ERROR: Cannot wait DFI_INIT_COMPLETE\n");
3485a6422204SWesley Yao 			while (1)
3486a6422204SWesley Yao 				;
3487a6422204SWesley Yao 		}
3488a6422204SWesley Yao 	}
3489f520bb22SYouMin Chen 
3490f520bb22SYouMin Chen 	sw_set_req(dram);
3491f520bb22SYouMin Chen 	setbits_le32(pctl_base + DDR_PCTL2_MSTR, 0x1 << 29);
3492f520bb22SYouMin Chen 	clrsetbits_le32(pctl_base + DDR_PCTL2_MSTR2, 0x3, dst_fsp);
3493f520bb22SYouMin Chen 	sw_set_ack(dram);
3494f520bb22SYouMin Chen 	update_refresh_reg(dram);
3495f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0xc), 0x3 << 2, dst_fsp << 2);
3496f520bb22SYouMin Chen 
3497f4f57f8eSTang Yun ping 	enter_sr(dram, 0);
3498f520bb22SYouMin Chen 
3499f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
3500f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
3501f520bb22SYouMin Chen 
3502f520bb22SYouMin Chen 	mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_INIT4);
3503f520bb22SYouMin Chen 	if (dramtype == LPDDR3) {
3504f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 1,
3505f520bb22SYouMin Chen 			      (dst_init3 >> PCTL2_LPDDR234_MR1_SHIFT) &
3506f520bb22SYouMin Chen 			      PCTL2_MR_MASK,
3507f520bb22SYouMin Chen 			      dramtype);
3508f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 2, dst_init3 & PCTL2_MR_MASK,
3509f520bb22SYouMin Chen 			      dramtype);
3510f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 3,
3511f520bb22SYouMin Chen 			      (mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT) &
3512f520bb22SYouMin Chen 			      PCTL2_MR_MASK,
3513f520bb22SYouMin Chen 			      dramtype);
3514f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 11, lp3_odt_value, dramtype);
3515f520bb22SYouMin Chen 	} else if ((dramtype == DDR3) || (dramtype == DDR4)) {
3516f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 1, dst_init3 & PCTL2_MR_MASK,
3517f520bb22SYouMin Chen 			      dramtype);
3518f520bb22SYouMin Chen 		if (!dest_dll_off) {
3519f520bb22SYouMin Chen 			pctl_write_mr(dram->pctl, 3, 0,
3520f520bb22SYouMin Chen 				      ((dst_init3 >> PCTL2_DDR34_MR0_SHIFT) &
3521f520bb22SYouMin Chen 				      PCTL2_MR_MASK) | DDR3_DLL_RESET,
3522f520bb22SYouMin Chen 				      dramtype);
3523f520bb22SYouMin Chen 			udelay(2);
3524f520bb22SYouMin Chen 		}
3525f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 0,
3526f520bb22SYouMin Chen 			      (dst_init3 >> PCTL2_DDR34_MR0_SHIFT &
3527f520bb22SYouMin Chen 			       PCTL2_MR_MASK) & (~DDR3_DLL_RESET),
3528f520bb22SYouMin Chen 			      dramtype);
3529f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 2,
3530f520bb22SYouMin Chen 			      ((mr_tmp >> PCTL2_DDR34_MR2_SHIFT) &
3531f520bb22SYouMin Chen 			       PCTL2_MR_MASK), dramtype);
3532f520bb22SYouMin Chen 		if (dramtype == DDR4) {
3533f520bb22SYouMin Chen 			pctl_write_mr(dram->pctl, 3, 3, mr_tmp & PCTL2_MR_MASK,
3534f520bb22SYouMin Chen 				      dramtype);
3535f520bb22SYouMin Chen 			mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3536f520bb22SYouMin Chen 				       DDR_PCTL2_INIT6);
3537f520bb22SYouMin Chen 			pctl_write_mr(dram->pctl, 3, 4,
3538f520bb22SYouMin Chen 				      (mr_tmp >> PCTL2_DDR4_MR4_SHIFT) &
3539f520bb22SYouMin Chen 				       PCTL2_MR_MASK,
3540f520bb22SYouMin Chen 				      dramtype);
3541f520bb22SYouMin Chen 			pctl_write_mr(dram->pctl, 3, 5,
3542f520bb22SYouMin Chen 				      mr_tmp >> PCTL2_DDR4_MR5_SHIFT &
3543f520bb22SYouMin Chen 				      PCTL2_MR_MASK,
3544f520bb22SYouMin Chen 				      dramtype);
3545f520bb22SYouMin Chen 
3546f520bb22SYouMin Chen 			mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3547f520bb22SYouMin Chen 				       DDR_PCTL2_INIT7);
3548df9ee7ebSWesley Yao 			/* updata ddr4 vrefdq */
3549df9ee7ebSWesley Yao 			pctl_write_mr(dram->pctl, 3, 6,
3550df9ee7ebSWesley Yao 				      (mr_tmp | (0x1 << 7)) >> PCTL2_DDR4_MR6_SHIFT &
3551df9ee7ebSWesley Yao 				      PCTL2_MR_MASK, dramtype);
3552df9ee7ebSWesley Yao 			pctl_write_mr(dram->pctl, 3, 6,
3553df9ee7ebSWesley Yao 				      (mr_tmp | (0x1 << 7)) >> PCTL2_DDR4_MR6_SHIFT &
3554df9ee7ebSWesley Yao 				      PCTL2_MR_MASK, dramtype);
3555f520bb22SYouMin Chen 			pctl_write_mr(dram->pctl, 3, 6,
3556f520bb22SYouMin Chen 				      mr_tmp >> PCTL2_DDR4_MR6_SHIFT &
3557f520bb22SYouMin Chen 				      PCTL2_MR_MASK,
3558f520bb22SYouMin Chen 				      dramtype);
3559f520bb22SYouMin Chen 		}
3560c2a03d5dSZhihuan He 	} else if (dramtype == LPDDR4 || dramtype == LPDDR4X) {
3561f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 13,
3562f520bb22SYouMin Chen 			      ((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
3563f520bb22SYouMin Chen 			       PCTL2_MR_MASK) & (~(BIT(7)))) |
3564f520bb22SYouMin Chen 			      dst_fsp_lp4 << 7, dramtype);
3565f520bb22SYouMin Chen 	}
3566f4f57f8eSTang Yun ping 	clrbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3,
3567f4f57f8eSTang Yun ping 		     PCTL2_DIS_AUTO_REFRESH);
3568f4f57f8eSTang Yun ping 	update_refresh_reg(dram);
3569f520bb22SYouMin Chen 
3570f520bb22SYouMin Chen 	/* training */
3571f520bb22SYouMin Chen 	high_freq_training(dram, sdram_params_new, dst_fsp);
3572f520bb22SYouMin Chen 	low_power_update(dram, lp_stat);
3573f520bb22SYouMin Chen 
3574f520bb22SYouMin Chen 	save_fsp_param(dram, dst_fsp, sdram_params_new);
3575f520bb22SYouMin Chen }
3576f520bb22SYouMin Chen 
ddr_set_rate_for_fsp(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)3577f520bb22SYouMin Chen static void ddr_set_rate_for_fsp(struct dram_info *dram,
3578f520bb22SYouMin Chen 				 struct rv1126_sdram_params *sdram_params)
3579f520bb22SYouMin Chen {
3580f520bb22SYouMin Chen 	struct ddr2_3_4_lp2_3_info *ddr_info;
3581d3f5f12cSTang Yun ping 	u32 f0;
3582f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
3583958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT
3584d3f5f12cSTang Yun ping 	u32 f1, f2, f3;
3585d3f5f12cSTang Yun ping #endif
3586f520bb22SYouMin Chen 
3587f520bb22SYouMin Chen 	ddr_info = get_ddr_drv_odt_info(dramtype);
3588f520bb22SYouMin Chen 	if (!ddr_info)
3589f520bb22SYouMin Chen 		return;
3590f520bb22SYouMin Chen 
3591d3f5f12cSTang Yun ping 	f0 = (ddr_info->ddr_freq0_1 >> DDR_FREQ_F0_SHIFT) &
3592d3f5f12cSTang Yun ping 	     DDR_FREQ_MASK;
3593d3f5f12cSTang Yun ping 
3594958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT
3595f520bb22SYouMin Chen 	memset((void *)FSP_PARAM_STORE_ADDR, 0, sizeof(fsp_param));
3596f520bb22SYouMin Chen 	memset((void *)&fsp_param, 0, sizeof(fsp_param));
3597f520bb22SYouMin Chen 
3598f520bb22SYouMin Chen 	f1 = (ddr_info->ddr_freq0_1 >> DDR_FREQ_F1_SHIFT) &
3599f520bb22SYouMin Chen 	     DDR_FREQ_MASK;
3600f520bb22SYouMin Chen 	f2 = (ddr_info->ddr_freq2_3 >> DDR_FREQ_F2_SHIFT) &
3601f520bb22SYouMin Chen 	     DDR_FREQ_MASK;
3602f520bb22SYouMin Chen 	f3 = (ddr_info->ddr_freq2_3 >> DDR_FREQ_F3_SHIFT) &
3603f520bb22SYouMin Chen 	     DDR_FREQ_MASK;
3604d3f5f12cSTang Yun ping #endif
3605f520bb22SYouMin Chen 
3606f520bb22SYouMin Chen 	if (get_wrlvl_val(dram, sdram_params))
3607f520bb22SYouMin Chen 		printascii("get wrlvl value fail\n");
3608d3f5f12cSTang Yun ping 
3609958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT
3610f876ce9bSTang Yun ping 	printascii("change to: ");
3611f520bb22SYouMin Chen 	printdec(f1);
3612f520bb22SYouMin Chen 	printascii("MHz\n");
3613f520bb22SYouMin Chen 	ddr_set_rate(&dram_info, sdram_params, f1,
3614f520bb22SYouMin Chen 		     sdram_params->base.ddr_freq, 1, 1, 1);
3615f876ce9bSTang Yun ping 	printascii("change to: ");
3616f520bb22SYouMin Chen 	printdec(f2);
3617f520bb22SYouMin Chen 	printascii("MHz\n");
3618f520bb22SYouMin Chen 	ddr_set_rate(&dram_info, sdram_params, f2, f1, 2, 0, 1);
3619f876ce9bSTang Yun ping 	printascii("change to: ");
3620f520bb22SYouMin Chen 	printdec(f3);
3621f520bb22SYouMin Chen 	printascii("MHz\n");
3622f520bb22SYouMin Chen 	ddr_set_rate(&dram_info, sdram_params, f3, f2, 3, 1, 1);
3623d3f5f12cSTang Yun ping #endif
3624f876ce9bSTang Yun ping 	printascii("change to: ");
3625f520bb22SYouMin Chen 	printdec(f0);
3626f876ce9bSTang Yun ping 	printascii("MHz(final freq)\n");
3627958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT
3628f520bb22SYouMin Chen 	ddr_set_rate(&dram_info, sdram_params, f0, f3, 0, 0, 1);
3629d3f5f12cSTang Yun ping #else
3630d3f5f12cSTang Yun ping 	ddr_set_rate(&dram_info, sdram_params, f0, sdram_params->base.ddr_freq, 1, 1, 1);
3631d3f5f12cSTang Yun ping #endif
3632f520bb22SYouMin Chen }
3633f520bb22SYouMin Chen 
get_uart_config(void)3634f520bb22SYouMin Chen int get_uart_config(void)
3635f520bb22SYouMin Chen {
3636f520bb22SYouMin Chen 	struct sdram_head_info_index_v2 *index =
3637f520bb22SYouMin Chen 		(struct sdram_head_info_index_v2 *)common_info;
3638f520bb22SYouMin Chen 	struct global_info *gbl_info;
3639f520bb22SYouMin Chen 
3640f520bb22SYouMin Chen 	gbl_info = (struct global_info *)((void *)common_info +
3641f520bb22SYouMin Chen 		index->global_index.offset * 4);
3642f520bb22SYouMin Chen 
3643f520bb22SYouMin Chen 	return gbl_info->uart_info;
3644f520bb22SYouMin Chen }
3645f520bb22SYouMin Chen 
3646f520bb22SYouMin Chen /* return: 0 = success, other = fail */
sdram_init(void)3647f520bb22SYouMin Chen int sdram_init(void)
3648f520bb22SYouMin Chen {
3649f520bb22SYouMin Chen 	struct rv1126_sdram_params *sdram_params;
3650f520bb22SYouMin Chen 	int ret = 0;
3651f520bb22SYouMin Chen 	struct sdram_head_info_index_v2 *index =
3652f520bb22SYouMin Chen 		(struct sdram_head_info_index_v2 *)common_info;
3653f520bb22SYouMin Chen 	struct global_info *gbl_info;
3654f520bb22SYouMin Chen 
3655f520bb22SYouMin Chen 	dram_info.phy = (void *)DDR_PHY_BASE_ADDR;
3656f520bb22SYouMin Chen 	dram_info.pctl = (void *)UPCTL2_BASE_ADDR;
3657f520bb22SYouMin Chen 	dram_info.grf = (void *)GRF_BASE_ADDR;
3658f520bb22SYouMin Chen 	dram_info.cru = (void *)CRU_BASE_ADDR;
3659f520bb22SYouMin Chen 	dram_info.msch = (void *)SERVER_MSCH_BASE_ADDR;
3660f520bb22SYouMin Chen 	dram_info.ddrgrf = (void *)DDR_GRF_BASE_ADDR;
3661f520bb22SYouMin Chen 	dram_info.pmugrf = (void *)PMU_GRF_BASE_ADDR;
3662f520bb22SYouMin Chen 
3663ee5f0829STang Yun ping #ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT
3664ee5f0829STang Yun ping 	printascii("extended temp support\n");
3665ee5f0829STang Yun ping #endif
3666*c0a4decfSWesley Yao 	if (index->version_info != 3 ||
3667f520bb22SYouMin Chen 	    (index->global_index.size != sizeof(struct global_info) / 4) ||
3668f520bb22SYouMin Chen 	    (index->ddr3_index.size !=
3669f520bb22SYouMin Chen 		sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
3670f520bb22SYouMin Chen 	    (index->ddr4_index.size !=
3671f520bb22SYouMin Chen 		sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
3672f520bb22SYouMin Chen 	    (index->lp3_index.size !=
3673f520bb22SYouMin Chen 		sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
3674f520bb22SYouMin Chen 	    (index->lp4_index.size != (sizeof(struct lp4_info) / 4)) ||
3675c2a03d5dSZhihuan He 	    (index->lp4x_index.size != (sizeof(struct lp4_info) / 4)) ||
3676f520bb22SYouMin Chen 	    index->global_index.offset == 0 ||
3677f520bb22SYouMin Chen 	    index->ddr3_index.offset == 0 ||
3678f520bb22SYouMin Chen 	    index->ddr4_index.offset == 0 ||
3679f520bb22SYouMin Chen 	    index->lp3_index.offset == 0 ||
3680c2a03d5dSZhihuan He 	    index->lp4_index.offset == 0 ||
3681c2a03d5dSZhihuan He 	    index->lp4x_index.offset == 0) {
3682f520bb22SYouMin Chen 		printascii("common info error\n");
3683f520bb22SYouMin Chen 		goto error;
3684f520bb22SYouMin Chen 	}
3685f520bb22SYouMin Chen 
3686f520bb22SYouMin Chen 	gbl_info = (struct global_info *)((void *)common_info +
3687f520bb22SYouMin Chen 		index->global_index.offset * 4);
3688f520bb22SYouMin Chen 
3689f520bb22SYouMin Chen 	dram_info.sr_idle = SR_INFO(gbl_info->sr_pd_info);
3690f520bb22SYouMin Chen 	dram_info.pd_idle = PD_INFO(gbl_info->sr_pd_info);
3691f520bb22SYouMin Chen 
3692f520bb22SYouMin Chen 	sdram_params = &sdram_configs[0];
3693c2a03d5dSZhihuan He 	#if (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 8)
36949ebc0521SWesley Yao 	for (int j = 0; j < ARRAY_SIZE(sdram_configs); j++)
3695c2a03d5dSZhihuan He 		sdram_configs[j].base.dramtype = LPDDR4X;
3696c2a03d5dSZhihuan He 	#endif
3697f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR3 ||
3698f520bb22SYouMin Chen 	    sdram_params->base.dramtype == DDR4) {
3699f520bb22SYouMin Chen 		if (DDR_2T_INFO(gbl_info->info_2t))
3700f520bb22SYouMin Chen 			sdram_params->pctl_regs.pctl[0][1] |= 0x1 << 10;
3701f520bb22SYouMin Chen 		else
3702f520bb22SYouMin Chen 			sdram_params->pctl_regs.pctl[0][1] &=
3703f520bb22SYouMin Chen 				~(0x1 << 10);
3704f520bb22SYouMin Chen 	}
3705f520bb22SYouMin Chen 	ret = sdram_init_detect(&dram_info, sdram_params);
3706f520bb22SYouMin Chen 	if (ret) {
3707f520bb22SYouMin Chen 		sdram_print_dram_type(sdram_params->base.dramtype);
3708f520bb22SYouMin Chen 		printascii(", ");
3709f520bb22SYouMin Chen 		printdec(sdram_params->base.ddr_freq);
3710f520bb22SYouMin Chen 		printascii("MHz\n");
3711f520bb22SYouMin Chen 		goto error;
3712f520bb22SYouMin Chen 	}
3713f520bb22SYouMin Chen 	print_ddr_info(sdram_params);
371423817349SWesley Yao 
371523817349SWesley Yao 	if (check_lp4_rzqi(&dram_info, sdram_params))
371623817349SWesley Yao 		printascii("Please check the soldering and hardware design of DRAM ZQ.\n"
371723817349SWesley Yao 			   "ZQ error may lead to instability at high frequancies!\n");
371823817349SWesley Yao 
3719c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL)
3720c71eeac4SWesley Yao 	init_rw_trn_result_struct(&rw_trn_result, dram_info.phy,
3721c71eeac4SWesley Yao 				  (u8)sdram_params->ch.cap_info.rank);
3722c71eeac4SWesley Yao #endif
3723f520bb22SYouMin Chen 
3724f520bb22SYouMin Chen 	ddr_set_rate_for_fsp(&dram_info, sdram_params);
3725958e04deSTang Yun ping #ifndef CONFIG_SPL_KERNEL_BOOT
3726f520bb22SYouMin Chen 	copy_fsp_param_to_ddr();
3727d3f5f12cSTang Yun ping #endif
3728f520bb22SYouMin Chen 
3729f520bb22SYouMin Chen 	ddr_set_atags(&dram_info, sdram_params);
3730c71eeac4SWesley Yao #if defined(CONFIG_CMD_DDR_TEST_TOOL)
3731c71eeac4SWesley Yao 	save_rw_trn_result_to_ddr(&rw_trn_result);
3732c71eeac4SWesley Yao #endif
3733f520bb22SYouMin Chen 
3734f520bb22SYouMin Chen 	printascii("out\n");
3735f520bb22SYouMin Chen 
3736f520bb22SYouMin Chen 	return ret;
3737f520bb22SYouMin Chen error:
3738f520bb22SYouMin Chen 	printascii("error\n");
3739f520bb22SYouMin Chen 	return (-1);
3740f520bb22SYouMin Chen }
3741f520bb22SYouMin Chen #endif /* CONFIG_TPL_BUILD */
3742