xref: /rk3399_rockchip-uboot/drivers/ram/rockchip/sdram_rv1126.c (revision f876ce9b2e0046eeb7a543eccefb068a3e6f2cc8)
1f520bb22SYouMin Chen // SPDX-License-Identifier: GPL-2.0
2f520bb22SYouMin Chen /*
3f520bb22SYouMin Chen  * (C) Copyright 2020 Rockchip Electronics Co., Ltd.
4f520bb22SYouMin Chen  */
5f520bb22SYouMin Chen 
6f520bb22SYouMin Chen #include <common.h>
7f520bb22SYouMin Chen #include <debug_uart.h>
8f520bb22SYouMin Chen #include <dm.h>
9f520bb22SYouMin Chen #include <ram.h>
10f520bb22SYouMin Chen #include <syscon.h>
11f520bb22SYouMin Chen #include <asm/io.h>
12f520bb22SYouMin Chen #include <asm/arch/clock.h>
13f520bb22SYouMin Chen #include <asm/arch/hardware.h>
14f520bb22SYouMin Chen #include <asm/arch/rk_atags.h>
15f520bb22SYouMin Chen #include <asm/arch/cru_rv1126.h>
16f520bb22SYouMin Chen #include <asm/arch/grf_rv1126.h>
17f520bb22SYouMin Chen #include <asm/arch/sdram_common.h>
18f520bb22SYouMin Chen #include <asm/arch/sdram_rv1126.h>
19f520bb22SYouMin Chen 
20f520bb22SYouMin Chen /* define training flag */
21f520bb22SYouMin Chen #define CA_TRAINING			(0x1 << 0)
22f520bb22SYouMin Chen #define READ_GATE_TRAINING		(0x1 << 1)
23f520bb22SYouMin Chen #define WRITE_LEVELING			(0x1 << 2)
24f520bb22SYouMin Chen #define WRITE_TRAINING			(0x1 << 3)
25f520bb22SYouMin Chen #define READ_TRAINING			(0x1 << 4)
26f520bb22SYouMin Chen #define FULL_TRAINING			(0xff)
27f520bb22SYouMin Chen 
28f520bb22SYouMin Chen #define SKEW_RX_SIGNAL			(0)
29f520bb22SYouMin Chen #define SKEW_TX_SIGNAL			(1)
30f520bb22SYouMin Chen #define SKEW_CA_SIGNAL			(2)
31f520bb22SYouMin Chen 
32f520bb22SYouMin Chen #define DESKEW_MDF_ABS_VAL		(0)
33f520bb22SYouMin Chen #define DESKEW_MDF_DIFF_VAL		(1)
34f520bb22SYouMin Chen 
35f520bb22SYouMin Chen #ifdef CONFIG_TPL_BUILD
36f520bb22SYouMin Chen #ifndef CONFIG_TPL_TINY_FRAMEWORK
37f520bb22SYouMin Chen #error please defined CONFIG_TPL_TINY_FRAMEWORK for RV1126 !!!
38f520bb22SYouMin Chen #endif
39f520bb22SYouMin Chen #endif
40f520bb22SYouMin Chen 
41f520bb22SYouMin Chen #ifdef CONFIG_TPL_BUILD
42f520bb22SYouMin Chen 
43f520bb22SYouMin Chen struct dram_info {
44f520bb22SYouMin Chen 	void __iomem *pctl;
45f520bb22SYouMin Chen 	void __iomem *phy;
46f520bb22SYouMin Chen 	struct rv1126_cru *cru;
47f520bb22SYouMin Chen 	struct msch_regs *msch;
48f520bb22SYouMin Chen 	struct rv1126_ddrgrf *ddrgrf;
49f520bb22SYouMin Chen 	struct rv1126_grf *grf;
50f520bb22SYouMin Chen 	struct ram_info info;
51f520bb22SYouMin Chen 	struct rv1126_pmugrf *pmugrf;
52f520bb22SYouMin Chen 	u32 sr_idle;
53f520bb22SYouMin Chen 	u32 pd_idle;
54f520bb22SYouMin Chen };
55f520bb22SYouMin Chen 
56f520bb22SYouMin Chen #define GRF_BASE_ADDR			0xfe000000
57f520bb22SYouMin Chen #define PMU_GRF_BASE_ADDR		0xfe020000
58f520bb22SYouMin Chen #define DDR_GRF_BASE_ADDR		0xfe030000
59f520bb22SYouMin Chen #define BUS_SGRF_BASE_ADDR		0xfe0a0000
60f520bb22SYouMin Chen #define SERVER_MSCH_BASE_ADDR		0xfe800000
61f520bb22SYouMin Chen #define CRU_BASE_ADDR			0xff490000
62f520bb22SYouMin Chen #define DDR_PHY_BASE_ADDR		0xff4a0000
63f520bb22SYouMin Chen #define UPCTL2_BASE_ADDR		0xffa50000
64f520bb22SYouMin Chen 
65f520bb22SYouMin Chen #define SGRF_SOC_CON12			0x30
66f520bb22SYouMin Chen #define SGRF_SOC_CON13			0x34
67f520bb22SYouMin Chen 
68f520bb22SYouMin Chen struct dram_info dram_info;
69f520bb22SYouMin Chen 
70f520bb22SYouMin Chen #define TPL_INIT_DDR_TYPE_DDR3
71f520bb22SYouMin Chen #ifdef TPL_INIT_DDR_TYPE_DDR3
72f520bb22SYouMin Chen struct rv1126_sdram_params sdram_configs[] = {
73f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-330.inc"
74f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-396.inc"
75f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-528.inc"
76f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-664.inc"
77f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-784.inc"
78f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-924.inc"
7905431850SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-1056.inc"
80f520bb22SYouMin Chen };
81f520bb22SYouMin Chen #elif defined TPL_INIT_DDR_TYPE_DDR4
82f520bb22SYouMin Chen struct rv1126_sdram_params sdram_configs[] = {
83f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-330.inc"
84f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-396.inc"
85f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-528.inc"
86f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-664.inc"
87f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-784.inc"
88f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-924.inc"
89f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-1056.inc"
90f520bb22SYouMin Chen };
91f520bb22SYouMin Chen #elif defined TPL_INIT_DDR_TYPE_LPDDR3
92f520bb22SYouMin Chen struct rv1126_sdram_params sdram_configs[] = {
93f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-330.inc"
94f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-396.inc"
95f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-528.inc"
96f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-664.inc"
97f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-784.inc"
98f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-924.inc"
9905431850SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-1056.inc"
100f520bb22SYouMin Chen };
101f520bb22SYouMin Chen #elif defined TPL_INIT_DDR_TYPE_LPDDR4
102f520bb22SYouMin Chen struct rv1126_sdram_params sdram_configs[] = {
103f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-330.inc"
104f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-396.inc"
105f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-528.inc"
106f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-664.inc"
107f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-784.inc"
108f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-924.inc"
109f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-1056.inc"
110f520bb22SYouMin Chen };
111f520bb22SYouMin Chen #endif
112f520bb22SYouMin Chen 
113f520bb22SYouMin Chen u32 common_info[] = {
114f520bb22SYouMin Chen 	#include "sdram_inc/rv1126/sdram-rv1126-loader_params.inc"
115f520bb22SYouMin Chen };
116f520bb22SYouMin Chen 
117f520bb22SYouMin Chen static struct rv1126_fsp_param fsp_param[MAX_IDX];
118f520bb22SYouMin Chen 
119f520bb22SYouMin Chen static u8 lp3_odt_value;
120f520bb22SYouMin Chen 
121f520bb22SYouMin Chen static u8 wrlvl_result[2][4];
122f520bb22SYouMin Chen 
123f520bb22SYouMin Chen /* DDR configuration 0-9 */
124f520bb22SYouMin Chen u16 ddr_cfg_2_rbc[] = {
125f520bb22SYouMin Chen 	((0 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 3), /* 0 */
126f520bb22SYouMin Chen 	((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 2), /* 1 */
127f520bb22SYouMin Chen 	((1 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 3), /* 2 */
128f520bb22SYouMin Chen 	((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 1), /* 3 */
129f520bb22SYouMin Chen 	((0 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 4), /* 4 */
130f520bb22SYouMin Chen 	((0 << 8) | (3 << 5) | (1 << 4) | (1 << 3) | 1), /* 5 */
131f520bb22SYouMin Chen 	((0 << 8) | (3 << 5) | (1 << 4) | (1 << 3) | 2), /* 6 */
132f520bb22SYouMin Chen 	((0 << 8) | (2 << 5) | (1 << 4) | (1 << 3) | 3), /* 7 */
133f520bb22SYouMin Chen 	((1 << 8) | (3 << 5) | (0 << 4) | (0 << 3) | 2), /* 8 */
134f520bb22SYouMin Chen 	((1 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 2) /* 9 */
135f520bb22SYouMin Chen };
136f520bb22SYouMin Chen 
137f520bb22SYouMin Chen /* DDR configuration 10-21 */
138f520bb22SYouMin Chen u8 ddr4_cfg_2_rbc[] = {
139f520bb22SYouMin Chen 	((0 << 7) | (3 << 4) | (0 << 3) | (2 << 1) | 0), /* 10 */
140f520bb22SYouMin Chen 	((1 << 7) | (2 << 4) | (0 << 3) | (2 << 1) | 0), /* 11 */
141f520bb22SYouMin Chen 	((0 << 7) | (4 << 4) | (0 << 3) | (1 << 1) | 0), /* 12 */
142f520bb22SYouMin Chen 	((1 << 7) | (3 << 4) | (0 << 3) | (1 << 1) | 0), /* 13 */
143f520bb22SYouMin Chen 	((0 << 7) | (4 << 4) | (0 << 3) | (2 << 1) | 1), /* 14 */
144f520bb22SYouMin Chen 	((1 << 7) | (3 << 4) | (0 << 3) | (2 << 1) | 1), /* 15 */
145f520bb22SYouMin Chen 	((1 << 7) | (4 << 4) | (0 << 3) | (1 << 1) | 1), /* 16 */
146f520bb22SYouMin Chen 	((0 << 7) | (2 << 4) | (1 << 3) | (2 << 1) | 0), /* 17 */
147f520bb22SYouMin Chen 	((0 << 7) | (3 << 4) | (1 << 3) | (1 << 1) | 0), /* 18 */
148f520bb22SYouMin Chen 	((0 << 7) | (3 << 4) | (1 << 3) | (2 << 1) | 1), /* 19 */
149f520bb22SYouMin Chen 	((0 << 7) | (4 << 4) | (1 << 3) | (1 << 1) | 1), /* 20 */
150f520bb22SYouMin Chen 	((1 << 7) | (4 << 4) | (0 << 3) | (0 << 1) | 0) /* 21 */
151f520bb22SYouMin Chen };
152f520bb22SYouMin Chen 
153f520bb22SYouMin Chen /* DDR configuration 22-28 */
154f520bb22SYouMin Chen u16 ddr_cfg_2_rbc_p2[] = {
155f520bb22SYouMin Chen 	((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 0), /* 22 */
156f520bb22SYouMin Chen 	((0 << 8) | (4 << 5) | (0 << 4) | (1 << 3) | 2), /* 23 */
157f520bb22SYouMin Chen 	((1 << 8) | (3 << 5) | (0 << 4) | (0 << 3) | 3), /* 24 */
158f520bb22SYouMin Chen 	((0 << 8) | (3 << 5) | (1 << 4) | (0 << 3) | 3), /* 25 */
159f520bb22SYouMin Chen 	((0 << 8) | (4 << 5) | (1 << 4) | (0 << 3) | 2), /* 26 */
160f520bb22SYouMin Chen 	((1 << 8) | (4 << 5) | (0 << 4) | (0 << 3) | 2), /* 27 */
161f520bb22SYouMin Chen 	((0 << 8) | (4 << 5) | (0 << 4) | (0 << 3) | 3) /* 28 */
162f520bb22SYouMin Chen };
163f520bb22SYouMin Chen 
164f520bb22SYouMin Chen u8 d4_rbc_2_d3_rbc[][2] = {
165f520bb22SYouMin Chen 	{10, 0},
166f520bb22SYouMin Chen 	{11, 2},
167f520bb22SYouMin Chen 	{12, 23},
168f520bb22SYouMin Chen 	{13, 1},
169f520bb22SYouMin Chen 	{14, 28},
170f520bb22SYouMin Chen 	{15, 24},
171f520bb22SYouMin Chen 	{16, 27},
172f520bb22SYouMin Chen 	{17, 7},
173f520bb22SYouMin Chen 	{18, 6},
174f520bb22SYouMin Chen 	{19, 25},
175f520bb22SYouMin Chen 	{20, 26},
176f520bb22SYouMin Chen 	{21, 3}
177f520bb22SYouMin Chen };
178f520bb22SYouMin Chen 
179f520bb22SYouMin Chen u32 addrmap[23][9] = {
180f520bb22SYouMin Chen 	{24, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
181f520bb22SYouMin Chen 		0x08080808, 0x00000f0f, 0x3f3f}, /* 0 */
182f520bb22SYouMin Chen 	{23, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
183f520bb22SYouMin Chen 		0x07070707, 0x00000f0f, 0x3f3f}, /* 1 */
184f520bb22SYouMin Chen 	{23, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
185f520bb22SYouMin Chen 		0x0f080808, 0x00000f0f, 0x3f3f}, /* 2 */
186f520bb22SYouMin Chen 	{22, 0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x06060606,
187f520bb22SYouMin Chen 		0x06060606, 0x00000f0f, 0x3f3f}, /* 3 */
188f520bb22SYouMin Chen 	{24, 0x000a0a0a, 0x00000000, 0x00000000, 0x00000000, 0x09090909,
189f520bb22SYouMin Chen 		0x0f090909, 0x00000f0f, 0x3f3f}, /* 4 */
190f520bb22SYouMin Chen 	{6, 0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x07070707,
191f520bb22SYouMin Chen 		0x07070707, 0x00000f0f, 0x3f3f}, /* 5 */
192f520bb22SYouMin Chen 	{7, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x08080808,
193f520bb22SYouMin Chen 		0x08080808, 0x00000f0f, 0x3f3f}, /* 6 */
194f520bb22SYouMin Chen 	{8, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x09090909,
195f520bb22SYouMin Chen 		0x0f090909, 0x00000f0f, 0x3f3f}, /* 7 */
196f520bb22SYouMin Chen 	{22, 0x001f0808, 0x00000000, 0x00000000, 0x00001f1f, 0x06060606,
197f520bb22SYouMin Chen 		0x06060606, 0x00000f0f, 0x3f3f}, /* 8 */
198f520bb22SYouMin Chen 	{23, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
199f520bb22SYouMin Chen 		0x0f070707, 0x00000f0f, 0x3f3f}, /* 9 */
200f520bb22SYouMin Chen 
201f520bb22SYouMin Chen 	{24, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
202f520bb22SYouMin Chen 		0x08080808, 0x00000f0f, 0x0801}, /* 10 */
203f520bb22SYouMin Chen 	{23, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
204f520bb22SYouMin Chen 		0x0f080808, 0x00000f0f, 0x0801}, /* 11 */
205f520bb22SYouMin Chen 	{24, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
206f520bb22SYouMin Chen 		0x07070707, 0x00000f07, 0x0700}, /* 12 */
207f520bb22SYouMin Chen 	{23, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
208f520bb22SYouMin Chen 		0x07070707, 0x00000f0f, 0x0700}, /* 13 */
209f520bb22SYouMin Chen 	{24, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
210f520bb22SYouMin Chen 		0x07070707, 0x00000f07, 0x3f01}, /* 14 */
211f520bb22SYouMin Chen 	{23, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
212f520bb22SYouMin Chen 		0x07070707, 0x00000f0f, 0x3f01}, /* 15 */
213f520bb22SYouMin Chen 	{23, 0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x06060606,
214f520bb22SYouMin Chen 		0x06060606, 0x00000f06, 0x3f00}, /* 16 */
215f520bb22SYouMin Chen 	{8, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x09090909,
216f520bb22SYouMin Chen 		0x0f090909, 0x00000f0f, 0x0801}, /* 17 */
217f520bb22SYouMin Chen 	{7, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x08080808,
218f520bb22SYouMin Chen 		0x08080808, 0x00000f0f, 0x0700}, /* 18 */
219f520bb22SYouMin Chen 	{7, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
220f520bb22SYouMin Chen 		0x08080808, 0x00000f0f, 0x3f01}, /* 19 */
221f520bb22SYouMin Chen 
222f520bb22SYouMin Chen 	{6, 0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
223f520bb22SYouMin Chen 		0x07070707, 0x00000f07, 0x3f00}, /* 20 */
224f520bb22SYouMin Chen 	{23, 0x003f0909, 0x00000006, 0x1f1f0000, 0x00001f1f, 0x06060606,
225f520bb22SYouMin Chen 		0x06060606, 0x00000f06, 0x0600}, /* 21 */
226f520bb22SYouMin Chen 	{21, 0x00060606, 0x00000000, 0x1f1f0000, 0x00001f1f, 0x05050505,
227f520bb22SYouMin Chen 		0x05050505, 0x00000f0f, 0x3f3f} /* 22 */
228f520bb22SYouMin Chen };
229f520bb22SYouMin Chen 
230f520bb22SYouMin Chen static u8 dq_sel[22][3] = {
231f520bb22SYouMin Chen 	{0x0, 0x17, 0x22},
232f520bb22SYouMin Chen 	{0x1, 0x18, 0x23},
233f520bb22SYouMin Chen 	{0x2, 0x19, 0x24},
234f520bb22SYouMin Chen 	{0x3, 0x1a, 0x25},
235f520bb22SYouMin Chen 	{0x4, 0x1b, 0x26},
236f520bb22SYouMin Chen 	{0x5, 0x1c, 0x27},
237f520bb22SYouMin Chen 	{0x6, 0x1d, 0x28},
238f520bb22SYouMin Chen 	{0x7, 0x1e, 0x29},
239f520bb22SYouMin Chen 	{0x8, 0x16, 0x21},
240f520bb22SYouMin Chen 	{0x9, 0x1f, 0x2a},
241f520bb22SYouMin Chen 	{0xa, 0x20, 0x2b},
242f520bb22SYouMin Chen 	{0x10, 0x1, 0xc},
243f520bb22SYouMin Chen 	{0x11, 0x2, 0xd},
244f520bb22SYouMin Chen 	{0x12, 0x3, 0xe},
245f520bb22SYouMin Chen 	{0x13, 0x4, 0xf},
246f520bb22SYouMin Chen 	{0x14, 0x5, 0x10},
247f520bb22SYouMin Chen 	{0x15, 0x6, 0x11},
248f520bb22SYouMin Chen 	{0x16, 0x7, 0x12},
249f520bb22SYouMin Chen 	{0x17, 0x8, 0x13},
250f520bb22SYouMin Chen 	{0x18, 0x0, 0xb},
251f520bb22SYouMin Chen 	{0x19, 0x9, 0x14},
252f520bb22SYouMin Chen 	{0x1a, 0xa, 0x15}
253f520bb22SYouMin Chen };
254f520bb22SYouMin Chen 
255f520bb22SYouMin Chen static u16 grp_addr[4] = {
256f520bb22SYouMin Chen 	ADD_GROUP_CS0_A,
257f520bb22SYouMin Chen 	ADD_GROUP_CS0_B,
258f520bb22SYouMin Chen 	ADD_GROUP_CS1_A,
259f520bb22SYouMin Chen 	ADD_GROUP_CS1_B
260f520bb22SYouMin Chen };
261f520bb22SYouMin Chen 
262f520bb22SYouMin Chen static u8 wrlvl_result_offset[2][4] = {
263f520bb22SYouMin Chen 	{0xa0 + 0x26, 0xa0 + 0x27, 0xd0 + 0x26, 0xd0 + 0x27},
264f520bb22SYouMin Chen 	{0xa0 + 0x28, 0xa0 + 0x29, 0xd0 + 0x28, 0xd0 + 0x29},
265f520bb22SYouMin Chen };
266f520bb22SYouMin Chen 
267f520bb22SYouMin Chen static u16 dqs_dq_skew_adr[16] = {
268f520bb22SYouMin Chen 	0x170 + 0,	/* SKEW_UPDATE_RX_CS0_DQS0 */
269f520bb22SYouMin Chen 	0x170 + 0xb,	/* SKEW_UPDATE_RX_CS0_DQS1 */
270f520bb22SYouMin Chen 	0x1d0 + 0,	/* SKEW_UPDATE_RX_CS0_DQS2 */
271f520bb22SYouMin Chen 	0x1d0 + 0xb,	/* SKEW_UPDATE_RX_CS0_DQS3 */
272f520bb22SYouMin Chen 	0x1a0 + 0,	/* SKEW_UPDATE_RX_CS1_DQS0 */
273f520bb22SYouMin Chen 	0x1a0 + 0xb,	/* SKEW_UPDATE_RX_CS1_DQS1 */
274f520bb22SYouMin Chen 	0x200 + 0,	/* SKEW_UPDATE_RX_CS1_DQS2 */
275f520bb22SYouMin Chen 	0x200 + 0xb,	/* SKEW_UPDATE_RX_CS1_DQS3 */
276f520bb22SYouMin Chen 	0x170 + 0x16,	/* SKEW_UPDATE_TX_CS0_DQS0 */
277f520bb22SYouMin Chen 	0x170 + 0x21,	/* SKEW_UPDATE_TX_CS0_DQS1 */
278f520bb22SYouMin Chen 	0x1d0 + 0x16,	/* SKEW_UPDATE_TX_CS0_DQS2 */
279f520bb22SYouMin Chen 	0x1d0 + 0x21,	/* SKEW_UPDATE_TX_CS0_DQS3 */
280f520bb22SYouMin Chen 	0x1a0 + 0x16,	/* SKEW_UPDATE_TX_CS1_DQS0 */
281f520bb22SYouMin Chen 	0x1a0 + 0x21,	/* SKEW_UPDATE_TX_CS1_DQS1 */
282f520bb22SYouMin Chen 	0x200 + 0x16,	/* SKEW_UPDATE_TX_CS1_DQS2 */
283f520bb22SYouMin Chen 	0x200 + 0x21,	/* SKEW_UPDATE_TX_CS1_DQS3 */
284f520bb22SYouMin Chen };
285f520bb22SYouMin Chen 
286f520bb22SYouMin Chen static void rkclk_ddr_reset(struct dram_info *dram,
287f520bb22SYouMin Chen 			    u32 ctl_srstn, u32 ctl_psrstn,
288f520bb22SYouMin Chen 			    u32 phy_srstn, u32 phy_psrstn)
289f520bb22SYouMin Chen {
290f520bb22SYouMin Chen 	writel(UPCTL2_SRSTN_REQ(ctl_srstn) | UPCTL2_PSRSTN_REQ(ctl_psrstn) |
291f520bb22SYouMin Chen 	       UPCTL2_ASRSTN_REQ(ctl_srstn),
292f520bb22SYouMin Chen 	       BUS_SGRF_BASE_ADDR + SGRF_SOC_CON13);
293f520bb22SYouMin Chen 
294f520bb22SYouMin Chen 	writel(DDRPHY_SRSTN_REQ(phy_srstn) | DDRPHY_PSRSTN_REQ(phy_psrstn),
295f520bb22SYouMin Chen 	       &dram->cru->softrst_con[12]);
296f520bb22SYouMin Chen }
297f520bb22SYouMin Chen 
298f520bb22SYouMin Chen static void rkclk_set_dpll(struct dram_info *dram, unsigned int hz)
299f520bb22SYouMin Chen {
300f520bb22SYouMin Chen 	unsigned int refdiv, postdiv1, postdiv2, fbdiv;
301f520bb22SYouMin Chen 	int delay = 1000;
302f520bb22SYouMin Chen 	u32 mhz = hz / MHz;
303f520bb22SYouMin Chen 
304f520bb22SYouMin Chen 	refdiv = 1;
305f520bb22SYouMin Chen 	if (mhz <= 100) {
306f520bb22SYouMin Chen 		postdiv1 = 6;
307f520bb22SYouMin Chen 		postdiv2 = 4;
308f520bb22SYouMin Chen 	} else if (mhz <= 150) {
309f520bb22SYouMin Chen 		postdiv1 = 4;
310f520bb22SYouMin Chen 		postdiv2 = 4;
311f520bb22SYouMin Chen 	} else if (mhz <= 200) {
312f520bb22SYouMin Chen 		postdiv1 = 6;
313f520bb22SYouMin Chen 		postdiv2 = 2;
314f520bb22SYouMin Chen 	} else if (mhz <= 300) {
315f520bb22SYouMin Chen 		postdiv1 = 4;
316f520bb22SYouMin Chen 		postdiv2 = 2;
317f520bb22SYouMin Chen 	} else if (mhz <= 400) {
318f520bb22SYouMin Chen 		postdiv1 = 6;
319f520bb22SYouMin Chen 		postdiv2 = 1;
320f520bb22SYouMin Chen 	} else {
321f520bb22SYouMin Chen 		postdiv1 = 4;
322f520bb22SYouMin Chen 		postdiv2 = 1;
323f520bb22SYouMin Chen 	}
324f520bb22SYouMin Chen 	fbdiv = (mhz * refdiv * postdiv1 * postdiv2) / 24;
325f520bb22SYouMin Chen 
326f520bb22SYouMin Chen 	writel(DPLL_MODE(CLOCK_FROM_XIN_OSC), &dram->cru->mode);
327f520bb22SYouMin Chen 
328f520bb22SYouMin Chen 	writel(0x1f000000, &dram->cru->clksel_con[64]);
329f520bb22SYouMin Chen 	writel(POSTDIV1(postdiv1) | FBDIV(fbdiv), &dram->cru->pll[1].con0);
330f520bb22SYouMin Chen 	writel(DSMPD(1) | POSTDIV2(postdiv2) | REFDIV(refdiv),
331f520bb22SYouMin Chen 	       &dram->cru->pll[1].con1);
332f520bb22SYouMin Chen 
333f520bb22SYouMin Chen 	while (delay > 0) {
334f520bb22SYouMin Chen 		udelay(1);
335f520bb22SYouMin Chen 		if (LOCK(readl(&dram->cru->pll[1].con1)))
336f520bb22SYouMin Chen 			break;
337f520bb22SYouMin Chen 		delay--;
338f520bb22SYouMin Chen 	}
339f520bb22SYouMin Chen 
340f520bb22SYouMin Chen 	writel(DPLL_MODE(CLOCK_FROM_PLL), &dram->cru->mode);
341f520bb22SYouMin Chen }
342f520bb22SYouMin Chen 
343f520bb22SYouMin Chen static void rkclk_configure_ddr(struct dram_info *dram,
344f520bb22SYouMin Chen 				struct rv1126_sdram_params *sdram_params)
345f520bb22SYouMin Chen {
346f520bb22SYouMin Chen 	/* for inno ddr phy need freq / 2 */
347f520bb22SYouMin Chen 	rkclk_set_dpll(dram, sdram_params->base.ddr_freq * MHZ / 2);
348f520bb22SYouMin Chen }
349f520bb22SYouMin Chen 
350f520bb22SYouMin Chen static void phy_soft_reset(struct dram_info *dram)
351f520bb22SYouMin Chen {
352f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
353f520bb22SYouMin Chen 
354f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0), 0x3 << 2);
355f520bb22SYouMin Chen 	udelay(1);
356f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET | DIGITAL_DERESET);
357f520bb22SYouMin Chen 	udelay(1);
358f520bb22SYouMin Chen }
359f520bb22SYouMin Chen 
360f520bb22SYouMin Chen static unsigned int
361f520bb22SYouMin Chen 	calculate_ddrconfig(struct rv1126_sdram_params *sdram_params)
362f520bb22SYouMin Chen {
363f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
364f520bb22SYouMin Chen 	u32 cs, bw, die_bw, col, row, bank;
365f520bb22SYouMin Chen 	u32 cs1_row;
366f520bb22SYouMin Chen 	u32 i, tmp;
367f520bb22SYouMin Chen 	u32 ddrconf = -1;
368f520bb22SYouMin Chen 	u32 row_3_4;
369f520bb22SYouMin Chen 
370f520bb22SYouMin Chen 	cs = cap_info->rank;
371f520bb22SYouMin Chen 	bw = cap_info->bw;
372f520bb22SYouMin Chen 	die_bw = cap_info->dbw;
373f520bb22SYouMin Chen 	col = cap_info->col;
374f520bb22SYouMin Chen 	row = cap_info->cs0_row;
375f520bb22SYouMin Chen 	cs1_row = cap_info->cs1_row;
376f520bb22SYouMin Chen 	bank = cap_info->bk;
377f520bb22SYouMin Chen 	row_3_4 = cap_info->row_3_4;
378f520bb22SYouMin Chen 
379f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4) {
380f520bb22SYouMin Chen 		if (cs == 2 && row == cs1_row && !row_3_4) {
381f520bb22SYouMin Chen 			tmp = ((row - 13) << 4) | (1 << 3) | (bw << 1) |
382f520bb22SYouMin Chen 			      die_bw;
383f520bb22SYouMin Chen 			for (i = 17; i < 21; i++) {
384f520bb22SYouMin Chen 				if (((tmp & 0xf) ==
385f520bb22SYouMin Chen 				     (ddr4_cfg_2_rbc[i - 10] & 0xf)) &&
386f520bb22SYouMin Chen 				    ((tmp & 0x70) <=
387f520bb22SYouMin Chen 				     (ddr4_cfg_2_rbc[i - 10] & 0x70))) {
388f520bb22SYouMin Chen 					ddrconf = i;
389f520bb22SYouMin Chen 					goto out;
390f520bb22SYouMin Chen 				}
391f520bb22SYouMin Chen 			}
392f520bb22SYouMin Chen 		}
393f520bb22SYouMin Chen 
394f520bb22SYouMin Chen 		tmp = ((cs - 1) << 7) | ((row - 13) << 4) | (bw << 1) | die_bw;
395f520bb22SYouMin Chen 		for (i = 10; i < 21; i++) {
396f520bb22SYouMin Chen 			if (((tmp & 0xf) == (ddr4_cfg_2_rbc[i - 10] & 0xf)) &&
397f520bb22SYouMin Chen 			    ((tmp & 0x70) <= (ddr4_cfg_2_rbc[i - 10] & 0x70)) &&
398f520bb22SYouMin Chen 			    ((tmp & 0x80) <= (ddr4_cfg_2_rbc[i - 10] & 0x80))) {
399f520bb22SYouMin Chen 				ddrconf = i;
400f520bb22SYouMin Chen 				goto out;
401f520bb22SYouMin Chen 			}
402f520bb22SYouMin Chen 		}
403f520bb22SYouMin Chen 	} else {
404f520bb22SYouMin Chen 		if (cs == 2 && row == cs1_row && bank == 3) {
405f520bb22SYouMin Chen 			for (i = 5; i < 8; i++) {
406f520bb22SYouMin Chen 				if (((bw + col - 10) == (ddr_cfg_2_rbc[i] &
407f520bb22SYouMin Chen 							 0x7)) &&
408f520bb22SYouMin Chen 				    ((row - 13) << 5) <= (ddr_cfg_2_rbc[i] &
409f520bb22SYouMin Chen 							  (0x7 << 5))) {
410f520bb22SYouMin Chen 					ddrconf = i;
411f520bb22SYouMin Chen 					goto out;
412f520bb22SYouMin Chen 				}
413f520bb22SYouMin Chen 			}
414f520bb22SYouMin Chen 		}
415f520bb22SYouMin Chen 
416f520bb22SYouMin Chen 		tmp = ((cs - 1) << 8) | ((row - 13) << 5) |
417f520bb22SYouMin Chen 		      ((bw + col - 10) << 0);
418f520bb22SYouMin Chen 		if (bank == 3)
419f520bb22SYouMin Chen 			tmp |= (1 << 3);
420f520bb22SYouMin Chen 
421f520bb22SYouMin Chen 		for (i = 0; i < 9; i++)
422f520bb22SYouMin Chen 			if (((tmp & 0x1f) == (ddr_cfg_2_rbc[i] & 0x1f)) &&
423f520bb22SYouMin Chen 			    ((tmp & (7 << 5)) <=
424f520bb22SYouMin Chen 			     (ddr_cfg_2_rbc[i] & (7 << 5))) &&
425f520bb22SYouMin Chen 			    ((tmp & (1 << 8)) <=
426f520bb22SYouMin Chen 			     (ddr_cfg_2_rbc[i] & (1 << 8)))) {
427f520bb22SYouMin Chen 				ddrconf = i;
428f520bb22SYouMin Chen 				goto out;
429f520bb22SYouMin Chen 			}
430f520bb22SYouMin Chen 		if (cs == 1 && bank == 3 && row <= 17 &&
431f520bb22SYouMin Chen 		    (col + bw) == 12)
432f520bb22SYouMin Chen 			ddrconf = 23;
433f520bb22SYouMin Chen 	}
434f520bb22SYouMin Chen 
435f520bb22SYouMin Chen out:
436f520bb22SYouMin Chen 	if (ddrconf > 28)
437f520bb22SYouMin Chen 		printascii("calculate ddrconfig error\n");
438f520bb22SYouMin Chen 
439f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4) {
440f520bb22SYouMin Chen 		for (i = 0; i < ARRAY_SIZE(d4_rbc_2_d3_rbc) ; i++) {
441f520bb22SYouMin Chen 			if (ddrconf == d4_rbc_2_d3_rbc[i][0]) {
442f520bb22SYouMin Chen 				if (ddrconf == 21 && row > 16)
443f520bb22SYouMin Chen 					printascii("warn:ddrconf21 row > 16\n");
444f520bb22SYouMin Chen 				else
445f520bb22SYouMin Chen 					ddrconf = d4_rbc_2_d3_rbc[i][1];
446f520bb22SYouMin Chen 				break;
447f520bb22SYouMin Chen 			}
448f520bb22SYouMin Chen 		}
449f520bb22SYouMin Chen 	}
450f520bb22SYouMin Chen 
451f520bb22SYouMin Chen 	return ddrconf;
452f520bb22SYouMin Chen }
453f520bb22SYouMin Chen 
454f520bb22SYouMin Chen static void sw_set_req(struct dram_info *dram)
455f520bb22SYouMin Chen {
456f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
457f520bb22SYouMin Chen 
458f520bb22SYouMin Chen 	/* clear sw_done=0 */
459f520bb22SYouMin Chen 	writel(PCTL2_SW_DONE_CLEAR, pctl_base + DDR_PCTL2_SWCTL);
460f520bb22SYouMin Chen }
461f520bb22SYouMin Chen 
462f520bb22SYouMin Chen static void sw_set_ack(struct dram_info *dram)
463f520bb22SYouMin Chen {
464f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
465f520bb22SYouMin Chen 
466f520bb22SYouMin Chen 	/* set sw_done=1 */
467f520bb22SYouMin Chen 	writel(PCTL2_SW_DONE, pctl_base + DDR_PCTL2_SWCTL);
468f520bb22SYouMin Chen 	while (1) {
469f520bb22SYouMin Chen 		/* wait programming done */
470f520bb22SYouMin Chen 		if (readl(pctl_base + DDR_PCTL2_SWSTAT) &
471f520bb22SYouMin Chen 				PCTL2_SW_DONE_ACK)
472f520bb22SYouMin Chen 			break;
473f520bb22SYouMin Chen 	}
474f520bb22SYouMin Chen }
475f520bb22SYouMin Chen 
476f520bb22SYouMin Chen static void set_ctl_address_map(struct dram_info *dram,
477f520bb22SYouMin Chen 				struct rv1126_sdram_params *sdram_params)
478f520bb22SYouMin Chen {
479f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
480f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
481f520bb22SYouMin Chen 	u32 ddrconf = cap_info->ddrconfig;
482f520bb22SYouMin Chen 	u32 i, row;
483f520bb22SYouMin Chen 
484f520bb22SYouMin Chen 	row = cap_info->cs0_row;
485f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4) {
486f520bb22SYouMin Chen 		for (i = 0; i < ARRAY_SIZE(d4_rbc_2_d3_rbc) ; i++) {
487f520bb22SYouMin Chen 			if (ddrconf == d4_rbc_2_d3_rbc[i][1]) {
488f520bb22SYouMin Chen 				ddrconf = d4_rbc_2_d3_rbc[i][0];
489f520bb22SYouMin Chen 				break;
490f520bb22SYouMin Chen 			}
491f520bb22SYouMin Chen 		}
492f520bb22SYouMin Chen 	}
493f520bb22SYouMin Chen 
494f520bb22SYouMin Chen 	if (ddrconf > ARRAY_SIZE(addrmap)) {
495f520bb22SYouMin Chen 		printascii("set ctl address map fail\n");
496f520bb22SYouMin Chen 		return;
497f520bb22SYouMin Chen 	}
498f520bb22SYouMin Chen 
499f520bb22SYouMin Chen 	sdram_copy_to_reg((u32 *)(pctl_base + DDR_PCTL2_ADDRMAP0),
500f520bb22SYouMin Chen 			  &addrmap[ddrconf][0], 9 * 4);
501f520bb22SYouMin Chen 
502f520bb22SYouMin Chen 	/* unused row set to 0xf */
503f520bb22SYouMin Chen 	for (i = 17; i >= row; i--)
504f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6 +
505f520bb22SYouMin Chen 			((i - 12) * 8 / 32) * 4,
506f520bb22SYouMin Chen 			0xf << ((i - 12) * 8 % 32));
507f520bb22SYouMin Chen 
508f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == LPDDR3 && cap_info->row_3_4)
509f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6, 1 << 31);
510f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4 && cap_info->bw == 0x1)
511f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_PCCFG, 1 << 8);
512f520bb22SYouMin Chen 
513f520bb22SYouMin Chen 	if (cap_info->rank == 1)
514f520bb22SYouMin Chen 		clrsetbits_le32(pctl_base + DDR_PCTL2_ADDRMAP0, 0x1f, 0x1f);
515f520bb22SYouMin Chen }
516f520bb22SYouMin Chen 
517f520bb22SYouMin Chen static void phy_pll_set(struct dram_info *dram, u32 freq, u32 wait)
518f520bb22SYouMin Chen {
519f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
520f520bb22SYouMin Chen 	u32 fbdiv, prediv, postdiv, postdiv_en;
521f520bb22SYouMin Chen 
522f520bb22SYouMin Chen 	if (wait) {
523f520bb22SYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x53), PHY_PD_DISB);
524f520bb22SYouMin Chen 		while (!(readl(PHY_REG(phy_base, 0x90)) & PHY_PLL_LOCK))
525f520bb22SYouMin Chen 			continue;
526f520bb22SYouMin Chen 	} else {
527f520bb22SYouMin Chen 		freq /= MHz;
528f520bb22SYouMin Chen 		prediv = 1;
529f520bb22SYouMin Chen 		if (freq <= 200) {
530f520bb22SYouMin Chen 			fbdiv = 16;
531f520bb22SYouMin Chen 			postdiv = 2;
532f520bb22SYouMin Chen 			postdiv_en = 1;
533f520bb22SYouMin Chen 		} else if (freq <= 456) {
534f520bb22SYouMin Chen 			fbdiv = 8;
535f520bb22SYouMin Chen 			postdiv = 1;
536f520bb22SYouMin Chen 			postdiv_en = 1;
537f520bb22SYouMin Chen 		} else {
538f520bb22SYouMin Chen 			fbdiv = 4;
539f520bb22SYouMin Chen 			postdiv = 0;
540f520bb22SYouMin Chen 			postdiv_en = 0;
541f520bb22SYouMin Chen 		}
542f520bb22SYouMin Chen 		writel(fbdiv & 0xff, PHY_REG(phy_base, 0x50));
543f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x51), PHY_PBDIV_BIT9_MASK,
544f520bb22SYouMin Chen 				(fbdiv >> 8) & 1);
545f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x51), PHY_POSTDIV_EN_MASK,
546f520bb22SYouMin Chen 				postdiv_en << PHY_POSTDIV_EN_SHIFT);
547f520bb22SYouMin Chen 
548f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x52),
549f520bb22SYouMin Chen 				PHY_PREDIV_MASK << PHY_PREDIV_SHIFT, prediv);
550f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x53),
551f520bb22SYouMin Chen 				PHY_POSTDIV_MASK << PHY_POSTDIV_SHIFT,
552f520bb22SYouMin Chen 				postdiv << PHY_POSTDIV_SHIFT);
553f520bb22SYouMin Chen 	}
554f520bb22SYouMin Chen }
555f520bb22SYouMin Chen 
556f520bb22SYouMin Chen static const u16 d3_phy_drv_2_ohm[][2] = {
557f520bb22SYouMin Chen 	{PHY_DDR3_RON_506ohm, 506},
558f520bb22SYouMin Chen 	{PHY_DDR3_RON_253ohm, 253},
559f520bb22SYouMin Chen 	{PHY_DDR3_RON_169hm, 169},
560f520bb22SYouMin Chen 	{PHY_DDR3_RON_127ohm, 127},
561f520bb22SYouMin Chen 	{PHY_DDR3_RON_101ohm, 101},
562f520bb22SYouMin Chen 	{PHY_DDR3_RON_84ohm, 84},
563f520bb22SYouMin Chen 	{PHY_DDR3_RON_72ohm, 72},
564f520bb22SYouMin Chen 	{PHY_DDR3_RON_63ohm, 63},
565f520bb22SYouMin Chen 	{PHY_DDR3_RON_56ohm, 56},
566f520bb22SYouMin Chen 	{PHY_DDR3_RON_51ohm, 51},
567f520bb22SYouMin Chen 	{PHY_DDR3_RON_46ohm, 46},
568f520bb22SYouMin Chen 	{PHY_DDR3_RON_42ohm, 42},
569f520bb22SYouMin Chen 	{PHY_DDR3_RON_39ohm, 39},
570f520bb22SYouMin Chen 	{PHY_DDR3_RON_36ohm, 36},
571f520bb22SYouMin Chen 	{PHY_DDR3_RON_34ohm, 34},
572f520bb22SYouMin Chen 	{PHY_DDR3_RON_32ohm, 32},
573f520bb22SYouMin Chen 	{PHY_DDR3_RON_30ohm, 30},
574f520bb22SYouMin Chen 	{PHY_DDR3_RON_28ohm, 28},
575f520bb22SYouMin Chen 	{PHY_DDR3_RON_27ohm, 27},
576f520bb22SYouMin Chen 	{PHY_DDR3_RON_25ohm, 25},
577f520bb22SYouMin Chen 	{PHY_DDR3_RON_24ohm, 24},
578f520bb22SYouMin Chen 	{PHY_DDR3_RON_23ohm, 23},
579f520bb22SYouMin Chen 	{PHY_DDR3_RON_22ohm, 22}
580f520bb22SYouMin Chen };
581f520bb22SYouMin Chen 
582f520bb22SYouMin Chen static u16 d3_phy_odt_2_ohm[][2] = {
583f520bb22SYouMin Chen 	{PHY_DDR3_RTT_DISABLE, 0},
584f520bb22SYouMin Chen 	{PHY_DDR3_RTT_953ohm, 953},
585f520bb22SYouMin Chen 	{PHY_DDR3_RTT_483ohm, 483},
586f520bb22SYouMin Chen 	{PHY_DDR3_RTT_320ohm, 320},
587f520bb22SYouMin Chen 	{PHY_DDR3_RTT_241ohm, 241},
588f520bb22SYouMin Chen 	{PHY_DDR3_RTT_193ohm, 193},
589f520bb22SYouMin Chen 	{PHY_DDR3_RTT_161ohm, 161},
590f520bb22SYouMin Chen 	{PHY_DDR3_RTT_138ohm, 138},
591f520bb22SYouMin Chen 	{PHY_DDR3_RTT_121ohm, 121},
592f520bb22SYouMin Chen 	{PHY_DDR3_RTT_107ohm, 107},
593f520bb22SYouMin Chen 	{PHY_DDR3_RTT_97ohm, 97},
594f520bb22SYouMin Chen 	{PHY_DDR3_RTT_88ohm, 88},
595f520bb22SYouMin Chen 	{PHY_DDR3_RTT_80ohm, 80},
596f520bb22SYouMin Chen 	{PHY_DDR3_RTT_74ohm, 74},
597f520bb22SYouMin Chen 	{PHY_DDR3_RTT_69ohm, 69},
598f520bb22SYouMin Chen 	{PHY_DDR3_RTT_64ohm, 64},
599f520bb22SYouMin Chen 	{PHY_DDR3_RTT_60ohm, 60},
600f520bb22SYouMin Chen 	{PHY_DDR3_RTT_57ohm, 57},
601f520bb22SYouMin Chen 	{PHY_DDR3_RTT_54ohm, 54},
602f520bb22SYouMin Chen 	{PHY_DDR3_RTT_51ohm, 51},
603f520bb22SYouMin Chen 	{PHY_DDR3_RTT_48ohm, 48},
604f520bb22SYouMin Chen 	{PHY_DDR3_RTT_46ohm, 46},
605f520bb22SYouMin Chen 	{PHY_DDR3_RTT_44ohm, 44},
606f520bb22SYouMin Chen 	{PHY_DDR3_RTT_42ohm, 42}
607f520bb22SYouMin Chen };
608f520bb22SYouMin Chen 
609f520bb22SYouMin Chen static u16 d4lp3_phy_drv_2_ohm[][2] = {
610f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_570ohm, 570},
611f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_285ohm, 285},
612f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_190ohm, 190},
613f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_142ohm, 142},
614f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_114ohm, 114},
615f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_95ohm, 95},
616f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_81ohm, 81},
617f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_71ohm, 71},
618f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_63ohm, 63},
619f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_57ohm, 57},
620f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_52ohm, 52},
621f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_47ohm, 47},
622f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_44ohm, 44},
623f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_41ohm, 41},
624f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_38ohm, 38},
625f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_36ohm, 36},
626f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_34ohm, 34},
627f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_32ohm, 32},
628f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_30ohm, 30},
629f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_28ohm, 28},
630f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_27ohm, 27},
631f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_26ohm, 26},
632f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RON_25ohm, 25}
633f520bb22SYouMin Chen };
634f520bb22SYouMin Chen 
635f520bb22SYouMin Chen static u16 d4lp3_phy_odt_2_ohm[][2] = {
636f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_DISABLE, 0},
637f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_973ohm, 973},
638f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_493ohm, 493},
639f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_327ohm, 327},
640f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_247ohm, 247},
641f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_197ohm, 197},
642f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_164ohm, 164},
643f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_141ohm, 141},
644f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_123ohm, 123},
645f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_109ohm, 109},
646f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_99ohm, 99},
647f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_90ohm, 90},
648f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_82ohm, 82},
649f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_76ohm, 76},
650f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_70ohm, 70},
651f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_66ohm, 66},
652f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_62ohm, 62},
653f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_58ohm, 58},
654f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_55ohm, 55},
655f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_52ohm, 52},
656f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_49ohm, 49},
657f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_47ohm, 47},
658f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_45ohm, 45},
659f520bb22SYouMin Chen 	{PHY_DDR4_LPDDR3_RTT_43ohm, 43}
660f520bb22SYouMin Chen };
661f520bb22SYouMin Chen 
662f520bb22SYouMin Chen static u16 lp4_phy_drv_2_ohm[][2] = {
663f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_606ohm, 606},
664f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_303ohm, 303},
665f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_202ohm, 202},
666f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_152ohm, 153},
667f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_121ohm, 121},
668f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_101ohm, 101},
669f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_87ohm, 87},
670f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_76ohm, 76},
671f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_67ohm, 67},
672f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_61ohm, 61},
673f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_55ohm, 55},
674f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_51ohm, 51},
675f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_47ohm, 47},
676f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_43ohm, 43},
677f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_40ohm, 40},
678f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_38ohm, 38},
679f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_36ohm, 36},
680f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_34ohm, 34},
681f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_32ohm, 32},
682f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_30ohm, 30},
683f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_29ohm, 29},
684f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_28ohm, 28},
685f520bb22SYouMin Chen 	{PHY_LPDDR4_RON_26ohm, 26}
686f520bb22SYouMin Chen };
687f520bb22SYouMin Chen 
688f520bb22SYouMin Chen static u16 lp4_phy_odt_2_ohm[][2] = {
689f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_DISABLE, 0},
690f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_998ohm, 998},
691f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_506ohm, 506},
692f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_336ohm, 336},
693f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_253ohm, 253},
694f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_202ohm, 202},
695f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_169ohm, 169},
696f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_144ohm, 144},
697f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_127ohm, 127},
698f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_112ohm, 112},
699f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_101ohm, 101},
700f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_92ohm, 92},
701f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_84ohm, 84},
702f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_78ohm, 78},
703f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_72ohm, 72},
704f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_67ohm, 67},
705f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_63ohm, 63},
706f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_60ohm, 60},
707f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_56ohm, 56},
708f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_53ohm, 53},
709f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_51ohm, 51},
710f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_48ohm, 48},
711f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_46ohm, 46},
712f520bb22SYouMin Chen 	{PHY_LPDDR4_RTT_44ohm, 44}
713f520bb22SYouMin Chen };
714f520bb22SYouMin Chen 
715f520bb22SYouMin Chen static u32 lp4_odt_calc(u32 odt_ohm)
716f520bb22SYouMin Chen {
717f520bb22SYouMin Chen 	u32 odt;
718f520bb22SYouMin Chen 
719f520bb22SYouMin Chen 	if (odt_ohm == 0)
720f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_DIS;
721f520bb22SYouMin Chen 	else if (odt_ohm <= 40)
722f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_40;
723f520bb22SYouMin Chen 	else if (odt_ohm <= 48)
724f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_48;
725f520bb22SYouMin Chen 	else if (odt_ohm <= 60)
726f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_60;
727f520bb22SYouMin Chen 	else if (odt_ohm <= 80)
728f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_80;
729f520bb22SYouMin Chen 	else if (odt_ohm <= 120)
730f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_120;
731f520bb22SYouMin Chen 	else
732f520bb22SYouMin Chen 		odt = LPDDR4_DQODT_240;
733f520bb22SYouMin Chen 
734f520bb22SYouMin Chen 	return odt;
735f520bb22SYouMin Chen }
736f520bb22SYouMin Chen 
737f520bb22SYouMin Chen static void *get_ddr_drv_odt_info(u32 dramtype)
738f520bb22SYouMin Chen {
739f520bb22SYouMin Chen 	struct sdram_head_info_index_v2 *index =
740f520bb22SYouMin Chen 		(struct sdram_head_info_index_v2 *)common_info;
741f520bb22SYouMin Chen 	void *ddr_info = 0;
742f520bb22SYouMin Chen 
743f520bb22SYouMin Chen 	if (dramtype == DDR4)
744f520bb22SYouMin Chen 		ddr_info = (void *)common_info + index->ddr4_index.offset * 4;
745f520bb22SYouMin Chen 	else if (dramtype == DDR3)
746f520bb22SYouMin Chen 		ddr_info = (void *)common_info + index->ddr3_index.offset * 4;
747f520bb22SYouMin Chen 	else if (dramtype == LPDDR3)
748f520bb22SYouMin Chen 		ddr_info = (void *)common_info + index->lp3_index.offset * 4;
749f520bb22SYouMin Chen 	else if (dramtype == LPDDR4)
750f520bb22SYouMin Chen 		ddr_info = (void *)common_info + index->lp4_index.offset * 4;
751f520bb22SYouMin Chen 	else
752f520bb22SYouMin Chen 		printascii("unsupported dram type\n");
753f520bb22SYouMin Chen 	return ddr_info;
754f520bb22SYouMin Chen }
755f520bb22SYouMin Chen 
756f520bb22SYouMin Chen static void set_lp4_vref(struct dram_info *dram, struct lp4_info *lp4_info,
757f520bb22SYouMin Chen 			 u32 freq_mhz, u32 dst_fsp)
758f520bb22SYouMin Chen {
759f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
760f520bb22SYouMin Chen 	u32 ca_vref, dq_vref;
761f520bb22SYouMin Chen 
762f520bb22SYouMin Chen 	if (freq_mhz <= LP4_CA_ODT_EN_FREQ(lp4_info->ca_odten_freq))
763f520bb22SYouMin Chen 		ca_vref = LP4_CA_VREF(lp4_info->vref_when_odtoff);
764f520bb22SYouMin Chen 	else
765f520bb22SYouMin Chen 		ca_vref = LP4_CA_VREF(lp4_info->vref_when_odten);
766f520bb22SYouMin Chen 
767f520bb22SYouMin Chen 	if (freq_mhz <= LP4_DQ_ODT_EN_FREQ(lp4_info->dq_odten_freq))
768f520bb22SYouMin Chen 		dq_vref = LP4_DQ_VREF(lp4_info->vref_when_odtoff);
769f520bb22SYouMin Chen 	else
770f520bb22SYouMin Chen 		dq_vref = LP4_DQ_VREF(lp4_info->vref_when_odten);
771f520bb22SYouMin Chen 
772f520bb22SYouMin Chen 	if (ca_vref < 100)
773f520bb22SYouMin Chen 		ca_vref = 100;
774f520bb22SYouMin Chen 	if (ca_vref > 420)
775f520bb22SYouMin Chen 		ca_vref = 420;
776f520bb22SYouMin Chen 
777f520bb22SYouMin Chen 	if (ca_vref <= 300)
778f520bb22SYouMin Chen 		ca_vref = (0 << 6) | (ca_vref - 100) / 4;
779f520bb22SYouMin Chen 	else
780f520bb22SYouMin Chen 		ca_vref = (1 << 6) | (ca_vref - 220) / 4;
781f520bb22SYouMin Chen 
782f520bb22SYouMin Chen 	if (dq_vref < 100)
783f520bb22SYouMin Chen 		dq_vref = 100;
784f520bb22SYouMin Chen 	if (dq_vref > 420)
785f520bb22SYouMin Chen 		dq_vref = 420;
786f520bb22SYouMin Chen 
787f520bb22SYouMin Chen 	if (dq_vref <= 300)
788f520bb22SYouMin Chen 		dq_vref = (0 << 6) | (dq_vref - 100) / 4;
789f520bb22SYouMin Chen 	else
790f520bb22SYouMin Chen 		dq_vref = (1 << 6) | (dq_vref - 220) / 4;
791f520bb22SYouMin Chen 
792f520bb22SYouMin Chen 	sw_set_req(dram);
793f520bb22SYouMin Chen 	clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
794f520bb22SYouMin Chen 			DDR_PCTL2_INIT6,
795f520bb22SYouMin Chen 			PCTL2_MR_MASK << PCTL2_LPDDR4_MR12_SHIFT,
796f520bb22SYouMin Chen 			ca_vref << PCTL2_LPDDR4_MR12_SHIFT);
797f520bb22SYouMin Chen 
798f520bb22SYouMin Chen 	clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
799f520bb22SYouMin Chen 			DDR_PCTL2_INIT7,
800f520bb22SYouMin Chen 			PCTL2_MR_MASK << PCTL2_LPDDR4_MR14_SHIFT,
801f520bb22SYouMin Chen 			dq_vref << PCTL2_LPDDR4_MR14_SHIFT);
802f520bb22SYouMin Chen 	sw_set_ack(dram);
803f520bb22SYouMin Chen }
804f520bb22SYouMin Chen 
805f520bb22SYouMin Chen static void set_ds_odt(struct dram_info *dram,
806f520bb22SYouMin Chen 		       struct rv1126_sdram_params *sdram_params, u32 dst_fsp)
807f520bb22SYouMin Chen {
808f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
809f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
810f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
811f520bb22SYouMin Chen 	struct ddr2_3_4_lp2_3_info *ddr_info;
812f520bb22SYouMin Chen 	struct lp4_info *lp4_info;
813f520bb22SYouMin Chen 	u32 i, j, tmp;
814f520bb22SYouMin Chen 	const u16 (*p_drv)[2];
815f520bb22SYouMin Chen 	const u16 (*p_odt)[2];
816f520bb22SYouMin Chen 	u32 drv_info, sr_info;
817f520bb22SYouMin Chen 	u32 phy_dq_drv_ohm, phy_clk_drv_ohm, phy_ca_drv_ohm, dram_drv_ohm;
818f520bb22SYouMin Chen 	u32 phy_odt_ohm, dram_odt_ohm;
819f520bb22SYouMin Chen 	u32 lp4_pu_cal, phy_lp4_drv_pd_en;
820f520bb22SYouMin Chen 	u32 phy_odt_up_en, phy_odt_dn_en;
821f520bb22SYouMin Chen 	u32 sr_dq, sr_clk;
822f520bb22SYouMin Chen 	u32 freq = sdram_params->base.ddr_freq;
823f520bb22SYouMin Chen 	u32 mr1_mr3, mr11, mr22, vref_out, vref_inner;
824f520bb22SYouMin Chen 	u32 phy_clk_drv = 0, phy_odt = 0, phy_ca_drv = 0, dram_caodt_ohm = 0;
825f520bb22SYouMin Chen 	u32 phy_dq_drv = 0;
826f520bb22SYouMin Chen 	u32 phy_odt_up = 0, phy_odt_dn = 0;
827f520bb22SYouMin Chen 
828f520bb22SYouMin Chen 	ddr_info = get_ddr_drv_odt_info(dramtype);
829f520bb22SYouMin Chen 	lp4_info = (void *)ddr_info;
830f520bb22SYouMin Chen 
831f520bb22SYouMin Chen 	if (!ddr_info)
832f520bb22SYouMin Chen 		return;
833f520bb22SYouMin Chen 
834f520bb22SYouMin Chen 	/* dram odt en freq control phy drv, dram odt and phy sr */
835f520bb22SYouMin Chen 	if (freq <= DRAMODT_EN_FREQ(ddr_info->odten_freq)) {
836f520bb22SYouMin Chen 		drv_info = ddr_info->drv_when_odtoff;
837f520bb22SYouMin Chen 		dram_odt_ohm = 0;
838f520bb22SYouMin Chen 		sr_info = ddr_info->sr_when_odtoff;
839f520bb22SYouMin Chen 		phy_lp4_drv_pd_en =
840f520bb22SYouMin Chen 			PHY_LP4_DRV_PULLDOWN_EN_ODTOFF(lp4_info->odt_info);
841f520bb22SYouMin Chen 	} else {
842f520bb22SYouMin Chen 		drv_info = ddr_info->drv_when_odten;
843f520bb22SYouMin Chen 		dram_odt_ohm = ODT_INFO_DRAM_ODT(ddr_info->odt_info);
844f520bb22SYouMin Chen 		sr_info = ddr_info->sr_when_odten;
845f520bb22SYouMin Chen 		phy_lp4_drv_pd_en =
846f520bb22SYouMin Chen 			PHY_LP4_DRV_PULLDOWN_EN_ODTEN(lp4_info->odt_info);
847f520bb22SYouMin Chen 	}
848f520bb22SYouMin Chen 	phy_dq_drv_ohm =
849f520bb22SYouMin Chen 		DRV_INFO_PHY_DQ_DRV(drv_info);
850f520bb22SYouMin Chen 	phy_clk_drv_ohm =
851f520bb22SYouMin Chen 		DRV_INFO_PHY_CLK_DRV(drv_info);
852f520bb22SYouMin Chen 	phy_ca_drv_ohm =
853f520bb22SYouMin Chen 		DRV_INFO_PHY_CA_DRV(drv_info);
854f520bb22SYouMin Chen 
855f520bb22SYouMin Chen 	sr_dq = DQ_SR_INFO(sr_info);
856f520bb22SYouMin Chen 	sr_clk = CLK_SR_INFO(sr_info);
857f520bb22SYouMin Chen 
858f520bb22SYouMin Chen 	/* phy odt en freq control dram drv and phy odt */
859f520bb22SYouMin Chen 	if (freq <= PHYODT_EN_FREQ(ddr_info->odten_freq)) {
860f520bb22SYouMin Chen 		dram_drv_ohm = DRV_INFO_DRAM_DQ_DRV(ddr_info->drv_when_odtoff);
861f520bb22SYouMin Chen 		lp4_pu_cal = LP4_DRV_PU_CAL_ODTOFF(lp4_info->odt_info);
862f520bb22SYouMin Chen 		phy_odt_ohm = 0;
863f520bb22SYouMin Chen 		phy_odt_up_en = 0;
864f520bb22SYouMin Chen 		phy_odt_dn_en = 0;
865f520bb22SYouMin Chen 	} else {
866f520bb22SYouMin Chen 		dram_drv_ohm =
867f520bb22SYouMin Chen 			DRV_INFO_DRAM_DQ_DRV(ddr_info->drv_when_odten);
868f520bb22SYouMin Chen 		phy_odt_ohm = ODT_INFO_PHY_ODT(ddr_info->odt_info);
869f520bb22SYouMin Chen 		phy_odt_up_en =
870f520bb22SYouMin Chen 			ODT_INFO_PULLUP_EN(ddr_info->odt_info);
871f520bb22SYouMin Chen 		phy_odt_dn_en =
872f520bb22SYouMin Chen 			ODT_INFO_PULLDOWN_EN(ddr_info->odt_info);
873f520bb22SYouMin Chen 		lp4_pu_cal = LP4_DRV_PU_CAL_ODTEN(lp4_info->odt_info);
874f520bb22SYouMin Chen 	}
875f520bb22SYouMin Chen 
876f520bb22SYouMin Chen 	if (dramtype == LPDDR4) {
877f520bb22SYouMin Chen 		if (phy_odt_ohm) {
878f520bb22SYouMin Chen 			phy_odt_up_en = 0;
879f520bb22SYouMin Chen 			phy_odt_dn_en = 1;
880f520bb22SYouMin Chen 		}
881f520bb22SYouMin Chen 		if (freq <= LP4_CA_ODT_EN_FREQ(lp4_info->ca_odten_freq))
882f520bb22SYouMin Chen 			dram_caodt_ohm = 0;
883f520bb22SYouMin Chen 		else
884f520bb22SYouMin Chen 			dram_caodt_ohm =
885f520bb22SYouMin Chen 				ODT_INFO_LP4_CA_ODT(lp4_info->odt_info);
886f520bb22SYouMin Chen 	}
887f520bb22SYouMin Chen 
888f520bb22SYouMin Chen 	if (dramtype == DDR3) {
889f520bb22SYouMin Chen 		p_drv = d3_phy_drv_2_ohm;
890f520bb22SYouMin Chen 		p_odt = d3_phy_odt_2_ohm;
891f520bb22SYouMin Chen 	} else if (dramtype == LPDDR4) {
892f520bb22SYouMin Chen 		p_drv = lp4_phy_drv_2_ohm;
893f520bb22SYouMin Chen 		p_odt = lp4_phy_odt_2_ohm;
894f520bb22SYouMin Chen 	} else {
895f520bb22SYouMin Chen 		p_drv = d4lp3_phy_drv_2_ohm;
896f520bb22SYouMin Chen 		p_odt = d4lp3_phy_odt_2_ohm;
897f520bb22SYouMin Chen 	}
898f520bb22SYouMin Chen 
899f520bb22SYouMin Chen 	for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
900f520bb22SYouMin Chen 		if (phy_dq_drv_ohm <= *(*(p_drv + i) + 1)) {
901f520bb22SYouMin Chen 			phy_dq_drv = **(p_drv + i);
902f520bb22SYouMin Chen 			break;
903f520bb22SYouMin Chen 		}
904f520bb22SYouMin Chen 		if (i == 0)
905f520bb22SYouMin Chen 			break;
906f520bb22SYouMin Chen 	}
907f520bb22SYouMin Chen 	for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
908f520bb22SYouMin Chen 		if (phy_clk_drv_ohm <= *(*(p_drv + i) + 1)) {
909f520bb22SYouMin Chen 			phy_clk_drv = **(p_drv + i);
910f520bb22SYouMin Chen 			break;
911f520bb22SYouMin Chen 		}
912f520bb22SYouMin Chen 		if (i == 0)
913f520bb22SYouMin Chen 			break;
914f520bb22SYouMin Chen 	}
915f520bb22SYouMin Chen 	for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
916f520bb22SYouMin Chen 		if (phy_ca_drv_ohm <= *(*(p_drv + i) + 1)) {
917f520bb22SYouMin Chen 			phy_ca_drv = **(p_drv + i);
918f520bb22SYouMin Chen 			break;
919f520bb22SYouMin Chen 		}
920f520bb22SYouMin Chen 		if (i == 0)
921f520bb22SYouMin Chen 			break;
922f520bb22SYouMin Chen 	}
923f520bb22SYouMin Chen 	if (!phy_odt_ohm)
924f520bb22SYouMin Chen 		phy_odt = 0;
925f520bb22SYouMin Chen 	else
926f520bb22SYouMin Chen 		for (i = ARRAY_SIZE(d4lp3_phy_odt_2_ohm) - 1; ; i--) {
927f520bb22SYouMin Chen 			if (phy_odt_ohm <= *(*(p_odt + i) + 1)) {
928f520bb22SYouMin Chen 				phy_odt = **(p_odt + i);
929f520bb22SYouMin Chen 				break;
930f520bb22SYouMin Chen 			}
931f520bb22SYouMin Chen 			if (i == 0)
932f520bb22SYouMin Chen 				break;
933f520bb22SYouMin Chen 		}
934f520bb22SYouMin Chen 
935f520bb22SYouMin Chen 	if (dramtype != LPDDR4) {
936f520bb22SYouMin Chen 		if (!phy_odt_ohm || (phy_odt_up_en && phy_odt_dn_en))
937f520bb22SYouMin Chen 			vref_inner = 0x80;
938f520bb22SYouMin Chen 		else if (phy_odt_up_en)
939f520bb22SYouMin Chen 			vref_inner = (2 * dram_drv_ohm + phy_odt_ohm) * 128 /
940f520bb22SYouMin Chen 				     (dram_drv_ohm + phy_odt_ohm);
941f520bb22SYouMin Chen 		else
942f520bb22SYouMin Chen 			vref_inner = phy_odt_ohm * 128 /
943f520bb22SYouMin Chen 				(phy_odt_ohm + dram_drv_ohm);
944f520bb22SYouMin Chen 
945f520bb22SYouMin Chen 		if (dramtype != DDR3 && dram_odt_ohm)
946f520bb22SYouMin Chen 			vref_out = (2 * phy_dq_drv_ohm + dram_odt_ohm) * 128 /
947f520bb22SYouMin Chen 				   (phy_dq_drv_ohm + dram_odt_ohm);
948f520bb22SYouMin Chen 		else
949f520bb22SYouMin Chen 			vref_out = 0x80;
950f520bb22SYouMin Chen 	} else {
951f520bb22SYouMin Chen 		/* for lp4 */
952f520bb22SYouMin Chen 		if (phy_odt_ohm)
953f520bb22SYouMin Chen 			vref_inner =
954f520bb22SYouMin Chen 				(PHY_LP4_DQ_VREF(lp4_info->vref_when_odten) *
955f520bb22SYouMin Chen 				 256) / 1000;
956f520bb22SYouMin Chen 		else
957f520bb22SYouMin Chen 			vref_inner =
958f520bb22SYouMin Chen 				(PHY_LP4_DQ_VREF(lp4_info->vref_when_odtoff) *
959f520bb22SYouMin Chen 				 256) / 1000;
960f520bb22SYouMin Chen 
961f520bb22SYouMin Chen 		vref_out = 0x80;
962f520bb22SYouMin Chen 	}
963f520bb22SYouMin Chen 
964f520bb22SYouMin Chen 	/* default ZQCALIB bypass mode */
965f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x100), 0x1f, phy_ca_drv);
966f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x101), 0x1f, phy_ca_drv);
967f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x102), 0x1f, phy_clk_drv);
968f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x103), 0x1f, phy_clk_drv);
969f520bb22SYouMin Chen 	/* clk / cmd slew rate */
970f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x106), 0x1f, sr_clk);
971f520bb22SYouMin Chen 
972f520bb22SYouMin Chen 	phy_lp4_drv_pd_en = (~phy_lp4_drv_pd_en) & 1;
973f520bb22SYouMin Chen 	if (phy_odt_up_en)
974f520bb22SYouMin Chen 		phy_odt_up = phy_odt;
975f520bb22SYouMin Chen 	if (phy_odt_dn_en)
976f520bb22SYouMin Chen 		phy_odt_dn = phy_odt;
977f520bb22SYouMin Chen 
978f520bb22SYouMin Chen 	for (i = 0; i < 4; i++) {
979f520bb22SYouMin Chen 		j = 0x110 + i * 0x10;
980f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, j + 1), 0x1f, phy_odt_up);
981f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, j), 0x1f, phy_odt_dn);
982f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, j + 2), 0x1f, phy_dq_drv);
983f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, j + 3), 0x1f, phy_dq_drv);
984f520bb22SYouMin Chen 		writel(vref_inner, PHY_REG(phy_base, 0x118 + i * 0x10));
985f520bb22SYouMin Chen 
986f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x114 + i * 0x10),
987f520bb22SYouMin Chen 				1 << 3, phy_lp4_drv_pd_en << 3);
988f520bb22SYouMin Chen 		/* dq slew rate */
989f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x117 + i * 0x10),
990f520bb22SYouMin Chen 				0x1f, sr_dq);
991f520bb22SYouMin Chen 	}
992f520bb22SYouMin Chen 
993f520bb22SYouMin Chen 	/* reg_rx_vref_value_update */
994f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
995f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
996f520bb22SYouMin Chen 
997f520bb22SYouMin Chen 	/* RAM VREF */
998f520bb22SYouMin Chen 	writel(vref_out, PHY_REG(phy_base, 0x105));
999f520bb22SYouMin Chen 	udelay(8000);
1000f520bb22SYouMin Chen 
1001f520bb22SYouMin Chen 	if (dramtype == LPDDR4)
1002f520bb22SYouMin Chen 		set_lp4_vref(dram, lp4_info, freq, dst_fsp);
1003f520bb22SYouMin Chen 
1004f520bb22SYouMin Chen 	if (dramtype == DDR3 || dramtype == DDR4) {
1005f520bb22SYouMin Chen 		mr1_mr3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1006f520bb22SYouMin Chen 				DDR_PCTL2_INIT3);
1007f520bb22SYouMin Chen 		mr1_mr3 = mr1_mr3 >> PCTL2_DDR34_MR1_SHIFT & PCTL2_MR_MASK;
1008f520bb22SYouMin Chen 	} else {
1009f520bb22SYouMin Chen 		mr1_mr3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1010f520bb22SYouMin Chen 				DDR_PCTL2_INIT4);
1011f520bb22SYouMin Chen 		mr1_mr3 = mr1_mr3 >> PCTL2_LPDDR234_MR3_SHIFT & PCTL2_MR_MASK;
1012f520bb22SYouMin Chen 	}
1013f520bb22SYouMin Chen 
1014f520bb22SYouMin Chen 	if (dramtype == DDR3) {
1015f520bb22SYouMin Chen 		mr1_mr3 &= ~(DDR3_DS_MASK | DDR3_RTT_NOM_MASK);
1016f520bb22SYouMin Chen 		if (dram_drv_ohm == 34)
1017f520bb22SYouMin Chen 			mr1_mr3 |= DDR3_DS_34;
1018f520bb22SYouMin Chen 
1019f520bb22SYouMin Chen 		if (dram_odt_ohm == 0)
1020f520bb22SYouMin Chen 			mr1_mr3 |= DDR3_RTT_NOM_DIS;
1021f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 40)
1022f520bb22SYouMin Chen 			mr1_mr3 |= DDR3_RTT_NOM_40;
1023f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 60)
1024f520bb22SYouMin Chen 			mr1_mr3 |= DDR3_RTT_NOM_60;
1025f520bb22SYouMin Chen 		else
1026f520bb22SYouMin Chen 			mr1_mr3 |= DDR3_RTT_NOM_120;
1027f520bb22SYouMin Chen 
1028f520bb22SYouMin Chen 	} else if (dramtype == DDR4) {
1029f520bb22SYouMin Chen 		mr1_mr3 &= ~(DDR4_DS_MASK | DDR4_RTT_NOM_MASK);
1030f520bb22SYouMin Chen 		if (dram_drv_ohm == 48)
1031f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_DS_48;
1032f520bb22SYouMin Chen 
1033f520bb22SYouMin Chen 		if (dram_odt_ohm == 0)
1034f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_DIS;
1035f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 34)
1036f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_34;
1037f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 40)
1038f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_40;
1039f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 48)
1040f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_48;
1041f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 60)
1042f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_60;
1043f520bb22SYouMin Chen 		else
1044f520bb22SYouMin Chen 			mr1_mr3 |= DDR4_RTT_NOM_120;
1045f520bb22SYouMin Chen 
1046f520bb22SYouMin Chen 	} else if (dramtype == LPDDR3) {
1047f520bb22SYouMin Chen 		if (dram_drv_ohm <= 34)
1048f520bb22SYouMin Chen 			mr1_mr3 |= LPDDR3_DS_34;
1049f520bb22SYouMin Chen 		else if (dram_drv_ohm <= 40)
1050f520bb22SYouMin Chen 			mr1_mr3 |= LPDDR3_DS_40;
1051f520bb22SYouMin Chen 		else if (dram_drv_ohm <= 48)
1052f520bb22SYouMin Chen 			mr1_mr3 |= LPDDR3_DS_48;
1053f520bb22SYouMin Chen 		else if (dram_drv_ohm <= 60)
1054f520bb22SYouMin Chen 			mr1_mr3 |= LPDDR3_DS_60;
1055f520bb22SYouMin Chen 		else if (dram_drv_ohm <= 80)
1056f520bb22SYouMin Chen 			mr1_mr3 |= LPDDR3_DS_80;
1057f520bb22SYouMin Chen 
1058f520bb22SYouMin Chen 		if (dram_odt_ohm == 0)
1059f520bb22SYouMin Chen 			lp3_odt_value = LPDDR3_ODT_DIS;
1060f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 60)
1061f520bb22SYouMin Chen 			lp3_odt_value = LPDDR3_ODT_60;
1062f520bb22SYouMin Chen 		else if (dram_odt_ohm <= 120)
1063f520bb22SYouMin Chen 			lp3_odt_value = LPDDR3_ODT_120;
1064f520bb22SYouMin Chen 		else
1065f520bb22SYouMin Chen 			lp3_odt_value = LPDDR3_ODT_240;
1066f520bb22SYouMin Chen 	} else {/* for lpddr4 */
1067f520bb22SYouMin Chen 		/* MR3 for lp4 PU-CAL and PDDS */
1068f520bb22SYouMin Chen 		mr1_mr3 &= ~(LPDDR4_PDDS_MASK | LPDDR4_PU_CAL_MASK);
1069f520bb22SYouMin Chen 		mr1_mr3 |= lp4_pu_cal;
1070f520bb22SYouMin Chen 
1071f520bb22SYouMin Chen 		tmp = lp4_odt_calc(dram_drv_ohm);
1072f520bb22SYouMin Chen 		if (!tmp)
1073f520bb22SYouMin Chen 			tmp = LPDDR4_PDDS_240;
1074f520bb22SYouMin Chen 		mr1_mr3 |= (tmp << LPDDR4_PDDS_SHIFT);
1075f520bb22SYouMin Chen 
1076f520bb22SYouMin Chen 		/* MR11 for lp4 ca odt, dq odt set */
1077f520bb22SYouMin Chen 		mr11 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1078f520bb22SYouMin Chen 			     DDR_PCTL2_INIT6);
1079f520bb22SYouMin Chen 		mr11 = mr11 >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK;
1080f520bb22SYouMin Chen 
1081f520bb22SYouMin Chen 		mr11 &= ~(LPDDR4_DQODT_MASK | LPDDR4_CAODT_MASK);
1082f520bb22SYouMin Chen 
1083f520bb22SYouMin Chen 		tmp = lp4_odt_calc(dram_odt_ohm);
1084f520bb22SYouMin Chen 		mr11 |= (tmp << LPDDR4_DQODT_SHIFT);
1085f520bb22SYouMin Chen 
1086f520bb22SYouMin Chen 		tmp = lp4_odt_calc(dram_caodt_ohm);
1087f520bb22SYouMin Chen 		mr11 |= (tmp << LPDDR4_CAODT_SHIFT);
1088f520bb22SYouMin Chen 		sw_set_req(dram);
1089f520bb22SYouMin Chen 		clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1090f520bb22SYouMin Chen 				DDR_PCTL2_INIT6,
1091f520bb22SYouMin Chen 				PCTL2_MR_MASK << PCTL2_LPDDR4_MR11_SHIFT,
1092f520bb22SYouMin Chen 				mr11 << PCTL2_LPDDR4_MR11_SHIFT);
1093f520bb22SYouMin Chen 		sw_set_ack(dram);
1094f520bb22SYouMin Chen 
1095f520bb22SYouMin Chen 		/* MR22 for soc odt/odt-ck/odt-cs/odt-ca */
1096f520bb22SYouMin Chen 		mr22 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1097f520bb22SYouMin Chen 			     DDR_PCTL2_INIT7);
1098f520bb22SYouMin Chen 		mr22 = mr22 >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK;
1099f520bb22SYouMin Chen 		mr22 &= ~LPDDR4_SOC_ODT_MASK;
1100f520bb22SYouMin Chen 
1101f520bb22SYouMin Chen 		tmp = lp4_odt_calc(phy_odt_ohm);
1102f520bb22SYouMin Chen 		mr22 |= tmp;
1103f520bb22SYouMin Chen 		mr22 = mr22 |
1104f520bb22SYouMin Chen 		       (LP4_ODTE_CK_EN(lp4_info->cs_drv_ca_odt_info) <<
1105f520bb22SYouMin Chen 			LPDDR4_ODTE_CK_SHIFT) |
1106f520bb22SYouMin Chen 		       (LP4_ODTE_CS_EN(lp4_info->cs_drv_ca_odt_info) <<
1107f520bb22SYouMin Chen 			LPDDR4_ODTE_CS_SHIFT) |
1108f520bb22SYouMin Chen 		       (LP4_ODTD_CA_EN(lp4_info->cs_drv_ca_odt_info) <<
1109f520bb22SYouMin Chen 			LPDDR4_ODTD_CA_SHIFT);
1110f520bb22SYouMin Chen 
1111f520bb22SYouMin Chen 		sw_set_req(dram);
1112f520bb22SYouMin Chen 		clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1113f520bb22SYouMin Chen 				DDR_PCTL2_INIT7,
1114f520bb22SYouMin Chen 				PCTL2_MR_MASK << PCTL2_LPDDR4_MR22_SHIFT,
1115f520bb22SYouMin Chen 				mr22 << PCTL2_LPDDR4_MR22_SHIFT);
1116f520bb22SYouMin Chen 		sw_set_ack(dram);
1117f520bb22SYouMin Chen 	}
1118f520bb22SYouMin Chen 
1119f520bb22SYouMin Chen 	if (dramtype == DDR4 || dramtype == DDR3) {
1120f520bb22SYouMin Chen 		sw_set_req(dram);
1121f520bb22SYouMin Chen 		clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1122f520bb22SYouMin Chen 				DDR_PCTL2_INIT3,
1123f520bb22SYouMin Chen 				PCTL2_MR_MASK << PCTL2_DDR34_MR1_SHIFT,
1124f520bb22SYouMin Chen 				mr1_mr3 << PCTL2_DDR34_MR1_SHIFT);
1125f520bb22SYouMin Chen 		sw_set_ack(dram);
1126f520bb22SYouMin Chen 	} else {
1127f520bb22SYouMin Chen 		sw_set_req(dram);
1128f520bb22SYouMin Chen 		clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1129f520bb22SYouMin Chen 				DDR_PCTL2_INIT4,
1130f520bb22SYouMin Chen 				PCTL2_MR_MASK << PCTL2_LPDDR234_MR3_SHIFT,
1131f520bb22SYouMin Chen 				mr1_mr3 << PCTL2_LPDDR234_MR3_SHIFT);
1132f520bb22SYouMin Chen 		sw_set_ack(dram);
1133f520bb22SYouMin Chen 	}
1134f520bb22SYouMin Chen }
1135f520bb22SYouMin Chen 
1136f520bb22SYouMin Chen static int sdram_cmd_dq_path_remap(struct dram_info *dram,
1137f520bb22SYouMin Chen 				   struct rv1126_sdram_params *sdram_params)
1138f520bb22SYouMin Chen {
1139f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1140f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
1141f520bb22SYouMin Chen 	struct sdram_head_info_index_v2 *index =
1142f520bb22SYouMin Chen 		(struct sdram_head_info_index_v2 *)common_info;
1143f520bb22SYouMin Chen 	struct dq_map_info *map_info;
1144f520bb22SYouMin Chen 
1145f520bb22SYouMin Chen 	map_info = (struct dq_map_info *)((void *)common_info +
1146f520bb22SYouMin Chen 		index->dq_map_index.offset * 4);
1147f520bb22SYouMin Chen 
1148f520bb22SYouMin Chen 	if (dramtype <= LPDDR4)
1149f520bb22SYouMin Chen 		writel((map_info->byte_map[dramtype / 4] >>
1150f520bb22SYouMin Chen 			((dramtype % 4) * 8)) & 0xff,
1151f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x4f));
1152f520bb22SYouMin Chen 
1153f520bb22SYouMin Chen 	return 0;
1154f520bb22SYouMin Chen }
1155f520bb22SYouMin Chen 
1156f520bb22SYouMin Chen static void phy_cfg(struct dram_info *dram,
1157f520bb22SYouMin Chen 		    struct rv1126_sdram_params *sdram_params)
1158f520bb22SYouMin Chen {
1159f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
1160f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1161f520bb22SYouMin Chen 	u32 i, dq_map, tmp;
1162f520bb22SYouMin Chen 	u32 byte1 = 0, byte0 = 0;
1163f520bb22SYouMin Chen 
1164f520bb22SYouMin Chen 	sdram_cmd_dq_path_remap(dram, sdram_params);
1165f520bb22SYouMin Chen 
1166f520bb22SYouMin Chen 	phy_pll_set(dram, sdram_params->base.ddr_freq * MHZ, 0);
1167f520bb22SYouMin Chen 	for (i = 0; sdram_params->phy_regs.phy[i][0] != 0xFFFFFFFF; i++) {
1168f520bb22SYouMin Chen 		writel(sdram_params->phy_regs.phy[i][1],
1169f520bb22SYouMin Chen 		       phy_base + sdram_params->phy_regs.phy[i][0]);
1170f520bb22SYouMin Chen 	}
1171f520bb22SYouMin Chen 
1172f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x62), BIT(5));
1173f520bb22SYouMin Chen 	dq_map = readl(PHY_REG(phy_base, 0x4f));
1174f520bb22SYouMin Chen 	for (i = 0; i < 4; i++) {
1175f520bb22SYouMin Chen 		if (((dq_map >> (i * 2)) & 0x3) == 0)
1176f520bb22SYouMin Chen 			byte0 = i;
1177f520bb22SYouMin Chen 		if (((dq_map >> (i * 2)) & 0x3) == 1)
1178f520bb22SYouMin Chen 			byte1 = i;
1179f520bb22SYouMin Chen 	}
1180f520bb22SYouMin Chen 
1181f520bb22SYouMin Chen 	tmp = readl(PHY_REG(phy_base, 0xf)) & (~PHY_DQ_WIDTH_MASK);
1182f520bb22SYouMin Chen 	if (cap_info->bw == 2)
1183f520bb22SYouMin Chen 		tmp |= 0xf;
1184f520bb22SYouMin Chen 	else if (cap_info->bw == 1)
1185f520bb22SYouMin Chen 		tmp |= ((1 << byte0) | (1 << byte1));
1186f520bb22SYouMin Chen 	else
1187f520bb22SYouMin Chen 		tmp |= (1 << byte0);
1188f520bb22SYouMin Chen 
1189f520bb22SYouMin Chen 	writel(tmp, PHY_REG(phy_base, 0xf));
1190f520bb22SYouMin Chen 
1191f520bb22SYouMin Chen 	/* lpddr4 odt control by phy, enable cs0 odt */
1192f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4)
1193f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x20), 0x7 << 4,
1194f520bb22SYouMin Chen 				(1 << 6) | (1 << 4));
1195f520bb22SYouMin Chen 	/* for ca training ca vref choose range1 */
1196f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x1e), BIT(6));
1197f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x1f), BIT(6));
1198f520bb22SYouMin Chen 	/* for wr training PHY_0x7c[5], choose range0 */
1199f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x7c), BIT(5));
1200f520bb22SYouMin Chen }
1201f520bb22SYouMin Chen 
1202f520bb22SYouMin Chen static int update_refresh_reg(struct dram_info *dram)
1203f520bb22SYouMin Chen {
1204f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1205f520bb22SYouMin Chen 	u32 ret;
1206f520bb22SYouMin Chen 
1207f520bb22SYouMin Chen 	ret = readl(pctl_base + DDR_PCTL2_RFSHCTL3) ^ (1 << 1);
1208f520bb22SYouMin Chen 	writel(ret, pctl_base + DDR_PCTL2_RFSHCTL3);
1209f520bb22SYouMin Chen 
1210f520bb22SYouMin Chen 	return 0;
1211f520bb22SYouMin Chen }
1212f520bb22SYouMin Chen 
1213f520bb22SYouMin Chen /*
1214f520bb22SYouMin Chen  * rank = 1: cs0
1215f520bb22SYouMin Chen  * rank = 2: cs1
1216f520bb22SYouMin Chen  */
1217f520bb22SYouMin Chen int read_mr(struct dram_info *dram, u32 rank, u32 mr_num, u32 dramtype)
1218f520bb22SYouMin Chen {
1219f520bb22SYouMin Chen 	u32 ret;
1220f520bb22SYouMin Chen 	u32 i, temp;
1221f520bb22SYouMin Chen 	u32 dqmap;
1222f520bb22SYouMin Chen 
1223f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1224f520bb22SYouMin Chen 	struct sdram_head_info_index_v2 *index =
1225f520bb22SYouMin Chen 		(struct sdram_head_info_index_v2 *)common_info;
1226f520bb22SYouMin Chen 	struct dq_map_info *map_info;
1227f520bb22SYouMin Chen 
1228f520bb22SYouMin Chen 	map_info = (struct dq_map_info *)((void *)common_info +
1229f520bb22SYouMin Chen 		index->dq_map_index.offset * 4);
1230f520bb22SYouMin Chen 
1231f520bb22SYouMin Chen 	if (dramtype == LPDDR2)
1232f520bb22SYouMin Chen 		dqmap = map_info->lp2_dq0_7_map;
1233f520bb22SYouMin Chen 	else
1234f520bb22SYouMin Chen 		dqmap = map_info->lp3_dq0_7_map;
1235f520bb22SYouMin Chen 
1236f520bb22SYouMin Chen 	pctl_read_mr(pctl_base, rank, mr_num);
1237f520bb22SYouMin Chen 
1238f520bb22SYouMin Chen 	ret = (readl(&dram->ddrgrf->ddr_grf_status[0]) & 0xff);
1239f520bb22SYouMin Chen 
1240f520bb22SYouMin Chen 	if (dramtype != LPDDR4) {
1241f520bb22SYouMin Chen 		temp = 0;
1242f520bb22SYouMin Chen 		for (i = 0; i < 8; i++) {
1243f520bb22SYouMin Chen 			temp = temp | (((ret >> i) & 0x1) <<
1244f520bb22SYouMin Chen 				       ((dqmap >> (i * 4)) & 0xf));
1245f520bb22SYouMin Chen 		}
1246f520bb22SYouMin Chen 	} else {
1247f520bb22SYouMin Chen 		ret = (readl(&dram->ddrgrf->ddr_grf_status[1]) & 0xff);
1248f520bb22SYouMin Chen 	}
1249f520bb22SYouMin Chen 
1250f520bb22SYouMin Chen 	return ret;
1251f520bb22SYouMin Chen }
1252f520bb22SYouMin Chen 
1253f520bb22SYouMin Chen /* before call this function autorefresh should be disabled */
1254f520bb22SYouMin Chen void send_a_refresh(struct dram_info *dram)
1255f520bb22SYouMin Chen {
1256f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1257f520bb22SYouMin Chen 
1258f520bb22SYouMin Chen 	while (readl(pctl_base + DDR_PCTL2_DBGSTAT) & 0x3)
1259f520bb22SYouMin Chen 		continue;
1260f520bb22SYouMin Chen 	writel(0x3, pctl_base + DDR_PCTL2_DBGCMD);
1261f520bb22SYouMin Chen }
1262f520bb22SYouMin Chen 
1263f520bb22SYouMin Chen void record_dq_prebit(struct dram_info *dram)
1264f520bb22SYouMin Chen {
1265f520bb22SYouMin Chen 	u32 group, i, tmp;
1266f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1267f520bb22SYouMin Chen 
1268f520bb22SYouMin Chen 	for (group = 0; group < 4; group++) {
1269f520bb22SYouMin Chen 		for (i = 0; i < ARRAY_SIZE(dq_sel); i++) {
1270f520bb22SYouMin Chen 			/* l_loop_invdelaysel */
1271f520bb22SYouMin Chen 			writel(dq_sel[i][0], PHY_REG(phy_base,
1272f520bb22SYouMin Chen 						     grp_addr[group] + 0x2c));
1273f520bb22SYouMin Chen 			tmp = readl(PHY_REG(phy_base, grp_addr[group] + 0x2e));
1274f520bb22SYouMin Chen 			writel(tmp, PHY_REG(phy_base,
1275f520bb22SYouMin Chen 					    grp_addr[group] + dq_sel[i][1]));
1276f520bb22SYouMin Chen 
1277f520bb22SYouMin Chen 			/* r_loop_invdelaysel */
1278f520bb22SYouMin Chen 			writel(dq_sel[i][0], PHY_REG(phy_base,
1279f520bb22SYouMin Chen 						     grp_addr[group] + 0x2d));
1280f520bb22SYouMin Chen 			tmp = readl(PHY_REG(phy_base, grp_addr[group] + 0x2f));
1281f520bb22SYouMin Chen 			writel(tmp, PHY_REG(phy_base,
1282f520bb22SYouMin Chen 					    grp_addr[group] + dq_sel[i][2]));
1283f520bb22SYouMin Chen 		}
1284f520bb22SYouMin Chen 	}
1285f520bb22SYouMin Chen }
1286f520bb22SYouMin Chen 
1287f520bb22SYouMin Chen static void update_dq_rx_prebit(struct dram_info *dram)
1288f520bb22SYouMin Chen {
1289f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1290f520bb22SYouMin Chen 
1291f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x70), BIT(1) | BIT(6) | BIT(4),
1292f520bb22SYouMin Chen 			BIT(4));
1293f520bb22SYouMin Chen 	udelay(1);
1294f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x70), BIT(4));
1295f520bb22SYouMin Chen }
1296f520bb22SYouMin Chen 
1297f520bb22SYouMin Chen static void update_dq_tx_prebit(struct dram_info *dram)
1298f520bb22SYouMin Chen {
1299f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1300f520bb22SYouMin Chen 
1301f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
1302f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x2), BIT(3));
1303f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0xc), BIT(6));
1304f520bb22SYouMin Chen 	udelay(1);
1305f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0xc), BIT(6));
1306f520bb22SYouMin Chen }
1307f520bb22SYouMin Chen 
1308f520bb22SYouMin Chen static void update_ca_prebit(struct dram_info *dram)
1309f520bb22SYouMin Chen {
1310f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1311f520bb22SYouMin Chen 
1312f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x25), BIT(2));
1313f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x22), BIT(6));
1314f520bb22SYouMin Chen 	udelay(1);
1315f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x22), BIT(6));
1316f520bb22SYouMin Chen }
1317f520bb22SYouMin Chen 
1318f520bb22SYouMin Chen /*
1319f520bb22SYouMin Chen  * dir: 0: de-skew = delta_*
1320f520bb22SYouMin Chen  *	1: de-skew = reg val - delta_*
1321f520bb22SYouMin Chen  * delta_dir: value for differential signal: clk/
1322f520bb22SYouMin Chen  * delta_sig: value for single signal: ca/cmd
1323f520bb22SYouMin Chen  */
1324f520bb22SYouMin Chen static void modify_ca_deskew(struct dram_info *dram, u32 dir, int delta_dif,
1325f520bb22SYouMin Chen 			     int delta_sig, u32 cs, u32 dramtype)
1326f520bb22SYouMin Chen {
1327f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1328f520bb22SYouMin Chen 	u32 i, cs_en, tmp;
1329f520bb22SYouMin Chen 
1330f520bb22SYouMin Chen 	if (cs == 0)
1331f520bb22SYouMin Chen 		cs_en = 1;
1332f520bb22SYouMin Chen 	else if (cs == 2)
1333f520bb22SYouMin Chen 		cs_en = 2;
1334f520bb22SYouMin Chen 	else
1335f520bb22SYouMin Chen 		cs_en = 3;
1336f520bb22SYouMin Chen 
1337f520bb22SYouMin Chen 	for (i = 0; i < 0x20; i++) {
1338f520bb22SYouMin Chen 		if (dir == DESKEW_MDF_ABS_VAL)
1339f520bb22SYouMin Chen 			tmp = delta_sig;
1340f520bb22SYouMin Chen 		else
1341f520bb22SYouMin Chen 			tmp = readl(PHY_REG(phy_base, 0x150 + i)) +
1342f520bb22SYouMin Chen 			      delta_sig;
1343f520bb22SYouMin Chen 		writel(tmp, PHY_REG(phy_base, 0x150 + i));
1344f520bb22SYouMin Chen 	}
1345f520bb22SYouMin Chen 
1346f520bb22SYouMin Chen 	if (dir == DESKEW_MDF_ABS_VAL)
1347f520bb22SYouMin Chen 		tmp = delta_dif;
1348f520bb22SYouMin Chen 	else
1349f520bb22SYouMin Chen 		tmp = readl(PHY_REG(phy_base, 0x150 + 0x17)) -
1350f520bb22SYouMin Chen 		       delta_sig + delta_dif;
1351f520bb22SYouMin Chen 	writel(tmp, PHY_REG(phy_base, 0x150 + 0x17));
1352f520bb22SYouMin Chen 	writel(tmp, PHY_REG(phy_base, 0x150 + 0x18));
1353f520bb22SYouMin Chen 	if (dramtype == LPDDR4) {
1354f520bb22SYouMin Chen 		writel(tmp, PHY_REG(phy_base, 0x150 + 0x4));
1355f520bb22SYouMin Chen 		writel(tmp, PHY_REG(phy_base, 0x150 + 0xa));
1356f520bb22SYouMin Chen 
1357f520bb22SYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x10), cs_en << 6);
1358f520bb22SYouMin Chen 		update_ca_prebit(dram);
1359f520bb22SYouMin Chen 	}
1360f520bb22SYouMin Chen }
1361f520bb22SYouMin Chen 
1362f520bb22SYouMin Chen static u32 get_min_value(struct dram_info *dram, u32 signal, u32 rank)
1363f520bb22SYouMin Chen {
1364f520bb22SYouMin Chen 	u32 i, j, offset = 0;
1365f520bb22SYouMin Chen 	u32 min = 0x3f;
1366f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1367f520bb22SYouMin Chen 	u32 byte_en;
1368f520bb22SYouMin Chen 
1369f520bb22SYouMin Chen 	if (signal == SKEW_TX_SIGNAL)
1370f520bb22SYouMin Chen 		offset = 8;
1371f520bb22SYouMin Chen 
1372f520bb22SYouMin Chen 	if (signal == SKEW_CA_SIGNAL) {
1373f520bb22SYouMin Chen 		for (i = 0; i < 0x20; i++)
1374f520bb22SYouMin Chen 			min = MIN(min, readl(PHY_REG(phy_base, 0x150  + i)));
1375f520bb22SYouMin Chen 	} else {
1376f520bb22SYouMin Chen 		byte_en = readl(PHY_REG(phy_base, 0xf)) & 0xf;
1377f520bb22SYouMin Chen 		for (j = offset; j < offset + rank * 4; j++) {
1378f520bb22SYouMin Chen 			if (!((byte_en >> (j % 4)) & 1))
1379f520bb22SYouMin Chen 				continue;
1380f520bb22SYouMin Chen 			for (i = 0; i < 11; i++)
1381f520bb22SYouMin Chen 				min = MIN(min,
1382f520bb22SYouMin Chen 					  readl(PHY_REG(phy_base,
1383f520bb22SYouMin Chen 							dqs_dq_skew_adr[j] +
1384f520bb22SYouMin Chen 							i)));
1385f520bb22SYouMin Chen 		}
1386f520bb22SYouMin Chen 	}
1387f520bb22SYouMin Chen 
1388f520bb22SYouMin Chen 	return min;
1389f520bb22SYouMin Chen }
1390f520bb22SYouMin Chen 
1391f520bb22SYouMin Chen static u32 low_power_update(struct dram_info *dram, u32 en)
1392f520bb22SYouMin Chen {
1393f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1394f520bb22SYouMin Chen 	u32 lp_stat = 0;
1395f520bb22SYouMin Chen 
1396f520bb22SYouMin Chen 	if (en) {
1397f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, en & 0xf);
1398f520bb22SYouMin Chen 	} else {
1399f520bb22SYouMin Chen 		lp_stat = readl(pctl_base + DDR_PCTL2_PWRCTL) & 0xf;
1400f520bb22SYouMin Chen 		clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 0xf);
1401f520bb22SYouMin Chen 	}
1402f520bb22SYouMin Chen 
1403f520bb22SYouMin Chen 	return lp_stat;
1404f520bb22SYouMin Chen }
1405f520bb22SYouMin Chen 
1406f520bb22SYouMin Chen /*
1407f520bb22SYouMin Chen  * signal:
1408f520bb22SYouMin Chen  * dir: 0: de-skew = delta_*
1409f520bb22SYouMin Chen  *	1: de-skew = reg val - delta_*
1410f520bb22SYouMin Chen  * delta_dir: value for differential signal: dqs
1411f520bb22SYouMin Chen  * delta_sig: value for single signal: dq/dm
1412f520bb22SYouMin Chen  */
1413f520bb22SYouMin Chen static void modify_dq_deskew(struct dram_info *dram, u32 signal, u32 dir,
1414f520bb22SYouMin Chen 			     int delta_dif, int delta_sig, u32 rank)
1415f520bb22SYouMin Chen {
1416f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1417f520bb22SYouMin Chen 	u32 i, j, tmp, offset;
1418f520bb22SYouMin Chen 	u32 byte_en;
1419f520bb22SYouMin Chen 
1420f520bb22SYouMin Chen 	byte_en = readl(PHY_REG(phy_base, 0xf)) & 0xf;
1421f520bb22SYouMin Chen 
1422f520bb22SYouMin Chen 	if (signal == SKEW_RX_SIGNAL)
1423f520bb22SYouMin Chen 		offset = 0;
1424f520bb22SYouMin Chen 	else
1425f520bb22SYouMin Chen 		offset = 8;
1426f520bb22SYouMin Chen 
1427f520bb22SYouMin Chen 	for (j = offset; j < (offset + rank * 4); j++) {
1428f520bb22SYouMin Chen 		if (!((byte_en >> (j % 4)) & 1))
1429f520bb22SYouMin Chen 			continue;
1430f520bb22SYouMin Chen 		for (i = 0; i < 0x9; i++) {
1431f520bb22SYouMin Chen 			if (dir == DESKEW_MDF_ABS_VAL)
1432f520bb22SYouMin Chen 				tmp = delta_sig;
1433f520bb22SYouMin Chen 			else
1434f520bb22SYouMin Chen 				tmp = delta_sig + readl(PHY_REG(phy_base,
1435f520bb22SYouMin Chen 							dqs_dq_skew_adr[j] +
1436f520bb22SYouMin Chen 							i));
1437f520bb22SYouMin Chen 			writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + i));
1438f520bb22SYouMin Chen 		}
1439f520bb22SYouMin Chen 		if (dir == DESKEW_MDF_ABS_VAL)
1440f520bb22SYouMin Chen 			tmp = delta_dif;
1441f520bb22SYouMin Chen 		else
1442f520bb22SYouMin Chen 			tmp = delta_dif + readl(PHY_REG(phy_base,
1443f520bb22SYouMin Chen 						dqs_dq_skew_adr[j] + 9));
1444f520bb22SYouMin Chen 		writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + 9));
1445f520bb22SYouMin Chen 		writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + 0xa));
1446f520bb22SYouMin Chen 	}
1447f520bb22SYouMin Chen 	if (signal == SKEW_RX_SIGNAL)
1448f520bb22SYouMin Chen 		update_dq_rx_prebit(dram);
1449f520bb22SYouMin Chen 	else
1450f520bb22SYouMin Chen 		update_dq_tx_prebit(dram);
1451f520bb22SYouMin Chen }
1452f520bb22SYouMin Chen 
1453f520bb22SYouMin Chen static int data_training_rg(struct dram_info *dram, u32 cs, u32 dramtype)
1454f520bb22SYouMin Chen {
1455f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1456f520bb22SYouMin Chen 	u32 ret;
1457f520bb22SYouMin Chen 	u32 dis_auto_zq = 0;
1458f520bb22SYouMin Chen 	u32 odt_val_up, odt_val_dn;
1459f520bb22SYouMin Chen 	u32 i, j;
1460f520bb22SYouMin Chen 
1461f520bb22SYouMin Chen 	odt_val_dn = readl(PHY_REG(phy_base, 0x110));
1462f520bb22SYouMin Chen 	odt_val_up = readl(PHY_REG(phy_base, 0x111));
1463f520bb22SYouMin Chen 
1464f520bb22SYouMin Chen 	if (dramtype != LPDDR4) {
1465f520bb22SYouMin Chen 		for (i = 0; i < 4; i++) {
1466f520bb22SYouMin Chen 			j = 0x110 + i * 0x10;
1467f520bb22SYouMin Chen 			writel(PHY_DDR4_LPDDR3_RTT_247ohm,
1468f520bb22SYouMin Chen 			       PHY_REG(phy_base, j));
1469f520bb22SYouMin Chen 			writel(PHY_DDR4_LPDDR3_RTT_DISABLE,
1470f520bb22SYouMin Chen 			       PHY_REG(phy_base, j + 0x1));
1471f520bb22SYouMin Chen 		}
1472f520bb22SYouMin Chen 	}
1473f520bb22SYouMin Chen 	dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
1474f520bb22SYouMin Chen 	/* use normal read mode for data training */
1475f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0xc), BIT(1));
1476f520bb22SYouMin Chen 
14772c5208e2STang Yun ping 	if (dramtype == DDR4)
14782c5208e2STang Yun ping 		setbits_le32(PHY_REG(phy_base, 0xc), BIT(1));
1479f520bb22SYouMin Chen 
1480f520bb22SYouMin Chen 	/* choose training cs */
1481f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs));
1482f520bb22SYouMin Chen 	/* enable gate training */
1483f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1);
1484f520bb22SYouMin Chen 	udelay(50);
1485f520bb22SYouMin Chen 	ret = readl(PHY_REG(phy_base, 0x91));
1486f520bb22SYouMin Chen 	/* disable gate training */
1487f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0);
1488f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 2), 0x30);
1489f520bb22SYouMin Chen 	pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
1490f520bb22SYouMin Chen 
1491f520bb22SYouMin Chen 	if (ret & 0x20)
1492f520bb22SYouMin Chen 		ret = -1;
1493f520bb22SYouMin Chen 	else
1494f520bb22SYouMin Chen 		ret = (ret & 0xf) ^ (readl(PHY_REG(phy_base, 0xf)) & 0xf);
1495f520bb22SYouMin Chen 
1496f520bb22SYouMin Chen 	if (dramtype != LPDDR4) {
1497f520bb22SYouMin Chen 		for (i = 0; i < 4; i++) {
1498f520bb22SYouMin Chen 			j = 0x110 + i * 0x10;
1499f520bb22SYouMin Chen 			writel(odt_val_dn, PHY_REG(phy_base, j));
1500f520bb22SYouMin Chen 			writel(odt_val_up, PHY_REG(phy_base, j + 0x1));
1501f520bb22SYouMin Chen 		}
1502f520bb22SYouMin Chen 	}
1503f520bb22SYouMin Chen 	return ret;
1504f520bb22SYouMin Chen }
1505f520bb22SYouMin Chen 
1506f520bb22SYouMin Chen static int data_training_wl(struct dram_info *dram, u32 cs, u32 dramtype,
1507f520bb22SYouMin Chen 			    u32 rank)
1508f520bb22SYouMin Chen {
1509f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1510f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1511f520bb22SYouMin Chen 	u32 dis_auto_zq = 0;
1512f520bb22SYouMin Chen 	u32 tmp;
1513f520bb22SYouMin Chen 	u32 cur_fsp;
1514f520bb22SYouMin Chen 	u32 timeout_us = 1000;
1515f520bb22SYouMin Chen 
1516f520bb22SYouMin Chen 	dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
1517f520bb22SYouMin Chen 
1518f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x7a), 0x1);
1519f520bb22SYouMin Chen 
1520f520bb22SYouMin Chen 	cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
1521f520bb22SYouMin Chen 	tmp = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + DDR_PCTL2_INIT3) &
1522f520bb22SYouMin Chen 	      0xffff;
1523f520bb22SYouMin Chen 	writel(tmp & 0xff, PHY_REG(phy_base, 0x3));
1524f520bb22SYouMin Chen 
1525f520bb22SYouMin Chen 	/* disable another cs's output */
1526f520bb22SYouMin Chen 	if ((dramtype == DDR3 || dramtype == DDR4) && rank == 2)
1527f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, (cs + 1) & 1, 1, tmp | (1 << 12),
1528f520bb22SYouMin Chen 			      dramtype);
1529f520bb22SYouMin Chen 	if (dramtype == DDR3 || dramtype == DDR4)
1530f520bb22SYouMin Chen 		writel(0x40 | ((tmp >> 8) & 0x3f), PHY_REG(phy_base, 0x4));
1531f520bb22SYouMin Chen 	else
1532f520bb22SYouMin Chen 		writel(0x80 | ((tmp >> 8) & 0x3f), PHY_REG(phy_base, 0x4));
1533f520bb22SYouMin Chen 
1534f520bb22SYouMin Chen 	/* choose cs */
1535f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
1536f520bb22SYouMin Chen 			((0x2 >> cs) << 6) | (0 << 2));
1537f520bb22SYouMin Chen 	/* enable write leveling */
1538f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
1539f520bb22SYouMin Chen 			((0x2 >> cs) << 6) | (1 << 2));
1540f520bb22SYouMin Chen 
1541f520bb22SYouMin Chen 	while (1) {
1542f520bb22SYouMin Chen 		if ((readl(PHY_REG(phy_base, 0x92)) & 0xf) ==
1543f520bb22SYouMin Chen 		    (readl(PHY_REG(phy_base, 0xf)) & 0xf))
1544f520bb22SYouMin Chen 			break;
1545f520bb22SYouMin Chen 
1546f520bb22SYouMin Chen 		udelay(1);
1547f520bb22SYouMin Chen 		if (timeout_us-- == 0) {
1548f520bb22SYouMin Chen 			printascii("error: write leveling timeout\n");
1549f520bb22SYouMin Chen 			while (1)
1550f520bb22SYouMin Chen 				;
1551f520bb22SYouMin Chen 		}
1552f520bb22SYouMin Chen 	}
1553f520bb22SYouMin Chen 
1554f520bb22SYouMin Chen 	/* disable write leveling */
1555f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
1556f520bb22SYouMin Chen 			((0x2 >> cs) << 6) | (0 << 2));
1557f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x3 << 6, 0 << 6);
1558f520bb22SYouMin Chen 
1559f520bb22SYouMin Chen 	/* enable another cs's output */
1560f520bb22SYouMin Chen 	if ((dramtype == DDR3 || dramtype == DDR4) && rank == 2)
1561f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, (cs + 1) & 1, 1, tmp & ~(1 << 12),
1562f520bb22SYouMin Chen 			      dramtype);
1563f520bb22SYouMin Chen 
1564f520bb22SYouMin Chen 	pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
1565f520bb22SYouMin Chen 
1566f520bb22SYouMin Chen 	return 0;
1567f520bb22SYouMin Chen }
1568f520bb22SYouMin Chen 
1569f520bb22SYouMin Chen char pattern[32] = {
1570f520bb22SYouMin Chen 	0xaa, 0x55, 0xaa, 0x55, 0x55, 0xaa, 0x55, 0xaa,
1571f520bb22SYouMin Chen 	0x55, 0xaa, 0x55, 0xaa, 0xaa, 0x55, 0xaa, 0x55,
1572f520bb22SYouMin Chen 	0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55,
1573f520bb22SYouMin Chen 	0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa
1574f520bb22SYouMin Chen };
1575f520bb22SYouMin Chen 
1576f520bb22SYouMin Chen static int data_training_rd(struct dram_info *dram, u32 cs, u32 dramtype,
1577f520bb22SYouMin Chen 			    u32 mhz)
1578f520bb22SYouMin Chen {
1579f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1580f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1581f520bb22SYouMin Chen 	u32 trefi_1x, trfc_1x;
1582f520bb22SYouMin Chen 	u32 dis_auto_zq = 0;
1583f520bb22SYouMin Chen 	u32 timeout_us = 1000;
1584f520bb22SYouMin Chen 	u32 dqs_default;
1585f520bb22SYouMin Chen 	u32 cur_fsp;
158648c0a787SYouMin Chen 	u32 vref_inner;
1587f520bb22SYouMin Chen 	u32 i;
1588f520bb22SYouMin Chen 	struct sdram_head_info_index_v2 *index =
1589f520bb22SYouMin Chen 		(struct sdram_head_info_index_v2 *)common_info;
1590f520bb22SYouMin Chen 	struct dq_map_info *map_info;
1591f520bb22SYouMin Chen 
159248c0a787SYouMin Chen 	vref_inner = readl(PHY_REG(phy_base, 0x128)) & 0xff;
159348c0a787SYouMin Chen 	if (dramtype == DDR3 && vref_inner == 0x80) {
159448c0a787SYouMin Chen 		for (i = 0; i < 4; i++)
159548c0a787SYouMin Chen 			writel(vref_inner - 0xa,
159648c0a787SYouMin Chen 			       PHY_REG(phy_base, 0x118 + i * 0x10));
159748c0a787SYouMin Chen 
159848c0a787SYouMin Chen 		/* reg_rx_vref_value_update */
159948c0a787SYouMin Chen 		setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
160048c0a787SYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
160148c0a787SYouMin Chen 	}
160248c0a787SYouMin Chen 
1603f520bb22SYouMin Chen 	map_info = (struct dq_map_info *)((void *)common_info +
1604f520bb22SYouMin Chen 		index->dq_map_index.offset * 4);
1605f520bb22SYouMin Chen 	/* only 1cs a time, 0:cs0 1 cs1 */
1606f520bb22SYouMin Chen 	if (cs > 1)
1607f520bb22SYouMin Chen 		return -1;
1608f520bb22SYouMin Chen 
1609f520bb22SYouMin Chen 	dqs_default = 0xf;
1610f520bb22SYouMin Chen 	dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
1611f520bb22SYouMin Chen 
1612f520bb22SYouMin Chen 	cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
1613f520bb22SYouMin Chen 	/* config refresh timing */
1614f520bb22SYouMin Chen 	trefi_1x = ((readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1615f520bb22SYouMin Chen 			   DDR_PCTL2_RFSHTMG) >> 16) & 0xfff) * 32;
1616f520bb22SYouMin Chen 	trfc_1x = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1617f520bb22SYouMin Chen 			DDR_PCTL2_RFSHTMG) & 0x3ff;
1618f520bb22SYouMin Chen 	/* reg_phy_trefi[7:0] and reg_phy_trefi[13:8] */
1619f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x6e), 0xff, trefi_1x & 0xff);
1620f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x6f), 0x3f, (trefi_1x >> 8) & 0x3f);
1621f520bb22SYouMin Chen 	/* reg_phy_trfc */
1622f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x57), 0xff, trfc_1x);
1623f520bb22SYouMin Chen 	/* reg_max_refi_cnt */
1624f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x61), 0xf << 4, 0x8 << 4);
1625f520bb22SYouMin Chen 
1626f520bb22SYouMin Chen 	/* choose training cs */
1627f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x71), 0x3 << 6, (0x2 >> cs) << 6);
1628f520bb22SYouMin Chen 
1629f520bb22SYouMin Chen 	/* set dq map for ddr4 */
1630f520bb22SYouMin Chen 	if (dramtype == DDR4) {
1631f520bb22SYouMin Chen 		setbits_le32(PHY_REG(phy_base, 0x70), BIT(7));
1632f520bb22SYouMin Chen 		for (i = 0; i < 4; i++) {
1633f520bb22SYouMin Chen 			writel((map_info->ddr4_dq_map[cs * 2] >>
1634f520bb22SYouMin Chen 				((i % 4) * 8)) & 0xff,
1635f520bb22SYouMin Chen 				PHY_REG(phy_base, 0x238 + i));
1636f520bb22SYouMin Chen 			writel((map_info->ddr4_dq_map[cs * 2 + 1] >>
1637f520bb22SYouMin Chen 				((i % 4) * 8)) & 0xff,
1638f520bb22SYouMin Chen 				PHY_REG(phy_base, 0x2b8 + i));
1639f520bb22SYouMin Chen 		}
1640f520bb22SYouMin Chen 	}
1641f520bb22SYouMin Chen 
1642f520bb22SYouMin Chen 	/* cha_l reg_l_rd_train_dqs_default[5:0] */
1643f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x230), 0x3f, dqs_default);
1644f520bb22SYouMin Chen 	/* cha_h reg_h_rd_train_dqs_default[5:0] */
1645f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x234), 0x3f, dqs_default);
1646f520bb22SYouMin Chen 	/* chb_l reg_l_rd_train_dqs_default[5:0] */
1647f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x2b0), 0x3f, dqs_default);
1648f520bb22SYouMin Chen 	/* chb_h reg_h_rd_train_dqs_default[5:0] */
1649f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x2b4), 0x3f, dqs_default);
1650f520bb22SYouMin Chen 
1651f520bb22SYouMin Chen 	/* Choose the read train auto mode */
1652f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x70), 0x3, 0x1);
1653f520bb22SYouMin Chen 	/* Enable the auto train of the read train */
1654f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x70), 0x3, 0x3);
1655f520bb22SYouMin Chen 
1656f520bb22SYouMin Chen 	/* Wait the train done. */
1657f520bb22SYouMin Chen 	while (1) {
1658f520bb22SYouMin Chen 		if ((readl(PHY_REG(phy_base, 0x93)) >> 7) & 0x1)
1659f520bb22SYouMin Chen 			break;
1660f520bb22SYouMin Chen 
1661f520bb22SYouMin Chen 		udelay(1);
1662f520bb22SYouMin Chen 		if (timeout_us-- == 0) {
1663f520bb22SYouMin Chen 			printascii("error: read training timeout\n");
1664f520bb22SYouMin Chen 			return -1;
1665f520bb22SYouMin Chen 		}
1666f520bb22SYouMin Chen 	}
1667f520bb22SYouMin Chen 
1668f520bb22SYouMin Chen 	/* Check the read train state */
1669f520bb22SYouMin Chen 	if ((readl(PHY_REG(phy_base, 0x240)) & 0x3) ||
1670f520bb22SYouMin Chen 	    (readl(PHY_REG(phy_base, 0x2c0)) & 0x3)) {
1671f520bb22SYouMin Chen 		printascii("error: read training error\n");
1672f520bb22SYouMin Chen 		return -1;
1673f520bb22SYouMin Chen 	}
1674f520bb22SYouMin Chen 
1675f520bb22SYouMin Chen 	/* Exit the Read Training by setting */
1676f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x70), BIT(1));
1677f520bb22SYouMin Chen 
1678f520bb22SYouMin Chen 	pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
1679f520bb22SYouMin Chen 
168048c0a787SYouMin Chen 	if (dramtype == DDR3 && vref_inner == 0x80) {
168148c0a787SYouMin Chen 		for (i = 0; i < 4; i++)
168248c0a787SYouMin Chen 			writel(vref_inner,
168348c0a787SYouMin Chen 			       PHY_REG(phy_base, 0x118 + i * 0x10));
168448c0a787SYouMin Chen 
168548c0a787SYouMin Chen 		/* reg_rx_vref_value_update */
168648c0a787SYouMin Chen 		setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
168748c0a787SYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
168848c0a787SYouMin Chen 	}
168948c0a787SYouMin Chen 
1690f520bb22SYouMin Chen 	return 0;
1691f520bb22SYouMin Chen }
1692f520bb22SYouMin Chen 
1693f520bb22SYouMin Chen static int data_training_wr(struct dram_info *dram, u32 cs, u32 dramtype,
1694f520bb22SYouMin Chen 			    u32 mhz, u32 dst_fsp)
1695f520bb22SYouMin Chen {
1696f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1697f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1698f520bb22SYouMin Chen 	u32 trefi_1x, trfc_1x;
1699f520bb22SYouMin Chen 	u32 dis_auto_zq = 0;
1700f520bb22SYouMin Chen 	u32 timeout_us = 1000;
1701f520bb22SYouMin Chen 	u32 cur_fsp;
1702f520bb22SYouMin Chen 	u32 mr_tmp, cl, cwl, phy_fsp, offset = 0;
1703f520bb22SYouMin Chen 
1704f520bb22SYouMin Chen 	if (dramtype == LPDDR3 && mhz <= 400) {
1705f520bb22SYouMin Chen 		phy_fsp = (readl(PHY_REG(phy_base, 0xc)) >> 0x2) & 0x3;
1706f520bb22SYouMin Chen 		offset = (phy_fsp == 0) ? 0x5 : 0x387 + (phy_fsp - 1) * 3;
1707f520bb22SYouMin Chen 		cl = readl(PHY_REG(phy_base, offset));
1708f520bb22SYouMin Chen 		cwl = readl(PHY_REG(phy_base, offset + 2));
1709f520bb22SYouMin Chen 
1710f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, offset), 0x1f, 0x8);
1711f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, offset + 2), 0x1f, 0x4);
1712f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 2, 0x6, dramtype);
1713f520bb22SYouMin Chen 	}
1714f520bb22SYouMin Chen 
1715f520bb22SYouMin Chen 	dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
1716f520bb22SYouMin Chen 
1717f520bb22SYouMin Chen 	/* PHY_0x7b[7:0] reg_train_col_addr[7:0] */
1718f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7b), 0xff, 0x0);
1719f520bb22SYouMin Chen 	/* PHY_0x7c[4:2] reg_train_ba_addr[2:0] */
1720f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x7 << 2, 0x0 << 2);
1721f520bb22SYouMin Chen 	/* PHY_0x7c[1:0] reg_train_col_addr[9:8] */
1722f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x3, 0x0);
1723f520bb22SYouMin Chen 	/* PHY_0x7d[7:0] reg_train_row_addr[7:0] */
1724f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7d), 0xff, 0x0);
1725f520bb22SYouMin Chen 	/* PHY_0x7e[7:0] reg_train_row_addr[15:8] */
1726f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7e), 0xff, 0x0);
1727f520bb22SYouMin Chen 
1728f520bb22SYouMin Chen 	/* PHY_0x71[3] wrtrain_check_data_value_random_gen */
1729f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x71), BIT(3));
1730f520bb22SYouMin Chen 
1731f520bb22SYouMin Chen 	/* config refresh timing */
1732f520bb22SYouMin Chen 	cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
1733f520bb22SYouMin Chen 	trefi_1x = ((readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1734f520bb22SYouMin Chen 			   DDR_PCTL2_RFSHTMG) >> 16) & 0xfff) * 32;
1735f520bb22SYouMin Chen 	trfc_1x = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1736f520bb22SYouMin Chen 			DDR_PCTL2_RFSHTMG) & 0x3ff;
1737f520bb22SYouMin Chen 	/* reg_phy_trefi[7:0] and reg_phy_trefi[13:8] */
1738f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x6e), 0xff, trefi_1x & 0xff);
1739f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x6f), 0x3f, (trefi_1x >> 8) & 0x3f);
1740f520bb22SYouMin Chen 	/* reg_phy_trfc */
1741f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x57), 0xff, trfc_1x);
1742f520bb22SYouMin Chen 	/* reg_max_refi_cnt */
1743f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x61), 0xf << 4, 0x8 << 4);
1744f520bb22SYouMin Chen 
1745f520bb22SYouMin Chen 	/* choose training cs */
1746f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x3 << 6, (0x2 >> cs) << 6);
1747f520bb22SYouMin Chen 
1748f520bb22SYouMin Chen 	/* PHY_0x7a [4] reg_wr_train_dqs_default_bypass */
1749f520bb22SYouMin Chen 	/* 0: Use the write-leveling value. */
1750f520bb22SYouMin Chen 	/* 1: use reg0x233 0x237 0x2b3 0x2b7 */
1751f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x7a), BIT(4));
1752f520bb22SYouMin Chen 
1753f520bb22SYouMin Chen 	/* PHY_0x7a [0] reg_dq_wr_train_auto */
1754f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x7a), 0x1);
1755f520bb22SYouMin Chen 
1756f520bb22SYouMin Chen 	/* PHY_0x7a [1] reg_dq_wr_train_en */
1757f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
1758f520bb22SYouMin Chen 
1759f520bb22SYouMin Chen 	send_a_refresh(dram);
1760f520bb22SYouMin Chen 
1761f520bb22SYouMin Chen 	while (1) {
1762f520bb22SYouMin Chen 		if ((readl(PHY_REG(phy_base, 0x92)) >> 7) & 0x1)
1763f520bb22SYouMin Chen 			break;
1764f520bb22SYouMin Chen 
1765f520bb22SYouMin Chen 		udelay(1);
1766f520bb22SYouMin Chen 		if (timeout_us-- == 0) {
1767f520bb22SYouMin Chen 			printascii("error: write training timeout\n");
1768f520bb22SYouMin Chen 			while (1)
1769f520bb22SYouMin Chen 				;
1770f520bb22SYouMin Chen 		}
1771f520bb22SYouMin Chen 	}
1772f520bb22SYouMin Chen 
1773f520bb22SYouMin Chen 	/* Check the write train state */
1774f520bb22SYouMin Chen 	if ((readl(PHY_REG(phy_base, 0x90)) >> 5) & 0x7) {
1775f520bb22SYouMin Chen 		printascii("error: write training error\n");
1776f520bb22SYouMin Chen 		return -1;
1777f520bb22SYouMin Chen 	}
1778f520bb22SYouMin Chen 
1779f520bb22SYouMin Chen 	/* PHY_0x7a [1] reg_dq_wr_train_en */
1780f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
1781f520bb22SYouMin Chen 
1782f520bb22SYouMin Chen 	pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
1783f520bb22SYouMin Chen 
1784f520bb22SYouMin Chen 	/* save LPDDR4 write vref to fsp_param for dfs */
1785f520bb22SYouMin Chen 	if (dramtype == LPDDR4) {
1786f520bb22SYouMin Chen 		fsp_param[dst_fsp].vref_dq[cs] =
1787f520bb22SYouMin Chen 			((readl(PHY_REG(phy_base, 0x384)) & 0x3f) +
1788f520bb22SYouMin Chen 			 (readl(PHY_REG(phy_base, 0x385)) & 0x3f)) / 2;
1789f520bb22SYouMin Chen 		/* add range info */
1790f520bb22SYouMin Chen 		fsp_param[dst_fsp].vref_dq[cs] |=
1791f520bb22SYouMin Chen 			((readl(PHY_REG(phy_base, 0x7c)) & BIT(5)) << 1);
1792f520bb22SYouMin Chen 	}
1793f520bb22SYouMin Chen 
1794f520bb22SYouMin Chen 	if (dramtype == LPDDR3 && mhz <= 400) {
1795f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, offset), 0x1f, cl);
1796f520bb22SYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, offset + 2), 0x1f, cwl);
1797f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1798f520bb22SYouMin Chen 			       DDR_PCTL2_INIT3);
1799f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 2, mr_tmp & PCTL2_MR_MASK,
1800f520bb22SYouMin Chen 			      dramtype);
1801f520bb22SYouMin Chen 	}
1802f520bb22SYouMin Chen 
1803f520bb22SYouMin Chen 	return 0;
1804f520bb22SYouMin Chen }
1805f520bb22SYouMin Chen 
1806f520bb22SYouMin Chen static int data_training(struct dram_info *dram, u32 cs,
1807f520bb22SYouMin Chen 			 struct rv1126_sdram_params *sdram_params, u32 dst_fsp,
1808f520bb22SYouMin Chen 			 u32 training_flag)
1809f520bb22SYouMin Chen {
1810f520bb22SYouMin Chen 	u32 ret = 0;
1811f520bb22SYouMin Chen 
1812f520bb22SYouMin Chen 	if (training_flag == FULL_TRAINING)
1813f520bb22SYouMin Chen 		training_flag = READ_GATE_TRAINING | WRITE_LEVELING |
1814f520bb22SYouMin Chen 				WRITE_TRAINING | READ_TRAINING;
1815f520bb22SYouMin Chen 
1816f520bb22SYouMin Chen 	if ((training_flag & WRITE_LEVELING) == WRITE_LEVELING) {
1817f520bb22SYouMin Chen 		ret = data_training_wl(dram, cs,
1818f520bb22SYouMin Chen 				       sdram_params->base.dramtype,
1819f520bb22SYouMin Chen 				       sdram_params->ch.cap_info.rank);
1820f520bb22SYouMin Chen 		if (ret != 0)
1821f520bb22SYouMin Chen 			goto out;
1822f520bb22SYouMin Chen 	}
1823f520bb22SYouMin Chen 
1824f520bb22SYouMin Chen 	if ((training_flag & READ_GATE_TRAINING) == READ_GATE_TRAINING) {
1825f520bb22SYouMin Chen 		ret = data_training_rg(dram, cs,
1826f520bb22SYouMin Chen 				       sdram_params->base.dramtype);
1827f520bb22SYouMin Chen 		if (ret != 0)
1828f520bb22SYouMin Chen 			goto out;
1829f520bb22SYouMin Chen 	}
1830f520bb22SYouMin Chen 
1831f520bb22SYouMin Chen 	if ((training_flag & READ_TRAINING) == READ_TRAINING) {
1832f520bb22SYouMin Chen 		ret = data_training_rd(dram, cs,
1833f520bb22SYouMin Chen 				       sdram_params->base.dramtype,
1834f520bb22SYouMin Chen 				       sdram_params->base.ddr_freq);
1835f520bb22SYouMin Chen 		if (ret != 0)
1836f520bb22SYouMin Chen 			goto out;
1837f520bb22SYouMin Chen 	}
1838f520bb22SYouMin Chen 
1839f520bb22SYouMin Chen 	if ((training_flag & WRITE_TRAINING) == WRITE_TRAINING) {
1840f520bb22SYouMin Chen 		ret = data_training_wr(dram, cs,
1841f520bb22SYouMin Chen 				       sdram_params->base.dramtype,
1842f520bb22SYouMin Chen 				       sdram_params->base.ddr_freq, dst_fsp);
1843f520bb22SYouMin Chen 		if (ret != 0)
1844f520bb22SYouMin Chen 			goto out;
1845f520bb22SYouMin Chen 	}
1846f520bb22SYouMin Chen 
1847f520bb22SYouMin Chen out:
1848f520bb22SYouMin Chen 	return ret;
1849f520bb22SYouMin Chen }
1850f520bb22SYouMin Chen 
1851f520bb22SYouMin Chen static int get_wrlvl_val(struct dram_info *dram,
1852f520bb22SYouMin Chen 			 struct rv1126_sdram_params *sdram_params)
1853f520bb22SYouMin Chen {
1854f520bb22SYouMin Chen 	u32 i, j, clk_skew;
1855f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1856f520bb22SYouMin Chen 	u32 lp_stat;
1857f520bb22SYouMin Chen 	int ret;
1858f520bb22SYouMin Chen 
1859f520bb22SYouMin Chen 	lp_stat = low_power_update(dram, 0);
1860f520bb22SYouMin Chen 
1861f520bb22SYouMin Chen 	clk_skew = readl(PHY_REG(phy_base, 0x150 + 0x17));
1862f520bb22SYouMin Chen 
1863f520bb22SYouMin Chen 	ret = data_training(dram, 0, sdram_params, 0, WRITE_LEVELING);
1864f520bb22SYouMin Chen 	if (sdram_params->ch.cap_info.rank == 2)
1865f520bb22SYouMin Chen 		ret |= data_training(dram, 1, sdram_params, 0, WRITE_LEVELING);
1866f520bb22SYouMin Chen 
1867f520bb22SYouMin Chen 	for (j = 0; j < 2; j++)
1868f520bb22SYouMin Chen 		for (i = 0; i < 4; i++)
1869f520bb22SYouMin Chen 			wrlvl_result[j][i] =
1870f520bb22SYouMin Chen 				readl(PHY_REG(phy_base,
1871f520bb22SYouMin Chen 					      wrlvl_result_offset[j][i])) -
1872f520bb22SYouMin Chen 				clk_skew;
1873f520bb22SYouMin Chen 
1874f520bb22SYouMin Chen 	low_power_update(dram, lp_stat);
1875f520bb22SYouMin Chen 
1876f520bb22SYouMin Chen 	return ret;
1877f520bb22SYouMin Chen }
1878f520bb22SYouMin Chen 
1879f520bb22SYouMin Chen static int high_freq_training(struct dram_info *dram,
1880f520bb22SYouMin Chen 			      struct rv1126_sdram_params *sdram_params,
1881f520bb22SYouMin Chen 			      u32 fsp)
1882f520bb22SYouMin Chen {
1883f520bb22SYouMin Chen 	u32 i, j;
1884f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
1885f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
1886f520bb22SYouMin Chen 	int min_val;
1887f520bb22SYouMin Chen 	u32 dqs_skew, clk_skew, ca_skew;
1888f520bb22SYouMin Chen 	int ret;
1889f520bb22SYouMin Chen 
1890f520bb22SYouMin Chen 	dqs_skew = 0;
1891f520bb22SYouMin Chen 	for (j = 0; j < sdram_params->ch.cap_info.rank; j++)
1892f520bb22SYouMin Chen 		for (i = 0; i < ARRAY_SIZE(wrlvl_result[0]); i++)
1893f520bb22SYouMin Chen 			dqs_skew += wrlvl_result[j][i];
1894f520bb22SYouMin Chen 	dqs_skew = dqs_skew / (sdram_params->ch.cap_info.rank *
1895f520bb22SYouMin Chen 			       ARRAY_SIZE(wrlvl_result[0]));
1896f520bb22SYouMin Chen 
1897f520bb22SYouMin Chen 	clk_skew = 0x20 - dqs_skew;
1898f520bb22SYouMin Chen 	dqs_skew = 0x20;
1899f520bb22SYouMin Chen 
1900f520bb22SYouMin Chen 	if (dramtype == LPDDR4) {
1901f520bb22SYouMin Chen 		clk_skew = 0;
1902f520bb22SYouMin Chen 		ca_skew = 0;
1903f520bb22SYouMin Chen 	} else if (dramtype == LPDDR3) {
1904f520bb22SYouMin Chen 		ca_skew = clk_skew - 4;
1905f520bb22SYouMin Chen 	} else {
1906f520bb22SYouMin Chen 		ca_skew = clk_skew;
1907f520bb22SYouMin Chen 	}
1908f520bb22SYouMin Chen 	modify_ca_deskew(dram, DESKEW_MDF_ABS_VAL, clk_skew, ca_skew, 3,
1909f520bb22SYouMin Chen 			 dramtype);
1910f520bb22SYouMin Chen 
1911f520bb22SYouMin Chen 	writel(wrlvl_result[0][0] + clk_skew, PHY_REG(phy_base, 0x233));
1912f520bb22SYouMin Chen 	writel(wrlvl_result[0][1] + clk_skew, PHY_REG(phy_base, 0x237));
1913f520bb22SYouMin Chen 	writel(wrlvl_result[0][2] + clk_skew, PHY_REG(phy_base, 0x2b3));
1914f520bb22SYouMin Chen 	writel(wrlvl_result[0][3] + clk_skew, PHY_REG(phy_base, 0x2b7));
1915f520bb22SYouMin Chen 	ret = data_training(dram, 0, sdram_params, fsp, READ_GATE_TRAINING |
1916f520bb22SYouMin Chen 			    READ_TRAINING | WRITE_TRAINING);
1917f520bb22SYouMin Chen 	if (sdram_params->ch.cap_info.rank == 2) {
1918f520bb22SYouMin Chen 		writel(wrlvl_result[1][0] + clk_skew, PHY_REG(phy_base, 0x233));
1919f520bb22SYouMin Chen 		writel(wrlvl_result[1][1] + clk_skew, PHY_REG(phy_base, 0x237));
1920f520bb22SYouMin Chen 		writel(wrlvl_result[1][2] + clk_skew, PHY_REG(phy_base, 0x2b3));
1921f520bb22SYouMin Chen 		writel(wrlvl_result[1][3] + clk_skew, PHY_REG(phy_base, 0x2b7));
1922f520bb22SYouMin Chen 		ret |= data_training(dram, 1, sdram_params, fsp,
1923f520bb22SYouMin Chen 				     READ_GATE_TRAINING | READ_TRAINING |
1924f520bb22SYouMin Chen 				     WRITE_TRAINING);
1925f520bb22SYouMin Chen 	}
1926f520bb22SYouMin Chen 	if (ret)
1927f520bb22SYouMin Chen 		goto out;
1928f520bb22SYouMin Chen 
1929f520bb22SYouMin Chen 	record_dq_prebit(dram);
1930f520bb22SYouMin Chen 
1931f520bb22SYouMin Chen 	min_val = get_min_value(dram, SKEW_RX_SIGNAL,
1932f520bb22SYouMin Chen 				sdram_params->ch.cap_info.rank) * -1;
1933f520bb22SYouMin Chen 	modify_dq_deskew(dram, SKEW_RX_SIGNAL, DESKEW_MDF_DIFF_VAL,
1934f520bb22SYouMin Chen 			 min_val, min_val, sdram_params->ch.cap_info.rank);
1935f520bb22SYouMin Chen 
1936f520bb22SYouMin Chen 	min_val = MIN(get_min_value(dram, SKEW_TX_SIGNAL,
1937f520bb22SYouMin Chen 				    sdram_params->ch.cap_info.rank),
1938f520bb22SYouMin Chen 		      get_min_value(dram, SKEW_CA_SIGNAL,
1939f520bb22SYouMin Chen 				    sdram_params->ch.cap_info.rank)) * -1;
1940f520bb22SYouMin Chen 
1941f520bb22SYouMin Chen 	/* clk = 0, rx all skew -7, tx - min_value */
1942f520bb22SYouMin Chen 	modify_ca_deskew(dram, DESKEW_MDF_DIFF_VAL, min_val, min_val, 3,
1943f520bb22SYouMin Chen 			 dramtype);
1944f520bb22SYouMin Chen 
1945f520bb22SYouMin Chen 	modify_dq_deskew(dram, SKEW_TX_SIGNAL, DESKEW_MDF_DIFF_VAL,
1946f520bb22SYouMin Chen 			 min_val, min_val, sdram_params->ch.cap_info.rank);
1947f520bb22SYouMin Chen 
1948f520bb22SYouMin Chen 	ret = data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING);
1949f520bb22SYouMin Chen 	if (sdram_params->ch.cap_info.rank == 2)
1950f520bb22SYouMin Chen 		ret |= data_training(dram, 1, sdram_params, 0,
1951f520bb22SYouMin Chen 				     READ_GATE_TRAINING);
1952f520bb22SYouMin Chen out:
1953f520bb22SYouMin Chen 	return ret;
1954f520bb22SYouMin Chen }
1955f520bb22SYouMin Chen 
1956f520bb22SYouMin Chen static void set_ddrconfig(struct dram_info *dram, u32 ddrconfig)
1957f520bb22SYouMin Chen {
1958f520bb22SYouMin Chen 	writel(ddrconfig, &dram->msch->deviceconf);
1959f520bb22SYouMin Chen 	clrsetbits_le32(&dram->grf->noc_con0, 0x3 << 0, 0 << 0);
1960f520bb22SYouMin Chen }
1961f520bb22SYouMin Chen 
1962f520bb22SYouMin Chen static void update_noc_timing(struct dram_info *dram,
1963f520bb22SYouMin Chen 			      struct rv1126_sdram_params *sdram_params)
1964f520bb22SYouMin Chen {
1965f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.ddrtiminga0.d32,
1966f520bb22SYouMin Chen 	       &dram->msch->ddrtiminga0);
1967f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.ddrtimingb0.d32,
1968f520bb22SYouMin Chen 	       &dram->msch->ddrtimingb0);
1969f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.ddrtimingc0.d32,
1970f520bb22SYouMin Chen 	       &dram->msch->ddrtimingc0);
1971f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.devtodev0.d32,
1972f520bb22SYouMin Chen 	       &dram->msch->devtodev0);
1973f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.ddrmode.d32, &dram->msch->ddrmode);
1974f520bb22SYouMin Chen 	writel(sdram_params->ch.noc_timings.ddr4timing.d32,
1975f520bb22SYouMin Chen 	       &dram->msch->ddr4timing);
1976f520bb22SYouMin Chen }
1977f520bb22SYouMin Chen 
1978f520bb22SYouMin Chen static void dram_all_config(struct dram_info *dram,
1979f520bb22SYouMin Chen 			    struct rv1126_sdram_params *sdram_params)
1980f520bb22SYouMin Chen {
1981f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
1982f520bb22SYouMin Chen 	u32 dram_type = sdram_params->base.dramtype;
1983f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
1984f520bb22SYouMin Chen 	u32 sys_reg2 = 0;
1985f520bb22SYouMin Chen 	u32 sys_reg3 = 0;
1986f520bb22SYouMin Chen 	u64 cs_cap[2];
1987f520bb22SYouMin Chen 	u32 cs_pst;
1988f520bb22SYouMin Chen 
1989f520bb22SYouMin Chen 	set_ddrconfig(dram, cap_info->ddrconfig);
1990f520bb22SYouMin Chen 	sdram_org_config(cap_info, &sdram_params->base, &sys_reg2,
1991f520bb22SYouMin Chen 			 &sys_reg3, 0);
1992f520bb22SYouMin Chen 	writel(sys_reg2, &dram->pmugrf->os_reg[2]);
1993f520bb22SYouMin Chen 	writel(sys_reg3, &dram->pmugrf->os_reg[3]);
1994f520bb22SYouMin Chen 
1995f520bb22SYouMin Chen 	cs_cap[0] = sdram_get_cs_cap(cap_info, 0, dram_type);
1996f520bb22SYouMin Chen 	cs_cap[1] = sdram_get_cs_cap(cap_info, 1, dram_type);
1997f520bb22SYouMin Chen 
1998f520bb22SYouMin Chen 	if (cap_info->rank == 2) {
1999f520bb22SYouMin Chen 		cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) +
2000f520bb22SYouMin Chen 			6 + 2;
2001f520bb22SYouMin Chen 		if (cs_pst > 28)
2002f520bb22SYouMin Chen 			cs_cap[0] = 1 << cs_pst;
2003f520bb22SYouMin Chen 	}
2004f520bb22SYouMin Chen 
2005f520bb22SYouMin Chen 	writel(((((cs_cap[1] >> 20) / 64) & 0xff) << 8) |
2006f520bb22SYouMin Chen 			(((cs_cap[0] >> 20) / 64) & 0xff),
2007f520bb22SYouMin Chen 			&dram->msch->devicesize);
2008f520bb22SYouMin Chen 	update_noc_timing(dram, sdram_params);
2009f520bb22SYouMin Chen }
2010f520bb22SYouMin Chen 
2011f520bb22SYouMin Chen static void enable_low_power(struct dram_info *dram,
2012f520bb22SYouMin Chen 			     struct rv1126_sdram_params *sdram_params)
2013f520bb22SYouMin Chen {
2014f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2015f520bb22SYouMin Chen 	u32 grf_lp_con;
2016f520bb22SYouMin Chen 
2017f520bb22SYouMin Chen 	writel(0x1f1f0617, &dram->ddrgrf->ddr_grf_con[1]);
2018f520bb22SYouMin Chen 
2019f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4)
2020f520bb22SYouMin Chen 		grf_lp_con = (0x7 << 16) | (1 << 1);
2021f520bb22SYouMin Chen 	else if (sdram_params->base.dramtype == DDR3)
2022f520bb22SYouMin Chen 		grf_lp_con = (0x7 << 16) | (1 << 0);
2023f520bb22SYouMin Chen 	else
2024f520bb22SYouMin Chen 		grf_lp_con = (0x7 << 16) | (1 << 2);
2025f520bb22SYouMin Chen 
2026f520bb22SYouMin Chen 	/* en lpckdis_en */
2027f520bb22SYouMin Chen 	grf_lp_con = grf_lp_con | (0x1 << (9 + 16)) | (0x1 << 9);
2028f520bb22SYouMin Chen 	writel(grf_lp_con, &dram->ddrgrf->ddr_grf_lp_con);
2029f520bb22SYouMin Chen 
2030f520bb22SYouMin Chen 	/* enable sr, pd */
2031f520bb22SYouMin Chen 	if (dram->pd_idle == 0)
2032f520bb22SYouMin Chen 		clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
2033f520bb22SYouMin Chen 	else
2034f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
2035f520bb22SYouMin Chen 	if (dram->sr_idle == 0)
2036f520bb22SYouMin Chen 		clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
2037f520bb22SYouMin Chen 	else
2038f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
2039f520bb22SYouMin Chen 	setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 3));
2040f520bb22SYouMin Chen }
2041f520bb22SYouMin Chen 
2042f520bb22SYouMin Chen static void ddr_set_atags(struct dram_info *dram,
2043f520bb22SYouMin Chen 			  struct rv1126_sdram_params *sdram_params)
2044f520bb22SYouMin Chen {
2045f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2046f520bb22SYouMin Chen 	u32 dram_type = sdram_params->base.dramtype;
2047f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2048f520bb22SYouMin Chen 	struct tag_serial t_serial;
2049f520bb22SYouMin Chen 	struct tag_ddr_mem t_ddrmem;
2050f520bb22SYouMin Chen 	struct tag_soc_info t_socinfo;
2051f520bb22SYouMin Chen 	u64 cs_cap[2];
2052f520bb22SYouMin Chen 	u32 cs_pst = 0;
2053f520bb22SYouMin Chen 
2054f520bb22SYouMin Chen 	cs_cap[0] = sdram_get_cs_cap(cap_info, 0, dram_type);
2055f520bb22SYouMin Chen 	cs_cap[1] = sdram_get_cs_cap(cap_info, 1, dram_type);
2056f520bb22SYouMin Chen 
2057f520bb22SYouMin Chen 	memset(&t_serial, 0, sizeof(struct tag_serial));
2058f520bb22SYouMin Chen 
2059f520bb22SYouMin Chen 	t_serial.version = 0;
2060f520bb22SYouMin Chen 	t_serial.enable = 1;
2061f520bb22SYouMin Chen 	t_serial.addr = CONFIG_DEBUG_UART_BASE;
2062f520bb22SYouMin Chen 	t_serial.baudrate = CONFIG_BAUDRATE;
2063f520bb22SYouMin Chen 	t_serial.m_mode = SERIAL_M_MODE_M0;
2064f520bb22SYouMin Chen 	t_serial.id = 2;
2065f520bb22SYouMin Chen 
2066f520bb22SYouMin Chen 	atags_destroy();
2067f520bb22SYouMin Chen 	atags_set_tag(ATAG_SERIAL,  &t_serial);
2068f520bb22SYouMin Chen 
2069f520bb22SYouMin Chen 	memset(&t_ddrmem, 0, sizeof(struct tag_ddr_mem));
2070f520bb22SYouMin Chen 	if (cap_info->row_3_4) {
2071f520bb22SYouMin Chen 		cs_cap[0] =  cs_cap[0] * 3 / 4;
2072f520bb22SYouMin Chen 		cs_cap[1] =  cs_cap[1] * 3 / 4;
2073f520bb22SYouMin Chen 	}
2074f520bb22SYouMin Chen 	t_ddrmem.version = 0;
2075f520bb22SYouMin Chen 	t_ddrmem.bank[0] = CONFIG_SYS_SDRAM_BASE;
2076f520bb22SYouMin Chen 	if (cs_cap[1]) {
2077f520bb22SYouMin Chen 		cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) +
2078f520bb22SYouMin Chen 			6 + 2;
2079f520bb22SYouMin Chen 	}
2080f520bb22SYouMin Chen 
2081f520bb22SYouMin Chen 	if (cs_cap[1] && cs_pst > 27) {
2082f520bb22SYouMin Chen 		t_ddrmem.count = 2;
2083f520bb22SYouMin Chen 		t_ddrmem.bank[1] = 1 << cs_pst;
2084f520bb22SYouMin Chen 		t_ddrmem.bank[2] = cs_cap[0];
2085f520bb22SYouMin Chen 		t_ddrmem.bank[3] = cs_cap[1];
2086f520bb22SYouMin Chen 	} else {
2087f520bb22SYouMin Chen 		t_ddrmem.count = 1;
2088f520bb22SYouMin Chen 		t_ddrmem.bank[1] = (u64)cs_cap[0] + (u64)cs_cap[1];
2089f520bb22SYouMin Chen 	}
2090f520bb22SYouMin Chen 
2091f520bb22SYouMin Chen 	atags_set_tag(ATAG_DDR_MEM,  &t_ddrmem);
2092f520bb22SYouMin Chen 
2093f520bb22SYouMin Chen 	memset(&t_socinfo, 0, sizeof(struct tag_soc_info));
2094f520bb22SYouMin Chen 	t_socinfo.version = 0;
2095f520bb22SYouMin Chen 	t_socinfo.name = 0x1126;
2096f520bb22SYouMin Chen }
2097f520bb22SYouMin Chen 
2098f520bb22SYouMin Chen static void print_ddr_info(struct rv1126_sdram_params *sdram_params)
2099f520bb22SYouMin Chen {
2100f520bb22SYouMin Chen 	u32 split;
2101f520bb22SYouMin Chen 
2102f520bb22SYouMin Chen 	if ((readl(DDR_GRF_BASE_ADDR + DDR_GRF_SPLIT_CON) &
2103f520bb22SYouMin Chen 	     (1 << SPLIT_BYPASS_OFFSET)) != 0)
2104f520bb22SYouMin Chen 		split = 0;
2105f520bb22SYouMin Chen 	else
2106f520bb22SYouMin Chen 		split = readl(DDR_GRF_BASE_ADDR + DDR_GRF_SPLIT_CON) &
2107f520bb22SYouMin Chen 			SPLIT_SIZE_MASK;
2108f520bb22SYouMin Chen 
2109f520bb22SYouMin Chen 	sdram_print_ddr_info(&sdram_params->ch.cap_info,
2110f520bb22SYouMin Chen 			     &sdram_params->base, split);
2111f520bb22SYouMin Chen }
2112f520bb22SYouMin Chen 
2113f520bb22SYouMin Chen static int sdram_init_(struct dram_info *dram,
2114f520bb22SYouMin Chen 		       struct rv1126_sdram_params *sdram_params, u32 post_init)
2115f520bb22SYouMin Chen {
2116f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2117f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
2118f520bb22SYouMin Chen 	u32 ddr4_vref;
2119f520bb22SYouMin Chen 	u32 mr_tmp;
2120f520bb22SYouMin Chen 
2121f520bb22SYouMin Chen 	rkclk_configure_ddr(dram, sdram_params);
2122f520bb22SYouMin Chen 
2123f520bb22SYouMin Chen 	rkclk_ddr_reset(dram, 1, 1, 1, 1);
2124f520bb22SYouMin Chen 	udelay(10);
2125f520bb22SYouMin Chen 
2126f520bb22SYouMin Chen 	rkclk_ddr_reset(dram, 1, 1, 1, 0);
2127f520bb22SYouMin Chen 	phy_cfg(dram, sdram_params);
2128f520bb22SYouMin Chen 
2129f520bb22SYouMin Chen 	rkclk_ddr_reset(dram, 1, 1, 0, 0);
2130f520bb22SYouMin Chen 	phy_pll_set(dram, sdram_params->base.ddr_freq * MHZ, 1);
2131f520bb22SYouMin Chen 
2132f520bb22SYouMin Chen 	rkclk_ddr_reset(dram, 1, 0, 0, 0);
2133f520bb22SYouMin Chen 	pctl_cfg(dram->pctl, &sdram_params->pctl_regs,
2134f520bb22SYouMin Chen 		 dram->sr_idle, dram->pd_idle);
2135f520bb22SYouMin Chen 
2136f520bb22SYouMin Chen 	/* set frequency_mode */
2137f520bb22SYouMin Chen 	setbits_le32(pctl_base + DDR_PCTL2_MSTR, 0x1 << 29);
2138f520bb22SYouMin Chen 	/* set target_frequency to Frequency 0 */
2139f520bb22SYouMin Chen 	clrsetbits_le32(pctl_base + DDR_PCTL2_MSTR2, 0x3, 0);
2140f520bb22SYouMin Chen 
2141f520bb22SYouMin Chen 	set_ds_odt(dram, sdram_params, 0);
2142f520bb22SYouMin Chen 	sdram_params->ch.cap_info.ddrconfig = calculate_ddrconfig(sdram_params);
2143f520bb22SYouMin Chen 	set_ctl_address_map(dram, sdram_params);
2144f520bb22SYouMin Chen 
2145f520bb22SYouMin Chen 	setbits_le32(pctl_base + DDR_PCTL2_DFIMISC, (1 << 5) | (1 << 4));
2146f520bb22SYouMin Chen 
2147f520bb22SYouMin Chen 	rkclk_ddr_reset(dram, 0, 0, 0, 0);
2148f520bb22SYouMin Chen 
2149f520bb22SYouMin Chen 	while ((readl(pctl_base + DDR_PCTL2_STAT) & 0x7) == 0)
2150f520bb22SYouMin Chen 		continue;
2151f520bb22SYouMin Chen 
2152f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == LPDDR3) {
2153f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 11, lp3_odt_value, LPDDR3);
2154f520bb22SYouMin Chen 	} else if (sdram_params->base.dramtype == LPDDR4) {
2155f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + DDR_PCTL2_INIT6);
2156f520bb22SYouMin Chen 		/* MR11 */
2157f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 11,
2158f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
2159f520bb22SYouMin Chen 			      LPDDR4);
2160f520bb22SYouMin Chen 		/* MR12 */
2161f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 12,
2162f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR12_SHIFT & PCTL2_MR_MASK,
2163f520bb22SYouMin Chen 			      LPDDR4);
2164f520bb22SYouMin Chen 
2165f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + DDR_PCTL2_INIT7);
2166f520bb22SYouMin Chen 		/* MR22 */
2167f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 22,
2168f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
2169f520bb22SYouMin Chen 			      LPDDR4);
2170f520bb22SYouMin Chen 		/* MR14 */
2171f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 14,
2172f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
2173f520bb22SYouMin Chen 			      LPDDR4);
2174f520bb22SYouMin Chen 	}
2175f520bb22SYouMin Chen 
2176f520bb22SYouMin Chen 	if (data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING) != 0) {
2177f520bb22SYouMin Chen 		if (post_init != 0)
2178f520bb22SYouMin Chen 			printascii("DTT cs0 error\n");
2179f520bb22SYouMin Chen 		return -1;
2180f520bb22SYouMin Chen 	}
2181f520bb22SYouMin Chen 
2182f520bb22SYouMin Chen 	if (post_init != 0 && sdram_params->ch.cap_info.rank == 2) {
2183f520bb22SYouMin Chen 		if (data_training(dram, 1, sdram_params, 0,
2184f520bb22SYouMin Chen 				  READ_GATE_TRAINING) != 0) {
2185f520bb22SYouMin Chen 			printascii("DTT cs1 error\n");
2186f520bb22SYouMin Chen 			return -1;
2187f520bb22SYouMin Chen 		}
2188f520bb22SYouMin Chen 	}
2189f520bb22SYouMin Chen 
2190f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR4) {
2191f520bb22SYouMin Chen 		ddr4_vref = readl(PHY_REG(phy_base, 0x105)) * 39;
2192f520bb22SYouMin Chen 		pctl_write_vrefdq(dram->pctl, 0x3, ddr4_vref,
2193f520bb22SYouMin Chen 				  sdram_params->base.dramtype);
2194f520bb22SYouMin Chen 	}
2195f520bb22SYouMin Chen 
2196f520bb22SYouMin Chen 	dram_all_config(dram, sdram_params);
2197f520bb22SYouMin Chen 	enable_low_power(dram, sdram_params);
2198f520bb22SYouMin Chen 
2199f520bb22SYouMin Chen 	return 0;
2200f520bb22SYouMin Chen }
2201f520bb22SYouMin Chen 
2202f520bb22SYouMin Chen static u64 dram_detect_cap(struct dram_info *dram,
2203f520bb22SYouMin Chen 			   struct rv1126_sdram_params *sdram_params,
2204f520bb22SYouMin Chen 			   unsigned char channel)
2205f520bb22SYouMin Chen {
2206f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2207f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2208f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
2209f520bb22SYouMin Chen 	u32 mr8;
2210f520bb22SYouMin Chen 
2211f520bb22SYouMin Chen 	u32 bktmp;
2212f520bb22SYouMin Chen 	u32 coltmp;
2213f520bb22SYouMin Chen 	u32 rowtmp;
2214f520bb22SYouMin Chen 	u32 cs;
2215f520bb22SYouMin Chen 	u32 bw = 1;
2216f520bb22SYouMin Chen 	u32 dram_type = sdram_params->base.dramtype;
2217f520bb22SYouMin Chen 	u32 pwrctl;
2218f520bb22SYouMin Chen 
2219f520bb22SYouMin Chen 	cap_info->bw = bw;
2220f520bb22SYouMin Chen 	if (dram_type != LPDDR4) {
2221f520bb22SYouMin Chen 		if (dram_type != DDR4) {
2222f520bb22SYouMin Chen 			coltmp = 12;
2223f520bb22SYouMin Chen 			bktmp = 3;
2224f520bb22SYouMin Chen 			if (dram_type == LPDDR2)
2225f520bb22SYouMin Chen 				rowtmp = 15;
2226f520bb22SYouMin Chen 			else
2227f520bb22SYouMin Chen 				rowtmp = 16;
2228f520bb22SYouMin Chen 
2229f520bb22SYouMin Chen 			if (sdram_detect_col(cap_info, coltmp) != 0)
2230f520bb22SYouMin Chen 				goto cap_err;
2231f520bb22SYouMin Chen 
2232f520bb22SYouMin Chen 			sdram_detect_bank(cap_info, coltmp, bktmp);
2233f520bb22SYouMin Chen 			sdram_detect_dbw(cap_info, dram_type);
2234f520bb22SYouMin Chen 		} else {
2235f520bb22SYouMin Chen 			coltmp = 10;
2236f520bb22SYouMin Chen 			bktmp = 4;
2237f520bb22SYouMin Chen 			rowtmp = 17;
2238f520bb22SYouMin Chen 
2239f520bb22SYouMin Chen 			cap_info->col = 10;
2240f520bb22SYouMin Chen 			cap_info->bk = 2;
2241f520bb22SYouMin Chen 			sdram_detect_bg(cap_info, coltmp);
2242f520bb22SYouMin Chen 		}
2243f520bb22SYouMin Chen 
2244f520bb22SYouMin Chen 		if (sdram_detect_row(cap_info, coltmp, bktmp, rowtmp) != 0)
2245f520bb22SYouMin Chen 			goto cap_err;
2246f520bb22SYouMin Chen 
2247f520bb22SYouMin Chen 		sdram_detect_row_3_4(cap_info, coltmp, bktmp);
2248f520bb22SYouMin Chen 	} else {
2249f520bb22SYouMin Chen 		mr8 = (read_mr(dram, 1, 8, dram_type) >> 2) & 0xf;
2250f520bb22SYouMin Chen 		cap_info->col = 10;
2251f520bb22SYouMin Chen 		cap_info->bk = 3;
2252f520bb22SYouMin Chen 		cap_info->cs0_row = 14 + (mr8 + 1) / 2;
2253f520bb22SYouMin Chen 		if (mr8 % 2)
2254f520bb22SYouMin Chen 			cap_info->row_3_4 = 1;
2255f520bb22SYouMin Chen 		else
2256f520bb22SYouMin Chen 			cap_info->row_3_4 = 0;
2257f520bb22SYouMin Chen 		cap_info->dbw = 1;
2258f520bb22SYouMin Chen 		cap_info->bw = 2;
2259f520bb22SYouMin Chen 	}
2260f520bb22SYouMin Chen 
2261f520bb22SYouMin Chen 	pwrctl = readl(pctl_base + DDR_PCTL2_PWRCTL);
2262f520bb22SYouMin Chen 	writel(0, pctl_base + DDR_PCTL2_PWRCTL);
2263f520bb22SYouMin Chen 
2264f520bb22SYouMin Chen 	if (data_training(dram, 1, sdram_params, 0, READ_GATE_TRAINING) == 0)
2265f520bb22SYouMin Chen 		cs = 1;
2266f520bb22SYouMin Chen 	else
2267f520bb22SYouMin Chen 		cs = 0;
2268f520bb22SYouMin Chen 	cap_info->rank = cs + 1;
2269f520bb22SYouMin Chen 
2270f520bb22SYouMin Chen 	if (dram_type != LPDDR4) {
2271f520bb22SYouMin Chen 		setbits_le32(PHY_REG(phy_base, 0xf), 0xf);
2272f520bb22SYouMin Chen 
2273f520bb22SYouMin Chen 		phy_soft_reset(dram);
2274f520bb22SYouMin Chen 
2275f520bb22SYouMin Chen 		if (data_training(dram, 0, sdram_params, 0,
2276f520bb22SYouMin Chen 				  READ_GATE_TRAINING) == 0)
2277f520bb22SYouMin Chen 			cap_info->bw = 2;
2278f520bb22SYouMin Chen 		else
2279f520bb22SYouMin Chen 			cap_info->bw = 1;
2280f520bb22SYouMin Chen 	}
2281f520bb22SYouMin Chen 
2282f520bb22SYouMin Chen 	writel(pwrctl, pctl_base + DDR_PCTL2_PWRCTL);
2283f520bb22SYouMin Chen 
2284f520bb22SYouMin Chen 	cap_info->cs0_high16bit_row = cap_info->cs0_row;
2285f520bb22SYouMin Chen 	if (cs) {
2286f520bb22SYouMin Chen 		cap_info->cs1_row = cap_info->cs0_row;
2287f520bb22SYouMin Chen 		cap_info->cs1_high16bit_row = cap_info->cs0_row;
2288f520bb22SYouMin Chen 	} else {
2289f520bb22SYouMin Chen 		cap_info->cs1_row = 0;
2290f520bb22SYouMin Chen 		cap_info->cs1_high16bit_row = 0;
2291f520bb22SYouMin Chen 	}
2292f520bb22SYouMin Chen 
2293f520bb22SYouMin Chen 	return 0;
2294f520bb22SYouMin Chen cap_err:
2295f520bb22SYouMin Chen 	return -1;
2296f520bb22SYouMin Chen }
2297f520bb22SYouMin Chen 
2298f520bb22SYouMin Chen static int dram_detect_cs1_row(struct dram_info *dram,
2299f520bb22SYouMin Chen 			       struct rv1126_sdram_params *sdram_params,
2300f520bb22SYouMin Chen 			       unsigned char channel)
2301f520bb22SYouMin Chen {
2302f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2303f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2304f520bb22SYouMin Chen 	u32 ret = 0;
2305f520bb22SYouMin Chen 	void __iomem *test_addr;
2306f520bb22SYouMin Chen 	u32 row, bktmp, coltmp, bw;
2307f520bb22SYouMin Chen 	u64 cs0_cap;
2308f520bb22SYouMin Chen 	u32 byte_mask;
2309f520bb22SYouMin Chen 	u32 cs_pst;
2310f520bb22SYouMin Chen 	u32 cs_add = 0;
2311f520bb22SYouMin Chen 	u32 max_row;
2312f520bb22SYouMin Chen 
2313f520bb22SYouMin Chen 	if (cap_info->rank == 2) {
2314f520bb22SYouMin Chen 		cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) +
2315f520bb22SYouMin Chen 			6 + 2;
2316f520bb22SYouMin Chen 		if (cs_pst < 28)
2317f520bb22SYouMin Chen 			cs_add = 1;
2318f520bb22SYouMin Chen 
2319f520bb22SYouMin Chen 		cs0_cap = 1 << cs_pst;
2320f520bb22SYouMin Chen 
2321f520bb22SYouMin Chen 		if (sdram_params->base.dramtype == DDR4) {
2322f520bb22SYouMin Chen 			if (cap_info->dbw == 0)
2323f520bb22SYouMin Chen 				bktmp = cap_info->bk + 2;
2324f520bb22SYouMin Chen 			else
2325f520bb22SYouMin Chen 				bktmp = cap_info->bk + 1;
2326f520bb22SYouMin Chen 		} else {
2327f520bb22SYouMin Chen 			bktmp = cap_info->bk;
2328f520bb22SYouMin Chen 		}
2329f520bb22SYouMin Chen 		bw = cap_info->bw;
2330f520bb22SYouMin Chen 		coltmp = cap_info->col;
2331f520bb22SYouMin Chen 
2332f520bb22SYouMin Chen 		if (bw == 2)
2333f520bb22SYouMin Chen 			byte_mask = 0xFFFF;
2334f520bb22SYouMin Chen 		else
2335f520bb22SYouMin Chen 			byte_mask = 0xFF;
2336f520bb22SYouMin Chen 
2337f520bb22SYouMin Chen 		max_row = (cs_pst == 31) ? 30 : 31;
2338f520bb22SYouMin Chen 
2339f520bb22SYouMin Chen 		max_row = max_row - bktmp - coltmp - bw - cs_add + 1;
2340f520bb22SYouMin Chen 
2341f520bb22SYouMin Chen 		row = (cap_info->cs0_row > max_row) ? max_row :
2342f520bb22SYouMin Chen 			cap_info->cs0_row;
2343f520bb22SYouMin Chen 
2344f520bb22SYouMin Chen 		for (; row > 12; row--) {
2345f520bb22SYouMin Chen 			test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
2346f520bb22SYouMin Chen 				    (u32)cs0_cap +
2347f520bb22SYouMin Chen 				    (1ul << (row + bktmp + coltmp +
2348f520bb22SYouMin Chen 					     cs_add + bw - 1ul)));
2349f520bb22SYouMin Chen 
2350f520bb22SYouMin Chen 			writel(0, CONFIG_SYS_SDRAM_BASE + (u32)cs0_cap);
2351f520bb22SYouMin Chen 			writel(PATTERN, test_addr);
2352f520bb22SYouMin Chen 
2353f520bb22SYouMin Chen 			if (((readl(test_addr) & byte_mask) ==
2354f520bb22SYouMin Chen 			     (PATTERN & byte_mask)) &&
2355f520bb22SYouMin Chen 			    ((readl(CONFIG_SYS_SDRAM_BASE + (u32)cs0_cap) &
2356f520bb22SYouMin Chen 			      byte_mask) == 0)) {
2357f520bb22SYouMin Chen 				ret = row;
2358f520bb22SYouMin Chen 				break;
2359f520bb22SYouMin Chen 			}
2360f520bb22SYouMin Chen 		}
2361f520bb22SYouMin Chen 	}
2362f520bb22SYouMin Chen 
2363f520bb22SYouMin Chen 	return ret;
2364f520bb22SYouMin Chen }
2365f520bb22SYouMin Chen 
2366f520bb22SYouMin Chen /* return: 0 = success, other = fail */
2367f520bb22SYouMin Chen static int sdram_init_detect(struct dram_info *dram,
2368f520bb22SYouMin Chen 			     struct rv1126_sdram_params *sdram_params)
2369f520bb22SYouMin Chen {
2370f520bb22SYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2371f520bb22SYouMin Chen 	u32 ret;
2372f520bb22SYouMin Chen 	u32 sys_reg = 0;
2373f520bb22SYouMin Chen 	u32 sys_reg3 = 0;
2374f520bb22SYouMin Chen 
2375f520bb22SYouMin Chen 	if (sdram_init_(dram, sdram_params, 0) != 0)
2376f520bb22SYouMin Chen 		return -1;
2377f520bb22SYouMin Chen 
2378f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR3) {
2379f520bb22SYouMin Chen 		writel(PATTERN, CONFIG_SYS_SDRAM_BASE);
2380f520bb22SYouMin Chen 		if (readl(CONFIG_SYS_SDRAM_BASE) != PATTERN)
2381f520bb22SYouMin Chen 			return -1;
2382f520bb22SYouMin Chen 	}
2383f520bb22SYouMin Chen 
2384f520bb22SYouMin Chen 	if (dram_detect_cap(dram, sdram_params, 0) != 0)
2385f520bb22SYouMin Chen 		return -1;
2386f520bb22SYouMin Chen 
2387f520bb22SYouMin Chen 	pctl_remodify_sdram_params(&sdram_params->pctl_regs, cap_info,
2388f520bb22SYouMin Chen 				   sdram_params->base.dramtype);
2389f520bb22SYouMin Chen 	ret = sdram_init_(dram, sdram_params, 1);
2390f520bb22SYouMin Chen 	if (ret != 0)
2391f520bb22SYouMin Chen 		goto out;
2392f520bb22SYouMin Chen 
2393f520bb22SYouMin Chen 	cap_info->cs1_row =
2394f520bb22SYouMin Chen 		dram_detect_cs1_row(dram, sdram_params, 0);
2395f520bb22SYouMin Chen 	if (cap_info->cs1_row) {
2396f520bb22SYouMin Chen 		sys_reg = readl(&dram->pmugrf->os_reg[2]);
2397f520bb22SYouMin Chen 		sys_reg3 = readl(&dram->pmugrf->os_reg[3]);
2398f520bb22SYouMin Chen 		SYS_REG_ENC_CS1_ROW(cap_info->cs1_row,
2399f520bb22SYouMin Chen 				    sys_reg, sys_reg3, 0);
2400f520bb22SYouMin Chen 		writel(sys_reg, &dram->pmugrf->os_reg[2]);
2401f520bb22SYouMin Chen 		writel(sys_reg3, &dram->pmugrf->os_reg[3]);
2402f520bb22SYouMin Chen 	}
2403f520bb22SYouMin Chen 
2404f520bb22SYouMin Chen 	sdram_detect_high_row(cap_info);
2405f520bb22SYouMin Chen 
2406f520bb22SYouMin Chen out:
2407f520bb22SYouMin Chen 	return ret;
2408f520bb22SYouMin Chen }
2409f520bb22SYouMin Chen 
2410f520bb22SYouMin Chen struct rv1126_sdram_params *get_default_sdram_config(u32 freq_mhz)
2411f520bb22SYouMin Chen {
2412f520bb22SYouMin Chen 	u32 i;
2413f520bb22SYouMin Chen 	u32 offset = 0;
2414f520bb22SYouMin Chen 	struct ddr2_3_4_lp2_3_info *ddr_info;
2415f520bb22SYouMin Chen 
2416f520bb22SYouMin Chen 	if (!freq_mhz) {
2417f520bb22SYouMin Chen 		ddr_info = get_ddr_drv_odt_info(sdram_configs[0].base.dramtype);
2418f520bb22SYouMin Chen 		if (ddr_info)
2419f520bb22SYouMin Chen 			freq_mhz =
2420f520bb22SYouMin Chen 				(ddr_info->ddr_freq0_1 >> DDR_FREQ_F0_SHIFT) &
2421f520bb22SYouMin Chen 				DDR_FREQ_MASK;
2422f520bb22SYouMin Chen 		else
2423f520bb22SYouMin Chen 			freq_mhz = 0;
2424f520bb22SYouMin Chen 	}
2425f520bb22SYouMin Chen 
2426f520bb22SYouMin Chen 	for (i = 0; i < ARRAY_SIZE(sdram_configs); i++) {
2427f520bb22SYouMin Chen 		if (sdram_configs[i].base.ddr_freq == 0 ||
2428f520bb22SYouMin Chen 		    freq_mhz < sdram_configs[i].base.ddr_freq)
2429f520bb22SYouMin Chen 			break;
2430f520bb22SYouMin Chen 	}
2431f520bb22SYouMin Chen 	offset = i == 0 ? 0 : i - 1;
2432f520bb22SYouMin Chen 
2433f520bb22SYouMin Chen 	return &sdram_configs[offset];
2434f520bb22SYouMin Chen }
2435f520bb22SYouMin Chen 
2436f520bb22SYouMin Chen static const u16 pctl_need_update_reg[] = {
2437f520bb22SYouMin Chen 	DDR_PCTL2_RFSHTMG,
2438f520bb22SYouMin Chen 	DDR_PCTL2_INIT3,
2439f520bb22SYouMin Chen 	DDR_PCTL2_INIT4,
2440f520bb22SYouMin Chen 	DDR_PCTL2_INIT6,
2441f520bb22SYouMin Chen 	DDR_PCTL2_INIT7,
2442f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG0,
2443f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG1,
2444f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG2,
2445f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG3,
2446f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG4,
2447f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG5,
2448f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG6,
2449f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG7,
2450f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG8,
2451f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG9,
2452f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG12,
2453f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG13,
2454f520bb22SYouMin Chen 	DDR_PCTL2_DRAMTMG14,
2455f520bb22SYouMin Chen 	DDR_PCTL2_ZQCTL0,
2456f520bb22SYouMin Chen 	DDR_PCTL2_DFITMG0,
2457f520bb22SYouMin Chen 	DDR_PCTL2_ODTCFG
2458f520bb22SYouMin Chen };
2459f520bb22SYouMin Chen 
2460f520bb22SYouMin Chen static const u16 phy_need_update_reg[] = {
2461f520bb22SYouMin Chen 	0x14,
2462f520bb22SYouMin Chen 	0x18,
2463f520bb22SYouMin Chen 	0x1c
2464f520bb22SYouMin Chen };
2465f520bb22SYouMin Chen 
2466f520bb22SYouMin Chen static void pre_set_rate(struct dram_info *dram,
2467f520bb22SYouMin Chen 			 struct rv1126_sdram_params *sdram_params,
2468f520bb22SYouMin Chen 			 u32 dst_fsp, u32 dst_fsp_lp4)
2469f520bb22SYouMin Chen {
2470f520bb22SYouMin Chen 	u32 i, j, find;
2471f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2472f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
2473f520bb22SYouMin Chen 	u32 phy_offset;
2474f520bb22SYouMin Chen 	u32 mr_tmp;
2475f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
2476f520bb22SYouMin Chen 
2477f520bb22SYouMin Chen 	sw_set_req(dram);
2478f520bb22SYouMin Chen 	/* pctl timing update */
2479f520bb22SYouMin Chen 	for (i = 0, find = 0; i < ARRAY_SIZE(pctl_need_update_reg); i++) {
2480f520bb22SYouMin Chen 		for (j = find; sdram_params->pctl_regs.pctl[j][0] != 0xFFFFFFFF;
2481f520bb22SYouMin Chen 		     j++) {
2482f520bb22SYouMin Chen 			if (sdram_params->pctl_regs.pctl[j][0] ==
2483f520bb22SYouMin Chen 			    pctl_need_update_reg[i]) {
2484f520bb22SYouMin Chen 				writel(sdram_params->pctl_regs.pctl[j][1],
2485f520bb22SYouMin Chen 				       pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2486f520bb22SYouMin Chen 				       pctl_need_update_reg[i]);
2487f520bb22SYouMin Chen 				find = j;
2488f520bb22SYouMin Chen 				break;
2489f520bb22SYouMin Chen 			}
2490f520bb22SYouMin Chen 		}
2491f520bb22SYouMin Chen 	}
2492f520bb22SYouMin Chen 	sw_set_ack(dram);
2493f520bb22SYouMin Chen 
2494f520bb22SYouMin Chen 	/* phy timing update */
2495f520bb22SYouMin Chen 	if (dst_fsp == 0)
2496f520bb22SYouMin Chen 		phy_offset = 0;
2497f520bb22SYouMin Chen 	else
2498f520bb22SYouMin Chen 		phy_offset = PHY_REG(0, 0x387 - 5 + (dst_fsp - 1) * 3);
2499f520bb22SYouMin Chen 	/* cl cwl al update */
2500f520bb22SYouMin Chen 	for (i = 0, find = 0; i < ARRAY_SIZE(phy_need_update_reg); i++) {
2501f520bb22SYouMin Chen 		for (j = find; sdram_params->phy_regs.phy[j][0] != 0xFFFFFFFF;
2502f520bb22SYouMin Chen 		     j++) {
2503f520bb22SYouMin Chen 			if (sdram_params->phy_regs.phy[j][0] ==
2504f520bb22SYouMin Chen 			    phy_need_update_reg[i]) {
2505f520bb22SYouMin Chen 				writel(sdram_params->phy_regs.phy[j][1],
2506f520bb22SYouMin Chen 				       phy_base + phy_offset +
2507f520bb22SYouMin Chen 				       phy_need_update_reg[i]);
2508f520bb22SYouMin Chen 				find = j;
2509f520bb22SYouMin Chen 				break;
2510f520bb22SYouMin Chen 			}
2511f520bb22SYouMin Chen 		}
2512f520bb22SYouMin Chen 	}
2513f520bb22SYouMin Chen 
2514f520bb22SYouMin Chen 	set_ds_odt(dram, sdram_params, dst_fsp);
2515f520bb22SYouMin Chen 	if (dramtype == LPDDR4) {
2516f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2517f520bb22SYouMin Chen 			       DDR_PCTL2_INIT4);
2518f520bb22SYouMin Chen 		/* MR13 */
2519f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 13,
2520f520bb22SYouMin Chen 			      ((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
2521f520bb22SYouMin Chen 			       PCTL2_MR_MASK) & (~(BIT(7) | BIT(6)))) |
2522f520bb22SYouMin Chen 			      ((0x2 << 6) >> dst_fsp_lp4), dramtype);
2523f520bb22SYouMin Chen 		writel(((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
2524f520bb22SYouMin Chen 				      PCTL2_MR_MASK) & (~(BIT(7) | BIT(6)))) |
2525f520bb22SYouMin Chen 				      ((0x2 << 6) >> dst_fsp_lp4),
2526f520bb22SYouMin Chen 				       PHY_REG(phy_base, 0x1b));
2527f520bb22SYouMin Chen 		/* MR3 */
2528f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 3,
2529f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT &
2530f520bb22SYouMin Chen 			      PCTL2_MR_MASK,
2531f520bb22SYouMin Chen 			      dramtype);
2532f520bb22SYouMin Chen 		writel(mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT & PCTL2_MR_MASK,
2533f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x19));
2534f520bb22SYouMin Chen 
2535f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2536f520bb22SYouMin Chen 			       DDR_PCTL2_INIT3);
2537f520bb22SYouMin Chen 		/* MR1 */
2538f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 1,
2539f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR234_MR1_SHIFT &
2540f520bb22SYouMin Chen 			      PCTL2_MR_MASK,
2541f520bb22SYouMin Chen 			      dramtype);
2542f520bb22SYouMin Chen 		writel(mr_tmp >> PCTL2_LPDDR234_MR1_SHIFT & PCTL2_MR_MASK,
2543f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x17));
2544f520bb22SYouMin Chen 		/* MR2 */
2545f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 2, mr_tmp & PCTL2_MR_MASK,
2546f520bb22SYouMin Chen 			      dramtype);
2547f520bb22SYouMin Chen 		writel(mr_tmp & PCTL2_MR_MASK,
2548f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x18));
2549f520bb22SYouMin Chen 
2550f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2551f520bb22SYouMin Chen 			       DDR_PCTL2_INIT6);
2552f520bb22SYouMin Chen 		/* MR11 */
2553f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 11,
2554f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
2555f520bb22SYouMin Chen 			      dramtype);
2556f520bb22SYouMin Chen 		writel(mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
2557f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x1a));
2558f520bb22SYouMin Chen 		/* MR12 */
2559f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 12,
2560f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR12_SHIFT & PCTL2_MR_MASK,
2561f520bb22SYouMin Chen 			      dramtype);
2562f520bb22SYouMin Chen 
2563f520bb22SYouMin Chen 		mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2564f520bb22SYouMin Chen 			       DDR_PCTL2_INIT7);
2565f520bb22SYouMin Chen 		/* MR22 */
2566f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 22,
2567f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
2568f520bb22SYouMin Chen 			      dramtype);
2569f520bb22SYouMin Chen 		writel(mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
2570f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x1d));
2571f520bb22SYouMin Chen 		/* MR14 */
2572f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 14,
2573f520bb22SYouMin Chen 			      mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
2574f520bb22SYouMin Chen 			      dramtype);
2575f520bb22SYouMin Chen 		writel(mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
2576f520bb22SYouMin Chen 		       PHY_REG(phy_base, 0x1c));
2577f520bb22SYouMin Chen 	}
2578f520bb22SYouMin Chen 
2579f520bb22SYouMin Chen 	update_noc_timing(dram, sdram_params);
2580f520bb22SYouMin Chen }
2581f520bb22SYouMin Chen 
2582f520bb22SYouMin Chen static void save_fsp_param(struct dram_info *dram, u32 dst_fsp,
2583f520bb22SYouMin Chen 			   struct rv1126_sdram_params *sdram_params)
2584f520bb22SYouMin Chen {
2585f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2586f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
2587f520bb22SYouMin Chen 	struct rv1126_fsp_param *p_fsp_param = &fsp_param[dst_fsp];
2588f520bb22SYouMin Chen 	u32 temp, temp1;
2589f520bb22SYouMin Chen 	struct ddr2_3_4_lp2_3_info *ddr_info;
2590f520bb22SYouMin Chen 
2591f520bb22SYouMin Chen 	ddr_info = get_ddr_drv_odt_info(sdram_params->base.dramtype);
2592f520bb22SYouMin Chen 
2593f520bb22SYouMin Chen 	p_fsp_param->freq_mhz = sdram_params->base.ddr_freq;
2594f520bb22SYouMin Chen 
2595f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4) {
2596f520bb22SYouMin Chen 		p_fsp_param->rd_odt_up_en = 0;
2597f520bb22SYouMin Chen 		p_fsp_param->rd_odt_down_en = 1;
2598f520bb22SYouMin Chen 	} else {
2599f520bb22SYouMin Chen 		p_fsp_param->rd_odt_up_en =
2600f520bb22SYouMin Chen 			ODT_INFO_PULLUP_EN(ddr_info->odt_info);
2601f520bb22SYouMin Chen 		p_fsp_param->rd_odt_down_en =
2602f520bb22SYouMin Chen 			ODT_INFO_PULLDOWN_EN(ddr_info->odt_info);
2603f520bb22SYouMin Chen 	}
2604f520bb22SYouMin Chen 
2605f520bb22SYouMin Chen 	if (p_fsp_param->rd_odt_up_en)
2606f520bb22SYouMin Chen 		p_fsp_param->rd_odt = readl(PHY_REG(phy_base, 0x111));
2607f520bb22SYouMin Chen 	else if (p_fsp_param->rd_odt_down_en)
2608f520bb22SYouMin Chen 		p_fsp_param->rd_odt = readl(PHY_REG(phy_base, 0x110));
2609f520bb22SYouMin Chen 	else
2610f520bb22SYouMin Chen 		p_fsp_param->rd_odt = 0;
2611f520bb22SYouMin Chen 	p_fsp_param->wr_dq_drv = readl(PHY_REG(phy_base, 0x112));
2612f520bb22SYouMin Chen 	p_fsp_param->wr_ca_drv = readl(PHY_REG(phy_base, 0x100));
2613f520bb22SYouMin Chen 	p_fsp_param->wr_ckcs_drv = readl(PHY_REG(phy_base, 0x102));
2614f520bb22SYouMin Chen 	p_fsp_param->vref_inner = readl(PHY_REG(phy_base, 0x128));
2615f520bb22SYouMin Chen 	p_fsp_param->vref_out = readl(PHY_REG(phy_base, 0x105));
2616f520bb22SYouMin Chen 
2617f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR3) {
2618f520bb22SYouMin Chen 		temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2619f520bb22SYouMin Chen 			     DDR_PCTL2_INIT3);
2620f520bb22SYouMin Chen 		temp = (temp >> PCTL2_DDR34_MR1_SHIFT) & PCTL2_MR_MASK;
2621f520bb22SYouMin Chen 		p_fsp_param->ds_pdds = ((temp >> 1) & 0x1) |
2622f520bb22SYouMin Chen 				       (((temp >> 5) & 0x1) << 1);
2623f520bb22SYouMin Chen 		p_fsp_param->dq_odt = ((temp >> 2) & 0x1) |
2624f520bb22SYouMin Chen 				      (((temp >> 6) & 0x1) << 1) |
2625f520bb22SYouMin Chen 				      (((temp >> 9) & 0x1) << 2);
2626f520bb22SYouMin Chen 		p_fsp_param->ca_odt = p_fsp_param->dq_odt;
2627f520bb22SYouMin Chen 	} else if (sdram_params->base.dramtype == DDR4) {
2628f520bb22SYouMin Chen 		temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2629f520bb22SYouMin Chen 			     DDR_PCTL2_INIT3);
2630f520bb22SYouMin Chen 		temp = (temp >> PCTL2_DDR34_MR1_SHIFT) & PCTL2_MR_MASK;
2631f520bb22SYouMin Chen 		p_fsp_param->ds_pdds = (temp >> 1) & 0x3;
2632f520bb22SYouMin Chen 		p_fsp_param->dq_odt = (temp >> 8) & 0x7;
2633f520bb22SYouMin Chen 		p_fsp_param->ca_odt = p_fsp_param->dq_odt;
2634f520bb22SYouMin Chen 	} else if (sdram_params->base.dramtype == LPDDR3) {
2635f520bb22SYouMin Chen 		temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2636f520bb22SYouMin Chen 			     DDR_PCTL2_INIT4);
2637f520bb22SYouMin Chen 		temp = (temp >> PCTL2_LPDDR234_MR3_SHIFT) & PCTL2_MR_MASK;
2638f520bb22SYouMin Chen 		p_fsp_param->ds_pdds = temp & 0xf;
2639f520bb22SYouMin Chen 
2640f520bb22SYouMin Chen 		p_fsp_param->dq_odt = lp3_odt_value;
2641f520bb22SYouMin Chen 		p_fsp_param->ca_odt = p_fsp_param->dq_odt;
2642f520bb22SYouMin Chen 	} else if (sdram_params->base.dramtype == LPDDR4) {
2643f520bb22SYouMin Chen 		temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2644f520bb22SYouMin Chen 			     DDR_PCTL2_INIT4);
2645f520bb22SYouMin Chen 		temp = (temp >> PCTL2_LPDDR234_MR3_SHIFT) & PCTL2_MR_MASK;
2646f520bb22SYouMin Chen 		p_fsp_param->ds_pdds = (temp >> 3) & 0x7;
2647f520bb22SYouMin Chen 
2648f520bb22SYouMin Chen 		temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2649f520bb22SYouMin Chen 			     DDR_PCTL2_INIT6);
2650f520bb22SYouMin Chen 		temp = (temp >> PCTL2_LPDDR4_MR11_SHIFT) & PCTL2_MR_MASK;
2651f520bb22SYouMin Chen 		p_fsp_param->dq_odt = temp & 0x7;
2652f520bb22SYouMin Chen 		p_fsp_param->ca_odt = (temp >> 4) & 0x7;
2653f520bb22SYouMin Chen 
2654f520bb22SYouMin Chen 		temp = MAX(readl(PHY_REG(phy_base, 0x3ae)),
2655f520bb22SYouMin Chen 			   readl(PHY_REG(phy_base, 0x3ce)));
2656f520bb22SYouMin Chen 		temp1 = MIN(readl(PHY_REG(phy_base, 0x3be)),
2657f520bb22SYouMin Chen 			    readl(PHY_REG(phy_base, 0x3de)));
2658f520bb22SYouMin Chen 		p_fsp_param->vref_ca[0] = (temp + temp1) / 2;
2659f520bb22SYouMin Chen 		temp = MAX(readl(PHY_REG(phy_base, 0x3af)),
2660f520bb22SYouMin Chen 			   readl(PHY_REG(phy_base, 0x3cf)));
2661f520bb22SYouMin Chen 		temp1 = MIN(readl(PHY_REG(phy_base, 0x3bf)),
2662f520bb22SYouMin Chen 			    readl(PHY_REG(phy_base, 0x3df)));
2663f520bb22SYouMin Chen 		p_fsp_param->vref_ca[1] = (temp + temp1) / 2;
2664f520bb22SYouMin Chen 		p_fsp_param->vref_ca[0] |=
2665f520bb22SYouMin Chen 			(readl(PHY_REG(phy_base, 0x1e)) & BIT(6));
2666f520bb22SYouMin Chen 		p_fsp_param->vref_ca[1] |=
2667f520bb22SYouMin Chen 			(readl(PHY_REG(phy_base, 0x1e)) & BIT(6));
2668f520bb22SYouMin Chen 
2669f520bb22SYouMin Chen 		p_fsp_param->lp4_drv_pd_en = (readl(PHY_REG(phy_base, 0x114)) >>
2670f520bb22SYouMin Chen 					      3) & 0x1;
2671f520bb22SYouMin Chen 	}
2672f520bb22SYouMin Chen 
2673f520bb22SYouMin Chen 	p_fsp_param->noc_timings.ddrtiminga0 =
2674f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.ddrtiminga0;
2675f520bb22SYouMin Chen 	p_fsp_param->noc_timings.ddrtimingb0 =
2676f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.ddrtimingb0;
2677f520bb22SYouMin Chen 	p_fsp_param->noc_timings.ddrtimingc0 =
2678f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.ddrtimingc0;
2679f520bb22SYouMin Chen 	p_fsp_param->noc_timings.devtodev0 =
2680f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.devtodev0;
2681f520bb22SYouMin Chen 	p_fsp_param->noc_timings.ddrmode =
2682f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.ddrmode;
2683f520bb22SYouMin Chen 	p_fsp_param->noc_timings.ddr4timing =
2684f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.ddr4timing;
2685f520bb22SYouMin Chen 	p_fsp_param->noc_timings.agingx0 =
2686f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.agingx0;
2687f520bb22SYouMin Chen 	p_fsp_param->noc_timings.aging0 =
2688f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.aging0;
2689f520bb22SYouMin Chen 	p_fsp_param->noc_timings.aging1 =
2690f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.aging1;
2691f520bb22SYouMin Chen 	p_fsp_param->noc_timings.aging2 =
2692f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.aging2;
2693f520bb22SYouMin Chen 	p_fsp_param->noc_timings.aging3 =
2694f520bb22SYouMin Chen 		sdram_params->ch.noc_timings.aging3;
2695f520bb22SYouMin Chen 
2696f520bb22SYouMin Chen 	p_fsp_param->flag = FSP_FLAG;
2697f520bb22SYouMin Chen }
2698f520bb22SYouMin Chen 
2699f520bb22SYouMin Chen static void copy_fsp_param_to_ddr(void)
2700f520bb22SYouMin Chen {
2701f520bb22SYouMin Chen 	memcpy((void *)FSP_PARAM_STORE_ADDR, (void *)&fsp_param,
2702f520bb22SYouMin Chen 	       sizeof(fsp_param));
2703f520bb22SYouMin Chen }
2704f520bb22SYouMin Chen 
2705f520bb22SYouMin Chen void ddr_set_rate(struct dram_info *dram,
2706f520bb22SYouMin Chen 		  struct rv1126_sdram_params *sdram_params,
2707f520bb22SYouMin Chen 		  u32 freq, u32 cur_freq, u32 dst_fsp,
2708f520bb22SYouMin Chen 		  u32 dst_fsp_lp4, u32 training_en)
2709f520bb22SYouMin Chen {
2710f520bb22SYouMin Chen 	u32 dest_dll_off, cur_init3, dst_init3, cur_fsp, cur_dll_off;
2711f520bb22SYouMin Chen 	u32 mr_tmp;
2712f520bb22SYouMin Chen 	u32 lp_stat;
2713f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
2714f520bb22SYouMin Chen 	struct rv1126_sdram_params *sdram_params_new;
2715f520bb22SYouMin Chen 	void __iomem *pctl_base = dram->pctl;
2716f520bb22SYouMin Chen 	void __iomem *phy_base = dram->phy;
2717f520bb22SYouMin Chen 
2718f520bb22SYouMin Chen 	lp_stat = low_power_update(dram, 0);
2719f520bb22SYouMin Chen 	sdram_params_new = get_default_sdram_config(freq);
2720f520bb22SYouMin Chen 	sdram_params_new->ch.cap_info.rank = sdram_params->ch.cap_info.rank;
2721f520bb22SYouMin Chen 
2722f520bb22SYouMin Chen 	pre_set_rate(dram, sdram_params_new, dst_fsp, dst_fsp_lp4);
2723f520bb22SYouMin Chen 
2724f520bb22SYouMin Chen 	while ((readl(pctl_base + DDR_PCTL2_STAT) &
2725f520bb22SYouMin Chen 			 PCTL2_OPERATING_MODE_MASK) ==
2726f520bb22SYouMin Chen 			 PCTL2_OPERATING_MODE_SR)
2727f520bb22SYouMin Chen 		continue;
2728f520bb22SYouMin Chen 
2729f520bb22SYouMin Chen 	dest_dll_off = 0;
2730f520bb22SYouMin Chen 	dst_init3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2731f520bb22SYouMin Chen 			  DDR_PCTL2_INIT3);
2732f520bb22SYouMin Chen 	if ((dramtype == DDR3 && (dst_init3 & 1)) ||
2733f520bb22SYouMin Chen 	    (dramtype == DDR4 && !(dst_init3 & 1)))
2734f520bb22SYouMin Chen 		dest_dll_off = 1;
2735f520bb22SYouMin Chen 
2736f520bb22SYouMin Chen 	cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
2737f520bb22SYouMin Chen 	cur_init3 = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
2738f520bb22SYouMin Chen 			  DDR_PCTL2_INIT3);
2739f520bb22SYouMin Chen 	cur_init3 &= PCTL2_MR_MASK;
2740f520bb22SYouMin Chen 	cur_dll_off = 1;
2741f520bb22SYouMin Chen 	if ((dramtype == DDR3 && !(cur_init3 & 1)) ||
2742f520bb22SYouMin Chen 	    (dramtype == DDR4 && (cur_init3 & 1)))
2743f520bb22SYouMin Chen 		cur_dll_off = 0;
2744f520bb22SYouMin Chen 
2745f520bb22SYouMin Chen 	if (!cur_dll_off) {
2746f520bb22SYouMin Chen 		if (dramtype == DDR3)
2747f520bb22SYouMin Chen 			cur_init3 |= 1;
2748f520bb22SYouMin Chen 		else
2749f520bb22SYouMin Chen 			cur_init3 &= ~1;
2750f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 2, 1, cur_init3, dramtype);
2751f520bb22SYouMin Chen 	}
2752f520bb22SYouMin Chen 
2753f520bb22SYouMin Chen 	setbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3,
2754f520bb22SYouMin Chen 		     PCTL2_DIS_AUTO_REFRESH);
2755f520bb22SYouMin Chen 	update_refresh_reg(dram);
2756f520bb22SYouMin Chen 
2757f520bb22SYouMin Chen 	setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, PCTL2_SELFREF_SW);
2758f520bb22SYouMin Chen 	while (1) {
2759f520bb22SYouMin Chen 		if (((readl(pctl_base + DDR_PCTL2_STAT) &
2760f520bb22SYouMin Chen 		      PCTL2_SELFREF_TYPE_MASK) ==
2761f520bb22SYouMin Chen 		     PCTL2_SELFREF_TYPE_SR_NOT_AUTO) &&
2762f520bb22SYouMin Chen 		    ((readl(pctl_base + DDR_PCTL2_STAT) &
2763f520bb22SYouMin Chen 		      PCTL2_OPERATING_MODE_MASK) ==
2764f520bb22SYouMin Chen 		     PCTL2_OPERATING_MODE_SR)) {
2765f520bb22SYouMin Chen 			break;
2766f520bb22SYouMin Chen 		}
2767f520bb22SYouMin Chen 	}
2768f520bb22SYouMin Chen 
2769f520bb22SYouMin Chen 	writel(PMUGRF_CON_DDRPHY_BUFFEREN_MASK |
2770f520bb22SYouMin Chen 	       PMUGRF_CON_DDRPHY_BUFFEREN_EN,
2771f520bb22SYouMin Chen 	       dram->pmugrf->soc_con[0]);
2772f520bb22SYouMin Chen 	sw_set_req(dram);
2773f520bb22SYouMin Chen 	clrbits_le32(pctl_base + DDR_PCTL2_DFIMISC,
2774f520bb22SYouMin Chen 		     PCTL2_DFI_INIT_COMPLETE_EN);
2775f520bb22SYouMin Chen 	sw_set_ack(dram);
2776f520bb22SYouMin Chen 
2777f520bb22SYouMin Chen 	sw_set_req(dram);
2778f520bb22SYouMin Chen 	if ((dramtype == DDR3 || dramtype == DDR4) && dest_dll_off)
2779f520bb22SYouMin Chen 		setbits_le32(pctl_base + DDR_PCTL2_MSTR, PCTL2_DLL_OFF_MODE);
2780f520bb22SYouMin Chen 	else
2781f520bb22SYouMin Chen 		clrbits_le32(pctl_base + DDR_PCTL2_MSTR, PCTL2_DLL_OFF_MODE);
2782f520bb22SYouMin Chen 
2783f520bb22SYouMin Chen 	setbits_le32(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + DDR_PCTL2_ZQCTL0,
2784f520bb22SYouMin Chen 		     PCTL2_DIS_SRX_ZQCL);
2785f520bb22SYouMin Chen 	setbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_ZQCTL0,
2786f520bb22SYouMin Chen 		     PCTL2_DIS_SRX_ZQCL);
2787f520bb22SYouMin Chen 	sw_set_ack(dram);
2788f520bb22SYouMin Chen 
2789f520bb22SYouMin Chen 	writel(DDR_MSCH_EN_MASK | (0x1 << DDR_MSCH_EN_SHIFT),
2790f520bb22SYouMin Chen 	       dram->cru->clkgate_con[2]);
2791f520bb22SYouMin Chen 	writel(CLK_DDR_UPCTL_EN_MASK | ACLK_DDR_UPCTL_EN_MASK |
2792f520bb22SYouMin Chen 					(0x1 << CLK_DDR_UPCTL_EN_SHIFT) |
2793f520bb22SYouMin Chen 					(0x1 << ACLK_DDR_UPCTL_EN_SHIFT),
2794f520bb22SYouMin Chen 			BUS_SGRF_BASE_ADDR + SGRF_SOC_CON12);
2795f520bb22SYouMin Chen 
2796f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET | DIGITAL_DERESET);
2797f520bb22SYouMin Chen 	rkclk_set_dpll(dram, freq * MHz / 2);
2798f520bb22SYouMin Chen 	phy_pll_set(dram, freq * MHz, 0);
2799f520bb22SYouMin Chen 	phy_pll_set(dram, freq * MHz, 1);
2800f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET | DIGITAL_DERESET);
2801f520bb22SYouMin Chen 
2802f520bb22SYouMin Chen 	writel(PMUGRF_CON_DDRPHY_BUFFEREN_MASK |
2803f520bb22SYouMin Chen 			PMUGRF_CON_DDRPHY_BUFFEREN_DIS,
2804f520bb22SYouMin Chen 			dram->pmugrf->soc_con[0]);
2805f520bb22SYouMin Chen 	writel(DDR_MSCH_EN_MASK | (0x0 << DDR_MSCH_EN_SHIFT),
2806f520bb22SYouMin Chen 	       dram->cru->clkgate_con[2]);
2807f520bb22SYouMin Chen 	writel(CLK_DDR_UPCTL_EN_MASK | ACLK_DDR_UPCTL_EN_MASK |
2808f520bb22SYouMin Chen 					(0x0 << CLK_DDR_UPCTL_EN_SHIFT) |
2809f520bb22SYouMin Chen 					(0x0 << ACLK_DDR_UPCTL_EN_SHIFT),
2810f520bb22SYouMin Chen 			BUS_SGRF_BASE_ADDR + SGRF_SOC_CON12);
2811f520bb22SYouMin Chen 	while ((readl(pctl_base + DDR_PCTL2_DFISTAT) &
2812f520bb22SYouMin Chen 	       PCTL2_DFI_INIT_COMPLETE) != PCTL2_DFI_INIT_COMPLETE)
2813f520bb22SYouMin Chen 		continue;
2814f520bb22SYouMin Chen 
2815f520bb22SYouMin Chen 	sw_set_req(dram);
2816f520bb22SYouMin Chen 	setbits_le32(pctl_base + DDR_PCTL2_MSTR, 0x1 << 29);
2817f520bb22SYouMin Chen 	clrsetbits_le32(pctl_base + DDR_PCTL2_MSTR2, 0x3, dst_fsp);
2818f520bb22SYouMin Chen 	sw_set_ack(dram);
2819f520bb22SYouMin Chen 	update_refresh_reg(dram);
2820f520bb22SYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0xc), 0x3 << 2, dst_fsp << 2);
2821f520bb22SYouMin Chen 
2822f520bb22SYouMin Chen 	clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, PCTL2_SELFREF_SW);
2823f520bb22SYouMin Chen 	while ((readl(pctl_base + DDR_PCTL2_STAT) &
2824f520bb22SYouMin Chen 	       PCTL2_OPERATING_MODE_MASK) == PCTL2_OPERATING_MODE_SR)
2825f520bb22SYouMin Chen 		continue;
2826f520bb22SYouMin Chen 
2827f520bb22SYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
2828f520bb22SYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
2829f520bb22SYouMin Chen 
2830f520bb22SYouMin Chen 	mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_INIT4);
2831f520bb22SYouMin Chen 	if (dramtype == LPDDR3) {
2832f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 1,
2833f520bb22SYouMin Chen 			      (dst_init3 >> PCTL2_LPDDR234_MR1_SHIFT) &
2834f520bb22SYouMin Chen 			      PCTL2_MR_MASK,
2835f520bb22SYouMin Chen 			      dramtype);
2836f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 2, dst_init3 & PCTL2_MR_MASK,
2837f520bb22SYouMin Chen 			      dramtype);
2838f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 3,
2839f520bb22SYouMin Chen 			      (mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT) &
2840f520bb22SYouMin Chen 			      PCTL2_MR_MASK,
2841f520bb22SYouMin Chen 			      dramtype);
2842f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 11, lp3_odt_value, dramtype);
2843f520bb22SYouMin Chen 	} else if ((dramtype == DDR3) || (dramtype == DDR4)) {
2844f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 1, dst_init3 & PCTL2_MR_MASK,
2845f520bb22SYouMin Chen 			      dramtype);
2846f520bb22SYouMin Chen 		if (!dest_dll_off) {
2847f520bb22SYouMin Chen 			pctl_write_mr(dram->pctl, 3, 0,
2848f520bb22SYouMin Chen 				      ((dst_init3 >> PCTL2_DDR34_MR0_SHIFT) &
2849f520bb22SYouMin Chen 				      PCTL2_MR_MASK) | DDR3_DLL_RESET,
2850f520bb22SYouMin Chen 				      dramtype);
2851f520bb22SYouMin Chen 			udelay(2);
2852f520bb22SYouMin Chen 		}
2853f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 0,
2854f520bb22SYouMin Chen 			      (dst_init3 >> PCTL2_DDR34_MR0_SHIFT &
2855f520bb22SYouMin Chen 			       PCTL2_MR_MASK) & (~DDR3_DLL_RESET),
2856f520bb22SYouMin Chen 			      dramtype);
2857f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 2,
2858f520bb22SYouMin Chen 			      ((mr_tmp >> PCTL2_DDR34_MR2_SHIFT) &
2859f520bb22SYouMin Chen 			       PCTL2_MR_MASK), dramtype);
2860f520bb22SYouMin Chen 		if (dramtype == DDR4) {
2861f520bb22SYouMin Chen 			pctl_write_mr(dram->pctl, 3, 3, mr_tmp & PCTL2_MR_MASK,
2862f520bb22SYouMin Chen 				      dramtype);
2863f520bb22SYouMin Chen 			mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2864f520bb22SYouMin Chen 				       DDR_PCTL2_INIT6);
2865f520bb22SYouMin Chen 			pctl_write_mr(dram->pctl, 3, 4,
2866f520bb22SYouMin Chen 				      (mr_tmp >> PCTL2_DDR4_MR4_SHIFT) &
2867f520bb22SYouMin Chen 				       PCTL2_MR_MASK,
2868f520bb22SYouMin Chen 				      dramtype);
2869f520bb22SYouMin Chen 			pctl_write_mr(dram->pctl, 3, 5,
2870f520bb22SYouMin Chen 				      mr_tmp >> PCTL2_DDR4_MR5_SHIFT &
2871f520bb22SYouMin Chen 				      PCTL2_MR_MASK,
2872f520bb22SYouMin Chen 				      dramtype);
2873f520bb22SYouMin Chen 
2874f520bb22SYouMin Chen 			mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2875f520bb22SYouMin Chen 				       DDR_PCTL2_INIT7);
2876f520bb22SYouMin Chen 			pctl_write_mr(dram->pctl, 3, 6,
2877f520bb22SYouMin Chen 				      mr_tmp >> PCTL2_DDR4_MR6_SHIFT &
2878f520bb22SYouMin Chen 				      PCTL2_MR_MASK,
2879f520bb22SYouMin Chen 				      dramtype);
2880f520bb22SYouMin Chen 		}
2881f520bb22SYouMin Chen 	} else if (dramtype == LPDDR4) {
2882f520bb22SYouMin Chen 		pctl_write_mr(dram->pctl, 3, 13,
2883f520bb22SYouMin Chen 			      ((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
2884f520bb22SYouMin Chen 			       PCTL2_MR_MASK) & (~(BIT(7)))) |
2885f520bb22SYouMin Chen 			      dst_fsp_lp4 << 7, dramtype);
2886f520bb22SYouMin Chen 	}
2887f520bb22SYouMin Chen 
2888f520bb22SYouMin Chen 	/* training */
2889f520bb22SYouMin Chen 	high_freq_training(dram, sdram_params_new, dst_fsp);
2890f520bb22SYouMin Chen 
2891f520bb22SYouMin Chen 	clrbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3,
2892f520bb22SYouMin Chen 		     PCTL2_DIS_AUTO_REFRESH);
2893f520bb22SYouMin Chen 	low_power_update(dram, lp_stat);
2894f520bb22SYouMin Chen 
2895f520bb22SYouMin Chen 	save_fsp_param(dram, dst_fsp, sdram_params_new);
2896f520bb22SYouMin Chen }
2897f520bb22SYouMin Chen 
2898f520bb22SYouMin Chen static void ddr_set_rate_for_fsp(struct dram_info *dram,
2899f520bb22SYouMin Chen 				 struct rv1126_sdram_params *sdram_params)
2900f520bb22SYouMin Chen {
2901f520bb22SYouMin Chen 	struct ddr2_3_4_lp2_3_info *ddr_info;
2902f520bb22SYouMin Chen 	u32 f0, f1, f2, f3;
2903f520bb22SYouMin Chen 	u32 dramtype = sdram_params->base.dramtype;
2904f520bb22SYouMin Chen 
2905f520bb22SYouMin Chen 	ddr_info = get_ddr_drv_odt_info(dramtype);
2906f520bb22SYouMin Chen 	if (!ddr_info)
2907f520bb22SYouMin Chen 		return;
2908f520bb22SYouMin Chen 
2909f520bb22SYouMin Chen 	memset((void *)FSP_PARAM_STORE_ADDR, 0, sizeof(fsp_param));
2910f520bb22SYouMin Chen 	memset((void *)&fsp_param, 0, sizeof(fsp_param));
2911f520bb22SYouMin Chen 
2912f520bb22SYouMin Chen 	f0 = (ddr_info->ddr_freq0_1 >> DDR_FREQ_F0_SHIFT) &
2913f520bb22SYouMin Chen 	     DDR_FREQ_MASK;
2914f520bb22SYouMin Chen 	f1 = (ddr_info->ddr_freq0_1 >> DDR_FREQ_F1_SHIFT) &
2915f520bb22SYouMin Chen 	     DDR_FREQ_MASK;
2916f520bb22SYouMin Chen 	f2 = (ddr_info->ddr_freq2_3 >> DDR_FREQ_F2_SHIFT) &
2917f520bb22SYouMin Chen 	     DDR_FREQ_MASK;
2918f520bb22SYouMin Chen 	f3 = (ddr_info->ddr_freq2_3 >> DDR_FREQ_F3_SHIFT) &
2919f520bb22SYouMin Chen 	     DDR_FREQ_MASK;
2920f520bb22SYouMin Chen 
2921f520bb22SYouMin Chen 	if (get_wrlvl_val(dram, sdram_params))
2922f520bb22SYouMin Chen 		printascii("get wrlvl value fail\n");
2923*f876ce9bSTang Yun ping 	printascii("change to: ");
2924f520bb22SYouMin Chen 	printdec(f1);
2925f520bb22SYouMin Chen 	printascii("MHz\n");
2926f520bb22SYouMin Chen 	ddr_set_rate(&dram_info, sdram_params, f1,
2927f520bb22SYouMin Chen 		     sdram_params->base.ddr_freq, 1, 1, 1);
2928*f876ce9bSTang Yun ping 	printascii("change to: ");
2929f520bb22SYouMin Chen 	printdec(f2);
2930f520bb22SYouMin Chen 	printascii("MHz\n");
2931f520bb22SYouMin Chen 	ddr_set_rate(&dram_info, sdram_params, f2, f1, 2, 0, 1);
2932*f876ce9bSTang Yun ping 	printascii("change to: ");
2933f520bb22SYouMin Chen 	printdec(f3);
2934f520bb22SYouMin Chen 	printascii("MHz\n");
2935f520bb22SYouMin Chen 	ddr_set_rate(&dram_info, sdram_params, f3, f2, 3, 1, 1);
2936*f876ce9bSTang Yun ping 	printascii("change to: ");
2937f520bb22SYouMin Chen 	printdec(f0);
2938*f876ce9bSTang Yun ping 	printascii("MHz(final freq)\n");
2939f520bb22SYouMin Chen 	ddr_set_rate(&dram_info, sdram_params, f0, f3, 0, 0, 1);
2940f520bb22SYouMin Chen }
2941f520bb22SYouMin Chen 
2942f520bb22SYouMin Chen int get_uart_config(void)
2943f520bb22SYouMin Chen {
2944f520bb22SYouMin Chen 	struct sdram_head_info_index_v2 *index =
2945f520bb22SYouMin Chen 		(struct sdram_head_info_index_v2 *)common_info;
2946f520bb22SYouMin Chen 	struct global_info *gbl_info;
2947f520bb22SYouMin Chen 
2948f520bb22SYouMin Chen 	gbl_info = (struct global_info *)((void *)common_info +
2949f520bb22SYouMin Chen 		index->global_index.offset * 4);
2950f520bb22SYouMin Chen 
2951f520bb22SYouMin Chen 	return gbl_info->uart_info;
2952f520bb22SYouMin Chen }
2953f520bb22SYouMin Chen 
2954f520bb22SYouMin Chen /* return: 0 = success, other = fail */
2955f520bb22SYouMin Chen int sdram_init(void)
2956f520bb22SYouMin Chen {
2957f520bb22SYouMin Chen 	struct rv1126_sdram_params *sdram_params;
2958f520bb22SYouMin Chen 	int ret = 0;
2959f520bb22SYouMin Chen 	struct sdram_head_info_index_v2 *index =
2960f520bb22SYouMin Chen 		(struct sdram_head_info_index_v2 *)common_info;
2961f520bb22SYouMin Chen 	struct global_info *gbl_info;
2962f520bb22SYouMin Chen 
2963f520bb22SYouMin Chen 	dram_info.phy = (void *)DDR_PHY_BASE_ADDR;
2964f520bb22SYouMin Chen 	dram_info.pctl = (void *)UPCTL2_BASE_ADDR;
2965f520bb22SYouMin Chen 	dram_info.grf = (void *)GRF_BASE_ADDR;
2966f520bb22SYouMin Chen 	dram_info.cru = (void *)CRU_BASE_ADDR;
2967f520bb22SYouMin Chen 	dram_info.msch = (void *)SERVER_MSCH_BASE_ADDR;
2968f520bb22SYouMin Chen 	dram_info.ddrgrf = (void *)DDR_GRF_BASE_ADDR;
2969f520bb22SYouMin Chen 	dram_info.pmugrf = (void *)PMU_GRF_BASE_ADDR;
2970f520bb22SYouMin Chen 
2971f520bb22SYouMin Chen 	if (index->version_info != 2 ||
2972f520bb22SYouMin Chen 	    (index->global_index.size != sizeof(struct global_info) / 4) ||
2973f520bb22SYouMin Chen 	    (index->ddr3_index.size !=
2974f520bb22SYouMin Chen 		sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
2975f520bb22SYouMin Chen 	    (index->ddr4_index.size !=
2976f520bb22SYouMin Chen 		sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
2977f520bb22SYouMin Chen 	    (index->lp3_index.size !=
2978f520bb22SYouMin Chen 		sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
2979f520bb22SYouMin Chen 	    (index->lp4_index.size != (sizeof(struct lp4_info) / 4)) ||
2980f520bb22SYouMin Chen 	    index->global_index.offset == 0 ||
2981f520bb22SYouMin Chen 	    index->ddr3_index.offset == 0 ||
2982f520bb22SYouMin Chen 	    index->ddr4_index.offset == 0 ||
2983f520bb22SYouMin Chen 	    index->lp3_index.offset == 0 ||
2984f520bb22SYouMin Chen 	    index->lp4_index.offset == 0) {
2985f520bb22SYouMin Chen 		printascii("common info error\n");
2986f520bb22SYouMin Chen 		goto error;
2987f520bb22SYouMin Chen 	}
2988f520bb22SYouMin Chen 
2989f520bb22SYouMin Chen 	gbl_info = (struct global_info *)((void *)common_info +
2990f520bb22SYouMin Chen 		index->global_index.offset * 4);
2991f520bb22SYouMin Chen 
2992f520bb22SYouMin Chen 	dram_info.sr_idle = SR_INFO(gbl_info->sr_pd_info);
2993f520bb22SYouMin Chen 	dram_info.pd_idle = PD_INFO(gbl_info->sr_pd_info);
2994f520bb22SYouMin Chen 
2995f520bb22SYouMin Chen 	sdram_params = &sdram_configs[0];
2996f520bb22SYouMin Chen 
2997f520bb22SYouMin Chen 	if (sdram_params->base.dramtype == DDR3 ||
2998f520bb22SYouMin Chen 	    sdram_params->base.dramtype == DDR4) {
2999f520bb22SYouMin Chen 		if (DDR_2T_INFO(gbl_info->info_2t))
3000f520bb22SYouMin Chen 			sdram_params->pctl_regs.pctl[0][1] |= 0x1 << 10;
3001f520bb22SYouMin Chen 		else
3002f520bb22SYouMin Chen 			sdram_params->pctl_regs.pctl[0][1] &=
3003f520bb22SYouMin Chen 				~(0x1 << 10);
3004f520bb22SYouMin Chen 	}
3005f520bb22SYouMin Chen 	ret = sdram_init_detect(&dram_info, sdram_params);
3006f520bb22SYouMin Chen 	if (ret) {
3007f520bb22SYouMin Chen 		sdram_print_dram_type(sdram_params->base.dramtype);
3008f520bb22SYouMin Chen 		printascii(", ");
3009f520bb22SYouMin Chen 		printdec(sdram_params->base.ddr_freq);
3010f520bb22SYouMin Chen 		printascii("MHz\n");
3011f520bb22SYouMin Chen 		goto error;
3012f520bb22SYouMin Chen 	}
3013f520bb22SYouMin Chen 	print_ddr_info(sdram_params);
3014f520bb22SYouMin Chen 
3015f520bb22SYouMin Chen 	ddr_set_rate_for_fsp(&dram_info, sdram_params);
3016f520bb22SYouMin Chen 	copy_fsp_param_to_ddr();
3017f520bb22SYouMin Chen 
3018f520bb22SYouMin Chen 	ddr_set_atags(&dram_info, sdram_params);
3019f520bb22SYouMin Chen 
3020f520bb22SYouMin Chen 	printascii("out\n");
3021f520bb22SYouMin Chen 
3022f520bb22SYouMin Chen 	return ret;
3023f520bb22SYouMin Chen error:
3024f520bb22SYouMin Chen 	printascii("error\n");
3025f520bb22SYouMin Chen 	return (-1);
3026f520bb22SYouMin Chen }
3027f520bb22SYouMin Chen #endif /* CONFIG_TPL_BUILD */
3028