xref: /OK3568_Linux_fs/u-boot/drivers/ram/rockchip/sdram_rk3399.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2016-2017 Rockchip Inc.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * SPDX-License-Identifier:     GPL-2.0
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Adapted from coreboot.
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <common.h>
10*4882a593Smuzhiyun #include <clk.h>
11*4882a593Smuzhiyun #include <dm.h>
12*4882a593Smuzhiyun #include <dt-structs.h>
13*4882a593Smuzhiyun #include <ram.h>
14*4882a593Smuzhiyun #include <regmap.h>
15*4882a593Smuzhiyun #include <syscon.h>
16*4882a593Smuzhiyun #include <asm/io.h>
17*4882a593Smuzhiyun #include <asm/arch/clock.h>
18*4882a593Smuzhiyun #include <asm/arch/sdram.h>
19*4882a593Smuzhiyun #include <asm/arch/sdram_rk3399.h>
20*4882a593Smuzhiyun #include <asm/arch/cru_rk3399.h>
21*4882a593Smuzhiyun #include <asm/arch/grf_rk3399.h>
22*4882a593Smuzhiyun #include <asm/arch/pmu_rk3399.h>
23*4882a593Smuzhiyun #include <asm/arch/hardware.h>
24*4882a593Smuzhiyun #include <linux/err.h>
25*4882a593Smuzhiyun #include <time.h>
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun struct chan_info {
30*4882a593Smuzhiyun 	struct rk3399_ddr_pctl_regs *pctl;
31*4882a593Smuzhiyun 	struct rk3399_ddr_pi_regs *pi;
32*4882a593Smuzhiyun 	struct rk3399_ddr_publ_regs *publ;
33*4882a593Smuzhiyun 	struct msch_regs *msch;
34*4882a593Smuzhiyun };
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun struct dram_info {
37*4882a593Smuzhiyun #ifdef CONFIG_TPL_BUILD
38*4882a593Smuzhiyun 	struct chan_info chan[2];
39*4882a593Smuzhiyun 	struct clk ddr_clk;
40*4882a593Smuzhiyun 	struct rk3399_cru *cru;
41*4882a593Smuzhiyun 	struct rk3399_grf_regs *grf;
42*4882a593Smuzhiyun 	struct rk3399_pmu_regs *pmu;
43*4882a593Smuzhiyun 	struct rk3399_pmucru *pmucru;
44*4882a593Smuzhiyun 	struct rk3399_pmusgrf_regs *pmusgrf;
45*4882a593Smuzhiyun 	struct rk3399_ddr_cic_regs *cic;
46*4882a593Smuzhiyun #endif
47*4882a593Smuzhiyun 	struct ram_info info;
48*4882a593Smuzhiyun 	struct rk3399_pmugrf_regs *pmugrf;
49*4882a593Smuzhiyun };
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #define PRESET_SGRF_HOLD(n)	((0x1 << (6 + 16)) | ((n) << 6))
52*4882a593Smuzhiyun #define PRESET_GPIO0_HOLD(n)	((0x1 << (7 + 16)) | ((n) << 7))
53*4882a593Smuzhiyun #define PRESET_GPIO1_HOLD(n)	((0x1 << (8 + 16)) | ((n) << 8))
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun #define PHY_DRV_ODT_HI_Z	0x0
56*4882a593Smuzhiyun #define PHY_DRV_ODT_240		0x1
57*4882a593Smuzhiyun #define PHY_DRV_ODT_120		0x8
58*4882a593Smuzhiyun #define PHY_DRV_ODT_80		0x9
59*4882a593Smuzhiyun #define PHY_DRV_ODT_60		0xc
60*4882a593Smuzhiyun #define PHY_DRV_ODT_48		0xd
61*4882a593Smuzhiyun #define PHY_DRV_ODT_40		0xe
62*4882a593Smuzhiyun #define PHY_DRV_ODT_34_3	0xf
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun #ifdef CONFIG_TPL_BUILD
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun struct rockchip_dmc_plat {
67*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(OF_PLATDATA)
68*4882a593Smuzhiyun 	struct dtd_rockchip_rk3399_dmc dtplat;
69*4882a593Smuzhiyun #else
70*4882a593Smuzhiyun 	struct rk3399_sdram_params sdram_params;
71*4882a593Smuzhiyun #endif
72*4882a593Smuzhiyun 	struct regmap *map;
73*4882a593Smuzhiyun };
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun u32 g_pwrup_srefresh_exit[2];
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun struct rk3399_sdram_params dfs_configs[] = {
78*4882a593Smuzhiyun #include "sdram-rk3399-lpddr4-400.inc"
79*4882a593Smuzhiyun #include "sdram-rk3399-lpddr4-800.inc"
80*4882a593Smuzhiyun };
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun #define CRU_SFTRST_DDR_CTRL(ch, n)	((0x1 << (8 + 16 + (ch) * 4)) | \
83*4882a593Smuzhiyun 						((n) << (8 + (ch) * 4)))
84*4882a593Smuzhiyun #define CRU_SFTRST_DDR_PHY(ch, n)	((0x1 << (9 + 16 + (ch) * 4)) | \
85*4882a593Smuzhiyun 						((n) << (9 + (ch) * 4)))
rkclk_ddr_reset(struct rk3399_cru * cru,u32 channel,u32 ctl,u32 phy)86*4882a593Smuzhiyun static void rkclk_ddr_reset(struct rk3399_cru *cru, u32 channel, u32 ctl,
87*4882a593Smuzhiyun 			    u32 phy)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun 	channel &= 0x1;
90*4882a593Smuzhiyun 	ctl &= 0x1;
91*4882a593Smuzhiyun 	phy &= 0x1;
92*4882a593Smuzhiyun 	writel(CRU_SFTRST_DDR_CTRL(channel, ctl) |
93*4882a593Smuzhiyun 					CRU_SFTRST_DDR_PHY(channel, phy),
94*4882a593Smuzhiyun 					&cru->softrst_con[4]);
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
phy_pctrl_reset(struct rk3399_cru * cru,u32 channel)97*4882a593Smuzhiyun static void phy_pctrl_reset(struct rk3399_cru *cru,
98*4882a593Smuzhiyun 			    u32 channel)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun 	rkclk_ddr_reset(cru, channel, 1, 1);
101*4882a593Smuzhiyun 	udelay(10);
102*4882a593Smuzhiyun 	rkclk_ddr_reset(cru, channel, 1, 0);
103*4882a593Smuzhiyun 	udelay(10);
104*4882a593Smuzhiyun 	rkclk_ddr_reset(cru, channel, 0, 0);
105*4882a593Smuzhiyun 	udelay(10);
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
phy_dll_bypass_set(struct rk3399_ddr_publ_regs * ddr_publ_regs,u32 freq)108*4882a593Smuzhiyun static void phy_dll_bypass_set(struct rk3399_ddr_publ_regs *ddr_publ_regs,
109*4882a593Smuzhiyun 			       u32 freq)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun 	u32 *denali_phy = ddr_publ_regs->denali_phy;
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	/* From IP spec, only freq small than 125 can enter dll bypass mode */
114*4882a593Smuzhiyun 	if (freq <= 125) {
115*4882a593Smuzhiyun 		/* phy_sw_master_mode_X PHY_86/214/342/470 4bits offset_8 */
116*4882a593Smuzhiyun 		setbits_le32(&denali_phy[86], (0x3 << 2) << 8);
117*4882a593Smuzhiyun 		setbits_le32(&denali_phy[214], (0x3 << 2) << 8);
118*4882a593Smuzhiyun 		setbits_le32(&denali_phy[342], (0x3 << 2) << 8);
119*4882a593Smuzhiyun 		setbits_le32(&denali_phy[470], (0x3 << 2) << 8);
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 		/* phy_adrctl_sw_master_mode PHY_547/675/803 4bits offset_16 */
122*4882a593Smuzhiyun 		setbits_le32(&denali_phy[547], (0x3 << 2) << 16);
123*4882a593Smuzhiyun 		setbits_le32(&denali_phy[675], (0x3 << 2) << 16);
124*4882a593Smuzhiyun 		setbits_le32(&denali_phy[803], (0x3 << 2) << 16);
125*4882a593Smuzhiyun 	} else {
126*4882a593Smuzhiyun 		/* phy_sw_master_mode_X PHY_86/214/342/470 4bits offset_8 */
127*4882a593Smuzhiyun 		clrbits_le32(&denali_phy[86], (0x3 << 2) << 8);
128*4882a593Smuzhiyun 		clrbits_le32(&denali_phy[214], (0x3 << 2) << 8);
129*4882a593Smuzhiyun 		clrbits_le32(&denali_phy[342], (0x3 << 2) << 8);
130*4882a593Smuzhiyun 		clrbits_le32(&denali_phy[470], (0x3 << 2) << 8);
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 		/* phy_adrctl_sw_master_mode PHY_547/675/803 4bits offset_16 */
133*4882a593Smuzhiyun 		clrbits_le32(&denali_phy[547], (0x3 << 2) << 16);
134*4882a593Smuzhiyun 		clrbits_le32(&denali_phy[675], (0x3 << 2) << 16);
135*4882a593Smuzhiyun 		clrbits_le32(&denali_phy[803], (0x3 << 2) << 16);
136*4882a593Smuzhiyun 	}
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun 
set_memory_map(const struct chan_info * chan,u32 channel,const struct rk3399_sdram_params * sdram_params)139*4882a593Smuzhiyun static void set_memory_map(const struct chan_info *chan, u32 channel,
140*4882a593Smuzhiyun 			   const struct rk3399_sdram_params *sdram_params)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	const struct rk3399_sdram_channel *sdram_ch =
143*4882a593Smuzhiyun 		&sdram_params->ch[channel];
144*4882a593Smuzhiyun 	u32 *denali_ctl = chan->pctl->denali_ctl;
145*4882a593Smuzhiyun 	u32 *denali_pi = chan->pi->denali_pi;
146*4882a593Smuzhiyun 	u32 cs_map;
147*4882a593Smuzhiyun 	u32 reduc;
148*4882a593Smuzhiyun 	u32 row;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	/* Get row number from ddrconfig setting */
151*4882a593Smuzhiyun 	if (sdram_ch->cap_info.ddrconfig < 2 ||
152*4882a593Smuzhiyun 	    sdram_ch->cap_info.ddrconfig == 4)
153*4882a593Smuzhiyun 		row = 16;
154*4882a593Smuzhiyun 	else if (sdram_ch->cap_info.ddrconfig == 3 ||
155*4882a593Smuzhiyun 		 sdram_ch->cap_info.ddrconfig == 5)
156*4882a593Smuzhiyun 		row = 14;
157*4882a593Smuzhiyun 	else
158*4882a593Smuzhiyun 		row = 15;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	cs_map = (sdram_ch->cap_info.rank > 1) ? 3 : 1;
161*4882a593Smuzhiyun 	reduc = (sdram_ch->cap_info.bw == 2) ? 0 : 1;
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	/* Set the dram configuration to ctrl */
164*4882a593Smuzhiyun 	clrsetbits_le32(&denali_ctl[191], 0xF, (12 - sdram_ch->cap_info.col));
165*4882a593Smuzhiyun 	clrsetbits_le32(&denali_ctl[190], (0x3 << 16) | (0x7 << 24),
166*4882a593Smuzhiyun 			((3 - sdram_ch->cap_info.bk) << 16) |
167*4882a593Smuzhiyun 			((16 - row) << 24));
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	clrsetbits_le32(&denali_ctl[196], 0x3 | (1 << 16),
170*4882a593Smuzhiyun 			cs_map | (reduc << 16));
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	/* PI_199 PI_COL_DIFF:RW:0:4 */
173*4882a593Smuzhiyun 	clrsetbits_le32(&denali_pi[199], 0xF, (12 - sdram_ch->cap_info.col));
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	/* PI_155 PI_ROW_DIFF:RW:24:3 PI_BANK_DIFF:RW:16:2 */
176*4882a593Smuzhiyun 	clrsetbits_le32(&denali_pi[155], (0x3 << 16) | (0x7 << 24),
177*4882a593Smuzhiyun 			((3 - sdram_ch->cap_info.bk) << 16) |
178*4882a593Smuzhiyun 			((16 - row) << 24));
179*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4) {
180*4882a593Smuzhiyun 		if (cs_map == 1)
181*4882a593Smuzhiyun 			cs_map = 0x5;
182*4882a593Smuzhiyun 		else if (cs_map == 2)
183*4882a593Smuzhiyun 			cs_map = 0xa;
184*4882a593Smuzhiyun 		else
185*4882a593Smuzhiyun 			cs_map = 0xF;
186*4882a593Smuzhiyun 	}
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	/* PI_41 PI_CS_MAP:RW:24:4 */
189*4882a593Smuzhiyun 	clrsetbits_le32(&denali_pi[41], 0xf << 24, cs_map << 24);
190*4882a593Smuzhiyun 	if (sdram_ch->cap_info.rank == 1 &&
191*4882a593Smuzhiyun 	    sdram_params->base.dramtype == DDR3)
192*4882a593Smuzhiyun 		writel(0x2EC7FFFF, &denali_pi[34]);
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun 
phy_io_config(const struct chan_info * chan,struct rk3399_sdram_params * sdram_params,u32 rd_vref,u32 b_reg,u32 channel)195*4882a593Smuzhiyun static void phy_io_config(const struct chan_info *chan,
196*4882a593Smuzhiyun 			  struct rk3399_sdram_params *sdram_params, u32 rd_vref,
197*4882a593Smuzhiyun 			  u32 b_reg, u32 channel)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun 	u32 *denali_phy;
200*4882a593Smuzhiyun 	u32 *denali_ctl;
201*4882a593Smuzhiyun 	u32 vref_mode_dq = 0, vref_value_dq = 0;
202*4882a593Smuzhiyun 	u32 vref_mode_ac = 0, vref_value_ac = 0;
203*4882a593Smuzhiyun 	u32 mode_sel = 0;
204*4882a593Smuzhiyun 	u32 boostp, boostn;
205*4882a593Smuzhiyun 	u32 slewp, slewn;
206*4882a593Smuzhiyun 	u32 speed;
207*4882a593Smuzhiyun 	u32 rx_cm_input;
208*4882a593Smuzhiyun 	u32 reg_value;
209*4882a593Smuzhiyun 	u32 ds_value, odt_value;
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	if (b_reg) {
212*4882a593Smuzhiyun 		denali_phy = chan->publ->denali_phy;
213*4882a593Smuzhiyun 		denali_ctl = chan->pctl->denali_ctl;
214*4882a593Smuzhiyun 	} else {
215*4882a593Smuzhiyun 		denali_phy = sdram_params->phy_regs.denali_phy;
216*4882a593Smuzhiyun 		denali_ctl = sdram_params->pctl_regs.denali_ctl;
217*4882a593Smuzhiyun 	}
218*4882a593Smuzhiyun 	rd_vref *= 1000;
219*4882a593Smuzhiyun 	/* vref setting & mode setting */
220*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4) {
221*4882a593Smuzhiyun 		if (rd_vref < 36700) {
222*4882a593Smuzhiyun 			/* MODE_LV[2:0] = LPDDR4 (Range 2)*/
223*4882a593Smuzhiyun 			vref_mode_dq = 0x7;
224*4882a593Smuzhiyun 			/* MODE[2:0]= LPDDR4 Range 2(0.4*VDDQ) */
225*4882a593Smuzhiyun 			mode_sel = 0x5;
226*4882a593Smuzhiyun 			vref_value_dq = (rd_vref - 3300) / 521;
227*4882a593Smuzhiyun 		} else {
228*4882a593Smuzhiyun 			/* MODE_LV[2:0] = LPDDR4 (Range 1)*/
229*4882a593Smuzhiyun 			vref_mode_dq = 0x6;
230*4882a593Smuzhiyun 			/* MODE[2:0]= LPDDR4 Range 1(0.33*VDDQ) */
231*4882a593Smuzhiyun 			mode_sel = 0x4;
232*4882a593Smuzhiyun 			vref_value_dq = (rd_vref - 15300) / 521;
233*4882a593Smuzhiyun 		}
234*4882a593Smuzhiyun 		vref_mode_ac = 0x6;
235*4882a593Smuzhiyun 		/* VDDQ/3/2=16.8% */
236*4882a593Smuzhiyun 		vref_value_ac = 0x3;
237*4882a593Smuzhiyun 	} else if (sdram_params->base.dramtype == LPDDR3) {
238*4882a593Smuzhiyun 		/* LPDDR3 */
239*4882a593Smuzhiyun 		if (sdram_params->base.odt == 1) {
240*4882a593Smuzhiyun 			vref_mode_dq = 0x5;  /*LPDDR3 ODT*/
241*4882a593Smuzhiyun 			ds_value = readl(&denali_ctl[138]) & 0xf;
242*4882a593Smuzhiyun 			odt_value = (readl(&denali_phy[6]) >> 4) & 0xf;
243*4882a593Smuzhiyun 			if (ds_value == 0x3) {	/* 48ohm */
244*4882a593Smuzhiyun 				switch (odt_value) {
245*4882a593Smuzhiyun 				case PHY_DRV_ODT_240:
246*4882a593Smuzhiyun 					vref_value_dq = 0x1B;
247*4882a593Smuzhiyun 					break;
248*4882a593Smuzhiyun 				case PHY_DRV_ODT_120:
249*4882a593Smuzhiyun 					vref_value_dq = 0x26;
250*4882a593Smuzhiyun 					break;
251*4882a593Smuzhiyun 				case PHY_DRV_ODT_60:
252*4882a593Smuzhiyun 					vref_value_dq = 0x36;
253*4882a593Smuzhiyun 					break;
254*4882a593Smuzhiyun 				}
255*4882a593Smuzhiyun 			} else if (ds_value == 0x2) {  /* 40ohm */
256*4882a593Smuzhiyun 				switch (odt_value) {
257*4882a593Smuzhiyun 				case PHY_DRV_ODT_240:
258*4882a593Smuzhiyun 					vref_value_dq = 0x19;
259*4882a593Smuzhiyun 					break;
260*4882a593Smuzhiyun 				case PHY_DRV_ODT_120:
261*4882a593Smuzhiyun 					vref_value_dq = 0x23;
262*4882a593Smuzhiyun 					break;
263*4882a593Smuzhiyun 				case PHY_DRV_ODT_60:
264*4882a593Smuzhiyun 					vref_value_dq = 0x31;
265*4882a593Smuzhiyun 					break;
266*4882a593Smuzhiyun 				}
267*4882a593Smuzhiyun 			} else if (ds_value == 0x1) {  /*34.3ohm*/
268*4882a593Smuzhiyun 				switch (odt_value) {
269*4882a593Smuzhiyun 				case PHY_DRV_ODT_240:
270*4882a593Smuzhiyun 					vref_value_dq = 0x17;
271*4882a593Smuzhiyun 					break;
272*4882a593Smuzhiyun 				case PHY_DRV_ODT_120:
273*4882a593Smuzhiyun 					vref_value_dq = 0x20;
274*4882a593Smuzhiyun 					break;
275*4882a593Smuzhiyun 				case PHY_DRV_ODT_60:
276*4882a593Smuzhiyun 					vref_value_dq = 0x2e;
277*4882a593Smuzhiyun 					break;
278*4882a593Smuzhiyun 				}
279*4882a593Smuzhiyun 			}
280*4882a593Smuzhiyun 		} else {
281*4882a593Smuzhiyun 			vref_mode_dq = 0x2;
282*4882a593Smuzhiyun 			vref_value_dq = 0x1f;
283*4882a593Smuzhiyun 		}
284*4882a593Smuzhiyun 		vref_mode_ac = 0x2;
285*4882a593Smuzhiyun 		vref_value_ac = 0x1f;
286*4882a593Smuzhiyun 		mode_sel = 0x0;
287*4882a593Smuzhiyun 	} else if (sdram_params->base.dramtype == DDR3) {
288*4882a593Smuzhiyun 		vref_mode_dq = 0x1;
289*4882a593Smuzhiyun 		vref_value_dq = 0x1f;
290*4882a593Smuzhiyun 		vref_mode_ac = 0x1;
291*4882a593Smuzhiyun 		vref_value_ac = 0x1f;
292*4882a593Smuzhiyun 		mode_sel = 0x1;
293*4882a593Smuzhiyun 	}
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 	reg_value = (vref_mode_dq << 9) | (0x1 << 8) | vref_value_dq;
296*4882a593Smuzhiyun 	/* PHY_913 PHY_PAD_VREF_CTRL_DQ_0 12bits offset_8 */
297*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[913], 0xfff << 8, reg_value << 8);
298*4882a593Smuzhiyun 	/* PHY_914 PHY_PAD_VREF_CTRL_DQ_1 12bits offset_0 */
299*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[914], 0xfff, reg_value);
300*4882a593Smuzhiyun 	/* PHY_914 PHY_PAD_VREF_CTRL_DQ_2 12bits offset_16 */
301*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[914], 0xfff << 16, reg_value << 16);
302*4882a593Smuzhiyun 	/* PHY_915 PHY_PAD_VREF_CTRL_DQ_3 12bits offset_0 */
303*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[915], 0xfff, reg_value);
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	reg_value = (vref_mode_ac << 9) | (0x1 << 8) | vref_value_ac;
306*4882a593Smuzhiyun 	/* PHY_915 PHY_PAD_VREF_CTRL_AC 12bits offset_16 */
307*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[915], 0xfff << 16, reg_value << 16);
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	/* PHY_924 PHY_PAD_FDBK_DRIVE */
310*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[924], 0x7 << 15, mode_sel << 15);
311*4882a593Smuzhiyun 	/* PHY_926 PHY_PAD_DATA_DRIVE */
312*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[926], 0x7 << 6, mode_sel << 6);
313*4882a593Smuzhiyun 	/* PHY_927 PHY_PAD_DQS_DRIVE */
314*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[927], 0x7 << 6, mode_sel << 6);
315*4882a593Smuzhiyun 	/* PHY_928 PHY_PAD_ADDR_DRIVE */
316*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[928], 0x7 << 14, mode_sel << 14);
317*4882a593Smuzhiyun 	/* PHY_929 PHY_PAD_CLK_DRIVE */
318*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[929], 0x7 << 14, mode_sel << 14);
319*4882a593Smuzhiyun 	/* PHY_935 PHY_PAD_CKE_DRIVE */
320*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[935], 0x7 << 14, mode_sel << 14);
321*4882a593Smuzhiyun 	/* PHY_937 PHY_PAD_RST_DRIVE */
322*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[937], 0x7 << 14, mode_sel << 14);
323*4882a593Smuzhiyun 	/* PHY_939 PHY_PAD_CS_DRIVE */
324*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[939], 0x7 << 14, mode_sel << 14);
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	/* BOOSTP_EN & BOOSTn_EN */
327*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4) {
328*4882a593Smuzhiyun 		boostp = 0x1;
329*4882a593Smuzhiyun 		boostn = 0x1;
330*4882a593Smuzhiyun 		reg_value = ((boostp << 4) | boostn);
331*4882a593Smuzhiyun 		/* PHY_925 PHY_PAD_FDBK_DRIVE2 */
332*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[925], 0xff << 8, reg_value << 8);
333*4882a593Smuzhiyun 		/* PHY_926 PHY_PAD_DATA_DRIVE */
334*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[926], 0xff << 12, reg_value << 12);
335*4882a593Smuzhiyun 		/* PHY_927 PHY_PAD_DQS_DRIVE */
336*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[927], 0xff << 14, reg_value << 14);
337*4882a593Smuzhiyun 		/* PHY_928 PHY_PAD_ADDR_DRIVE */
338*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[928], 0xff << 20, reg_value << 20);
339*4882a593Smuzhiyun 		/* PHY_929 PHY_PAD_CLK_DRIVE */
340*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[929], 0xff << 22, reg_value << 22);
341*4882a593Smuzhiyun 		/* PHY_935 PHY_PAD_CKE_DRIVE */
342*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[935], 0xff << 20, reg_value << 20);
343*4882a593Smuzhiyun 		/* PHY_937 PHY_PAD_RST_DRIVE */
344*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[937], 0xff << 20, reg_value << 20);
345*4882a593Smuzhiyun 		/* PHY_939 PHY_PAD_CS_DRIVE */
346*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[939], 0xff << 20, reg_value << 20);
347*4882a593Smuzhiyun 	}
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	/* SLEWP & SLEWN */
350*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4) {
351*4882a593Smuzhiyun 		slewp = 0x1;
352*4882a593Smuzhiyun 		slewn = 0x1;
353*4882a593Smuzhiyun 		reg_value = ((slewp << 3) | slewn);
354*4882a593Smuzhiyun 		/* PHY_924 PHY_PAD_FDBK_DRIVE */
355*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[924], 0x3f << 8, reg_value << 8);
356*4882a593Smuzhiyun 		/* PHY_926 PHY_PAD_DATA_DRIVE */
357*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[926], 0x3f, reg_value);
358*4882a593Smuzhiyun 		/* PHY_927 PHY_PAD_DQS_DRIVE */
359*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[927], 0x3f, reg_value);
360*4882a593Smuzhiyun 		/* PHY_928 PHY_PAD_ADDR_DRIVE */
361*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[928], 0x3f << 8, reg_value << 8);
362*4882a593Smuzhiyun 		/* PHY_929 PHY_PAD_CLK_DRIVE */
363*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[929], 0x3f << 8, reg_value << 8);
364*4882a593Smuzhiyun 		/* PHY_935 PHY_PAD_CKE_DRIVE */
365*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[935], 0x3f << 8, reg_value << 8);
366*4882a593Smuzhiyun 		/* PHY_937 PHY_PAD_RST_DRIVE */
367*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[937], 0x3f << 8, reg_value << 8);
368*4882a593Smuzhiyun 		/* PHY_939 PHY_PAD_CS_DRIVE */
369*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[939], 0x3f << 8, reg_value << 8);
370*4882a593Smuzhiyun 	}
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	/* speed setting */
373*4882a593Smuzhiyun 	if (sdram_params->base.ddr_freq < 400 * MHz)
374*4882a593Smuzhiyun 		speed = 0x0;
375*4882a593Smuzhiyun 	else if (sdram_params->base.ddr_freq < 800 * MHz)
376*4882a593Smuzhiyun 		speed = 0x1;
377*4882a593Smuzhiyun 	else if (sdram_params->base.ddr_freq < 1200 * MHz)
378*4882a593Smuzhiyun 		speed = 0x2;
379*4882a593Smuzhiyun 	speed = 0x2;
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun 	/* PHY_924 PHY_PAD_FDBK_DRIVE */
382*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[924], 0x3 << 21, speed << 21);
383*4882a593Smuzhiyun 	/* PHY_926 PHY_PAD_DATA_DRIVE */
384*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[926], 0x3 << 9, speed << 9);
385*4882a593Smuzhiyun 	/* PHY_927 PHY_PAD_DQS_DRIVE */
386*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[927], 0x3 << 9, speed << 9);
387*4882a593Smuzhiyun 	/* PHY_928 PHY_PAD_ADDR_DRIVE */
388*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[928], 0x3 << 17, speed << 17);
389*4882a593Smuzhiyun 	/* PHY_929 PHY_PAD_CLK_DRIVE */
390*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[929], 0x3 << 17, speed << 17);
391*4882a593Smuzhiyun 	/* PHY_935 PHY_PAD_CKE_DRIVE */
392*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[935], 0x3 << 17, speed << 17);
393*4882a593Smuzhiyun 	/* PHY_937 PHY_PAD_RST_DRIVE */
394*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[937], 0x3 << 17, speed << 17);
395*4882a593Smuzhiyun 	/* PHY_939 PHY_PAD_CS_DRIVE */
396*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[939], 0x3 << 17, speed << 17);
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	/* RX_CM_INPUT */
399*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4) {
400*4882a593Smuzhiyun 		rx_cm_input = 0x1;
401*4882a593Smuzhiyun 		/* PHY_924 PHY_PAD_FDBK_DRIVE */
402*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[924], 0x1 << 14, rx_cm_input << 14);
403*4882a593Smuzhiyun 		/* PHY_926 PHY_PAD_DATA_DRIVE */
404*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[926], 0x1 << 11, rx_cm_input << 11);
405*4882a593Smuzhiyun 		/* PHY_927 PHY_PAD_DQS_DRIVE */
406*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[927], 0x1 << 13, rx_cm_input << 13);
407*4882a593Smuzhiyun 		/* PHY_928 PHY_PAD_ADDR_DRIVE */
408*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[928], 0x1 << 19, rx_cm_input << 19);
409*4882a593Smuzhiyun 		/* PHY_929 PHY_PAD_CLK_DRIVE */
410*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[929], 0x1 << 21, rx_cm_input << 21);
411*4882a593Smuzhiyun 		/* PHY_935 PHY_PAD_CKE_DRIVE */
412*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[935], 0x1 << 19, rx_cm_input << 19);
413*4882a593Smuzhiyun 		/* PHY_937 PHY_PAD_RST_DRIVE */
414*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[937], 0x1 << 19, rx_cm_input << 19);
415*4882a593Smuzhiyun 		/* PHY_939 PHY_PAD_CS_DRIVE */
416*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[939], 0x1 << 19, rx_cm_input << 19);
417*4882a593Smuzhiyun 	}
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun struct io_setting {
421*4882a593Smuzhiyun 	u32 mhz;
422*4882a593Smuzhiyun 	u32 mr5;
423*4882a593Smuzhiyun 	/* dram side */
424*4882a593Smuzhiyun 	u32 dq_odt;
425*4882a593Smuzhiyun 	u32 ca_odt;
426*4882a593Smuzhiyun 	u32 pdds;
427*4882a593Smuzhiyun 	u32 dq_vref;
428*4882a593Smuzhiyun 	u32 ca_vref;
429*4882a593Smuzhiyun 	/* phy side */
430*4882a593Smuzhiyun 	u32 rd_odt;
431*4882a593Smuzhiyun 	u32 wr_dq_drv;
432*4882a593Smuzhiyun 	u32 wr_ca_drv;
433*4882a593Smuzhiyun 	u32 wr_ckcs_drv;
434*4882a593Smuzhiyun 	u32 rd_odt_en;
435*4882a593Smuzhiyun 	u32 rd_vref;
436*4882a593Smuzhiyun };
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun struct io_setting lp4_io_set[] = {
439*4882a593Smuzhiyun 	{
440*4882a593Smuzhiyun 		50 * MHz,
441*4882a593Smuzhiyun 		0,
442*4882a593Smuzhiyun 		/* dram side */
443*4882a593Smuzhiyun 		0,	/* dq_odt; */
444*4882a593Smuzhiyun 		0,	/* ca_odt; */
445*4882a593Smuzhiyun 		6,	/* pdds; */
446*4882a593Smuzhiyun 		0x72,	/* dq_vref; */
447*4882a593Smuzhiyun 		0x72,	/* ca_vref; */
448*4882a593Smuzhiyun 		/* phy side */
449*4882a593Smuzhiyun 		PHY_DRV_ODT_HI_Z,	/* rd_odt; */
450*4882a593Smuzhiyun 		PHY_DRV_ODT_40,	/* wr_dq_drv; */
451*4882a593Smuzhiyun 		PHY_DRV_ODT_40,	/* wr_ca_drv; */
452*4882a593Smuzhiyun 		PHY_DRV_ODT_40,	/* wr_ckcs_drv; */
453*4882a593Smuzhiyun 		0,	/* rd_odt_en;*/
454*4882a593Smuzhiyun 		41,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
455*4882a593Smuzhiyun 	},
456*4882a593Smuzhiyun 	{
457*4882a593Smuzhiyun 		400 * MHz,
458*4882a593Smuzhiyun 		0,
459*4882a593Smuzhiyun 		/* dram side */
460*4882a593Smuzhiyun 		0,	/* dq_odt; */
461*4882a593Smuzhiyun 		0,	/* ca_odt; */
462*4882a593Smuzhiyun 		6,	/* pdds; */
463*4882a593Smuzhiyun 		0x72,	/* dq_vref; */
464*4882a593Smuzhiyun 		0x72,	/* ca_vref; */
465*4882a593Smuzhiyun 		/* phy side */
466*4882a593Smuzhiyun 		PHY_DRV_ODT_HI_Z,	/* rd_odt; */
467*4882a593Smuzhiyun 		PHY_DRV_ODT_40,	/* wr_dq_drv; */
468*4882a593Smuzhiyun 		PHY_DRV_ODT_40,	/* wr_ca_drv; */
469*4882a593Smuzhiyun 		PHY_DRV_ODT_40,	/* wr_ckcs_drv; */
470*4882a593Smuzhiyun 		0,	/* rd_odt_en; */
471*4882a593Smuzhiyun 		/* shmoo result, read signal 41% is the best */
472*4882a593Smuzhiyun 		41,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
473*4882a593Smuzhiyun 	},
474*4882a593Smuzhiyun 	{
475*4882a593Smuzhiyun 		800 * MHz,
476*4882a593Smuzhiyun 		0,
477*4882a593Smuzhiyun 		/* dram side */
478*4882a593Smuzhiyun 		0,	/* dq_odt; */
479*4882a593Smuzhiyun 		0,	/* ca_odt; */
480*4882a593Smuzhiyun 		1,	/* pdds; */
481*4882a593Smuzhiyun 		0x72,	/* dq_vref; */
482*4882a593Smuzhiyun 		0x72,	/* ca_vref; */
483*4882a593Smuzhiyun 		/* phy side */
484*4882a593Smuzhiyun 		PHY_DRV_ODT_40,	/* rd_odt; */
485*4882a593Smuzhiyun 		PHY_DRV_ODT_40,	/* wr_dq_drv; */
486*4882a593Smuzhiyun 		PHY_DRV_ODT_40,	/* wr_ca_drv; */
487*4882a593Smuzhiyun 		PHY_DRV_ODT_40,	/* wr_ckcs_drv; */
488*4882a593Smuzhiyun 		1,	/* rd_odt_en; */
489*4882a593Smuzhiyun 		17,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
490*4882a593Smuzhiyun 	},
491*4882a593Smuzhiyun 	{
492*4882a593Smuzhiyun 		1066 * MHz,
493*4882a593Smuzhiyun 		0,
494*4882a593Smuzhiyun 		/* dram side */
495*4882a593Smuzhiyun 		6,	/* dq_odt; */
496*4882a593Smuzhiyun 		0,	/* ca_odt; */
497*4882a593Smuzhiyun 		1,	/* pdds; */
498*4882a593Smuzhiyun 		0x10,	/* dq_vref; */
499*4882a593Smuzhiyun 		0x72,	/* ca_vref; */
500*4882a593Smuzhiyun 		/* phy side */
501*4882a593Smuzhiyun 		PHY_DRV_ODT_40,	/* rd_odt; */
502*4882a593Smuzhiyun 		PHY_DRV_ODT_60,	/* wr_dq_drv; */
503*4882a593Smuzhiyun 		PHY_DRV_ODT_40,	/* wr_ca_drv; */
504*4882a593Smuzhiyun 		PHY_DRV_ODT_40,	/* wr_ckcs_drv; */
505*4882a593Smuzhiyun 		1,	/* rd_odt_en; */
506*4882a593Smuzhiyun 		17,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
507*4882a593Smuzhiyun 	},
508*4882a593Smuzhiyun };
509*4882a593Smuzhiyun 
get_io_set(struct rk3399_sdram_params * sdram_params,u32 mr5)510*4882a593Smuzhiyun static struct io_setting *get_io_set(struct rk3399_sdram_params *sdram_params,
511*4882a593Smuzhiyun 				     u32 mr5)
512*4882a593Smuzhiyun {
513*4882a593Smuzhiyun 	struct io_setting *io = NULL;
514*4882a593Smuzhiyun 	u32 n;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	for (n = 0; n < ARRAY_SIZE(lp4_io_set); n++) {
517*4882a593Smuzhiyun 		io = &lp4_io_set[n];
518*4882a593Smuzhiyun 		if (io->mr5 != 0) {
519*4882a593Smuzhiyun 			if (io->mhz >= sdram_params->base.ddr_freq &&
520*4882a593Smuzhiyun 			    io->mr5 == mr5)
521*4882a593Smuzhiyun 				break;
522*4882a593Smuzhiyun 		} else {
523*4882a593Smuzhiyun 			if (io->mhz >= sdram_params->base.ddr_freq)
524*4882a593Smuzhiyun 				break;
525*4882a593Smuzhiyun 		}
526*4882a593Smuzhiyun 	}
527*4882a593Smuzhiyun 	return io;
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun /*
531*4882a593Smuzhiyun  * b_reg: indicate whether set phy register
532*4882a593Smuzhiyun  * or just set sdram_params.
533*4882a593Smuzhiyun  * if b_reg = 0, channel, mr5 are not care
534*4882a593Smuzhiyun  */
set_ds_odt(const struct chan_info * chan,struct rk3399_sdram_params * sdram_params,u32 b_reg,u32 channel,u32 mr5)535*4882a593Smuzhiyun static void set_ds_odt(const struct chan_info *chan,
536*4882a593Smuzhiyun 		       struct rk3399_sdram_params *sdram_params, u32 b_reg,
537*4882a593Smuzhiyun 		       u32 channel, u32 mr5)
538*4882a593Smuzhiyun {
539*4882a593Smuzhiyun 	u32 *denali_phy;
540*4882a593Smuzhiyun 	u32 *denali_ctl;
541*4882a593Smuzhiyun 	u32 tsel_idle_en, tsel_wr_en, tsel_rd_en;
542*4882a593Smuzhiyun 	u32 tsel_idle_select_p, tsel_rd_select_p;
543*4882a593Smuzhiyun 	u32 tsel_idle_select_n, tsel_rd_select_n;
544*4882a593Smuzhiyun 	u32 tsel_wr_select_dq_p, tsel_wr_select_ca_p;
545*4882a593Smuzhiyun 	u32 tsel_wr_select_dq_n, tsel_wr_select_ca_n;
546*4882a593Smuzhiyun 	u32 soc_odt = 0;
547*4882a593Smuzhiyun 	u32 tsel_ckcs_select_p, tsel_ckcs_select_n;
548*4882a593Smuzhiyun 	u32 reg_value;
549*4882a593Smuzhiyun 	struct io_setting *io = NULL;
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	if (b_reg) {
552*4882a593Smuzhiyun 		denali_phy = chan->publ->denali_phy;
553*4882a593Smuzhiyun 		denali_ctl = chan->pctl->denali_ctl;
554*4882a593Smuzhiyun 	} else {
555*4882a593Smuzhiyun 		denali_phy = sdram_params->phy_regs.denali_phy;
556*4882a593Smuzhiyun 		denali_ctl = sdram_params->pctl_regs.denali_ctl;
557*4882a593Smuzhiyun 	}
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4) {
560*4882a593Smuzhiyun 		io = get_io_set(sdram_params, mr5);
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun 		tsel_rd_select_p = PHY_DRV_ODT_HI_Z;
563*4882a593Smuzhiyun 		tsel_rd_select_n = io->rd_odt;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 		tsel_idle_select_p = PHY_DRV_ODT_HI_Z;
566*4882a593Smuzhiyun 		tsel_idle_select_n = PHY_DRV_ODT_HI_Z;
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 		tsel_wr_select_dq_p = io->wr_dq_drv;
569*4882a593Smuzhiyun 		tsel_wr_select_dq_n = PHY_DRV_ODT_34_3;
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun 		tsel_wr_select_ca_p = io->wr_ca_drv;
572*4882a593Smuzhiyun 		tsel_wr_select_ca_n = PHY_DRV_ODT_34_3;
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 		tsel_ckcs_select_p = io->wr_ckcs_drv;
575*4882a593Smuzhiyun 		tsel_ckcs_select_n = PHY_DRV_ODT_34_3;
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 		switch (tsel_rd_select_n) {
578*4882a593Smuzhiyun 		case PHY_DRV_ODT_240:
579*4882a593Smuzhiyun 			soc_odt = 1;
580*4882a593Smuzhiyun 			break;
581*4882a593Smuzhiyun 		case PHY_DRV_ODT_120:
582*4882a593Smuzhiyun 			soc_odt = 2;
583*4882a593Smuzhiyun 			break;
584*4882a593Smuzhiyun 		case PHY_DRV_ODT_80:
585*4882a593Smuzhiyun 			soc_odt = 3;
586*4882a593Smuzhiyun 			break;
587*4882a593Smuzhiyun 		case PHY_DRV_ODT_60:
588*4882a593Smuzhiyun 			soc_odt = 4;
589*4882a593Smuzhiyun 			break;
590*4882a593Smuzhiyun 		case PHY_DRV_ODT_48:
591*4882a593Smuzhiyun 			soc_odt = 5;
592*4882a593Smuzhiyun 			break;
593*4882a593Smuzhiyun 		case PHY_DRV_ODT_40:
594*4882a593Smuzhiyun 			soc_odt = 6;
595*4882a593Smuzhiyun 			break;
596*4882a593Smuzhiyun 		case PHY_DRV_ODT_34_3:
597*4882a593Smuzhiyun 			soc_odt = 6;
598*4882a593Smuzhiyun 			printf("LPDDR4 MR22 Soc ODT not support\n");
599*4882a593Smuzhiyun 			break;
600*4882a593Smuzhiyun 		case PHY_DRV_ODT_HI_Z:
601*4882a593Smuzhiyun 		default:
602*4882a593Smuzhiyun 			soc_odt = 0;
603*4882a593Smuzhiyun 			break;
604*4882a593Smuzhiyun 		}
605*4882a593Smuzhiyun 	} else if (sdram_params->base.dramtype == LPDDR3) {
606*4882a593Smuzhiyun 		tsel_rd_select_p = PHY_DRV_ODT_240;
607*4882a593Smuzhiyun 		tsel_rd_select_n = PHY_DRV_ODT_HI_Z;
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 		tsel_idle_select_p = PHY_DRV_ODT_240;
610*4882a593Smuzhiyun 		tsel_idle_select_n = PHY_DRV_ODT_HI_Z;
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 		tsel_wr_select_dq_p = PHY_DRV_ODT_34_3;
613*4882a593Smuzhiyun 		tsel_wr_select_dq_n = PHY_DRV_ODT_34_3;
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun 		tsel_wr_select_ca_p = PHY_DRV_ODT_34_3;
616*4882a593Smuzhiyun 		tsel_wr_select_ca_n = PHY_DRV_ODT_34_3;
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun 		tsel_ckcs_select_p = PHY_DRV_ODT_34_3;
619*4882a593Smuzhiyun 		tsel_ckcs_select_n = PHY_DRV_ODT_34_3;
620*4882a593Smuzhiyun 	} else {
621*4882a593Smuzhiyun 		tsel_rd_select_p = PHY_DRV_ODT_240;
622*4882a593Smuzhiyun 		tsel_rd_select_n = PHY_DRV_ODT_240;
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun 		tsel_idle_select_p = PHY_DRV_ODT_240;
625*4882a593Smuzhiyun 		tsel_idle_select_n = PHY_DRV_ODT_240;
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun 		tsel_wr_select_dq_p = PHY_DRV_ODT_34_3;
628*4882a593Smuzhiyun 		tsel_wr_select_dq_n = PHY_DRV_ODT_34_3;
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun 		tsel_wr_select_ca_p = PHY_DRV_ODT_34_3;
631*4882a593Smuzhiyun 		tsel_wr_select_ca_n = PHY_DRV_ODT_34_3;
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 		tsel_ckcs_select_p = PHY_DRV_ODT_34_3;
634*4882a593Smuzhiyun 		tsel_ckcs_select_n = PHY_DRV_ODT_34_3;
635*4882a593Smuzhiyun 	}
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4) {
638*4882a593Smuzhiyun 		if (sdram_params->base.odt == 1) {
639*4882a593Smuzhiyun 			tsel_rd_en = io->rd_odt_en;
640*4882a593Smuzhiyun 			tsel_idle_en = 0;
641*4882a593Smuzhiyun 		} else {
642*4882a593Smuzhiyun 			tsel_rd_en = 0;
643*4882a593Smuzhiyun 			tsel_idle_en = 0;
644*4882a593Smuzhiyun 		}
645*4882a593Smuzhiyun 	} else {
646*4882a593Smuzhiyun 		tsel_rd_en = sdram_params->base.odt;
647*4882a593Smuzhiyun 		tsel_idle_en = 0;
648*4882a593Smuzhiyun 	}
649*4882a593Smuzhiyun 	tsel_wr_en = 0;
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun #define CS0_MR22_VAL (0)
652*4882a593Smuzhiyun #define CS1_MR22_VAL (3)
653*4882a593Smuzhiyun 	/* F0_0 */
654*4882a593Smuzhiyun 	clrsetbits_le32(&denali_ctl[145], 0xFF << 16,
655*4882a593Smuzhiyun 			(soc_odt | (CS0_MR22_VAL << 3)) << 16);
656*4882a593Smuzhiyun 	/* F2_0, F1_0 */
657*4882a593Smuzhiyun 	clrsetbits_le32(&denali_ctl[146], 0xFF00FF,
658*4882a593Smuzhiyun 			((soc_odt | (CS0_MR22_VAL << 3)) << 16) |
659*4882a593Smuzhiyun 			(soc_odt | (CS0_MR22_VAL << 3)));
660*4882a593Smuzhiyun 	/* F0_1 */
661*4882a593Smuzhiyun 	clrsetbits_le32(&denali_ctl[159], 0xFF << 16,
662*4882a593Smuzhiyun 			(soc_odt | (CS1_MR22_VAL << 3)) << 16);
663*4882a593Smuzhiyun 	/* F2_1, F1_1 */
664*4882a593Smuzhiyun 	clrsetbits_le32(&denali_ctl[160], 0xFF00FF,
665*4882a593Smuzhiyun 			((soc_odt | (CS1_MR22_VAL << 3)) << 16) |
666*4882a593Smuzhiyun 			(soc_odt | (CS1_MR22_VAL << 3)));
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun 	/*
669*4882a593Smuzhiyun 	 * phy_dq_tsel_select_X 24bits DENALI_PHY_6/134/262/390 offset_0
670*4882a593Smuzhiyun 	 * sets termination values for read/idle cycles and drive strength
671*4882a593Smuzhiyun 	 * for write cycles for DQ/DM
672*4882a593Smuzhiyun 	 */
673*4882a593Smuzhiyun 	reg_value = tsel_rd_select_n | (tsel_rd_select_p << 0x4) |
674*4882a593Smuzhiyun 		(tsel_wr_select_dq_n << 8) | (tsel_wr_select_dq_p << 12) |
675*4882a593Smuzhiyun 		(tsel_idle_select_n << 16) | (tsel_idle_select_p << 20);
676*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[6], 0xffffff, reg_value);
677*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[134], 0xffffff, reg_value);
678*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[262], 0xffffff, reg_value);
679*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[390], 0xffffff, reg_value);
680*4882a593Smuzhiyun 
681*4882a593Smuzhiyun 	/*
682*4882a593Smuzhiyun 	 * phy_dqs_tsel_select_X 24bits DENALI_PHY_7/135/263/391 offset_0
683*4882a593Smuzhiyun 	 * sets termination values for read/idle cycles and drive strength
684*4882a593Smuzhiyun 	 * for write cycles for DQS
685*4882a593Smuzhiyun 	 */
686*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[7], 0xffffff, reg_value);
687*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[135], 0xffffff, reg_value);
688*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[263], 0xffffff, reg_value);
689*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[391], 0xffffff, reg_value);
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 	/* phy_adr_tsel_select_ 8bits DENALI_PHY_544/672/800 offset_0 */
692*4882a593Smuzhiyun 	reg_value = tsel_wr_select_ca_n | (tsel_wr_select_ca_p << 0x4);
693*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4) {
694*4882a593Smuzhiyun 		/* LPDDR4 these register read always return 0, so
695*4882a593Smuzhiyun 		 * can not use clrsetbits_le32(), need to write32
696*4882a593Smuzhiyun 		 */
697*4882a593Smuzhiyun 		writel((0x300 << 8) | reg_value, &denali_phy[544]);
698*4882a593Smuzhiyun 		writel((0x300 << 8) | reg_value, &denali_phy[672]);
699*4882a593Smuzhiyun 		writel((0x300 << 8) | reg_value, &denali_phy[800]);
700*4882a593Smuzhiyun 	} else {
701*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[544], 0xff, reg_value);
702*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[672], 0xff, reg_value);
703*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[800], 0xff, reg_value);
704*4882a593Smuzhiyun 	}
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun 	/* phy_pad_addr_drive 8bits DENALI_PHY_928 offset_0 */
707*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[928], 0xff, reg_value);
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 	/* phy_pad_rst_drive 8bits DENALI_PHY_937 offset_0 */
710*4882a593Smuzhiyun 	if (!b_reg)
711*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[937], 0xff, reg_value);
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun 	/* phy_pad_cke_drive 8bits DENALI_PHY_935 offset_0 */
714*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[935], 0xff, reg_value);
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun 	/* phy_pad_cs_drive 8bits DENALI_PHY_939 offset_0 */
717*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[939], 0xff,
718*4882a593Smuzhiyun 			tsel_ckcs_select_n | (tsel_ckcs_select_p << 0x4));
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun 	/* phy_pad_clk_drive 8bits DENALI_PHY_929 offset_0 */
721*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[929], 0xff,
722*4882a593Smuzhiyun 			tsel_ckcs_select_n | (tsel_ckcs_select_p << 0x4));
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun 	/* phy_pad_fdbk_drive 23bit DENALI_PHY_924/925 */
725*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[924], 0xff,
726*4882a593Smuzhiyun 			tsel_wr_select_ca_n | (tsel_wr_select_ca_p << 4));
727*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[925], 0xff,
728*4882a593Smuzhiyun 			tsel_wr_select_dq_n | (tsel_wr_select_dq_p << 4));
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun 	/* phy_dq_tsel_enable_X 3bits DENALI_PHY_5/133/261/389 offset_16 */
731*4882a593Smuzhiyun 	reg_value = (tsel_rd_en | (tsel_wr_en << 1) | (tsel_idle_en << 2))
732*4882a593Smuzhiyun 		<< 16;
733*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[5], 0x7 << 16, reg_value);
734*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[133], 0x7 << 16, reg_value);
735*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[261], 0x7 << 16, reg_value);
736*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[389], 0x7 << 16, reg_value);
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun 	/* phy_dqs_tsel_enable_X 3bits DENALI_PHY_6/134/262/390 offset_24 */
739*4882a593Smuzhiyun 	reg_value = (tsel_rd_en | (tsel_wr_en << 1) | (tsel_idle_en << 2))
740*4882a593Smuzhiyun 		<< 24;
741*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[6], 0x7 << 24, reg_value);
742*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[134], 0x7 << 24, reg_value);
743*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[262], 0x7 << 24, reg_value);
744*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[390], 0x7 << 24, reg_value);
745*4882a593Smuzhiyun 
746*4882a593Smuzhiyun 	/* phy_adr_tsel_enable_ 1bit DENALI_PHY_518/646/774 offset_8 */
747*4882a593Smuzhiyun 	reg_value = tsel_wr_en << 8;
748*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[518], 0x1 << 8, reg_value);
749*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[646], 0x1 << 8, reg_value);
750*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[774], 0x1 << 8, reg_value);
751*4882a593Smuzhiyun 
752*4882a593Smuzhiyun 	/* phy_pad_addr_term tsel 1bit DENALI_PHY_933 offset_17 */
753*4882a593Smuzhiyun 	reg_value = tsel_wr_en << 17;
754*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[933], 0x1 << 17, reg_value);
755*4882a593Smuzhiyun 	/*
756*4882a593Smuzhiyun 	 * pad_rst/cke/cs/clk_term tsel 1bits
757*4882a593Smuzhiyun 	 * DENALI_PHY_938/936/940/934 offset_17
758*4882a593Smuzhiyun 	 */
759*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[938], 0x1 << 17, reg_value);
760*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[936], 0x1 << 17, reg_value);
761*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[940], 0x1 << 17, reg_value);
762*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[934], 0x1 << 17, reg_value);
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun 	/* phy_pad_fdbk_term 1bit DENALI_PHY_930 offset_17 */
765*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[930], 0x1 << 17, reg_value);
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4)
768*4882a593Smuzhiyun 		phy_io_config(chan, sdram_params, io->rd_vref, b_reg, channel);
769*4882a593Smuzhiyun 	else
770*4882a593Smuzhiyun 		phy_io_config(chan, sdram_params, 0, b_reg, channel);
771*4882a593Smuzhiyun }
772*4882a593Smuzhiyun 
pctl_start(struct dram_info * dram,struct rk3399_sdram_params * sdram_params,u32 channel_mask)773*4882a593Smuzhiyun static void pctl_start(struct dram_info *dram,
774*4882a593Smuzhiyun 		       struct rk3399_sdram_params *sdram_params,
775*4882a593Smuzhiyun 		       u32 channel_mask)
776*4882a593Smuzhiyun {
777*4882a593Smuzhiyun 	const struct chan_info *chan_0 = &dram->chan[0];
778*4882a593Smuzhiyun 	const struct chan_info *chan_1 = &dram->chan[1];
779*4882a593Smuzhiyun 
780*4882a593Smuzhiyun 	u32 *denali_ctl_0 = chan_0->pctl->denali_ctl;
781*4882a593Smuzhiyun 	u32 *denali_phy_0 = chan_0->publ->denali_phy;
782*4882a593Smuzhiyun 	u32 *denali_ctl_1 = chan_1->pctl->denali_ctl;
783*4882a593Smuzhiyun 	u32 *denali_phy_1 = chan_1->publ->denali_phy;
784*4882a593Smuzhiyun 	u32 count, byte, tmp;
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun 	/* PHY_DLL_RST_EN */
787*4882a593Smuzhiyun 	if (channel_mask & 1) {
788*4882a593Smuzhiyun 		writel(0x01000000, &dram->grf->ddrc0_con0);
789*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy_0[957], 0x3 << 24, 0x2 << 24);
790*4882a593Smuzhiyun 	}
791*4882a593Smuzhiyun 
792*4882a593Smuzhiyun 	if (channel_mask & 1) {
793*4882a593Smuzhiyun 		count = 0;
794*4882a593Smuzhiyun 		while (!(readl(&denali_ctl_0[203]) & (1 << 3))) {
795*4882a593Smuzhiyun 			if (count > 1000) {
796*4882a593Smuzhiyun 				printf("channel 0 init err!\n");
797*4882a593Smuzhiyun 				while (1)
798*4882a593Smuzhiyun 					;
799*4882a593Smuzhiyun 			}
800*4882a593Smuzhiyun 			udelay(1);
801*4882a593Smuzhiyun 			count++;
802*4882a593Smuzhiyun 		}
803*4882a593Smuzhiyun 
804*4882a593Smuzhiyun 		writel(0x01000100, &dram->grf->ddrc0_con0);
805*4882a593Smuzhiyun 		for (byte = 0; byte < 4; byte++)	{
806*4882a593Smuzhiyun 			tmp = 0x820;
807*4882a593Smuzhiyun 			writel((tmp << 16) | tmp,
808*4882a593Smuzhiyun 			       &denali_phy_0[53 + (128 * byte)]);
809*4882a593Smuzhiyun 			writel((tmp << 16) | tmp,
810*4882a593Smuzhiyun 			       &denali_phy_0[54 + (128 * byte)]);
811*4882a593Smuzhiyun 			writel((tmp << 16) | tmp,
812*4882a593Smuzhiyun 			       &denali_phy_0[55 + (128 * byte)]);
813*4882a593Smuzhiyun 			writel((tmp << 16) | tmp,
814*4882a593Smuzhiyun 			       &denali_phy_0[56 + (128 * byte)]);
815*4882a593Smuzhiyun 			writel((tmp << 16) | tmp,
816*4882a593Smuzhiyun 			       &denali_phy_0[57 + (128 * byte)]);
817*4882a593Smuzhiyun 			clrsetbits_le32(&denali_phy_0[58 + (128 * byte)],
818*4882a593Smuzhiyun 					0xffff, tmp);
819*4882a593Smuzhiyun 		}
820*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl_0[68], PWRUP_SREFRESH_EXIT,
821*4882a593Smuzhiyun 				g_pwrup_srefresh_exit[0]);
822*4882a593Smuzhiyun 	}
823*4882a593Smuzhiyun 
824*4882a593Smuzhiyun 	if (channel_mask & 2) {
825*4882a593Smuzhiyun 		writel(0x01000000, &dram->grf->ddrc1_con0);
826*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy_1[957], 0x3 << 24, 0x2 << 24);
827*4882a593Smuzhiyun 	}
828*4882a593Smuzhiyun 	if (channel_mask & 2) {
829*4882a593Smuzhiyun 		count = 0;
830*4882a593Smuzhiyun 		while (!(readl(&denali_ctl_1[203]) & (1 << 3))) {
831*4882a593Smuzhiyun 			if (count > 1000) {
832*4882a593Smuzhiyun 				printf("channel 1 init err!\n");
833*4882a593Smuzhiyun 				while (1)
834*4882a593Smuzhiyun 					;
835*4882a593Smuzhiyun 			}
836*4882a593Smuzhiyun 			udelay(1);
837*4882a593Smuzhiyun 			count++;
838*4882a593Smuzhiyun 		}
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun 		writel(0x01000100, &dram->grf->ddrc1_con0);
841*4882a593Smuzhiyun 		for (byte = 0; byte < 4; byte++)	{
842*4882a593Smuzhiyun 			tmp = 0x820;
843*4882a593Smuzhiyun 			writel((tmp << 16) | tmp,
844*4882a593Smuzhiyun 			       &denali_phy_1[53 + (128 * byte)]);
845*4882a593Smuzhiyun 			writel((tmp << 16) | tmp,
846*4882a593Smuzhiyun 			       &denali_phy_1[54 + (128 * byte)]);
847*4882a593Smuzhiyun 			writel((tmp << 16) | tmp,
848*4882a593Smuzhiyun 			       &denali_phy_1[55 + (128 * byte)]);
849*4882a593Smuzhiyun 			writel((tmp << 16) | tmp,
850*4882a593Smuzhiyun 			       &denali_phy_1[56 + (128 * byte)]);
851*4882a593Smuzhiyun 			writel((tmp << 16) | tmp,
852*4882a593Smuzhiyun 			       &denali_phy_1[57 + (128 * byte)]);
853*4882a593Smuzhiyun 			clrsetbits_le32(&denali_phy_1[58 + (128 * byte)],
854*4882a593Smuzhiyun 					0xffff, tmp);
855*4882a593Smuzhiyun 		}
856*4882a593Smuzhiyun 
857*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl_1[68], PWRUP_SREFRESH_EXIT,
858*4882a593Smuzhiyun 				g_pwrup_srefresh_exit[1]);
859*4882a593Smuzhiyun 
860*4882a593Smuzhiyun 		/*
861*4882a593Smuzhiyun 		 * restore channel 1 RESET original setting
862*4882a593Smuzhiyun 		 * to avoid 240ohm too weak to prevent ESD test
863*4882a593Smuzhiyun 		 */
864*4882a593Smuzhiyun 		if (sdram_params->base.dramtype == LPDDR4)
865*4882a593Smuzhiyun 			clrsetbits_le32(&denali_phy_1[937], 0xff,
866*4882a593Smuzhiyun 					sdram_params->phy_regs.denali_phy[937] &
867*4882a593Smuzhiyun 					0xFF);
868*4882a593Smuzhiyun 	}
869*4882a593Smuzhiyun }
870*4882a593Smuzhiyun 
871*4882a593Smuzhiyun /* phy_fn = 0, PHY boot freq
872*4882a593Smuzhiyun  * phy_fn = 1, PHY index 0
873*4882a593Smuzhiyun  * phy_fn = 2, PHY index 1
874*4882a593Smuzhiyun  */
875*4882a593Smuzhiyun static struct rk3399_sdram_params
get_phy_index_params(u32 phy_fn,struct rk3399_sdram_params * sdram_params)876*4882a593Smuzhiyun 	*get_phy_index_params(u32 phy_fn,
877*4882a593Smuzhiyun 			      struct rk3399_sdram_params *sdram_params)
878*4882a593Smuzhiyun {
879*4882a593Smuzhiyun 	if (phy_fn == 0)
880*4882a593Smuzhiyun 		return sdram_params;
881*4882a593Smuzhiyun 	else if (phy_fn == 1)
882*4882a593Smuzhiyun 		return &dfs_configs[1];
883*4882a593Smuzhiyun 	else if (phy_fn == 2)
884*4882a593Smuzhiyun 		return &dfs_configs[0];
885*4882a593Smuzhiyun 	else
886*4882a593Smuzhiyun 		return NULL;
887*4882a593Smuzhiyun }
888*4882a593Smuzhiyun 
889*4882a593Smuzhiyun /*
890*4882a593Smuzhiyun  * b_reg: indicate whether set phy register
891*4882a593Smuzhiyun  * or just set sdram_params.
892*4882a593Smuzhiyun  * if b_reg = 0, channel, mr5 are not care
893*4882a593Smuzhiyun  */
set_lp4_dq_odt(const struct chan_info * chan,struct rk3399_sdram_params * sdram_params,u32 ctl_fn,u32 en,u32 b_reg,u32 channel,u32 mr5)894*4882a593Smuzhiyun static void set_lp4_dq_odt(const struct chan_info *chan,
895*4882a593Smuzhiyun 			   struct rk3399_sdram_params *sdram_params, u32 ctl_fn,
896*4882a593Smuzhiyun 			   u32 en, u32 b_reg, u32 channel, u32 mr5)
897*4882a593Smuzhiyun {
898*4882a593Smuzhiyun 	u32 *denali_ctl;
899*4882a593Smuzhiyun 	u32 *denali_pi;
900*4882a593Smuzhiyun 	u32 reg_value;
901*4882a593Smuzhiyun 	struct io_setting *io;
902*4882a593Smuzhiyun 
903*4882a593Smuzhiyun 	if (b_reg) {
904*4882a593Smuzhiyun 		denali_pi = chan->pi->denali_pi;
905*4882a593Smuzhiyun 		denali_ctl = chan->pctl->denali_ctl;
906*4882a593Smuzhiyun 	} else {
907*4882a593Smuzhiyun 		denali_pi = sdram_params->pi_regs.denali_pi;
908*4882a593Smuzhiyun 		denali_ctl = sdram_params->pctl_regs.denali_ctl;
909*4882a593Smuzhiyun 	}
910*4882a593Smuzhiyun 	io = get_io_set(sdram_params, mr5);
911*4882a593Smuzhiyun 	if (en)
912*4882a593Smuzhiyun 		reg_value = io->dq_odt;
913*4882a593Smuzhiyun 	else
914*4882a593Smuzhiyun 		reg_value = 0;
915*4882a593Smuzhiyun 
916*4882a593Smuzhiyun 	switch (ctl_fn) {
917*4882a593Smuzhiyun 	case 0:
918*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[139], 0x7 << 24, reg_value << 24);
919*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[153], 0x7 << 24, reg_value << 24);
920*4882a593Smuzhiyun 
921*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[132], 0x7 << 0, (reg_value << 0));
922*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[139], 0x7 << 16, (reg_value << 16));
923*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[147], 0x7 << 0, (reg_value << 0));
924*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[154], 0x7 << 16, (reg_value << 16));
925*4882a593Smuzhiyun 		break;
926*4882a593Smuzhiyun 	case 1:
927*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[140], 0x7 << 0, reg_value << 0);
928*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[154], 0x7 << 0, reg_value << 0);
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[129], 0x7 << 16, (reg_value << 16));
931*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[137], 0x7 << 0, (reg_value << 0));
932*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[144], 0x7 << 16, (reg_value << 16));
933*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[152], 0x7 << 0, (reg_value << 0));
934*4882a593Smuzhiyun 		break;
935*4882a593Smuzhiyun 	case 2:
936*4882a593Smuzhiyun 	default:
937*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[140], 0x7 << 8, (reg_value << 8));
938*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[154], 0x7 << 8, (reg_value << 8));
939*4882a593Smuzhiyun 
940*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[127], 0x7 << 0, (reg_value << 0));
941*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[134], 0x7 << 16, (reg_value << 16));
942*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[142], 0x7 << 0, (reg_value << 0));
943*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[149], 0x7 << 16, (reg_value << 16));
944*4882a593Smuzhiyun 		break;
945*4882a593Smuzhiyun 	}
946*4882a593Smuzhiyun }
947*4882a593Smuzhiyun 
948*4882a593Smuzhiyun /*
949*4882a593Smuzhiyun  * b_reg: indicate whether set phy register
950*4882a593Smuzhiyun  * or just set sdram_params.
951*4882a593Smuzhiyun  * if b_reg = 0, channel, mr5 are not care
952*4882a593Smuzhiyun  */
set_lp4_ca_odt(const struct chan_info * chan,struct rk3399_sdram_params * sdram_params,u32 ctl_fn,u32 en,u32 b_reg,u32 channel,u32 mr5)953*4882a593Smuzhiyun static void set_lp4_ca_odt(const struct chan_info *chan,
954*4882a593Smuzhiyun 			   struct rk3399_sdram_params *sdram_params, u32 ctl_fn,
955*4882a593Smuzhiyun 			   u32 en, u32 b_reg, u32 channel, u32 mr5)
956*4882a593Smuzhiyun {
957*4882a593Smuzhiyun 	u32 *denali_ctl;
958*4882a593Smuzhiyun 	u32 *denali_pi;
959*4882a593Smuzhiyun 	u32 reg_value;
960*4882a593Smuzhiyun 	struct io_setting *io;
961*4882a593Smuzhiyun 
962*4882a593Smuzhiyun 	if (b_reg) {
963*4882a593Smuzhiyun 		denali_pi = chan->pi->denali_pi;
964*4882a593Smuzhiyun 		denali_ctl = chan->pctl->denali_ctl;
965*4882a593Smuzhiyun 	} else {
966*4882a593Smuzhiyun 		denali_pi = sdram_params->pi_regs.denali_pi;
967*4882a593Smuzhiyun 		denali_ctl = sdram_params->pctl_regs.denali_ctl;
968*4882a593Smuzhiyun 	}
969*4882a593Smuzhiyun 	io = get_io_set(sdram_params, mr5);
970*4882a593Smuzhiyun 	if (en)
971*4882a593Smuzhiyun 		reg_value = io->ca_odt;
972*4882a593Smuzhiyun 	else
973*4882a593Smuzhiyun 		reg_value = 0;
974*4882a593Smuzhiyun 
975*4882a593Smuzhiyun 	switch (ctl_fn) {
976*4882a593Smuzhiyun 	case 0:
977*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[139], 0x7 << 28, reg_value << 28);
978*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[153], 0x7 << 28, reg_value << 28);
979*4882a593Smuzhiyun 
980*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[132], 0x7 << 4, reg_value << 4);
981*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[139], 0x7 << 20, reg_value << 20);
982*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[147], 0x7 << 4, reg_value << 4);
983*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[154], 0x7 << 20, reg_value << 20);
984*4882a593Smuzhiyun 		break;
985*4882a593Smuzhiyun 	case 1:
986*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[140], 0x7 << 4, reg_value << 4);
987*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[154], 0x7 << 4, reg_value << 4);
988*4882a593Smuzhiyun 
989*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[129], 0x7 << 20, reg_value << 20);
990*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[137], 0x7 << 4, reg_value << 4);
991*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[144], 0x7 << 20, reg_value << 20);
992*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[152], 0x7 << 4, reg_value << 4);
993*4882a593Smuzhiyun 		break;
994*4882a593Smuzhiyun 	case 2:
995*4882a593Smuzhiyun 	default:
996*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[140], 0x7 << 12, (reg_value << 12));
997*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[154], 0x7 << 12, (reg_value << 12));
998*4882a593Smuzhiyun 
999*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[127], 0x7 << 4, reg_value << 4);
1000*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[134], 0x7 << 20, reg_value << 20);
1001*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[142], 0x7 << 4, reg_value << 4);
1002*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[149], 0x7 << 20, reg_value << 20);
1003*4882a593Smuzhiyun 		break;
1004*4882a593Smuzhiyun 	}
1005*4882a593Smuzhiyun }
1006*4882a593Smuzhiyun 
1007*4882a593Smuzhiyun /*
1008*4882a593Smuzhiyun  * b_reg: indicate whether set phy register
1009*4882a593Smuzhiyun  * or just set sdram_params.
1010*4882a593Smuzhiyun  * if b_reg = 0, channel, mr5 are not care
1011*4882a593Smuzhiyun  */
set_lp4_MR3(const struct chan_info * chan,struct rk3399_sdram_params * sdram_params,u32 ctl_fn,u32 b_reg,u32 channel,u32 mr5)1012*4882a593Smuzhiyun static void set_lp4_MR3(const struct chan_info *chan,
1013*4882a593Smuzhiyun 			struct rk3399_sdram_params *sdram_params, u32 ctl_fn,
1014*4882a593Smuzhiyun 			u32 b_reg, u32 channel, u32 mr5)
1015*4882a593Smuzhiyun {
1016*4882a593Smuzhiyun 	u32 *denali_ctl;
1017*4882a593Smuzhiyun 	u32 *denali_pi;
1018*4882a593Smuzhiyun 	u32 reg_value;
1019*4882a593Smuzhiyun 	struct io_setting *io;
1020*4882a593Smuzhiyun 
1021*4882a593Smuzhiyun 	if (b_reg) {
1022*4882a593Smuzhiyun 		denali_pi = chan->pi->denali_pi;
1023*4882a593Smuzhiyun 		denali_ctl = chan->pctl->denali_ctl;
1024*4882a593Smuzhiyun 	} else {
1025*4882a593Smuzhiyun 		denali_pi = sdram_params->pi_regs.denali_pi;
1026*4882a593Smuzhiyun 		denali_ctl = sdram_params->pctl_regs.denali_ctl;
1027*4882a593Smuzhiyun 	}
1028*4882a593Smuzhiyun 	io = get_io_set(sdram_params, mr5);
1029*4882a593Smuzhiyun 
1030*4882a593Smuzhiyun 	reg_value = ((io->pdds << 3) | 1);
1031*4882a593Smuzhiyun 	switch (ctl_fn) {
1032*4882a593Smuzhiyun 	case 0:
1033*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[138], 0xFFFF, reg_value);
1034*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[152], 0xFFFF, reg_value);
1035*4882a593Smuzhiyun 
1036*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[131], 0xFFFF << 16, reg_value << 16);
1037*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[139], 0xFFFF, reg_value);
1038*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[146], 0xFFFF << 16, reg_value << 16);
1039*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[154], 0xFFFF, reg_value);
1040*4882a593Smuzhiyun 		break;
1041*4882a593Smuzhiyun 	case 1:
1042*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[138], 0xFFFF << 16,
1043*4882a593Smuzhiyun 				reg_value << 16);
1044*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[152], 0xFFFF << 16,
1045*4882a593Smuzhiyun 				reg_value << 16);
1046*4882a593Smuzhiyun 
1047*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[129], 0xFFFF, reg_value);
1048*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[136], 0xFFFF << 16, reg_value << 16);
1049*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[144], 0xFFFF, reg_value);
1050*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[151], 0xFFFF << 16, reg_value << 16);
1051*4882a593Smuzhiyun 		break;
1052*4882a593Smuzhiyun 	case 2:
1053*4882a593Smuzhiyun 	default:
1054*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[139], 0xFFFF, reg_value);
1055*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[153], 0xFFFF, reg_value);
1056*4882a593Smuzhiyun 
1057*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[126], 0xFFFF << 16, reg_value << 16);
1058*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[134], 0xFFFF, reg_value);
1059*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[141], 0xFFFF << 16, reg_value << 16);
1060*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[149], 0xFFFF, reg_value);
1061*4882a593Smuzhiyun 		break;
1062*4882a593Smuzhiyun 	}
1063*4882a593Smuzhiyun }
1064*4882a593Smuzhiyun 
1065*4882a593Smuzhiyun /*
1066*4882a593Smuzhiyun  * b_reg: indicate whether set phy register
1067*4882a593Smuzhiyun  * or just set sdram_params.
1068*4882a593Smuzhiyun  * if b_reg = 0, channel, mr5 are not care
1069*4882a593Smuzhiyun  */
set_lp4_MR12(const struct chan_info * chan,struct rk3399_sdram_params * sdram_params,u32 ctl_fn,u32 b_reg,u32 channel,u32 mr5)1070*4882a593Smuzhiyun static void set_lp4_MR12(const struct chan_info *chan,
1071*4882a593Smuzhiyun 			 struct rk3399_sdram_params *sdram_params, u32 ctl_fn,
1072*4882a593Smuzhiyun 			 u32 b_reg, u32 channel, u32 mr5)
1073*4882a593Smuzhiyun {
1074*4882a593Smuzhiyun 	u32 *denali_ctl;
1075*4882a593Smuzhiyun 	u32 *denali_pi;
1076*4882a593Smuzhiyun 	u32 reg_value;
1077*4882a593Smuzhiyun 	struct io_setting *io;
1078*4882a593Smuzhiyun 
1079*4882a593Smuzhiyun 	if (b_reg) {
1080*4882a593Smuzhiyun 		denali_pi = chan->pi->denali_pi;
1081*4882a593Smuzhiyun 		denali_ctl = chan->pctl->denali_ctl;
1082*4882a593Smuzhiyun 	} else {
1083*4882a593Smuzhiyun 		denali_pi = sdram_params->pi_regs.denali_pi;
1084*4882a593Smuzhiyun 		denali_ctl = sdram_params->pctl_regs.denali_ctl;
1085*4882a593Smuzhiyun 	}
1086*4882a593Smuzhiyun 	io = get_io_set(sdram_params, mr5);
1087*4882a593Smuzhiyun 
1088*4882a593Smuzhiyun 	reg_value = io->ca_vref;
1089*4882a593Smuzhiyun 	switch (ctl_fn) {
1090*4882a593Smuzhiyun 	case 0:
1091*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[140], 0xFFFF << 16,
1092*4882a593Smuzhiyun 				reg_value << 16);
1093*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[154], 0xFFFF << 16,
1094*4882a593Smuzhiyun 				reg_value << 16);
1095*4882a593Smuzhiyun 
1096*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[132], 0xFF << 8, reg_value << 8);
1097*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[139], 0xFF << 24, reg_value << 24);
1098*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[147], 0xFF << 8, reg_value << 8);
1099*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[154], 0xFF << 24, reg_value << 24);
1100*4882a593Smuzhiyun 		break;
1101*4882a593Smuzhiyun 	case 1:
1102*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[141], 0xFFFF, reg_value);
1103*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[155], 0xFFFF, reg_value);
1104*4882a593Smuzhiyun 
1105*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[129], 0xFF << 24, reg_value << 24);
1106*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[137], 0xFF << 8, reg_value << 8);
1107*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[144], 0xFF << 24, reg_value << 24);
1108*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[152], 0xFF << 8, reg_value << 8);
1109*4882a593Smuzhiyun 		break;
1110*4882a593Smuzhiyun 	case 2:
1111*4882a593Smuzhiyun 	default:
1112*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[141], 0xFFFF << 16,
1113*4882a593Smuzhiyun 				reg_value << 16);
1114*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[155], 0xFFFF << 16,
1115*4882a593Smuzhiyun 				reg_value << 16);
1116*4882a593Smuzhiyun 
1117*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[127], 0xFF << 8, reg_value << 8);
1118*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[134], 0xFF << 24, reg_value << 24);
1119*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[142], 0xFF << 8, reg_value << 8);
1120*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[149], 0xFF << 24, reg_value << 24);
1121*4882a593Smuzhiyun 		break;
1122*4882a593Smuzhiyun 	}
1123*4882a593Smuzhiyun }
1124*4882a593Smuzhiyun 
1125*4882a593Smuzhiyun /*
1126*4882a593Smuzhiyun  * b_reg: indicate whether set phy register
1127*4882a593Smuzhiyun  * or just set sdram_params.
1128*4882a593Smuzhiyun  * if b_reg = 0, channel, mr5 are not care
1129*4882a593Smuzhiyun  */
set_lp4_MR14(const struct chan_info * chan,struct rk3399_sdram_params * sdram_params,u32 ctl_fn,u32 b_reg,u32 channel,u32 mr5)1130*4882a593Smuzhiyun static void set_lp4_MR14(const struct chan_info *chan,
1131*4882a593Smuzhiyun 			 struct rk3399_sdram_params *sdram_params, u32 ctl_fn,
1132*4882a593Smuzhiyun 			 u32 b_reg, u32 channel, u32 mr5)
1133*4882a593Smuzhiyun {
1134*4882a593Smuzhiyun 	u32 *denali_ctl;
1135*4882a593Smuzhiyun 	u32 *denali_pi;
1136*4882a593Smuzhiyun 	u32 reg_value;
1137*4882a593Smuzhiyun 	struct io_setting *io;
1138*4882a593Smuzhiyun 
1139*4882a593Smuzhiyun 	if (b_reg) {
1140*4882a593Smuzhiyun 		denali_pi = chan->pi->denali_pi;
1141*4882a593Smuzhiyun 		denali_ctl = chan->pctl->denali_ctl;
1142*4882a593Smuzhiyun 	} else {
1143*4882a593Smuzhiyun 		denali_pi = sdram_params->pi_regs.denali_pi;
1144*4882a593Smuzhiyun 		denali_ctl = sdram_params->pctl_regs.denali_ctl;
1145*4882a593Smuzhiyun 	}
1146*4882a593Smuzhiyun 	io = get_io_set(sdram_params, mr5);
1147*4882a593Smuzhiyun 
1148*4882a593Smuzhiyun 	reg_value = io->dq_vref;
1149*4882a593Smuzhiyun 	switch (ctl_fn) {
1150*4882a593Smuzhiyun 	case 0:
1151*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[142], 0xFFFF << 16,
1152*4882a593Smuzhiyun 				reg_value << 16);
1153*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[156], 0xFFFF << 16,
1154*4882a593Smuzhiyun 				reg_value << 16);
1155*4882a593Smuzhiyun 
1156*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[132], 0xFF << 16, reg_value << 16);
1157*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[140], 0xFF << 0, reg_value << 0);
1158*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[147], 0xFF << 16, reg_value << 16);
1159*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[155], 0xFF << 0, reg_value << 0);
1160*4882a593Smuzhiyun 		break;
1161*4882a593Smuzhiyun 	case 1:
1162*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[143], 0xFFFF, reg_value);
1163*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[157], 0xFFFF, reg_value);
1164*4882a593Smuzhiyun 
1165*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[130], 0xFF << 0, reg_value << 0);
1166*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[137], 0xFF << 16, reg_value << 16);
1167*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[145], 0xFF << 0, reg_value << 0);
1168*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[152], 0xFF << 16, reg_value << 16);
1169*4882a593Smuzhiyun 		break;
1170*4882a593Smuzhiyun 	case 2:
1171*4882a593Smuzhiyun 	default:
1172*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[143], 0xFFFF << 16,
1173*4882a593Smuzhiyun 				reg_value << 16);
1174*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[157], 0xFFFF << 16,
1175*4882a593Smuzhiyun 				reg_value << 16);
1176*4882a593Smuzhiyun 
1177*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[127], 0xFF << 16, reg_value << 16);
1178*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[135], 0xFF << 0, reg_value << 0);
1179*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[142], 0xFF << 16, reg_value << 16);
1180*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[150], 0xFF << 0, reg_value << 0);
1181*4882a593Smuzhiyun 		break;
1182*4882a593Smuzhiyun 	}
1183*4882a593Smuzhiyun }
1184*4882a593Smuzhiyun 
modify_param(const struct chan_info * chan,struct rk3399_sdram_params * sdram_params)1185*4882a593Smuzhiyun static void modify_param(const struct chan_info *chan,
1186*4882a593Smuzhiyun 			 struct rk3399_sdram_params *sdram_params)
1187*4882a593Smuzhiyun {
1188*4882a593Smuzhiyun 	struct rk3399_sdram_params *params;
1189*4882a593Smuzhiyun 	u32 *denali_ctl_params;
1190*4882a593Smuzhiyun 	u32 *denali_pi_params;
1191*4882a593Smuzhiyun 	u32 *denali_phy_params;
1192*4882a593Smuzhiyun 
1193*4882a593Smuzhiyun 	denali_ctl_params = sdram_params->pctl_regs.denali_ctl;
1194*4882a593Smuzhiyun 	denali_pi_params = sdram_params->pi_regs.denali_pi;
1195*4882a593Smuzhiyun 	denali_phy_params = sdram_params->phy_regs.denali_phy;
1196*4882a593Smuzhiyun 
1197*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4) {
1198*4882a593Smuzhiyun 		set_lp4_dq_odt(chan, sdram_params, 2, 1, 0, 0, 0);
1199*4882a593Smuzhiyun 		set_lp4_ca_odt(chan, sdram_params, 2, 1, 0, 0, 0);
1200*4882a593Smuzhiyun 		set_lp4_MR3(chan, sdram_params, 2, 0, 0, 0);
1201*4882a593Smuzhiyun 		set_lp4_MR12(chan, sdram_params, 2, 0, 0, 0);
1202*4882a593Smuzhiyun 		set_lp4_MR14(chan, sdram_params, 2, 0, 0, 0);
1203*4882a593Smuzhiyun 		params = get_phy_index_params(0, sdram_params);
1204*4882a593Smuzhiyun 		set_ds_odt(chan, params, 0, 0, 0);
1205*4882a593Smuzhiyun 		/* read two cycle preamble */
1206*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl_params[200], 0x3 << 24, 0x3 << 24);
1207*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy_params[7], 0x3 << 24, 0x3 << 24);
1208*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy_params[135], 0x3 << 24, 0x3 << 24);
1209*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy_params[263], 0x3 << 24, 0x3 << 24);
1210*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy_params[391], 0x3 << 24, 0x3 << 24);
1211*4882a593Smuzhiyun 
1212*4882a593Smuzhiyun 		/* boot frequency two cycle preamble */
1213*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy_params[2], 0x3 << 16, 0x3 << 16);
1214*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy_params[130], 0x3 << 16, 0x3 << 16);
1215*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy_params[258], 0x3 << 16, 0x3 << 16);
1216*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy_params[386], 0x3 << 16, 0x3 << 16);
1217*4882a593Smuzhiyun 
1218*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi_params[45], 0x3 << 8, 0x3 << 8);
1219*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi_params[58], 0x1, 0x1);
1220*4882a593Smuzhiyun 
1221*4882a593Smuzhiyun 		/*
1222*4882a593Smuzhiyun 		 * bypass mode need PHY_SLICE_PWR_RDC_DISABLE_x = 1,
1223*4882a593Smuzhiyun 		 * boot frequency mode use bypass mode
1224*4882a593Smuzhiyun 		 */
1225*4882a593Smuzhiyun 		setbits_le32(&denali_phy_params[10], 1 << 16);
1226*4882a593Smuzhiyun 		setbits_le32(&denali_phy_params[138], 1 << 16);
1227*4882a593Smuzhiyun 		setbits_le32(&denali_phy_params[266], 1 << 16);
1228*4882a593Smuzhiyun 		setbits_le32(&denali_phy_params[394], 1 << 16);
1229*4882a593Smuzhiyun 	} else {
1230*4882a593Smuzhiyun 		/* modify PHY F0/F1/F2 params */
1231*4882a593Smuzhiyun 		params = get_phy_index_params(0, sdram_params);
1232*4882a593Smuzhiyun 		set_ds_odt(chan, params, 0, 0, 0);
1233*4882a593Smuzhiyun 	}
1234*4882a593Smuzhiyun 
1235*4882a593Smuzhiyun 	clrsetbits_le32(&denali_pi_params[45], 0x1 << 24, 0x1 << 24);
1236*4882a593Smuzhiyun 	clrsetbits_le32(&denali_pi_params[61], 0x1 << 24, 0x1 << 24);
1237*4882a593Smuzhiyun 	clrsetbits_le32(&denali_pi_params[76], 0x1 << 24, 0x1 << 24);
1238*4882a593Smuzhiyun 	clrsetbits_le32(&denali_pi_params[77], 0x1, 0x1);
1239*4882a593Smuzhiyun }
1240*4882a593Smuzhiyun 
pctl_cfg(const struct chan_info * chan,u32 channel,struct rk3399_sdram_params * sdram_params)1241*4882a593Smuzhiyun static int pctl_cfg(const struct chan_info *chan, u32 channel,
1242*4882a593Smuzhiyun 		    struct rk3399_sdram_params *sdram_params)
1243*4882a593Smuzhiyun {
1244*4882a593Smuzhiyun 	u32 *denali_ctl = chan->pctl->denali_ctl;
1245*4882a593Smuzhiyun 	u32 *denali_pi = chan->pi->denali_pi;
1246*4882a593Smuzhiyun 	u32 *denali_phy = chan->publ->denali_phy;
1247*4882a593Smuzhiyun 	const u32 *params_ctl = sdram_params->pctl_regs.denali_ctl;
1248*4882a593Smuzhiyun 	const u32 *params_phy = sdram_params->phy_regs.denali_phy;
1249*4882a593Smuzhiyun 	u32 tmp, tmp1, tmp2;
1250*4882a593Smuzhiyun 	struct rk3399_sdram_params *params;
1251*4882a593Smuzhiyun 	u32 byte;
1252*4882a593Smuzhiyun 
1253*4882a593Smuzhiyun 	modify_param(chan, sdram_params);
1254*4882a593Smuzhiyun 	/*
1255*4882a593Smuzhiyun 	 * work around controller bug:
1256*4882a593Smuzhiyun 	 * Do not program DRAM_CLASS until NO_PHY_IND_TRAIN_INT is programmed
1257*4882a593Smuzhiyun 	 */
1258*4882a593Smuzhiyun 	sdram_copy_to_reg(&denali_ctl[1], &params_ctl[1],
1259*4882a593Smuzhiyun 			  sizeof(struct rk3399_ddr_pctl_regs) - 4);
1260*4882a593Smuzhiyun 	writel(params_ctl[0], &denali_ctl[0]);
1261*4882a593Smuzhiyun 
1262*4882a593Smuzhiyun 	/*
1263*4882a593Smuzhiyun 	 * two channel init at the same time, then ZQ Cal Start
1264*4882a593Smuzhiyun 	 * at the same time, it will use the same RZQ.
1265*4882a593Smuzhiyun 	 * to fix it: increase tINIT3 for channel 1, will avoid two
1266*4882a593Smuzhiyun 	 * channel ZQ Cal Start at the same time
1267*4882a593Smuzhiyun 	 */
1268*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4 && channel == 1) {
1269*4882a593Smuzhiyun 		tmp = ((1000000 * (sdram_params->base.ddr_freq / MHz) + 999) /
1270*4882a593Smuzhiyun 		       1000);
1271*4882a593Smuzhiyun 		tmp1 = readl(&denali_ctl[14]);
1272*4882a593Smuzhiyun 		writel(tmp + tmp1, &denali_ctl[14]);
1273*4882a593Smuzhiyun 	}
1274*4882a593Smuzhiyun 
1275*4882a593Smuzhiyun 	sdram_copy_to_reg(denali_pi, &sdram_params->pi_regs.denali_pi[0],
1276*4882a593Smuzhiyun 			  sizeof(struct rk3399_ddr_pi_regs));
1277*4882a593Smuzhiyun 	/* rank count need to set for init */
1278*4882a593Smuzhiyun 	set_memory_map(chan, channel, sdram_params);
1279*4882a593Smuzhiyun 
1280*4882a593Smuzhiyun 	writel(sdram_params->phy_regs.denali_phy[910], &denali_phy[910]);
1281*4882a593Smuzhiyun 	writel(sdram_params->phy_regs.denali_phy[911], &denali_phy[911]);
1282*4882a593Smuzhiyun 	writel(sdram_params->phy_regs.denali_phy[912], &denali_phy[912]);
1283*4882a593Smuzhiyun 
1284*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4) {
1285*4882a593Smuzhiyun 		writel(sdram_params->phy_regs.denali_phy[898],
1286*4882a593Smuzhiyun 		       &denali_phy[898]);
1287*4882a593Smuzhiyun 		writel(sdram_params->phy_regs.denali_phy[919],
1288*4882a593Smuzhiyun 		       &denali_phy[919]);
1289*4882a593Smuzhiyun 	}
1290*4882a593Smuzhiyun 
1291*4882a593Smuzhiyun 	g_pwrup_srefresh_exit[channel] = readl(&denali_ctl[68]) &
1292*4882a593Smuzhiyun 					 PWRUP_SREFRESH_EXIT;
1293*4882a593Smuzhiyun 	clrbits_le32(&denali_ctl[68], PWRUP_SREFRESH_EXIT);
1294*4882a593Smuzhiyun 
1295*4882a593Smuzhiyun 	/* PHY_DLL_RST_EN */
1296*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[957], 0x3 << 24, 1 << 24);
1297*4882a593Smuzhiyun 
1298*4882a593Smuzhiyun 	setbits_le32(&denali_pi[0], START);
1299*4882a593Smuzhiyun 	setbits_le32(&denali_ctl[0], START);
1300*4882a593Smuzhiyun 
1301*4882a593Smuzhiyun 	/* because LPDDR4 use PLL bypass mode for init
1302*4882a593Smuzhiyun 	 * not need to wait for the PLL to lock
1303*4882a593Smuzhiyun 	 */
1304*4882a593Smuzhiyun 	if (sdram_params->base.dramtype != LPDDR4) {
1305*4882a593Smuzhiyun 		/* wait lock */
1306*4882a593Smuzhiyun 		while (1) {
1307*4882a593Smuzhiyun 			tmp = readl(&denali_phy[920]);
1308*4882a593Smuzhiyun 			tmp1 = readl(&denali_phy[921]);
1309*4882a593Smuzhiyun 			tmp2 = readl(&denali_phy[922]);
1310*4882a593Smuzhiyun 			if ((((tmp >> 16) & 0x1) == 0x1) &&
1311*4882a593Smuzhiyun 			    (((tmp1 >> 16) & 0x1) == 0x1) &&
1312*4882a593Smuzhiyun 			    (((tmp1 >> 0) & 0x1) == 0x1) &&
1313*4882a593Smuzhiyun 			    (((tmp2 >> 0) & 0x1) == 0x1))
1314*4882a593Smuzhiyun 				break;
1315*4882a593Smuzhiyun 		}
1316*4882a593Smuzhiyun 	}
1317*4882a593Smuzhiyun 
1318*4882a593Smuzhiyun 	sdram_copy_to_reg(&denali_phy[896], &params_phy[896], (958 - 895) * 4);
1319*4882a593Smuzhiyun 	sdram_copy_to_reg(&denali_phy[0], &params_phy[0], (90 - 0 + 1) * 4);
1320*4882a593Smuzhiyun 	sdram_copy_to_reg(&denali_phy[128],
1321*4882a593Smuzhiyun 			  &params_phy[128], (218 - 128 + 1) * 4);
1322*4882a593Smuzhiyun 	sdram_copy_to_reg(&denali_phy[256],
1323*4882a593Smuzhiyun 			  &params_phy[256], (346 - 256 + 1) * 4);
1324*4882a593Smuzhiyun 	sdram_copy_to_reg(&denali_phy[384],
1325*4882a593Smuzhiyun 			  &params_phy[384], (474 - 384 + 1) * 4);
1326*4882a593Smuzhiyun 	sdram_copy_to_reg(&denali_phy[512],
1327*4882a593Smuzhiyun 			  &params_phy[512], (549 - 512 + 1) * 4);
1328*4882a593Smuzhiyun 	sdram_copy_to_reg(&denali_phy[640],
1329*4882a593Smuzhiyun 			  &params_phy[640], (677 - 640 + 1) * 4);
1330*4882a593Smuzhiyun 	sdram_copy_to_reg(&denali_phy[768],
1331*4882a593Smuzhiyun 			  &params_phy[768], (805 - 768 + 1) * 4);
1332*4882a593Smuzhiyun 
1333*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4)
1334*4882a593Smuzhiyun 		params = get_phy_index_params(1, sdram_params);
1335*4882a593Smuzhiyun 	else
1336*4882a593Smuzhiyun 		params = get_phy_index_params(0, sdram_params);
1337*4882a593Smuzhiyun 
1338*4882a593Smuzhiyun 	clrsetbits_le32(&params->phy_regs.denali_phy[896], 0x3 << 8,
1339*4882a593Smuzhiyun 			0 << 8);
1340*4882a593Smuzhiyun 	writel(params->phy_regs.denali_phy[896], &denali_phy[896]);
1341*4882a593Smuzhiyun 
1342*4882a593Smuzhiyun 	writel(sdram_params->phy_regs.denali_phy[83] + (0x10 << 16),
1343*4882a593Smuzhiyun 	       &denali_phy[83]);
1344*4882a593Smuzhiyun 	writel(sdram_params->phy_regs.denali_phy[84] + (0x10 << 8),
1345*4882a593Smuzhiyun 	       &denali_phy[84]);
1346*4882a593Smuzhiyun 	writel(sdram_params->phy_regs.denali_phy[211] + (0x10 << 16),
1347*4882a593Smuzhiyun 	       &denali_phy[211]);
1348*4882a593Smuzhiyun 	writel(sdram_params->phy_regs.denali_phy[212] + (0x10 << 8),
1349*4882a593Smuzhiyun 	       &denali_phy[212]);
1350*4882a593Smuzhiyun 	writel(sdram_params->phy_regs.denali_phy[339] + (0x10 << 16),
1351*4882a593Smuzhiyun 	       &denali_phy[339]);
1352*4882a593Smuzhiyun 	writel(sdram_params->phy_regs.denali_phy[340] + (0x10 << 8),
1353*4882a593Smuzhiyun 	       &denali_phy[340]);
1354*4882a593Smuzhiyun 	writel(sdram_params->phy_regs.denali_phy[467] + (0x10 << 16),
1355*4882a593Smuzhiyun 	       &denali_phy[467]);
1356*4882a593Smuzhiyun 	writel(sdram_params->phy_regs.denali_phy[468] + (0x10 << 8),
1357*4882a593Smuzhiyun 	       &denali_phy[468]);
1358*4882a593Smuzhiyun 
1359*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4) {
1360*4882a593Smuzhiyun 		/*
1361*4882a593Smuzhiyun 		 * to improve write dqs and dq phase from 1.5ns to 3.5ns
1362*4882a593Smuzhiyun 		 * at 50MHz.
1363*4882a593Smuzhiyun 		 */
1364*4882a593Smuzhiyun 		for (byte = 0; byte < 4; byte++) {
1365*4882a593Smuzhiyun 			tmp = 0x680;
1366*4882a593Smuzhiyun 			clrsetbits_le32(&denali_phy[1 + (128 * byte)],
1367*4882a593Smuzhiyun 					0xfff << 8, tmp << 8);
1368*4882a593Smuzhiyun 		}
1369*4882a593Smuzhiyun 		/*
1370*4882a593Smuzhiyun 		 * to workaround 366ball two channel's RESET connect to
1371*4882a593Smuzhiyun 		 * one RESET signal of die
1372*4882a593Smuzhiyun 		 */
1373*4882a593Smuzhiyun 		if (channel == 1)
1374*4882a593Smuzhiyun 			clrsetbits_le32(&denali_phy[937], 0xff,
1375*4882a593Smuzhiyun 					PHY_DRV_ODT_240 |
1376*4882a593Smuzhiyun 					(PHY_DRV_ODT_240 << 0x4));
1377*4882a593Smuzhiyun 	}
1378*4882a593Smuzhiyun 
1379*4882a593Smuzhiyun 	return 0;
1380*4882a593Smuzhiyun }
1381*4882a593Smuzhiyun 
select_per_cs_training_index(const struct chan_info * chan,u32 rank)1382*4882a593Smuzhiyun static void select_per_cs_training_index(const struct chan_info *chan,
1383*4882a593Smuzhiyun 					 u32 rank)
1384*4882a593Smuzhiyun {
1385*4882a593Smuzhiyun 	u32 *denali_phy = chan->publ->denali_phy;
1386*4882a593Smuzhiyun 
1387*4882a593Smuzhiyun 	/* PHY_84 PHY_PER_CS_TRAINING_EN_0 1bit offset_16 */
1388*4882a593Smuzhiyun 	if ((readl(&denali_phy[84]) >> 16) & 1) {
1389*4882a593Smuzhiyun 		/*
1390*4882a593Smuzhiyun 		 * PHY_8/136/264/392
1391*4882a593Smuzhiyun 		 * phy_per_cs_training_index_X 1bit offset_24
1392*4882a593Smuzhiyun 		 */
1393*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[8], 0x1 << 24, rank << 24);
1394*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[136], 0x1 << 24, rank << 24);
1395*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[264], 0x1 << 24, rank << 24);
1396*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[392], 0x1 << 24, rank << 24);
1397*4882a593Smuzhiyun 	}
1398*4882a593Smuzhiyun }
1399*4882a593Smuzhiyun 
override_write_leveling_value(const struct chan_info * chan)1400*4882a593Smuzhiyun static void override_write_leveling_value(const struct chan_info *chan)
1401*4882a593Smuzhiyun {
1402*4882a593Smuzhiyun 	u32 *denali_ctl = chan->pctl->denali_ctl;
1403*4882a593Smuzhiyun 	u32 *denali_phy = chan->publ->denali_phy;
1404*4882a593Smuzhiyun 	u32 byte;
1405*4882a593Smuzhiyun 
1406*4882a593Smuzhiyun 	/* PHY_896 PHY_FREQ_SEL_MULTICAST_EN 1bit offset_0 */
1407*4882a593Smuzhiyun 	setbits_le32(&denali_phy[896], 1);
1408*4882a593Smuzhiyun 
1409*4882a593Smuzhiyun 	/*
1410*4882a593Smuzhiyun 	 * PHY_8/136/264/392
1411*4882a593Smuzhiyun 	 * phy_per_cs_training_multicast_en_X 1bit offset_16
1412*4882a593Smuzhiyun 	 */
1413*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[8], 0x1 << 16, 1 << 16);
1414*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[136], 0x1 << 16, 1 << 16);
1415*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[264], 0x1 << 16, 1 << 16);
1416*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[392], 0x1 << 16, 1 << 16);
1417*4882a593Smuzhiyun 
1418*4882a593Smuzhiyun 	for (byte = 0; byte < 4; byte++)
1419*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[63 + (128 * byte)], 0xffff << 16,
1420*4882a593Smuzhiyun 				0x200 << 16);
1421*4882a593Smuzhiyun 
1422*4882a593Smuzhiyun 	/* PHY_896 PHY_FREQ_SEL_MULTICAST_EN 1bit offset_0 */
1423*4882a593Smuzhiyun 	clrbits_le32(&denali_phy[896], 1);
1424*4882a593Smuzhiyun 
1425*4882a593Smuzhiyun 	/* CTL_200 ctrlupd_req 1bit offset_8 */
1426*4882a593Smuzhiyun 	clrsetbits_le32(&denali_ctl[200], 0x1 << 8, 0x1 << 8);
1427*4882a593Smuzhiyun }
1428*4882a593Smuzhiyun 
data_training_ca(const struct chan_info * chan,u32 channel,const struct rk3399_sdram_params * sdram_params)1429*4882a593Smuzhiyun static int data_training_ca(const struct chan_info *chan, u32 channel,
1430*4882a593Smuzhiyun 			    const struct rk3399_sdram_params *sdram_params)
1431*4882a593Smuzhiyun {
1432*4882a593Smuzhiyun 	u32 *denali_pi = chan->pi->denali_pi;
1433*4882a593Smuzhiyun 	u32 *denali_phy = chan->publ->denali_phy;
1434*4882a593Smuzhiyun 	u32 i, tmp;
1435*4882a593Smuzhiyun 	u32 obs_0, obs_1, obs_2, obs_err = 0;
1436*4882a593Smuzhiyun 	u32 rank = sdram_params->ch[channel].cap_info.rank;
1437*4882a593Smuzhiyun 	u32 rank_mask;
1438*4882a593Smuzhiyun 
1439*4882a593Smuzhiyun 	/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
1440*4882a593Smuzhiyun 	writel(0x00003f7c, (&denali_pi[175]));
1441*4882a593Smuzhiyun 
1442*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4)
1443*4882a593Smuzhiyun 		rank_mask = (rank == 1) ? 0x5 : 0xf;
1444*4882a593Smuzhiyun 	else
1445*4882a593Smuzhiyun 		rank_mask = (rank == 1) ? 0x1 : 0x3;
1446*4882a593Smuzhiyun 
1447*4882a593Smuzhiyun 	for (i = 0; i < 4; i++) {
1448*4882a593Smuzhiyun 		if (!(rank_mask & (1 << i)))
1449*4882a593Smuzhiyun 			continue;
1450*4882a593Smuzhiyun 		select_per_cs_training_index(chan, i);
1451*4882a593Smuzhiyun 		/* PI_100 PI_CALVL_EN:RW:8:2 */
1452*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[100], 0x3 << 8, 0x2 << 8);
1453*4882a593Smuzhiyun 		/* PI_92 PI_CALVL_REQ:WR:16:1,PI_CALVL_CS:RW:24:2 */
1454*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[92],
1455*4882a593Smuzhiyun 				(0x1 << 16) | (0x3 << 24),
1456*4882a593Smuzhiyun 				(0x1 << 16) | (i << 24));
1457*4882a593Smuzhiyun 
1458*4882a593Smuzhiyun 		/* Waiting for training complete */
1459*4882a593Smuzhiyun 		while (1) {
1460*4882a593Smuzhiyun 			/* PI_174 PI_INT_STATUS:RD:8:18 */
1461*4882a593Smuzhiyun 			tmp = readl(&denali_pi[174]) >> 8;
1462*4882a593Smuzhiyun 			/*
1463*4882a593Smuzhiyun 			 * check status obs
1464*4882a593Smuzhiyun 			 * PHY_532/660/789 phy_adr_calvl_obs1_:0:32
1465*4882a593Smuzhiyun 			 */
1466*4882a593Smuzhiyun 			obs_0 = readl(&denali_phy[532]);
1467*4882a593Smuzhiyun 			obs_1 = readl(&denali_phy[660]);
1468*4882a593Smuzhiyun 			obs_2 = readl(&denali_phy[788]);
1469*4882a593Smuzhiyun 			if (((obs_0 >> 30) & 0x3) ||
1470*4882a593Smuzhiyun 			    ((obs_1 >> 30) & 0x3) ||
1471*4882a593Smuzhiyun 			    ((obs_2 >> 30) & 0x3))
1472*4882a593Smuzhiyun 				obs_err = 1;
1473*4882a593Smuzhiyun 			if ((((tmp >> 11) & 0x1) == 0x1) &&
1474*4882a593Smuzhiyun 			    (((tmp >> 13) & 0x1) == 0x1) &&
1475*4882a593Smuzhiyun 			    (((tmp >> 5) & 0x1) == 0x0) &&
1476*4882a593Smuzhiyun 			    obs_err == 0)
1477*4882a593Smuzhiyun 				break;
1478*4882a593Smuzhiyun 			else if ((((tmp >> 5) & 0x1) == 0x1) ||
1479*4882a593Smuzhiyun 				 (obs_err == 1))
1480*4882a593Smuzhiyun 				return -EIO;
1481*4882a593Smuzhiyun 		}
1482*4882a593Smuzhiyun 		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
1483*4882a593Smuzhiyun 		writel(0x00003f7c, (&denali_pi[175]));
1484*4882a593Smuzhiyun 	}
1485*4882a593Smuzhiyun 	clrbits_le32(&denali_pi[100], 0x3 << 8);
1486*4882a593Smuzhiyun 
1487*4882a593Smuzhiyun 	return 0;
1488*4882a593Smuzhiyun }
1489*4882a593Smuzhiyun 
data_training_wl(const struct chan_info * chan,u32 channel,const struct rk3399_sdram_params * sdram_params)1490*4882a593Smuzhiyun static int data_training_wl(const struct chan_info *chan, u32 channel,
1491*4882a593Smuzhiyun 			    const struct rk3399_sdram_params *sdram_params)
1492*4882a593Smuzhiyun {
1493*4882a593Smuzhiyun 	u32 *denali_pi = chan->pi->denali_pi;
1494*4882a593Smuzhiyun 	u32 *denali_phy = chan->publ->denali_phy;
1495*4882a593Smuzhiyun 	u32 i, tmp;
1496*4882a593Smuzhiyun 	u32 obs_0, obs_1, obs_2, obs_3, obs_err = 0;
1497*4882a593Smuzhiyun 	u32 rank = sdram_params->ch[channel].cap_info.rank;
1498*4882a593Smuzhiyun 
1499*4882a593Smuzhiyun 	/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
1500*4882a593Smuzhiyun 	writel(0x00003f7c, (&denali_pi[175]));
1501*4882a593Smuzhiyun 
1502*4882a593Smuzhiyun 	for (i = 0; i < rank; i++) {
1503*4882a593Smuzhiyun 		select_per_cs_training_index(chan, i);
1504*4882a593Smuzhiyun 		/* PI_60 PI_WRLVL_EN:RW:8:2 */
1505*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[60], 0x3 << 8, 0x2 << 8);
1506*4882a593Smuzhiyun 		/* PI_59 PI_WRLVL_REQ:WR:8:1,PI_WRLVL_CS:RW:16:2 */
1507*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[59],
1508*4882a593Smuzhiyun 				(0x1 << 8) | (0x3 << 16),
1509*4882a593Smuzhiyun 				(0x1 << 8) | (i << 16));
1510*4882a593Smuzhiyun 
1511*4882a593Smuzhiyun 		/* Waiting for training complete */
1512*4882a593Smuzhiyun 		while (1) {
1513*4882a593Smuzhiyun 			/* PI_174 PI_INT_STATUS:RD:8:18 */
1514*4882a593Smuzhiyun 			tmp = readl(&denali_pi[174]) >> 8;
1515*4882a593Smuzhiyun 
1516*4882a593Smuzhiyun 			/*
1517*4882a593Smuzhiyun 			 * check status obs, if error maybe can not
1518*4882a593Smuzhiyun 			 * get leveling done PHY_40/168/296/424
1519*4882a593Smuzhiyun 			 * phy_wrlvl_status_obs_X:0:13
1520*4882a593Smuzhiyun 			 */
1521*4882a593Smuzhiyun 			obs_0 = readl(&denali_phy[40]);
1522*4882a593Smuzhiyun 			obs_1 = readl(&denali_phy[168]);
1523*4882a593Smuzhiyun 			obs_2 = readl(&denali_phy[296]);
1524*4882a593Smuzhiyun 			obs_3 = readl(&denali_phy[424]);
1525*4882a593Smuzhiyun 			if (((obs_0 >> 12) & 0x1) ||
1526*4882a593Smuzhiyun 			    ((obs_1 >> 12) & 0x1) ||
1527*4882a593Smuzhiyun 			    ((obs_2 >> 12) & 0x1) ||
1528*4882a593Smuzhiyun 			    ((obs_3 >> 12) & 0x1))
1529*4882a593Smuzhiyun 				obs_err = 1;
1530*4882a593Smuzhiyun 			if ((((tmp >> 10) & 0x1) == 0x1) &&
1531*4882a593Smuzhiyun 			    (((tmp >> 13) & 0x1) == 0x1) &&
1532*4882a593Smuzhiyun 			    (((tmp >> 4) & 0x1) == 0x0) &&
1533*4882a593Smuzhiyun 			    obs_err == 0)
1534*4882a593Smuzhiyun 				break;
1535*4882a593Smuzhiyun 			else if ((((tmp >> 4) & 0x1) == 0x1) ||
1536*4882a593Smuzhiyun 				 (obs_err == 1))
1537*4882a593Smuzhiyun 				return -EIO;
1538*4882a593Smuzhiyun 		}
1539*4882a593Smuzhiyun 		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
1540*4882a593Smuzhiyun 		writel(0x00003f7c, (&denali_pi[175]));
1541*4882a593Smuzhiyun 	}
1542*4882a593Smuzhiyun 
1543*4882a593Smuzhiyun 	override_write_leveling_value(chan);
1544*4882a593Smuzhiyun 	clrbits_le32(&denali_pi[60], 0x3 << 8);
1545*4882a593Smuzhiyun 
1546*4882a593Smuzhiyun 	return 0;
1547*4882a593Smuzhiyun }
1548*4882a593Smuzhiyun 
data_training_rg(const struct chan_info * chan,u32 channel,const struct rk3399_sdram_params * sdram_params)1549*4882a593Smuzhiyun static int data_training_rg(const struct chan_info *chan, u32 channel,
1550*4882a593Smuzhiyun 			    const struct rk3399_sdram_params *sdram_params)
1551*4882a593Smuzhiyun {
1552*4882a593Smuzhiyun 	u32 *denali_pi = chan->pi->denali_pi;
1553*4882a593Smuzhiyun 	u32 *denali_phy = chan->publ->denali_phy;
1554*4882a593Smuzhiyun 	u32 i, tmp;
1555*4882a593Smuzhiyun 	u32 obs_0, obs_1, obs_2, obs_3, obs_err = 0;
1556*4882a593Smuzhiyun 	u32 rank = sdram_params->ch[channel].cap_info.rank;
1557*4882a593Smuzhiyun 
1558*4882a593Smuzhiyun 	/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
1559*4882a593Smuzhiyun 	writel(0x00003f7c, (&denali_pi[175]));
1560*4882a593Smuzhiyun 
1561*4882a593Smuzhiyun 	for (i = 0; i < rank; i++) {
1562*4882a593Smuzhiyun 		select_per_cs_training_index(chan, i);
1563*4882a593Smuzhiyun 		/* PI_80 PI_RDLVL_GATE_EN:RW:24:2 */
1564*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[80], 0x3 << 24, 0x2 << 24);
1565*4882a593Smuzhiyun 		/*
1566*4882a593Smuzhiyun 		 * PI_74 PI_RDLVL_GATE_REQ:WR:16:1
1567*4882a593Smuzhiyun 		 * PI_RDLVL_CS:RW:24:2
1568*4882a593Smuzhiyun 		 */
1569*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[74],
1570*4882a593Smuzhiyun 				(0x1 << 16) | (0x3 << 24),
1571*4882a593Smuzhiyun 				(0x1 << 16) | (i << 24));
1572*4882a593Smuzhiyun 
1573*4882a593Smuzhiyun 		/* Waiting for training complete */
1574*4882a593Smuzhiyun 		while (1) {
1575*4882a593Smuzhiyun 			/* PI_174 PI_INT_STATUS:RD:8:18 */
1576*4882a593Smuzhiyun 			tmp = readl(&denali_pi[174]) >> 8;
1577*4882a593Smuzhiyun 
1578*4882a593Smuzhiyun 			/*
1579*4882a593Smuzhiyun 			 * check status obs
1580*4882a593Smuzhiyun 			 * PHY_43/171/299/427
1581*4882a593Smuzhiyun 			 *     PHY_GTLVL_STATUS_OBS_x:16:8
1582*4882a593Smuzhiyun 			 */
1583*4882a593Smuzhiyun 			obs_0 = readl(&denali_phy[43]);
1584*4882a593Smuzhiyun 			obs_1 = readl(&denali_phy[171]);
1585*4882a593Smuzhiyun 			obs_2 = readl(&denali_phy[299]);
1586*4882a593Smuzhiyun 			obs_3 = readl(&denali_phy[427]);
1587*4882a593Smuzhiyun 			if (((obs_0 >> (16 + 6)) & 0x3) ||
1588*4882a593Smuzhiyun 			    ((obs_1 >> (16 + 6)) & 0x3) ||
1589*4882a593Smuzhiyun 			    ((obs_2 >> (16 + 6)) & 0x3) ||
1590*4882a593Smuzhiyun 			    ((obs_3 >> (16 + 6)) & 0x3))
1591*4882a593Smuzhiyun 				obs_err = 1;
1592*4882a593Smuzhiyun 			if ((((tmp >> 9) & 0x1) == 0x1) &&
1593*4882a593Smuzhiyun 			    (((tmp >> 13) & 0x1) == 0x1) &&
1594*4882a593Smuzhiyun 			    (((tmp >> 3) & 0x1) == 0x0) &&
1595*4882a593Smuzhiyun 			    obs_err == 0)
1596*4882a593Smuzhiyun 				break;
1597*4882a593Smuzhiyun 			else if ((((tmp >> 3) & 0x1) == 0x1) ||
1598*4882a593Smuzhiyun 				 (obs_err == 1))
1599*4882a593Smuzhiyun 				return -EIO;
1600*4882a593Smuzhiyun 		}
1601*4882a593Smuzhiyun 		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
1602*4882a593Smuzhiyun 		writel(0x00003f7c, (&denali_pi[175]));
1603*4882a593Smuzhiyun 	}
1604*4882a593Smuzhiyun 	clrbits_le32(&denali_pi[80], 0x3 << 24);
1605*4882a593Smuzhiyun 
1606*4882a593Smuzhiyun 	return 0;
1607*4882a593Smuzhiyun }
1608*4882a593Smuzhiyun 
data_training_rl(const struct chan_info * chan,u32 channel,const struct rk3399_sdram_params * sdram_params)1609*4882a593Smuzhiyun static int data_training_rl(const struct chan_info *chan, u32 channel,
1610*4882a593Smuzhiyun 			    const struct rk3399_sdram_params *sdram_params)
1611*4882a593Smuzhiyun {
1612*4882a593Smuzhiyun 	u32 *denali_pi = chan->pi->denali_pi;
1613*4882a593Smuzhiyun 	u32 i, tmp;
1614*4882a593Smuzhiyun 	u32 rank = sdram_params->ch[channel].cap_info.rank;
1615*4882a593Smuzhiyun 
1616*4882a593Smuzhiyun 	/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
1617*4882a593Smuzhiyun 	writel(0x00003f7c, (&denali_pi[175]));
1618*4882a593Smuzhiyun 
1619*4882a593Smuzhiyun 	for (i = 0; i < rank; i++) {
1620*4882a593Smuzhiyun 		select_per_cs_training_index(chan, i);
1621*4882a593Smuzhiyun 		/* PI_80 PI_RDLVL_EN:RW:16:2 */
1622*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[80], 0x3 << 16, 0x2 << 16);
1623*4882a593Smuzhiyun 		/* PI_74 PI_RDLVL_REQ:WR:8:1,PI_RDLVL_CS:RW:24:2 */
1624*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[74],
1625*4882a593Smuzhiyun 				(0x1 << 8) | (0x3 << 24),
1626*4882a593Smuzhiyun 				(0x1 << 8) | (i << 24));
1627*4882a593Smuzhiyun 
1628*4882a593Smuzhiyun 		/* Waiting for training complete */
1629*4882a593Smuzhiyun 		while (1) {
1630*4882a593Smuzhiyun 			/* PI_174 PI_INT_STATUS:RD:8:18 */
1631*4882a593Smuzhiyun 			tmp = readl(&denali_pi[174]) >> 8;
1632*4882a593Smuzhiyun 
1633*4882a593Smuzhiyun 			/*
1634*4882a593Smuzhiyun 			 * make sure status obs not report error bit
1635*4882a593Smuzhiyun 			 * PHY_46/174/302/430
1636*4882a593Smuzhiyun 			 *     phy_rdlvl_status_obs_X:16:8
1637*4882a593Smuzhiyun 			 */
1638*4882a593Smuzhiyun 			if ((((tmp >> 8) & 0x1) == 0x1) &&
1639*4882a593Smuzhiyun 			    (((tmp >> 13) & 0x1) == 0x1) &&
1640*4882a593Smuzhiyun 			    (((tmp >> 2) & 0x1) == 0x0))
1641*4882a593Smuzhiyun 				break;
1642*4882a593Smuzhiyun 			else if (((tmp >> 2) & 0x1) == 0x1)
1643*4882a593Smuzhiyun 				return -EIO;
1644*4882a593Smuzhiyun 		}
1645*4882a593Smuzhiyun 		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
1646*4882a593Smuzhiyun 		writel(0x00003f7c, (&denali_pi[175]));
1647*4882a593Smuzhiyun 	}
1648*4882a593Smuzhiyun 	clrbits_le32(&denali_pi[80], 0x3 << 16);
1649*4882a593Smuzhiyun 
1650*4882a593Smuzhiyun 	return 0;
1651*4882a593Smuzhiyun }
1652*4882a593Smuzhiyun 
data_training_wdql(const struct chan_info * chan,u32 channel,const struct rk3399_sdram_params * sdram_params)1653*4882a593Smuzhiyun static int data_training_wdql(const struct chan_info *chan, u32 channel,
1654*4882a593Smuzhiyun 			      const struct rk3399_sdram_params *sdram_params)
1655*4882a593Smuzhiyun {
1656*4882a593Smuzhiyun 	u32 *denali_pi = chan->pi->denali_pi;
1657*4882a593Smuzhiyun 	u32 i, tmp;
1658*4882a593Smuzhiyun 	u32 rank = sdram_params->ch[channel].cap_info.rank;
1659*4882a593Smuzhiyun 	u32 rank_mask;
1660*4882a593Smuzhiyun 
1661*4882a593Smuzhiyun 	/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
1662*4882a593Smuzhiyun 	writel(0x00003f7c, (&denali_pi[175]));
1663*4882a593Smuzhiyun 
1664*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4)
1665*4882a593Smuzhiyun 		rank_mask = (rank == 1) ? 0x5 : 0xf;
1666*4882a593Smuzhiyun 	else
1667*4882a593Smuzhiyun 		rank_mask = (rank == 1) ? 0x1 : 0x3;
1668*4882a593Smuzhiyun 
1669*4882a593Smuzhiyun 	for (i = 0; i < 4; i++) {
1670*4882a593Smuzhiyun 		if (!(rank_mask & (1 << i)))
1671*4882a593Smuzhiyun 			continue;
1672*4882a593Smuzhiyun 
1673*4882a593Smuzhiyun 		select_per_cs_training_index(chan, i);
1674*4882a593Smuzhiyun 		/*
1675*4882a593Smuzhiyun 		 * disable PI_WDQLVL_VREF_EN before wdq leveling?
1676*4882a593Smuzhiyun 		 * PI_117 PI_WDQLVL_VREF_EN:RW:8:1
1677*4882a593Smuzhiyun 		 */
1678*4882a593Smuzhiyun 		clrbits_le32(&denali_pi[117], 0x1 << 8);
1679*4882a593Smuzhiyun 		/* PI_124 PI_WDQLVL_EN:RW:16:2 */
1680*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[124], 0x3 << 16, 0x2 << 16);
1681*4882a593Smuzhiyun 		/* PI_121 PI_WDQLVL_REQ:WR:8:1,PI_WDQLVL_CS:RW:16:2 */
1682*4882a593Smuzhiyun 		clrsetbits_le32(&denali_pi[121],
1683*4882a593Smuzhiyun 				(0x1 << 8) | (0x3 << 16),
1684*4882a593Smuzhiyun 				(0x1 << 8) | (i << 16));
1685*4882a593Smuzhiyun 
1686*4882a593Smuzhiyun 		/* Waiting for training complete */
1687*4882a593Smuzhiyun 		while (1) {
1688*4882a593Smuzhiyun 			/* PI_174 PI_INT_STATUS:RD:8:18 */
1689*4882a593Smuzhiyun 			tmp = readl(&denali_pi[174]) >> 8;
1690*4882a593Smuzhiyun 			if ((((tmp >> 12) & 0x1) == 0x1) &&
1691*4882a593Smuzhiyun 			    (((tmp >> 13) & 0x1) == 0x1) &&
1692*4882a593Smuzhiyun 			    (((tmp >> 6) & 0x1) == 0x0))
1693*4882a593Smuzhiyun 				break;
1694*4882a593Smuzhiyun 			else if (((tmp >> 6) & 0x1) == 0x1)
1695*4882a593Smuzhiyun 				return -EIO;
1696*4882a593Smuzhiyun 		}
1697*4882a593Smuzhiyun 		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
1698*4882a593Smuzhiyun 		writel(0x00003f7c, (&denali_pi[175]));
1699*4882a593Smuzhiyun 	}
1700*4882a593Smuzhiyun 	clrbits_le32(&denali_pi[124], 0x3 << 16);
1701*4882a593Smuzhiyun 
1702*4882a593Smuzhiyun 	return 0;
1703*4882a593Smuzhiyun }
1704*4882a593Smuzhiyun 
data_training(const struct chan_info * chan,u32 channel,const struct rk3399_sdram_params * sdram_params,u32 training_flag)1705*4882a593Smuzhiyun static int data_training(const struct chan_info *chan, u32 channel,
1706*4882a593Smuzhiyun 			 const struct rk3399_sdram_params *sdram_params,
1707*4882a593Smuzhiyun 			 u32 training_flag)
1708*4882a593Smuzhiyun {
1709*4882a593Smuzhiyun 	u32 *denali_phy = chan->publ->denali_phy;
1710*4882a593Smuzhiyun 	int ret = 0;
1711*4882a593Smuzhiyun 
1712*4882a593Smuzhiyun 	/* PHY_927 PHY_PAD_DQS_DRIVE  RPULL offset_22 */
1713*4882a593Smuzhiyun 	setbits_le32(&denali_phy[927], (1 << 22));
1714*4882a593Smuzhiyun 
1715*4882a593Smuzhiyun 	if (training_flag == PI_FULL_TRAINING) {
1716*4882a593Smuzhiyun 		if (sdram_params->base.dramtype == LPDDR4) {
1717*4882a593Smuzhiyun 			training_flag = PI_WRITE_LEVELING |
1718*4882a593Smuzhiyun 					PI_READ_GATE_TRAINING |
1719*4882a593Smuzhiyun 					PI_READ_LEVELING | PI_WDQ_LEVELING;
1720*4882a593Smuzhiyun 		} else if (sdram_params->base.dramtype == LPDDR3) {
1721*4882a593Smuzhiyun 			training_flag = PI_CA_TRAINING | PI_WRITE_LEVELING |
1722*4882a593Smuzhiyun 					PI_READ_GATE_TRAINING;
1723*4882a593Smuzhiyun 		} else if (sdram_params->base.dramtype == DDR3) {
1724*4882a593Smuzhiyun 			training_flag = PI_WRITE_LEVELING |
1725*4882a593Smuzhiyun 					PI_READ_GATE_TRAINING |
1726*4882a593Smuzhiyun 					PI_READ_LEVELING;
1727*4882a593Smuzhiyun 		}
1728*4882a593Smuzhiyun 	}
1729*4882a593Smuzhiyun 
1730*4882a593Smuzhiyun 	/* ca training(LPDDR4,LPDDR3 support) */
1731*4882a593Smuzhiyun 	if ((training_flag & PI_CA_TRAINING) == PI_CA_TRAINING) {
1732*4882a593Smuzhiyun 		ret = data_training_ca(chan, channel, sdram_params);
1733*4882a593Smuzhiyun 		if (ret != 0)
1734*4882a593Smuzhiyun 			goto out;
1735*4882a593Smuzhiyun 	}
1736*4882a593Smuzhiyun 
1737*4882a593Smuzhiyun 	/* write leveling(LPDDR4,LPDDR3,DDR3 support) */
1738*4882a593Smuzhiyun 	if ((training_flag & PI_WRITE_LEVELING) == PI_WRITE_LEVELING) {
1739*4882a593Smuzhiyun 		ret = data_training_wl(chan, channel, sdram_params);
1740*4882a593Smuzhiyun 		if (ret != 0)
1741*4882a593Smuzhiyun 			goto out;
1742*4882a593Smuzhiyun 	}
1743*4882a593Smuzhiyun 
1744*4882a593Smuzhiyun 	/* read gate training(LPDDR4,LPDDR3,DDR3 support) */
1745*4882a593Smuzhiyun 	if ((training_flag & PI_READ_GATE_TRAINING) == PI_READ_GATE_TRAINING) {
1746*4882a593Smuzhiyun 		ret = data_training_rg(chan, channel, sdram_params);
1747*4882a593Smuzhiyun 		if (ret != 0)
1748*4882a593Smuzhiyun 			goto out;
1749*4882a593Smuzhiyun 	}
1750*4882a593Smuzhiyun 
1751*4882a593Smuzhiyun 	/* read leveling(LPDDR4,LPDDR3,DDR3 support) */
1752*4882a593Smuzhiyun 	if ((training_flag & PI_READ_LEVELING) == PI_READ_LEVELING) {
1753*4882a593Smuzhiyun 		ret = data_training_rl(chan, channel, sdram_params);
1754*4882a593Smuzhiyun 		if (ret != 0)
1755*4882a593Smuzhiyun 			goto out;
1756*4882a593Smuzhiyun 	}
1757*4882a593Smuzhiyun 
1758*4882a593Smuzhiyun 	/* wdq leveling(LPDDR4 support) */
1759*4882a593Smuzhiyun 	if ((training_flag & PI_WDQ_LEVELING) == PI_WDQ_LEVELING) {
1760*4882a593Smuzhiyun 		ret = data_training_wdql(chan, channel, sdram_params);
1761*4882a593Smuzhiyun 		if (ret != 0)
1762*4882a593Smuzhiyun 			goto out;
1763*4882a593Smuzhiyun 	}
1764*4882a593Smuzhiyun 
1765*4882a593Smuzhiyun 	/* PHY_927 PHY_PAD_DQS_DRIVE  RPULL offset_22 */
1766*4882a593Smuzhiyun 	clrbits_le32(&denali_phy[927], (1 << 22));
1767*4882a593Smuzhiyun 
1768*4882a593Smuzhiyun out:
1769*4882a593Smuzhiyun 	return ret;
1770*4882a593Smuzhiyun }
1771*4882a593Smuzhiyun 
set_ddrconfig(const struct chan_info * chan,const struct rk3399_sdram_params * sdram_params,unsigned char channel,u32 ddrconfig)1772*4882a593Smuzhiyun static void set_ddrconfig(const struct chan_info *chan,
1773*4882a593Smuzhiyun 			  const struct rk3399_sdram_params *sdram_params,
1774*4882a593Smuzhiyun 			  unsigned char channel, u32 ddrconfig)
1775*4882a593Smuzhiyun {
1776*4882a593Smuzhiyun 	/* only need to set ddrconfig */
1777*4882a593Smuzhiyun 	struct msch_regs *ddr_msch_regs = chan->msch;
1778*4882a593Smuzhiyun 	unsigned int cs0_cap = 0;
1779*4882a593Smuzhiyun 	unsigned int cs1_cap = 0;
1780*4882a593Smuzhiyun 
1781*4882a593Smuzhiyun 	cs0_cap = (1 << (sdram_params->ch[channel].cap_info.cs0_row
1782*4882a593Smuzhiyun 			+ sdram_params->ch[channel].cap_info.col
1783*4882a593Smuzhiyun 			+ sdram_params->ch[channel].cap_info.bk
1784*4882a593Smuzhiyun 			+ sdram_params->ch[channel].cap_info.bw - 20));
1785*4882a593Smuzhiyun 	if (sdram_params->ch[channel].cap_info.rank > 1)
1786*4882a593Smuzhiyun 		cs1_cap = cs0_cap >> (sdram_params->ch[channel].cap_info.cs0_row
1787*4882a593Smuzhiyun 				- sdram_params->ch[channel].cap_info.cs1_row);
1788*4882a593Smuzhiyun 	if (sdram_params->ch[channel].cap_info.row_3_4) {
1789*4882a593Smuzhiyun 		cs0_cap = cs0_cap * 3 / 4;
1790*4882a593Smuzhiyun 		cs1_cap = cs1_cap * 3 / 4;
1791*4882a593Smuzhiyun 	}
1792*4882a593Smuzhiyun 
1793*4882a593Smuzhiyun 	writel(ddrconfig | (ddrconfig << 8), &ddr_msch_regs->ddrconf);
1794*4882a593Smuzhiyun 	writel(((cs0_cap / 32) & 0xff) | (((cs1_cap / 32) & 0xff) << 8),
1795*4882a593Smuzhiyun 	       &ddr_msch_regs->ddrsize);
1796*4882a593Smuzhiyun }
1797*4882a593Smuzhiyun 
sdram_msch_config(struct msch_regs * msch,struct sdram_msch_timings * noc_timings)1798*4882a593Smuzhiyun static void sdram_msch_config(struct msch_regs *msch,
1799*4882a593Smuzhiyun 			      struct sdram_msch_timings *noc_timings)
1800*4882a593Smuzhiyun {
1801*4882a593Smuzhiyun 	writel(noc_timings->ddrtiminga0.d32,
1802*4882a593Smuzhiyun 	       &msch->ddrtiminga0.d32);
1803*4882a593Smuzhiyun 	writel(noc_timings->ddrtimingb0.d32,
1804*4882a593Smuzhiyun 	       &msch->ddrtimingb0.d32);
1805*4882a593Smuzhiyun 	writel(noc_timings->ddrtimingc0.d32,
1806*4882a593Smuzhiyun 	       &msch->ddrtimingc0.d32);
1807*4882a593Smuzhiyun 	writel(noc_timings->devtodev0.d32,
1808*4882a593Smuzhiyun 	       &msch->devtodev0.d32);
1809*4882a593Smuzhiyun 	writel(noc_timings->ddrmode.d32,
1810*4882a593Smuzhiyun 	       &msch->ddrmode.d32);
1811*4882a593Smuzhiyun }
1812*4882a593Smuzhiyun 
dram_all_config(struct dram_info * dram,struct rk3399_sdram_params * sdram_params)1813*4882a593Smuzhiyun static void dram_all_config(struct dram_info *dram,
1814*4882a593Smuzhiyun 			    struct rk3399_sdram_params *sdram_params)
1815*4882a593Smuzhiyun {
1816*4882a593Smuzhiyun 	u32 sys_reg2 = 0;
1817*4882a593Smuzhiyun 	u32 sys_reg3 = 0;
1818*4882a593Smuzhiyun 	unsigned int channel, idx;
1819*4882a593Smuzhiyun 
1820*4882a593Smuzhiyun 	for (channel = 0, idx = 0;
1821*4882a593Smuzhiyun 	     (idx < sdram_params->base.num_channels) && (channel < 2);
1822*4882a593Smuzhiyun 	     channel++) {
1823*4882a593Smuzhiyun 		struct msch_regs *ddr_msch_regs;
1824*4882a593Smuzhiyun 		struct sdram_msch_timings *noc_timing;
1825*4882a593Smuzhiyun 
1826*4882a593Smuzhiyun 		if (sdram_params->ch[channel].cap_info.col == 0)
1827*4882a593Smuzhiyun 			continue;
1828*4882a593Smuzhiyun 		idx++;
1829*4882a593Smuzhiyun 		sdram_org_config(&sdram_params->ch[channel].cap_info,
1830*4882a593Smuzhiyun 				 &sdram_params->base, &sys_reg2,
1831*4882a593Smuzhiyun 				 &sys_reg3, channel);
1832*4882a593Smuzhiyun 		ddr_msch_regs = dram->chan[channel].msch;
1833*4882a593Smuzhiyun 		noc_timing = &sdram_params->ch[channel].noc_timings;
1834*4882a593Smuzhiyun 		sdram_msch_config(ddr_msch_regs, noc_timing);
1835*4882a593Smuzhiyun 
1836*4882a593Smuzhiyun 		/* rank 1 memory clock disable (dfi_dram_clk_disable = 1) */
1837*4882a593Smuzhiyun 		if (sdram_params->ch[channel].cap_info.rank == 1)
1838*4882a593Smuzhiyun 			setbits_le32(&dram->chan[channel].pctl->denali_ctl[276],
1839*4882a593Smuzhiyun 				     1 << 17);
1840*4882a593Smuzhiyun 	}
1841*4882a593Smuzhiyun 
1842*4882a593Smuzhiyun 	writel(sys_reg2, &dram->pmugrf->os_reg2);
1843*4882a593Smuzhiyun 	writel(sys_reg3, &dram->pmugrf->os_reg3);
1844*4882a593Smuzhiyun 	rk_clrsetreg(&dram->pmusgrf->soc_con4, 0x1f << 10,
1845*4882a593Smuzhiyun 		     sdram_params->base.stride << 10);
1846*4882a593Smuzhiyun 
1847*4882a593Smuzhiyun 	/* reboot hold register set */
1848*4882a593Smuzhiyun 	writel(PRESET_SGRF_HOLD(0) | PRESET_GPIO0_HOLD(1) |
1849*4882a593Smuzhiyun 		PRESET_GPIO1_HOLD(1),
1850*4882a593Smuzhiyun 		&dram->pmucru->pmucru_rstnhold_con[1]);
1851*4882a593Smuzhiyun 	clrsetbits_le32(&dram->cru->glb_rst_con, 0x3, 0x3);
1852*4882a593Smuzhiyun }
1853*4882a593Smuzhiyun 
switch_to_phy_index1(struct dram_info * dram,const struct rk3399_sdram_params * sdram_params)1854*4882a593Smuzhiyun static int switch_to_phy_index1(struct dram_info *dram,
1855*4882a593Smuzhiyun 				const struct rk3399_sdram_params *sdram_params)
1856*4882a593Smuzhiyun {
1857*4882a593Smuzhiyun 	u32 channel;
1858*4882a593Smuzhiyun 	u32 *denali_phy;
1859*4882a593Smuzhiyun 	u32 ch_count = sdram_params->base.num_channels;
1860*4882a593Smuzhiyun 	int ret;
1861*4882a593Smuzhiyun 	int i = 0;
1862*4882a593Smuzhiyun 
1863*4882a593Smuzhiyun 	writel(RK_CLRSETBITS(0x03 << 4 | 1 << 2 | 1,
1864*4882a593Smuzhiyun 			     1 << 4 | 1 << 2 | 1),
1865*4882a593Smuzhiyun 			&dram->cic->cic_ctrl0);
1866*4882a593Smuzhiyun 	while (!(readl(&dram->cic->cic_status0) & (1 << 2))) {
1867*4882a593Smuzhiyun 		mdelay(10);
1868*4882a593Smuzhiyun 		i++;
1869*4882a593Smuzhiyun 		if (i > 10) {
1870*4882a593Smuzhiyun 			debug("index1 frequency change overtime\n");
1871*4882a593Smuzhiyun 			return -ETIME;
1872*4882a593Smuzhiyun 		}
1873*4882a593Smuzhiyun 	}
1874*4882a593Smuzhiyun 
1875*4882a593Smuzhiyun 	i = 0;
1876*4882a593Smuzhiyun 	writel(RK_CLRSETBITS(1 << 1, 1 << 1), &dram->cic->cic_ctrl0);
1877*4882a593Smuzhiyun 	while (!(readl(&dram->cic->cic_status0) & (1 << 0))) {
1878*4882a593Smuzhiyun 		mdelay(10);
1879*4882a593Smuzhiyun 		if (i > 10) {
1880*4882a593Smuzhiyun 			debug("index1 frequency done overtime\n");
1881*4882a593Smuzhiyun 			return -ETIME;
1882*4882a593Smuzhiyun 		}
1883*4882a593Smuzhiyun 	}
1884*4882a593Smuzhiyun 
1885*4882a593Smuzhiyun 	for (channel = 0; channel < ch_count; channel++) {
1886*4882a593Smuzhiyun 		denali_phy = dram->chan[channel].publ->denali_phy;
1887*4882a593Smuzhiyun 		clrsetbits_le32(&denali_phy[896], (0x3 << 8) | 1, 1 << 8);
1888*4882a593Smuzhiyun 		ret = data_training(&dram->chan[channel], channel,
1889*4882a593Smuzhiyun 				    sdram_params, PI_FULL_TRAINING);
1890*4882a593Smuzhiyun 		if (ret) {
1891*4882a593Smuzhiyun 			debug("index1 training failed\n");
1892*4882a593Smuzhiyun 			return ret;
1893*4882a593Smuzhiyun 		}
1894*4882a593Smuzhiyun 	}
1895*4882a593Smuzhiyun 
1896*4882a593Smuzhiyun 	return 0;
1897*4882a593Smuzhiyun }
1898*4882a593Smuzhiyun 
1899*4882a593Smuzhiyun u16  ddr_cfg_2_rbc[] = {
1900*4882a593Smuzhiyun 		/*
1901*4882a593Smuzhiyun 		 * [6]	  highest bit col
1902*4882a593Smuzhiyun 		 * [5:3]  max row(14+n)
1903*4882a593Smuzhiyun 		 * [2]    insertion row
1904*4882a593Smuzhiyun 		 * [1:0]  col(9+n),col, data bus 32bit
1905*4882a593Smuzhiyun 		 *
1906*4882a593Smuzhiyun 		 * highbitcol, max_row, insertion_row,  col
1907*4882a593Smuzhiyun 		 */
1908*4882a593Smuzhiyun 		((0 << 6) | (2 << 3) | (0 << 2) | 0), /* 0 */
1909*4882a593Smuzhiyun 		((0 << 6) | (2 << 3) | (0 << 2) | 1), /* 1 */
1910*4882a593Smuzhiyun 		((0 << 6) | (1 << 3) | (0 << 2) | 2), /* 2 */
1911*4882a593Smuzhiyun 		((0 << 6) | (0 << 3) | (0 << 2) | 3), /* 3 */
1912*4882a593Smuzhiyun 		((0 << 6) | (2 << 3) | (1 << 2) | 1), /* 4 */
1913*4882a593Smuzhiyun 		((0 << 6) | (1 << 3) | (1 << 2) | 2), /* 5 */
1914*4882a593Smuzhiyun 		((1 << 6) | (0 << 3) | (0 << 2) | 2), /* 6 */
1915*4882a593Smuzhiyun 		((1 << 6) | (1 << 3) | (0 << 2) | 2), /* 7 */
1916*4882a593Smuzhiyun };
1917*4882a593Smuzhiyun 
calculate_ddrconfig(struct rk3399_sdram_params * sdram_params,u32 channel)1918*4882a593Smuzhiyun static u32 calculate_ddrconfig(struct rk3399_sdram_params *sdram_params,
1919*4882a593Smuzhiyun 			       u32 channel)
1920*4882a593Smuzhiyun {
1921*4882a593Smuzhiyun 	unsigned int i;
1922*4882a593Smuzhiyun 	unsigned int cs0_row = sdram_params->ch[channel].cap_info.cs0_row;
1923*4882a593Smuzhiyun 	unsigned int col = sdram_params->ch[channel].cap_info.col;
1924*4882a593Smuzhiyun 	unsigned int bw = sdram_params->ch[channel].cap_info.bw;
1925*4882a593Smuzhiyun 
1926*4882a593Smuzhiyun 	col -= (bw == 2) ? 0 : 1;
1927*4882a593Smuzhiyun 	col -= 9;
1928*4882a593Smuzhiyun 
1929*4882a593Smuzhiyun 	for (i = 0; i < 4; i++) {
1930*4882a593Smuzhiyun 		if ((col == (ddr_cfg_2_rbc[i] & 0x3)) &&
1931*4882a593Smuzhiyun 		    (cs0_row <= (((ddr_cfg_2_rbc[i] >> 3) & 0x7) + 14)))
1932*4882a593Smuzhiyun 			break;
1933*4882a593Smuzhiyun 	}
1934*4882a593Smuzhiyun 
1935*4882a593Smuzhiyun 	if (i >= 4)
1936*4882a593Smuzhiyun 		i = -1;
1937*4882a593Smuzhiyun 
1938*4882a593Smuzhiyun 	return i;
1939*4882a593Smuzhiyun }
1940*4882a593Smuzhiyun 
calculate_stride(struct rk3399_sdram_params * sdram_params)1941*4882a593Smuzhiyun static unsigned char calculate_stride(struct rk3399_sdram_params *sdram_params)
1942*4882a593Smuzhiyun {
1943*4882a593Smuzhiyun 	unsigned int gstride_type;
1944*4882a593Smuzhiyun 	unsigned int channel;
1945*4882a593Smuzhiyun 	unsigned int chinfo = 0;
1946*4882a593Smuzhiyun 	unsigned int cap = 0;
1947*4882a593Smuzhiyun 	unsigned int stride = -1;
1948*4882a593Smuzhiyun 	unsigned int ch_cap[2] = {0, 0};
1949*4882a593Smuzhiyun 
1950*4882a593Smuzhiyun 	gstride_type = STRIDE_256B;
1951*4882a593Smuzhiyun 
1952*4882a593Smuzhiyun 	for (channel = 0; channel < 2; channel++) {
1953*4882a593Smuzhiyun 		unsigned int cs0_cap = 0;
1954*4882a593Smuzhiyun 		unsigned int cs1_cap = 0;
1955*4882a593Smuzhiyun 		struct sdram_cap_info *cap_info =
1956*4882a593Smuzhiyun 			&sdram_params->ch[channel].cap_info;
1957*4882a593Smuzhiyun 
1958*4882a593Smuzhiyun 		if (cap_info->col == 0)
1959*4882a593Smuzhiyun 			continue;
1960*4882a593Smuzhiyun 
1961*4882a593Smuzhiyun 		cs0_cap = (1 << (cap_info->cs0_row + cap_info->col +
1962*4882a593Smuzhiyun 				 cap_info->bk + cap_info->bw - 20));
1963*4882a593Smuzhiyun 		if (cap_info->rank > 1)
1964*4882a593Smuzhiyun 			cs1_cap = cs0_cap >> (cap_info->cs0_row
1965*4882a593Smuzhiyun 					      - cap_info->cs1_row);
1966*4882a593Smuzhiyun 		if (cap_info->row_3_4) {
1967*4882a593Smuzhiyun 			cs0_cap = cs0_cap * 3 / 4;
1968*4882a593Smuzhiyun 			cs1_cap = cs1_cap * 3 / 4;
1969*4882a593Smuzhiyun 		}
1970*4882a593Smuzhiyun 		ch_cap[channel] = cs0_cap + cs1_cap;
1971*4882a593Smuzhiyun 		chinfo |= 1 << channel;
1972*4882a593Smuzhiyun 	}
1973*4882a593Smuzhiyun 
1974*4882a593Smuzhiyun 	cap = ch_cap[0] + ch_cap[1];
1975*4882a593Smuzhiyun 	if (sdram_params->base.num_channels == 1) {
1976*4882a593Smuzhiyun 		if (chinfo & 1) /* channel a only */
1977*4882a593Smuzhiyun 			stride = 0x17;
1978*4882a593Smuzhiyun 		else /* channel b only */
1979*4882a593Smuzhiyun 			stride = 0x18;
1980*4882a593Smuzhiyun 	} else {/* 2 channel */
1981*4882a593Smuzhiyun 		if (ch_cap[0] == ch_cap[1]) {
1982*4882a593Smuzhiyun 			/* interleaved */
1983*4882a593Smuzhiyun 			if (gstride_type == PART_STRIDE) {
1984*4882a593Smuzhiyun 			/*
1985*4882a593Smuzhiyun 			 * first 64MB no interleaved other 256B interleaved
1986*4882a593Smuzhiyun 			 * if 786M+768M.useful space from 0-1280MB and
1987*4882a593Smuzhiyun 			 * 1536MB-1792MB
1988*4882a593Smuzhiyun 			 * if 1.5G+1.5G(continuous).useful space from 0-2560MB
1989*4882a593Smuzhiyun 			 * and 3072MB-3584MB
1990*4882a593Smuzhiyun 			 */
1991*4882a593Smuzhiyun 				stride = 0x1F;
1992*4882a593Smuzhiyun 			} else {
1993*4882a593Smuzhiyun 				switch (cap) {
1994*4882a593Smuzhiyun 				/* 512MB */
1995*4882a593Smuzhiyun 				case 512:
1996*4882a593Smuzhiyun 					stride = 0;
1997*4882a593Smuzhiyun 					break;
1998*4882a593Smuzhiyun 				/* 1GB unstride or 256B stride*/
1999*4882a593Smuzhiyun 				case 1024:
2000*4882a593Smuzhiyun 					stride = (gstride_type == UN_STRIDE) ?
2001*4882a593Smuzhiyun 						0x1 : 0x5;
2002*4882a593Smuzhiyun 					break;
2003*4882a593Smuzhiyun 				/*
2004*4882a593Smuzhiyun 				 * 768MB + 768MB same as total 2GB memory
2005*4882a593Smuzhiyun 				 * useful space: 0-768MB 1GB-1792MB
2006*4882a593Smuzhiyun 				 */
2007*4882a593Smuzhiyun 				case 1536:
2008*4882a593Smuzhiyun 				/* 2GB unstride or 256B or 512B stride */
2009*4882a593Smuzhiyun 				case 2048:
2010*4882a593Smuzhiyun 					stride = (gstride_type == UN_STRIDE) ?
2011*4882a593Smuzhiyun 						0x2 :
2012*4882a593Smuzhiyun 						((gstride_type == STRIDE_512B) ?
2013*4882a593Smuzhiyun 						 0xA : 0x9);
2014*4882a593Smuzhiyun 					break;
2015*4882a593Smuzhiyun 				/* 1536MB + 1536MB */
2016*4882a593Smuzhiyun 				case 3072:
2017*4882a593Smuzhiyun 					stride = (gstride_type == UN_STRIDE) ?
2018*4882a593Smuzhiyun 						0x3 :
2019*4882a593Smuzhiyun 						((gstride_type == STRIDE_512B) ?
2020*4882a593Smuzhiyun 						 0x12 : 0x11);
2021*4882a593Smuzhiyun 					break;
2022*4882a593Smuzhiyun 				/* 4GB  unstride or 128B,256B,512B,4KB stride */
2023*4882a593Smuzhiyun 				case 4096:
2024*4882a593Smuzhiyun 					stride = (gstride_type == UN_STRIDE) ?
2025*4882a593Smuzhiyun 						0x3 : (0xC + gstride_type);
2026*4882a593Smuzhiyun 					break;
2027*4882a593Smuzhiyun 				}
2028*4882a593Smuzhiyun 			}
2029*4882a593Smuzhiyun 		}
2030*4882a593Smuzhiyun 		if (ch_cap[0] == 2048 && ch_cap[1] == 1024) {
2031*4882a593Smuzhiyun 			/* 2GB + 1GB */
2032*4882a593Smuzhiyun 			stride = (gstride_type == UN_STRIDE) ? 0x3 : 0x19;
2033*4882a593Smuzhiyun 		}
2034*4882a593Smuzhiyun 		/*
2035*4882a593Smuzhiyun 		 * remain two channel capability not equal OR capability
2036*4882a593Smuzhiyun 		 * power function of 2
2037*4882a593Smuzhiyun 		 */
2038*4882a593Smuzhiyun 		if (stride == (-1)) {
2039*4882a593Smuzhiyun 			switch ((ch_cap[0] > ch_cap[1]) ?
2040*4882a593Smuzhiyun 				ch_cap[0] : ch_cap[1]) {
2041*4882a593Smuzhiyun 			case 256: /* 256MB + 128MB */
2042*4882a593Smuzhiyun 				stride = 0;
2043*4882a593Smuzhiyun 				break;
2044*4882a593Smuzhiyun 			case 512: /* 512MB + 256MB */
2045*4882a593Smuzhiyun 				stride = 1;
2046*4882a593Smuzhiyun 				break;
2047*4882a593Smuzhiyun 			case 1024:/* 1GB + 128MB/256MB/384MB/512MB/768MB */
2048*4882a593Smuzhiyun 				stride = 2;
2049*4882a593Smuzhiyun 				break;
2050*4882a593Smuzhiyun 			case 2048: /* 2GB + 128MB/256MB/384MB/512MB/768MB/1GB */
2051*4882a593Smuzhiyun 				stride = 3;
2052*4882a593Smuzhiyun 				break;
2053*4882a593Smuzhiyun 			default:
2054*4882a593Smuzhiyun 				break;
2055*4882a593Smuzhiyun 			}
2056*4882a593Smuzhiyun 		}
2057*4882a593Smuzhiyun 		if (stride == (-1))
2058*4882a593Smuzhiyun 			goto error;
2059*4882a593Smuzhiyun 	}
2060*4882a593Smuzhiyun 	switch (stride) {
2061*4882a593Smuzhiyun 	case 0xc:
2062*4882a593Smuzhiyun 		printf("128B stride\n");
2063*4882a593Smuzhiyun 		break;
2064*4882a593Smuzhiyun 	case 5:
2065*4882a593Smuzhiyun 	case 9:
2066*4882a593Smuzhiyun 	case 0xd:
2067*4882a593Smuzhiyun 	case 0x11:
2068*4882a593Smuzhiyun 	case 0x19:
2069*4882a593Smuzhiyun 		printf("256B stride\n");
2070*4882a593Smuzhiyun 		break;
2071*4882a593Smuzhiyun 	case 0xa:
2072*4882a593Smuzhiyun 	case 0xe:
2073*4882a593Smuzhiyun 	case 0x12:
2074*4882a593Smuzhiyun 		printf("512B stride\n");
2075*4882a593Smuzhiyun 		break;
2076*4882a593Smuzhiyun 	case 0xf:
2077*4882a593Smuzhiyun 		printf("4K stride\n");
2078*4882a593Smuzhiyun 		break;
2079*4882a593Smuzhiyun 	case 0x1f:
2080*4882a593Smuzhiyun 		printf("32MB + 256B stride\n");
2081*4882a593Smuzhiyun 		break;
2082*4882a593Smuzhiyun 	default:
2083*4882a593Smuzhiyun 		printf("no stride\n");
2084*4882a593Smuzhiyun 	}
2085*4882a593Smuzhiyun 
2086*4882a593Smuzhiyun 	return stride;
2087*4882a593Smuzhiyun error:
2088*4882a593Smuzhiyun 	printf("Cap not support!\n");
2089*4882a593Smuzhiyun 	return (-1);
2090*4882a593Smuzhiyun }
2091*4882a593Smuzhiyun 
get_ddr_stride(struct rk3399_pmusgrf_regs * pmusgrf)2092*4882a593Smuzhiyun static u32 get_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf)
2093*4882a593Smuzhiyun {
2094*4882a593Smuzhiyun 	u32 val;
2095*4882a593Smuzhiyun 
2096*4882a593Smuzhiyun 	val = (readl(&pmusgrf->soc_con4) >> 10) & 0x1F;
2097*4882a593Smuzhiyun 
2098*4882a593Smuzhiyun 	return val;
2099*4882a593Smuzhiyun }
2100*4882a593Smuzhiyun 
set_ddr_stride(struct rk3399_pmusgrf_regs * pmusgrf,u32 stride)2101*4882a593Smuzhiyun static void set_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf, u32 stride)
2102*4882a593Smuzhiyun {
2103*4882a593Smuzhiyun 	rk_clrsetreg(&pmusgrf->soc_con4, 0x1f << 10,
2104*4882a593Smuzhiyun 		     stride << 10);
2105*4882a593Smuzhiyun }
2106*4882a593Smuzhiyun 
set_cap_relate_config(const struct chan_info * chan,struct rk3399_sdram_params * sdram_params,unsigned int channel)2107*4882a593Smuzhiyun static void set_cap_relate_config(const struct chan_info *chan,
2108*4882a593Smuzhiyun 				  struct rk3399_sdram_params *sdram_params,
2109*4882a593Smuzhiyun 				  unsigned int channel)
2110*4882a593Smuzhiyun {
2111*4882a593Smuzhiyun 	u32 *denali_ctl = chan->pctl->denali_ctl;
2112*4882a593Smuzhiyun 	u32 tmp;
2113*4882a593Smuzhiyun 	struct sdram_msch_timings *noc_timing;
2114*4882a593Smuzhiyun 
2115*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR3) {
2116*4882a593Smuzhiyun 		tmp = (8 << sdram_params->ch[channel].cap_info.bw) /
2117*4882a593Smuzhiyun 			(8 << sdram_params->ch[channel].cap_info.dbw);
2118*4882a593Smuzhiyun 		/* memdata_ratio
2119*4882a593Smuzhiyun 		 * 1 -> 0, 2 -> 1, 4 -> 2
2120*4882a593Smuzhiyun 		 */
2121*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[197], 0x7,
2122*4882a593Smuzhiyun 				(tmp >> 1));
2123*4882a593Smuzhiyun 		clrsetbits_le32(&denali_ctl[198], 0x7 << 8,
2124*4882a593Smuzhiyun 				(tmp >> 1) << 8);
2125*4882a593Smuzhiyun 	}
2126*4882a593Smuzhiyun 	noc_timing = &sdram_params->ch[channel].noc_timings;
2127*4882a593Smuzhiyun 	/*
2128*4882a593Smuzhiyun 	 * noc timing bw relate timing is 32 bit, and real bw is 16bit
2129*4882a593Smuzhiyun 	 * actually noc reg is setting at function dram_all_config
2130*4882a593Smuzhiyun 	 */
2131*4882a593Smuzhiyun 	if (sdram_params->ch[channel].cap_info.bw == 16 &&
2132*4882a593Smuzhiyun 	    noc_timing->ddrmode.b.mwrsize == 2) {
2133*4882a593Smuzhiyun 		if (noc_timing->ddrmode.b.burstsize)
2134*4882a593Smuzhiyun 			noc_timing->ddrmode.b.burstsize -= 1;
2135*4882a593Smuzhiyun 		noc_timing->ddrmode.b.mwrsize -= 1;
2136*4882a593Smuzhiyun 		noc_timing->ddrtimingc0.b.burstpenalty *= 2;
2137*4882a593Smuzhiyun 		noc_timing->ddrtimingc0.b.wrtomwr *= 2;
2138*4882a593Smuzhiyun 	}
2139*4882a593Smuzhiyun }
2140*4882a593Smuzhiyun 
clear_channel_params(struct rk3399_sdram_params * sdram_params,unsigned int channel)2141*4882a593Smuzhiyun static void clear_channel_params(struct rk3399_sdram_params *sdram_params,
2142*4882a593Smuzhiyun 				 unsigned int channel)
2143*4882a593Smuzhiyun {
2144*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.rank = 0;
2145*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.col = 0;
2146*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.bk = 0;
2147*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.bw = 32;
2148*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.dbw = 32;
2149*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.row_3_4 = 0;
2150*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.cs0_row = 0;
2151*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.cs1_row = 0;
2152*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.ddrconfig = 0;
2153*4882a593Smuzhiyun }
2154*4882a593Smuzhiyun 
2155*4882a593Smuzhiyun /* CS0,n=1
2156*4882a593Smuzhiyun  * CS1,n=2
2157*4882a593Smuzhiyun  * CS0 & CS1, n=3
2158*4882a593Smuzhiyun  * cs0_cap: MB unit
2159*4882a593Smuzhiyun  */
dram_set_cs(const struct chan_info * chan,u32 cs_map,u32 cs0_cap,unsigned char dramtype)2160*4882a593Smuzhiyun static void dram_set_cs(const struct chan_info *chan, u32 cs_map, u32 cs0_cap,
2161*4882a593Smuzhiyun 			unsigned char dramtype)
2162*4882a593Smuzhiyun {
2163*4882a593Smuzhiyun 	u32 *denali_ctl = chan->pctl->denali_ctl;
2164*4882a593Smuzhiyun 	u32 *denali_pi = chan->pi->denali_pi;
2165*4882a593Smuzhiyun 	struct msch_regs *ddr_msch_regs = chan->msch;
2166*4882a593Smuzhiyun 
2167*4882a593Smuzhiyun 	clrsetbits_le32(&denali_ctl[196], 0x3, cs_map);
2168*4882a593Smuzhiyun 	writel((cs0_cap / 32) | (((4096 - cs0_cap) / 32) << 8),
2169*4882a593Smuzhiyun 	       &ddr_msch_regs->ddrsize);
2170*4882a593Smuzhiyun 	if (dramtype == LPDDR4) {
2171*4882a593Smuzhiyun 		if (cs_map == 1)
2172*4882a593Smuzhiyun 			cs_map = 0x5;
2173*4882a593Smuzhiyun 		else if (cs_map == 2)
2174*4882a593Smuzhiyun 			cs_map = 0xa;
2175*4882a593Smuzhiyun 		else
2176*4882a593Smuzhiyun 			cs_map = 0xF;
2177*4882a593Smuzhiyun 	}
2178*4882a593Smuzhiyun 	/*PI_41 PI_CS_MAP:RW:24:4*/
2179*4882a593Smuzhiyun 	clrsetbits_le32(&denali_pi[41],
2180*4882a593Smuzhiyun 			0xf << 24, cs_map << 24);
2181*4882a593Smuzhiyun 	if (cs_map == 1 && dramtype == DDR3)
2182*4882a593Smuzhiyun 		writel(0x2EC7FFFF, &denali_pi[34]);
2183*4882a593Smuzhiyun }
2184*4882a593Smuzhiyun 
dram_set_bw(const struct chan_info * chan,u32 bw)2185*4882a593Smuzhiyun static void dram_set_bw(const struct chan_info *chan, u32 bw)
2186*4882a593Smuzhiyun {
2187*4882a593Smuzhiyun 	u32 *denali_ctl = chan->pctl->denali_ctl;
2188*4882a593Smuzhiyun 
2189*4882a593Smuzhiyun 	if (bw == 2)
2190*4882a593Smuzhiyun 		clrbits_le32(&denali_ctl[196], 1 << 16);
2191*4882a593Smuzhiyun 	else
2192*4882a593Smuzhiyun 		setbits_le32(&denali_ctl[196], 1 << 16);
2193*4882a593Smuzhiyun }
2194*4882a593Smuzhiyun 
dram_set_max_col(const struct chan_info * chan,u32 bw,u32 * pcol)2195*4882a593Smuzhiyun static void dram_set_max_col(const struct chan_info *chan, u32 bw, u32 *pcol)
2196*4882a593Smuzhiyun {
2197*4882a593Smuzhiyun 	u32 *denali_ctl = chan->pctl->denali_ctl;
2198*4882a593Smuzhiyun 	struct msch_regs *ddr_msch_regs = chan->msch;
2199*4882a593Smuzhiyun 	u32 *denali_pi = chan->pi->denali_pi;
2200*4882a593Smuzhiyun 	u32 ddrconfig;
2201*4882a593Smuzhiyun 
2202*4882a593Smuzhiyun 	clrbits_le32(&denali_ctl[191], 0xf);
2203*4882a593Smuzhiyun 	clrsetbits_le32(&denali_ctl[190],
2204*4882a593Smuzhiyun 			(7 << 24),
2205*4882a593Smuzhiyun 			((16 - ((bw == 2) ? 14 : 15)) << 24));
2206*4882a593Smuzhiyun 	/*PI_199 PI_COL_DIFF:RW:0:4*/
2207*4882a593Smuzhiyun 	clrbits_le32(&denali_pi[199], 0xf);
2208*4882a593Smuzhiyun 	/*PI_155 PI_ROW_DIFF:RW:24:3*/
2209*4882a593Smuzhiyun 	clrsetbits_le32(&denali_pi[155],
2210*4882a593Smuzhiyun 			(7 << 24),
2211*4882a593Smuzhiyun 			((16 - 12) << 24));
2212*4882a593Smuzhiyun 	ddrconfig = (bw == 2) ? 3 : 2;
2213*4882a593Smuzhiyun 	writel(ddrconfig | (ddrconfig << 8), &ddr_msch_regs->ddrconf);
2214*4882a593Smuzhiyun 	/* set max cs0 size */
2215*4882a593Smuzhiyun 	writel((4096 / 32) | ((0 / 32) << 8),
2216*4882a593Smuzhiyun 	       &ddr_msch_regs->ddrsize);
2217*4882a593Smuzhiyun 
2218*4882a593Smuzhiyun 	*pcol = 12;
2219*4882a593Smuzhiyun }
2220*4882a593Smuzhiyun 
dram_set_max_bank(const struct chan_info * chan,u32 bw,u32 * pbank,u32 * pcol)2221*4882a593Smuzhiyun static void dram_set_max_bank(const struct chan_info *chan, u32 bw, u32 *pbank,
2222*4882a593Smuzhiyun 			      u32 *pcol)
2223*4882a593Smuzhiyun {
2224*4882a593Smuzhiyun 	u32 *denali_ctl = chan->pctl->denali_ctl;
2225*4882a593Smuzhiyun 	u32 *denali_pi = chan->pi->denali_pi;
2226*4882a593Smuzhiyun 
2227*4882a593Smuzhiyun 	clrbits_le32(&denali_ctl[191], 0xf);
2228*4882a593Smuzhiyun 	clrbits_le32(&denali_ctl[190], (3 << 16));
2229*4882a593Smuzhiyun 	/*PI_199 PI_COL_DIFF:RW:0:4*/
2230*4882a593Smuzhiyun 	clrbits_le32(&denali_pi[199], 0xf);
2231*4882a593Smuzhiyun 	/*PI_155 PI_BANK_DIFF:RW:16:2*/
2232*4882a593Smuzhiyun 	clrbits_le32(&denali_pi[155], (3 << 16));
2233*4882a593Smuzhiyun 
2234*4882a593Smuzhiyun 	*pbank = 3;
2235*4882a593Smuzhiyun 	*pcol = 12;
2236*4882a593Smuzhiyun }
2237*4882a593Smuzhiyun 
dram_set_max_row(const struct chan_info * chan,u32 bw,u32 * prow,u32 * pbank,u32 * pcol)2238*4882a593Smuzhiyun static void dram_set_max_row(const struct chan_info *chan, u32 bw, u32 *prow,
2239*4882a593Smuzhiyun 			     u32 *pbank, u32 *pcol)
2240*4882a593Smuzhiyun {
2241*4882a593Smuzhiyun 	u32 *denali_ctl = chan->pctl->denali_ctl;
2242*4882a593Smuzhiyun 	u32 *denali_pi = chan->pi->denali_pi;
2243*4882a593Smuzhiyun 	struct msch_regs *ddr_msch_regs = chan->msch;
2244*4882a593Smuzhiyun 
2245*4882a593Smuzhiyun 	clrsetbits_le32(&denali_ctl[191], 0xf, 12 - 10);
2246*4882a593Smuzhiyun 	clrbits_le32(&denali_ctl[190],
2247*4882a593Smuzhiyun 		     (0x3 << 16) | (0x7 << 24));
2248*4882a593Smuzhiyun 	/*PI_199 PI_COL_DIFF:RW:0:4*/
2249*4882a593Smuzhiyun 	clrsetbits_le32(&denali_pi[199], 0xf, 12 - 10);
2250*4882a593Smuzhiyun 	/*PI_155 PI_ROW_DIFF:RW:24:3 PI_BANK_DIFF:RW:16:2*/
2251*4882a593Smuzhiyun 	clrbits_le32(&denali_pi[155],
2252*4882a593Smuzhiyun 		     (0x3 << 16) | (0x7 << 24));
2253*4882a593Smuzhiyun 	writel(1 | (1 << 8), &ddr_msch_regs->ddrconf);
2254*4882a593Smuzhiyun 	/* set max cs0 size */
2255*4882a593Smuzhiyun 	writel((4096 / 32) | ((0 / 32) << 8),
2256*4882a593Smuzhiyun 	       &ddr_msch_regs->ddrsize);
2257*4882a593Smuzhiyun 
2258*4882a593Smuzhiyun 	*prow = 16;
2259*4882a593Smuzhiyun 	*pbank = 3;
2260*4882a593Smuzhiyun 	*pcol = (bw == 2) ? 10 : 11;
2261*4882a593Smuzhiyun }
2262*4882a593Smuzhiyun 
dram_detect_cap(struct dram_info * dram,struct rk3399_sdram_params * sdram_params,unsigned char channel)2263*4882a593Smuzhiyun static u64 dram_detect_cap(struct dram_info *dram,
2264*4882a593Smuzhiyun 			   struct rk3399_sdram_params *sdram_params,
2265*4882a593Smuzhiyun 			   unsigned char channel)
2266*4882a593Smuzhiyun {
2267*4882a593Smuzhiyun 	const struct chan_info *chan = &dram->chan[channel];
2268*4882a593Smuzhiyun 	struct sdram_cap_info *cap_info = &sdram_params->ch[channel].cap_info;
2269*4882a593Smuzhiyun 	u32 bw;
2270*4882a593Smuzhiyun 	u32 col_tmp;
2271*4882a593Smuzhiyun 	u32 bk_tmp;
2272*4882a593Smuzhiyun 	u32 row_tmp;
2273*4882a593Smuzhiyun 	u32 cs0_cap;
2274*4882a593Smuzhiyun 	u32 training_flag;
2275*4882a593Smuzhiyun 	u32 ddrconfig;
2276*4882a593Smuzhiyun 
2277*4882a593Smuzhiyun 	/* detect bw */
2278*4882a593Smuzhiyun 	bw = 2;
2279*4882a593Smuzhiyun 	if (sdram_params->base.dramtype != LPDDR4) {
2280*4882a593Smuzhiyun 		dram_set_bw(chan, bw);
2281*4882a593Smuzhiyun 		cap_info->bw = bw;
2282*4882a593Smuzhiyun 		if (data_training(chan, channel, sdram_params,
2283*4882a593Smuzhiyun 				  PI_READ_GATE_TRAINING)) {
2284*4882a593Smuzhiyun 			bw = 1;
2285*4882a593Smuzhiyun 			dram_set_bw(chan, 1);
2286*4882a593Smuzhiyun 			cap_info->bw = bw;
2287*4882a593Smuzhiyun 			if (data_training(chan, channel, sdram_params,
2288*4882a593Smuzhiyun 					  PI_READ_GATE_TRAINING)) {
2289*4882a593Smuzhiyun 				printf("16bit error!!!\n");
2290*4882a593Smuzhiyun 				goto error;
2291*4882a593Smuzhiyun 			}
2292*4882a593Smuzhiyun 		}
2293*4882a593Smuzhiyun 	}
2294*4882a593Smuzhiyun 	/*
2295*4882a593Smuzhiyun 	 * LPDDR3 CA training msut be trigger before other training.
2296*4882a593Smuzhiyun 	 * DDR3 is not have CA training.
2297*4882a593Smuzhiyun 	 */
2298*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR3)
2299*4882a593Smuzhiyun 		training_flag = PI_WRITE_LEVELING;
2300*4882a593Smuzhiyun 	else
2301*4882a593Smuzhiyun 		training_flag = PI_FULL_TRAINING;
2302*4882a593Smuzhiyun 
2303*4882a593Smuzhiyun 	if (sdram_params->base.dramtype != LPDDR4) {
2304*4882a593Smuzhiyun 		if (data_training(chan, channel, sdram_params, training_flag)) {
2305*4882a593Smuzhiyun 			printf("full training error!!!\n");
2306*4882a593Smuzhiyun 			goto error;
2307*4882a593Smuzhiyun 		}
2308*4882a593Smuzhiyun 	}
2309*4882a593Smuzhiyun 
2310*4882a593Smuzhiyun 	/* detect col */
2311*4882a593Smuzhiyun 	dram_set_max_col(chan, bw, &col_tmp);
2312*4882a593Smuzhiyun 	if (sdram_detect_col(cap_info, col_tmp) != 0)
2313*4882a593Smuzhiyun 		goto error;
2314*4882a593Smuzhiyun 
2315*4882a593Smuzhiyun 	/* detect bank */
2316*4882a593Smuzhiyun 	dram_set_max_bank(chan, bw, &bk_tmp, &col_tmp);
2317*4882a593Smuzhiyun 	sdram_detect_bank(cap_info, col_tmp, bk_tmp);
2318*4882a593Smuzhiyun 
2319*4882a593Smuzhiyun 	/* detect row */
2320*4882a593Smuzhiyun 	dram_set_max_row(chan, bw, &row_tmp, &bk_tmp, &col_tmp);
2321*4882a593Smuzhiyun 	if (sdram_detect_row(cap_info, col_tmp, bk_tmp, row_tmp) != 0)
2322*4882a593Smuzhiyun 		goto error;
2323*4882a593Smuzhiyun 
2324*4882a593Smuzhiyun 	/* detect row_3_4 */
2325*4882a593Smuzhiyun 	sdram_detect_row_3_4(cap_info, col_tmp, bk_tmp);
2326*4882a593Smuzhiyun 
2327*4882a593Smuzhiyun 	/* set ddrconfig */
2328*4882a593Smuzhiyun 	cs0_cap = (1 << (cap_info->cs0_row + cap_info->col + cap_info->bk +
2329*4882a593Smuzhiyun 			 cap_info->bw - 20));
2330*4882a593Smuzhiyun 	if (cap_info->row_3_4)
2331*4882a593Smuzhiyun 		cs0_cap = cs0_cap * 3 / 4;
2332*4882a593Smuzhiyun 
2333*4882a593Smuzhiyun 	cap_info->cs1_row = cap_info->cs0_row;
2334*4882a593Smuzhiyun 	set_memory_map(chan, channel, sdram_params);
2335*4882a593Smuzhiyun 	ddrconfig = calculate_ddrconfig(sdram_params, channel);
2336*4882a593Smuzhiyun 	if (-1 == ddrconfig)
2337*4882a593Smuzhiyun 		goto error;
2338*4882a593Smuzhiyun 	set_ddrconfig(chan, sdram_params, channel,
2339*4882a593Smuzhiyun 		      cap_info->ddrconfig);
2340*4882a593Smuzhiyun 
2341*4882a593Smuzhiyun 	/* detect cs1 row */
2342*4882a593Smuzhiyun 	sdram_detect_cs1_row(cap_info, sdram_params->base.dramtype);
2343*4882a593Smuzhiyun 
2344*4882a593Smuzhiyun 	/* detect die bw */
2345*4882a593Smuzhiyun 	sdram_detect_dbw(cap_info, sdram_params->base.dramtype);
2346*4882a593Smuzhiyun 
2347*4882a593Smuzhiyun 	return 0;
2348*4882a593Smuzhiyun error:
2349*4882a593Smuzhiyun 	return (-1);
2350*4882a593Smuzhiyun }
2351*4882a593Smuzhiyun 
2352*4882a593Smuzhiyun /* read mr_num mode register
2353*4882a593Smuzhiyun  * input: rank = 1: cs0, rank = 2: cs1
2354*4882a593Smuzhiyun  *        mr_num: mode register number
2355*4882a593Smuzhiyun  * output: buf
2356*4882a593Smuzhiyun  */
read_mr(struct rk3399_ddr_pctl_regs * ddr_pctl_regs,u32 rank,u32 mr_num,u32 * buf)2357*4882a593Smuzhiyun static int read_mr(struct rk3399_ddr_pctl_regs *ddr_pctl_regs, u32 rank,
2358*4882a593Smuzhiyun 		   u32 mr_num, u32 *buf)
2359*4882a593Smuzhiyun {
2360*4882a593Smuzhiyun 	s32 timeout = 100;
2361*4882a593Smuzhiyun 
2362*4882a593Smuzhiyun 	writel(((1 << 16) |
2363*4882a593Smuzhiyun 			(((rank == 2) ? 1 : 0) << 8) |
2364*4882a593Smuzhiyun 			mr_num) << 8,
2365*4882a593Smuzhiyun 			&ddr_pctl_regs->denali_ctl[118]);
2366*4882a593Smuzhiyun 	while (0 == (readl(&ddr_pctl_regs->denali_ctl[203]) &
2367*4882a593Smuzhiyun 			((1 << 21) | (1 << 12)))) {
2368*4882a593Smuzhiyun 		udelay(1);
2369*4882a593Smuzhiyun 		if (timeout <= 0)
2370*4882a593Smuzhiyun 			goto error;
2371*4882a593Smuzhiyun 		timeout--;
2372*4882a593Smuzhiyun 	}
2373*4882a593Smuzhiyun 	if (!(readl(&ddr_pctl_regs->denali_ctl[203]) & (1 << 12))) {
2374*4882a593Smuzhiyun 		*buf = readl(&ddr_pctl_regs->denali_ctl[119]) & 0xFF;
2375*4882a593Smuzhiyun 	} else {
2376*4882a593Smuzhiyun 		printf("read mr error\n");
2377*4882a593Smuzhiyun 		printf("MRR_ERROR_STATUS = 0x%x\n",
2378*4882a593Smuzhiyun 		       readl(&ddr_pctl_regs->denali_ctl[17]) & 0x3);
2379*4882a593Smuzhiyun 		*buf = 0;
2380*4882a593Smuzhiyun 	}
2381*4882a593Smuzhiyun 	setbits_le32(&ddr_pctl_regs->denali_ctl[205], (1 << 21) | (1 << 12));
2382*4882a593Smuzhiyun 	return 0;
2383*4882a593Smuzhiyun error:
2384*4882a593Smuzhiyun 	return (-1);
2385*4882a593Smuzhiyun }
2386*4882a593Smuzhiyun 
read_mr_for_detect(struct dram_info * dram,u32 channel,u32 rank,struct rk3399_sdram_params * sdram_params)2387*4882a593Smuzhiyun static int read_mr_for_detect(struct dram_info *dram, u32 channel, u32 rank,
2388*4882a593Smuzhiyun 			      struct rk3399_sdram_params *sdram_params)
2389*4882a593Smuzhiyun {
2390*4882a593Smuzhiyun 	u64 cs0_cap;
2391*4882a593Smuzhiyun 	u32 stride;
2392*4882a593Smuzhiyun 	u32 cs = 0, col = 0, bk = 0, bw = 0, row_3_4 = 0;
2393*4882a593Smuzhiyun 	u32 cs0_row = 0, cs1_row = 0, ddrconfig = 0;
2394*4882a593Smuzhiyun 	u32 mr5, mr12, mr14;
2395*4882a593Smuzhiyun 	struct chan_info *chan =
2396*4882a593Smuzhiyun 		&dram->chan[channel];
2397*4882a593Smuzhiyun 	struct rk3399_ddr_pctl_regs *ddr_pctl_regs = chan->pctl;
2398*4882a593Smuzhiyun 	int ret = 0;
2399*4882a593Smuzhiyun 	u32 val;
2400*4882a593Smuzhiyun 	void __iomem *addr = NULL;
2401*4882a593Smuzhiyun 
2402*4882a593Smuzhiyun 	stride = get_ddr_stride(dram->pmusgrf);
2403*4882a593Smuzhiyun 
2404*4882a593Smuzhiyun 	if (sdram_params->ch[channel].cap_info.col == 0) {
2405*4882a593Smuzhiyun 		ret = -1;
2406*4882a593Smuzhiyun 		goto end;
2407*4882a593Smuzhiyun 	}
2408*4882a593Smuzhiyun 
2409*4882a593Smuzhiyun 	cs = sdram_params->ch[channel].cap_info.rank;
2410*4882a593Smuzhiyun 	col = sdram_params->ch[channel].cap_info.col;
2411*4882a593Smuzhiyun 	bk = sdram_params->ch[channel].cap_info.bk;
2412*4882a593Smuzhiyun 	bw = sdram_params->ch[channel].cap_info.bw;
2413*4882a593Smuzhiyun 	row_3_4 = sdram_params->ch[channel].cap_info.row_3_4;
2414*4882a593Smuzhiyun 	cs0_row = sdram_params->ch[channel].cap_info.cs0_row;
2415*4882a593Smuzhiyun 	cs1_row = sdram_params->ch[channel].cap_info.cs1_row;
2416*4882a593Smuzhiyun 	ddrconfig = sdram_params->ch[channel].cap_info.ddrconfig;
2417*4882a593Smuzhiyun 
2418*4882a593Smuzhiyun 	/* 2GB */
2419*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.rank = 2;
2420*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.col = 10;
2421*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.bk = 3;
2422*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.bw = 2;
2423*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.row_3_4 = 0;
2424*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.cs0_row = 15;
2425*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.cs1_row = 15;
2426*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.ddrconfig = 1;
2427*4882a593Smuzhiyun 
2428*4882a593Smuzhiyun 	set_memory_map(chan, channel, sdram_params);
2429*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.ddrconfig =
2430*4882a593Smuzhiyun 			calculate_ddrconfig(sdram_params, channel);
2431*4882a593Smuzhiyun 	set_ddrconfig(chan, sdram_params, channel,
2432*4882a593Smuzhiyun 		      sdram_params->ch[channel].cap_info.ddrconfig);
2433*4882a593Smuzhiyun 	set_cap_relate_config(chan, sdram_params, channel);
2434*4882a593Smuzhiyun 
2435*4882a593Smuzhiyun 	cs0_cap = (1 << (sdram_params->ch[channel].cap_info.bw
2436*4882a593Smuzhiyun 			+ sdram_params->ch[channel].cap_info.col
2437*4882a593Smuzhiyun 			+ sdram_params->ch[channel].cap_info.bk
2438*4882a593Smuzhiyun 			+ sdram_params->ch[channel].cap_info.cs0_row));
2439*4882a593Smuzhiyun 
2440*4882a593Smuzhiyun 	if (sdram_params->ch[channel].cap_info.row_3_4)
2441*4882a593Smuzhiyun 		cs0_cap = cs0_cap * 3 / 4;
2442*4882a593Smuzhiyun 
2443*4882a593Smuzhiyun 	if (channel == 0)
2444*4882a593Smuzhiyun 		set_ddr_stride(dram->pmusgrf, 0x17);
2445*4882a593Smuzhiyun 	else
2446*4882a593Smuzhiyun 		set_ddr_stride(dram->pmusgrf, 0x18);
2447*4882a593Smuzhiyun 
2448*4882a593Smuzhiyun 	/* !will soiled DRAM space here!
2449*4882a593Smuzhiyun 	 * read and write data to DRAM, avoid be optimized by compiler.
2450*4882a593Smuzhiyun 	 */
2451*4882a593Smuzhiyun 	if (rank == 1)
2452*4882a593Smuzhiyun 		addr = (void __iomem *)0x100;
2453*4882a593Smuzhiyun 	else if (rank == 2)
2454*4882a593Smuzhiyun 		addr = (void __iomem *)(cs0_cap + 0x100);
2455*4882a593Smuzhiyun 
2456*4882a593Smuzhiyun 	val = readl(addr);
2457*4882a593Smuzhiyun 	writel(val + 1, addr);
2458*4882a593Smuzhiyun 
2459*4882a593Smuzhiyun 	read_mr(ddr_pctl_regs, rank, 5, &mr5);
2460*4882a593Smuzhiyun 	read_mr(ddr_pctl_regs, rank, 12, &mr12);
2461*4882a593Smuzhiyun 	read_mr(ddr_pctl_regs, rank, 14, &mr14);
2462*4882a593Smuzhiyun 
2463*4882a593Smuzhiyun 	if (mr5 == 0 || mr12 != 0x4d || mr14 != 0x4d) {
2464*4882a593Smuzhiyun 		ret = -1;
2465*4882a593Smuzhiyun 		goto end;
2466*4882a593Smuzhiyun 	}
2467*4882a593Smuzhiyun end:
2468*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.rank = cs;
2469*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.col = col;
2470*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.bk = bk;
2471*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.bw = bw;
2472*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.row_3_4 = row_3_4;
2473*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.cs0_row = cs0_row;
2474*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.cs1_row = cs1_row;
2475*4882a593Smuzhiyun 	sdram_params->ch[channel].cap_info.ddrconfig = ddrconfig;
2476*4882a593Smuzhiyun 
2477*4882a593Smuzhiyun 	set_ddr_stride(dram->pmusgrf, stride);
2478*4882a593Smuzhiyun 	return ret;
2479*4882a593Smuzhiyun }
2480*4882a593Smuzhiyun 
get_phy_fn(struct rk3399_sdram_params * sdram_params,u32 ctl_fn)2481*4882a593Smuzhiyun static u32 get_phy_fn(struct rk3399_sdram_params *sdram_params, u32 ctl_fn)
2482*4882a593Smuzhiyun {
2483*4882a593Smuzhiyun 	u32 lp4_phy_fn[] = {1, 0, 0xb};
2484*4882a593Smuzhiyun 
2485*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4)
2486*4882a593Smuzhiyun 		return lp4_phy_fn[ctl_fn];
2487*4882a593Smuzhiyun 	else
2488*4882a593Smuzhiyun 		return ctl_fn;
2489*4882a593Smuzhiyun }
2490*4882a593Smuzhiyun 
get_ctl_fn(struct rk3399_sdram_params * sdram_params,u32 phy_fn)2491*4882a593Smuzhiyun static u32 get_ctl_fn(struct rk3399_sdram_params *sdram_params, u32 phy_fn)
2492*4882a593Smuzhiyun {
2493*4882a593Smuzhiyun 	u32 lp4_ctl_fn[] = {1, 0, 2};
2494*4882a593Smuzhiyun 
2495*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4)
2496*4882a593Smuzhiyun 		return lp4_ctl_fn[phy_fn];
2497*4882a593Smuzhiyun 	else
2498*4882a593Smuzhiyun 		return phy_fn;
2499*4882a593Smuzhiyun }
2500*4882a593Smuzhiyun 
dram_copy_phy_fn(struct dram_info * dram,struct rk3399_sdram_params * sdram_params,u32 fn,struct rk3399_sdram_params * f1_sdram_params,u32 channel)2501*4882a593Smuzhiyun static void dram_copy_phy_fn(struct dram_info *dram,
2502*4882a593Smuzhiyun 			     struct rk3399_sdram_params *sdram_params, u32 fn,
2503*4882a593Smuzhiyun 			     struct rk3399_sdram_params *f1_sdram_params,
2504*4882a593Smuzhiyun 			     u32 channel)
2505*4882a593Smuzhiyun {
2506*4882a593Smuzhiyun 	u32 *denali_ctl;
2507*4882a593Smuzhiyun 	u32 *denali_phy;
2508*4882a593Smuzhiyun 	u32 *denali_phy_params;
2509*4882a593Smuzhiyun 	u32 speed = 0;
2510*4882a593Smuzhiyun 	u32 mr5;
2511*4882a593Smuzhiyun 	u32 ctl_fn;
2512*4882a593Smuzhiyun 
2513*4882a593Smuzhiyun 	denali_ctl = dram->chan[channel].pctl->denali_ctl;
2514*4882a593Smuzhiyun 	denali_phy = dram->chan[channel].publ->denali_phy;
2515*4882a593Smuzhiyun 	denali_phy_params = f1_sdram_params->phy_regs.denali_phy;
2516*4882a593Smuzhiyun 
2517*4882a593Smuzhiyun 	/* switch index */
2518*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy_params[896], 0x3 << 8,
2519*4882a593Smuzhiyun 			fn << 8);
2520*4882a593Smuzhiyun 	writel(denali_phy_params[896], &denali_phy[896]);
2521*4882a593Smuzhiyun 
2522*4882a593Smuzhiyun 	/* phy_pll_ctrl_ca, phy_pll_ctrl */
2523*4882a593Smuzhiyun 	writel(denali_phy_params[911], &denali_phy[911]);
2524*4882a593Smuzhiyun 	/* phy_low_freq_sel */
2525*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[913], 0x1,
2526*4882a593Smuzhiyun 			denali_phy_params[913] & 0x1);
2527*4882a593Smuzhiyun 	/* PHY_GRP_SLAVE_DELAY_X, phy_cslvl_dly_step */
2528*4882a593Smuzhiyun 	writel(denali_phy_params[916], &denali_phy[916]);
2529*4882a593Smuzhiyun 	writel(denali_phy_params[917], &denali_phy[917]);
2530*4882a593Smuzhiyun 	writel(denali_phy_params[918], &denali_phy[918]);
2531*4882a593Smuzhiyun 	/* phy_adrZ_sw_wraddr_shift_X  */
2532*4882a593Smuzhiyun 	writel(denali_phy_params[512], &denali_phy[512]);
2533*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[513], 0xFFFF,
2534*4882a593Smuzhiyun 			denali_phy_params[513] & 0xFFFF);
2535*4882a593Smuzhiyun 	writel(denali_phy_params[640], &denali_phy[640]);
2536*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[641], 0xFFFF,
2537*4882a593Smuzhiyun 			denali_phy_params[641] & 0xFFFF);
2538*4882a593Smuzhiyun 	writel(denali_phy_params[768], &denali_phy[768]);
2539*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[769], 0xFFFF,
2540*4882a593Smuzhiyun 			denali_phy_params[769] & 0xFFFF);
2541*4882a593Smuzhiyun 
2542*4882a593Smuzhiyun 	writel(denali_phy_params[544], &denali_phy[544]);
2543*4882a593Smuzhiyun 	writel(denali_phy_params[545], &denali_phy[545]);
2544*4882a593Smuzhiyun 	writel(denali_phy_params[546], &denali_phy[546]);
2545*4882a593Smuzhiyun 	writel(denali_phy_params[547], &denali_phy[547]);
2546*4882a593Smuzhiyun 
2547*4882a593Smuzhiyun 	writel(denali_phy_params[672], &denali_phy[672]);
2548*4882a593Smuzhiyun 	writel(denali_phy_params[673], &denali_phy[673]);
2549*4882a593Smuzhiyun 	writel(denali_phy_params[674], &denali_phy[674]);
2550*4882a593Smuzhiyun 	writel(denali_phy_params[675], &denali_phy[675]);
2551*4882a593Smuzhiyun 
2552*4882a593Smuzhiyun 	writel(denali_phy_params[800], &denali_phy[800]);
2553*4882a593Smuzhiyun 	writel(denali_phy_params[801], &denali_phy[801]);
2554*4882a593Smuzhiyun 	writel(denali_phy_params[802], &denali_phy[802]);
2555*4882a593Smuzhiyun 	writel(denali_phy_params[803], &denali_phy[803]);
2556*4882a593Smuzhiyun 
2557*4882a593Smuzhiyun 	/*
2558*4882a593Smuzhiyun 	 * phy_adr_master_delay_start_X
2559*4882a593Smuzhiyun 	 * phy_adr_master_delay_step_X
2560*4882a593Smuzhiyun 	 * phy_adr_master_delay_wait_X
2561*4882a593Smuzhiyun 	 */
2562*4882a593Smuzhiyun 	writel(denali_phy_params[548], &denali_phy[548]);
2563*4882a593Smuzhiyun 	writel(denali_phy_params[676], &denali_phy[676]);
2564*4882a593Smuzhiyun 	writel(denali_phy_params[804], &denali_phy[804]);
2565*4882a593Smuzhiyun 
2566*4882a593Smuzhiyun 	/* phy_adr_calvl_dly_step_X */
2567*4882a593Smuzhiyun 	writel(denali_phy_params[549], &denali_phy[549]);
2568*4882a593Smuzhiyun 	writel(denali_phy_params[677], &denali_phy[677]);
2569*4882a593Smuzhiyun 	writel(denali_phy_params[805], &denali_phy[805]);
2570*4882a593Smuzhiyun 
2571*4882a593Smuzhiyun 	/*
2572*4882a593Smuzhiyun 	 * phy_clk_wrdm_slave_delay_X
2573*4882a593Smuzhiyun 	 * phy_clk_wrdqZ_slave_delay_X
2574*4882a593Smuzhiyun 	 * phy_clk_wrdqs_slave_delay_X
2575*4882a593Smuzhiyun 	 */
2576*4882a593Smuzhiyun 	sdram_copy_to_reg((u32 *)&denali_phy[59],
2577*4882a593Smuzhiyun 			  (u32 *)&denali_phy_params[59],
2578*4882a593Smuzhiyun 			  (63 - 58) * 4);
2579*4882a593Smuzhiyun 	sdram_copy_to_reg((u32 *)&denali_phy[187],
2580*4882a593Smuzhiyun 			  (u32 *)&denali_phy_params[187],
2581*4882a593Smuzhiyun 			  (191 - 186) * 4);
2582*4882a593Smuzhiyun 	sdram_copy_to_reg((u32 *)&denali_phy[315],
2583*4882a593Smuzhiyun 			  (u32 *)&denali_phy_params[315],
2584*4882a593Smuzhiyun 			  (319 - 314) * 4);
2585*4882a593Smuzhiyun 	sdram_copy_to_reg((u32 *)&denali_phy[443],
2586*4882a593Smuzhiyun 			  (u32 *)&denali_phy_params[443],
2587*4882a593Smuzhiyun 			  (447 - 442) * 4);
2588*4882a593Smuzhiyun 
2589*4882a593Smuzhiyun 	/*
2590*4882a593Smuzhiyun 	 * phy_dqs_tsel_wr_timing_X 8bits DENALI_PHY_84/212/340/468 offset_8
2591*4882a593Smuzhiyun 	 * dqs_tsel_wr_end[7:4] add Half cycle
2592*4882a593Smuzhiyun 	 * phy_dq_tsel_wr_timing_X 8bits DENALI_PHY_83/211/339/467 offset_8
2593*4882a593Smuzhiyun 	 * dq_tsel_wr_end[7:4] add Half cycle
2594*4882a593Smuzhiyun 	 */
2595*4882a593Smuzhiyun 	writel(denali_phy_params[83] + (0x10 << 16), &denali_phy[83]);
2596*4882a593Smuzhiyun 	writel(denali_phy_params[84] + (0x10 << 8), &denali_phy[84]);
2597*4882a593Smuzhiyun 	writel(denali_phy_params[85], &denali_phy[85]);
2598*4882a593Smuzhiyun 
2599*4882a593Smuzhiyun 	writel(denali_phy_params[211] + (0x10 << 16), &denali_phy[211]);
2600*4882a593Smuzhiyun 	writel(denali_phy_params[212] + (0x10 << 8), &denali_phy[212]);
2601*4882a593Smuzhiyun 	writel(denali_phy_params[213], &denali_phy[213]);
2602*4882a593Smuzhiyun 
2603*4882a593Smuzhiyun 	writel(denali_phy_params[339] + (0x10 << 16), &denali_phy[339]);
2604*4882a593Smuzhiyun 	writel(denali_phy_params[340] + (0x10 << 8), &denali_phy[340]);
2605*4882a593Smuzhiyun 	writel(denali_phy_params[341], &denali_phy[341]);
2606*4882a593Smuzhiyun 
2607*4882a593Smuzhiyun 	writel(denali_phy_params[467] + (0x10 << 16), &denali_phy[467]);
2608*4882a593Smuzhiyun 	writel(denali_phy_params[468] + (0x10 << 8), &denali_phy[468]);
2609*4882a593Smuzhiyun 	writel(denali_phy_params[469], &denali_phy[469]);
2610*4882a593Smuzhiyun 
2611*4882a593Smuzhiyun 	/*
2612*4882a593Smuzhiyun 	 * phy_gtlvl_resp_wait_cnt_X
2613*4882a593Smuzhiyun 	 * phy_gtlvl_dly_step_X
2614*4882a593Smuzhiyun 	 * phy_wrlvl_resp_wait_cnt_X
2615*4882a593Smuzhiyun 	 * phy_gtlvl_final_step_X
2616*4882a593Smuzhiyun 	 * phy_gtlvl_back_step_X
2617*4882a593Smuzhiyun 	 * phy_rdlvl_dly_step_X
2618*4882a593Smuzhiyun 	 *
2619*4882a593Smuzhiyun 	 * phy_master_delay_step_X
2620*4882a593Smuzhiyun 	 * phy_master_delay_wait_X
2621*4882a593Smuzhiyun 	 * phy_wrlvl_dly_step_X
2622*4882a593Smuzhiyun 	 * phy_rptr_update_X
2623*4882a593Smuzhiyun 	 * phy_wdqlvl_dly_step_X
2624*4882a593Smuzhiyun 	 */
2625*4882a593Smuzhiyun 	writel(denali_phy_params[87], &denali_phy[87]);
2626*4882a593Smuzhiyun 	writel(denali_phy_params[88], &denali_phy[88]);
2627*4882a593Smuzhiyun 	writel(denali_phy_params[89], &denali_phy[89]);
2628*4882a593Smuzhiyun 	writel(denali_phy_params[90], &denali_phy[90]);
2629*4882a593Smuzhiyun 
2630*4882a593Smuzhiyun 	writel(denali_phy_params[215], &denali_phy[215]);
2631*4882a593Smuzhiyun 	writel(denali_phy_params[216], &denali_phy[216]);
2632*4882a593Smuzhiyun 	writel(denali_phy_params[217], &denali_phy[217]);
2633*4882a593Smuzhiyun 	writel(denali_phy_params[218], &denali_phy[218]);
2634*4882a593Smuzhiyun 
2635*4882a593Smuzhiyun 	writel(denali_phy_params[343], &denali_phy[343]);
2636*4882a593Smuzhiyun 	writel(denali_phy_params[344], &denali_phy[344]);
2637*4882a593Smuzhiyun 	writel(denali_phy_params[345], &denali_phy[345]);
2638*4882a593Smuzhiyun 	writel(denali_phy_params[346], &denali_phy[346]);
2639*4882a593Smuzhiyun 
2640*4882a593Smuzhiyun 	writel(denali_phy_params[471], &denali_phy[471]);
2641*4882a593Smuzhiyun 	writel(denali_phy_params[472], &denali_phy[472]);
2642*4882a593Smuzhiyun 	writel(denali_phy_params[473], &denali_phy[473]);
2643*4882a593Smuzhiyun 	writel(denali_phy_params[474], &denali_phy[474]);
2644*4882a593Smuzhiyun 
2645*4882a593Smuzhiyun 	/*
2646*4882a593Smuzhiyun 	 * phy_gtlvl_lat_adj_start_X
2647*4882a593Smuzhiyun 	 * phy_gtlvl_rddqs_slv_dly_start_X
2648*4882a593Smuzhiyun 	 * phy_rdlvl_rddqs_dq_slv_dly_start_X
2649*4882a593Smuzhiyun 	 * phy_wdqlvl_dqdm_slv_dly_start_X
2650*4882a593Smuzhiyun 	 */
2651*4882a593Smuzhiyun 	writel(denali_phy_params[80], &denali_phy[80]);
2652*4882a593Smuzhiyun 	writel(denali_phy_params[81], &denali_phy[81]);
2653*4882a593Smuzhiyun 
2654*4882a593Smuzhiyun 	writel(denali_phy_params[208], &denali_phy[208]);
2655*4882a593Smuzhiyun 	writel(denali_phy_params[209], &denali_phy[209]);
2656*4882a593Smuzhiyun 
2657*4882a593Smuzhiyun 	writel(denali_phy_params[336], &denali_phy[336]);
2658*4882a593Smuzhiyun 	writel(denali_phy_params[337], &denali_phy[337]);
2659*4882a593Smuzhiyun 
2660*4882a593Smuzhiyun 	writel(denali_phy_params[464], &denali_phy[464]);
2661*4882a593Smuzhiyun 	writel(denali_phy_params[465], &denali_phy[465]);
2662*4882a593Smuzhiyun 
2663*4882a593Smuzhiyun 	/*
2664*4882a593Smuzhiyun 	 * phy_master_delay_start_X
2665*4882a593Smuzhiyun 	 * phy_sw_master_mode_X
2666*4882a593Smuzhiyun 	 * phy_rddata_en_tsel_dly_X
2667*4882a593Smuzhiyun 	 */
2668*4882a593Smuzhiyun 	writel(denali_phy_params[86], &denali_phy[86]);
2669*4882a593Smuzhiyun 	writel(denali_phy_params[214], &denali_phy[214]);
2670*4882a593Smuzhiyun 	writel(denali_phy_params[342], &denali_phy[342]);
2671*4882a593Smuzhiyun 	writel(denali_phy_params[470], &denali_phy[470]);
2672*4882a593Smuzhiyun 
2673*4882a593Smuzhiyun 	/*
2674*4882a593Smuzhiyun 	 * phy_rddqZ_slave_delay_X
2675*4882a593Smuzhiyun 	 * phy_rddqs_dqZ_fall_slave_delay_X
2676*4882a593Smuzhiyun 	 * phy_rddqs_dqZ_rise_slave_delay_X
2677*4882a593Smuzhiyun 	 * phy_rddqs_dm_fall_slave_delay_X
2678*4882a593Smuzhiyun 	 * phy_rddqs_dm_rise_slave_delay_X
2679*4882a593Smuzhiyun 	 * phy_rddqs_gate_slave_delay_X
2680*4882a593Smuzhiyun 	 * phy_wrlvl_delay_early_threshold_X
2681*4882a593Smuzhiyun 	 * phy_write_path_lat_add_X
2682*4882a593Smuzhiyun 	 * phy_rddqs_latency_adjust_X
2683*4882a593Smuzhiyun 	 * phy_wrlvl_delay_period_threshold_X
2684*4882a593Smuzhiyun 	 * phy_wrlvl_early_force_zero_X
2685*4882a593Smuzhiyun 	 */
2686*4882a593Smuzhiyun 	sdram_copy_to_reg((u32 *)&denali_phy[64],
2687*4882a593Smuzhiyun 			  (u32 *)&denali_phy_params[64],
2688*4882a593Smuzhiyun 			  (67 - 63) * 4);
2689*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[68], 0xFFFFFC00,
2690*4882a593Smuzhiyun 			denali_phy_params[68] & 0xFFFFFC00);
2691*4882a593Smuzhiyun 	sdram_copy_to_reg((u32 *)&denali_phy[69],
2692*4882a593Smuzhiyun 			  (u32 *)&denali_phy_params[69],
2693*4882a593Smuzhiyun 			  (79 - 68) * 4);
2694*4882a593Smuzhiyun 
2695*4882a593Smuzhiyun 	sdram_copy_to_reg((u32 *)&denali_phy[192],
2696*4882a593Smuzhiyun 			  (u32 *)&denali_phy_params[192],
2697*4882a593Smuzhiyun 			  (195 - 191) * 4);
2698*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[196], 0xFFFFFC00,
2699*4882a593Smuzhiyun 			denali_phy_params[196] & 0xFFFFFC00);
2700*4882a593Smuzhiyun 	sdram_copy_to_reg((u32 *)&denali_phy[197],
2701*4882a593Smuzhiyun 			  (u32 *)&denali_phy_params[197],
2702*4882a593Smuzhiyun 			  (207 - 196) * 4);
2703*4882a593Smuzhiyun 
2704*4882a593Smuzhiyun 	sdram_copy_to_reg((u32 *)&denali_phy[320],
2705*4882a593Smuzhiyun 			  (u32 *)&denali_phy_params[320],
2706*4882a593Smuzhiyun 			  (323 - 319) * 4);
2707*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[324], 0xFFFFFC00,
2708*4882a593Smuzhiyun 			denali_phy_params[324] & 0xFFFFFC00);
2709*4882a593Smuzhiyun 	sdram_copy_to_reg((u32 *)&denali_phy[325],
2710*4882a593Smuzhiyun 			  (u32 *)&denali_phy_params[325],
2711*4882a593Smuzhiyun 			  (335 - 324) * 4);
2712*4882a593Smuzhiyun 
2713*4882a593Smuzhiyun 	sdram_copy_to_reg((u32 *)&denali_phy[448],
2714*4882a593Smuzhiyun 			  (u32 *)&denali_phy_params[448],
2715*4882a593Smuzhiyun 			  (451 - 447) * 4);
2716*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[452], 0xFFFFFC00,
2717*4882a593Smuzhiyun 			denali_phy_params[452] & 0xFFFFFC00);
2718*4882a593Smuzhiyun 	sdram_copy_to_reg((u32 *)&denali_phy[453],
2719*4882a593Smuzhiyun 			  (u32 *)&denali_phy_params[453],
2720*4882a593Smuzhiyun 			  (463 - 452) * 4);
2721*4882a593Smuzhiyun 
2722*4882a593Smuzhiyun 	/* phy_two_cyc_preamble_X */
2723*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[7], 0x3 << 24,
2724*4882a593Smuzhiyun 			denali_phy_params[7] & (0x3 << 24));
2725*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[135], 0x3 << 24,
2726*4882a593Smuzhiyun 			denali_phy_params[135] & (0x3 << 24));
2727*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[263], 0x3 << 24,
2728*4882a593Smuzhiyun 			denali_phy_params[263] & (0x3 << 24));
2729*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[391], 0x3 << 24,
2730*4882a593Smuzhiyun 			denali_phy_params[391] & (0x3 << 24));
2731*4882a593Smuzhiyun 
2732*4882a593Smuzhiyun 	/* speed */
2733*4882a593Smuzhiyun 	if (f1_sdram_params->base.ddr_freq < 400 * MHz)
2734*4882a593Smuzhiyun 		speed = 0x0;
2735*4882a593Smuzhiyun 	else if (f1_sdram_params->base.ddr_freq < 800 * MHz)
2736*4882a593Smuzhiyun 		speed = 0x1;
2737*4882a593Smuzhiyun 	else if (f1_sdram_params->base.ddr_freq < 1200 * MHz)
2738*4882a593Smuzhiyun 		speed = 0x2;
2739*4882a593Smuzhiyun 
2740*4882a593Smuzhiyun 	/* PHY_924 PHY_PAD_FDBK_DRIVE */
2741*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[924],
2742*4882a593Smuzhiyun 			0x3 << 21, speed << 21);
2743*4882a593Smuzhiyun 	/* PHY_926 PHY_PAD_DATA_DRIVE */
2744*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[926],
2745*4882a593Smuzhiyun 			0x3 << 9, speed << 9);
2746*4882a593Smuzhiyun 	/* PHY_927 PHY_PAD_DQS_DRIVE */
2747*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[927],
2748*4882a593Smuzhiyun 			0x3 << 9, speed << 9);
2749*4882a593Smuzhiyun 	/* PHY_928 PHY_PAD_ADDR_DRIVE */
2750*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[928],
2751*4882a593Smuzhiyun 			0x3 << 17, speed << 17);
2752*4882a593Smuzhiyun 	/* PHY_929 PHY_PAD_CLK_DRIVE */
2753*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[929],
2754*4882a593Smuzhiyun 			0x3 << 17, speed << 17);
2755*4882a593Smuzhiyun 	/* PHY_935 PHY_PAD_CKE_DRIVE */
2756*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[935],
2757*4882a593Smuzhiyun 			0x3 << 17, speed << 17);
2758*4882a593Smuzhiyun 	/* PHY_937 PHY_PAD_RST_DRIVE */
2759*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[937],
2760*4882a593Smuzhiyun 			0x3 << 17, speed << 17);
2761*4882a593Smuzhiyun 	/* PHY_939 PHY_PAD_CS_DRIVE */
2762*4882a593Smuzhiyun 	clrsetbits_le32(&denali_phy[939],
2763*4882a593Smuzhiyun 			0x3 << 17, speed << 17);
2764*4882a593Smuzhiyun 
2765*4882a593Smuzhiyun 	if (f1_sdram_params->base.dramtype == LPDDR4) {
2766*4882a593Smuzhiyun 		read_mr(dram->chan[channel].pctl, 1, 5, &mr5);
2767*4882a593Smuzhiyun 		set_ds_odt(&dram->chan[channel], f1_sdram_params, 1, 0, mr5);
2768*4882a593Smuzhiyun 		set_ds_odt(&dram->chan[channel], f1_sdram_params, 1, 1, mr5);
2769*4882a593Smuzhiyun 
2770*4882a593Smuzhiyun 		ctl_fn = get_ctl_fn(f1_sdram_params, fn);
2771*4882a593Smuzhiyun 		set_lp4_dq_odt(&dram->chan[channel], f1_sdram_params,
2772*4882a593Smuzhiyun 			       ctl_fn, 1, 1, 0, mr5);
2773*4882a593Smuzhiyun 		set_lp4_ca_odt(&dram->chan[channel], f1_sdram_params,
2774*4882a593Smuzhiyun 			       ctl_fn, 1, 1, 0, mr5);
2775*4882a593Smuzhiyun 		set_lp4_MR3(&dram->chan[channel], f1_sdram_params,
2776*4882a593Smuzhiyun 			    ctl_fn, 1, 0, mr5);
2777*4882a593Smuzhiyun 		set_lp4_MR12(&dram->chan[channel], f1_sdram_params,
2778*4882a593Smuzhiyun 			     ctl_fn, 1, 0, mr5);
2779*4882a593Smuzhiyun 		set_lp4_MR14(&dram->chan[channel], f1_sdram_params,
2780*4882a593Smuzhiyun 			     ctl_fn, 1, 0, mr5);
2781*4882a593Smuzhiyun 
2782*4882a593Smuzhiyun 		set_lp4_dq_odt(&dram->chan[channel], f1_sdram_params,
2783*4882a593Smuzhiyun 			       ctl_fn, 1, 1, 1, mr5);
2784*4882a593Smuzhiyun 		set_lp4_ca_odt(&dram->chan[channel], f1_sdram_params,
2785*4882a593Smuzhiyun 			       ctl_fn, 1, 1, 1, mr5);
2786*4882a593Smuzhiyun 		set_lp4_MR3(&dram->chan[channel], f1_sdram_params,
2787*4882a593Smuzhiyun 			    ctl_fn, 1, 1, mr5);
2788*4882a593Smuzhiyun 		set_lp4_MR12(&dram->chan[channel], f1_sdram_params,
2789*4882a593Smuzhiyun 			     ctl_fn, 1, 1, mr5);
2790*4882a593Smuzhiyun 		set_lp4_MR14(&dram->chan[channel], f1_sdram_params,
2791*4882a593Smuzhiyun 			     ctl_fn, 1, 1, mr5);
2792*4882a593Smuzhiyun 
2793*4882a593Smuzhiyun 		/*
2794*4882a593Smuzhiyun 		 * if phy_sw_master_mode_X not bypass mode,
2795*4882a593Smuzhiyun 		 * clear PHY_SLICE_PWR_RDC_DISABLE.
2796*4882a593Smuzhiyun 		 * NOTE: need use f1_sdram_params, not ddr_publ_regs
2797*4882a593Smuzhiyun 		 */
2798*4882a593Smuzhiyun 		if (!((denali_phy_params[86] >> 8)
2799*4882a593Smuzhiyun 			& (1 << 2))) {
2800*4882a593Smuzhiyun 			clrbits_le32(&denali_phy[10], 1 << 16);
2801*4882a593Smuzhiyun 			clrbits_le32(&denali_phy[138], 1 << 16);
2802*4882a593Smuzhiyun 			clrbits_le32(&denali_phy[266], 1 << 16);
2803*4882a593Smuzhiyun 			clrbits_le32(&denali_phy[394], 1 << 16);
2804*4882a593Smuzhiyun 		}
2805*4882a593Smuzhiyun 
2806*4882a593Smuzhiyun 		/*
2807*4882a593Smuzhiyun 		 * when PHY_PER_CS_TRAINING_EN=1, W2W_DIFFCS_DLY_Fx can't
2808*4882a593Smuzhiyun 		 * smaller than 8
2809*4882a593Smuzhiyun 		 * NOTE: need use f1_sdram_params, not ddr_publ_regs
2810*4882a593Smuzhiyun 		 */
2811*4882a593Smuzhiyun 		if ((denali_phy_params[84] >> 16) & 1) {
2812*4882a593Smuzhiyun 			if (((readl(&denali_ctl[217 + ctl_fn]) >>
2813*4882a593Smuzhiyun 				16) & 0x1f) < 8)
2814*4882a593Smuzhiyun 				clrsetbits_le32(&denali_ctl[217 + ctl_fn],
2815*4882a593Smuzhiyun 						0x1f << 16,
2816*4882a593Smuzhiyun 						8 << 16);
2817*4882a593Smuzhiyun 		}
2818*4882a593Smuzhiyun 	}
2819*4882a593Smuzhiyun }
2820*4882a593Smuzhiyun 
dram_set_phy_fn(struct dram_info * dram,struct rk3399_sdram_params * sdram_params,u32 fn,struct rk3399_sdram_params * f1_sdram_params)2821*4882a593Smuzhiyun static void dram_set_phy_fn(struct dram_info *dram,
2822*4882a593Smuzhiyun 			    struct rk3399_sdram_params *sdram_params, u32 fn,
2823*4882a593Smuzhiyun 			    struct rk3399_sdram_params *f1_sdram_params)
2824*4882a593Smuzhiyun {
2825*4882a593Smuzhiyun 	u32 channel;
2826*4882a593Smuzhiyun 
2827*4882a593Smuzhiyun 	for (channel = 0; channel < 2; channel++)
2828*4882a593Smuzhiyun 		dram_copy_phy_fn(dram, sdram_params, fn, f1_sdram_params,
2829*4882a593Smuzhiyun 				 channel);
2830*4882a593Smuzhiyun }
2831*4882a593Smuzhiyun 
dram_set_rate(struct dram_info * dram,struct rk3399_sdram_params * sdram_params,u32 fn,u32 hz)2832*4882a593Smuzhiyun static int dram_set_rate(struct dram_info *dram,
2833*4882a593Smuzhiyun 			 struct rk3399_sdram_params *sdram_params,
2834*4882a593Smuzhiyun 			 u32 fn, u32 hz)
2835*4882a593Smuzhiyun {
2836*4882a593Smuzhiyun 	u32 channel;
2837*4882a593Smuzhiyun 	int ret_clk, ret[2];
2838*4882a593Smuzhiyun 
2839*4882a593Smuzhiyun 	/* cci idle req stall */
2840*4882a593Smuzhiyun 	writel(0x70007, &dram->grf->soc_con0);
2841*4882a593Smuzhiyun 	/* enable all clk */
2842*4882a593Smuzhiyun 	setbits_le32(&dram->pmu->pmu_noc_auto_ena, (0x3 << 7));
2843*4882a593Smuzhiyun 	/* idle */
2844*4882a593Smuzhiyun 	setbits_le32(&dram->pmu->pmu_bus_idle_req, (0x3 << 18));
2845*4882a593Smuzhiyun 	while ((readl(&dram->pmu->pmu_bus_idle_st) & (0x3 << 18))
2846*4882a593Smuzhiyun 	       != (0x3 << 18))
2847*4882a593Smuzhiyun 		;
2848*4882a593Smuzhiyun 
2849*4882a593Smuzhiyun 	/* change freq */
2850*4882a593Smuzhiyun 	writel((((0x3 << 4) | (1 << 2) | 1) << 16) |
2851*4882a593Smuzhiyun 		(fn << 4) | (1 << 2) | 1, &dram->cic->cic_ctrl0);
2852*4882a593Smuzhiyun 	while (!(readl(&dram->cic->cic_status0) & (1 << 2)))
2853*4882a593Smuzhiyun 		;
2854*4882a593Smuzhiyun 
2855*4882a593Smuzhiyun 	ret_clk = clk_set_rate(&dram->ddr_clk, hz);
2856*4882a593Smuzhiyun 	if (ret_clk < 0) {
2857*4882a593Smuzhiyun 		printf("%s clk set failed %d\n", __func__, ret_clk);
2858*4882a593Smuzhiyun 		return ret_clk;
2859*4882a593Smuzhiyun 	}
2860*4882a593Smuzhiyun 
2861*4882a593Smuzhiyun 	writel(0x20002, &dram->cic->cic_ctrl0);
2862*4882a593Smuzhiyun 	while (!(readl(&dram->cic->cic_status0) & (1 << 0)))
2863*4882a593Smuzhiyun 		;
2864*4882a593Smuzhiyun 
2865*4882a593Smuzhiyun 	/* deidle */
2866*4882a593Smuzhiyun 	clrbits_le32(&dram->pmu->pmu_bus_idle_req, (0x3 << 18));
2867*4882a593Smuzhiyun 	while (readl(&dram->pmu->pmu_bus_idle_st) & (0x3 << 18))
2868*4882a593Smuzhiyun 		;
2869*4882a593Smuzhiyun 
2870*4882a593Smuzhiyun 	/* clear enable all clk */
2871*4882a593Smuzhiyun 	clrbits_le32(&dram->pmu->pmu_noc_auto_ena, (0x3 << 7));
2872*4882a593Smuzhiyun 
2873*4882a593Smuzhiyun 	/* LPDDR4 f2 can not do training, all training will fail */
2874*4882a593Smuzhiyun 	if (!(sdram_params->base.dramtype == LPDDR4 && fn == 2)) {
2875*4882a593Smuzhiyun 		for (channel = 0; channel < 2; channel++) {
2876*4882a593Smuzhiyun 			if (!(sdram_params->ch[channel].cap_info.col))
2877*4882a593Smuzhiyun 				continue;
2878*4882a593Smuzhiyun 			ret[channel] = data_training(&dram->chan[channel],
2879*4882a593Smuzhiyun 						     channel, sdram_params,
2880*4882a593Smuzhiyun 						     PI_FULL_TRAINING);
2881*4882a593Smuzhiyun 		}
2882*4882a593Smuzhiyun 		for (channel = 0; channel < 2; channel++) {
2883*4882a593Smuzhiyun 			if (!(sdram_params->ch[channel].cap_info.col))
2884*4882a593Smuzhiyun 				continue;
2885*4882a593Smuzhiyun 			if (ret[channel])
2886*4882a593Smuzhiyun 				printf("channel %d training failed!\n",
2887*4882a593Smuzhiyun 				       channel);
2888*4882a593Smuzhiyun 			else
2889*4882a593Smuzhiyun 				printf("channel %d training pass\n", channel);
2890*4882a593Smuzhiyun 		}
2891*4882a593Smuzhiyun 	}
2892*4882a593Smuzhiyun 
2893*4882a593Smuzhiyun 	return 0;
2894*4882a593Smuzhiyun }
2895*4882a593Smuzhiyun 
2896*4882a593Smuzhiyun static struct rk3399_sdram_params *g_sdram_params;
set_rate0(struct dram_info * dram)2897*4882a593Smuzhiyun static void set_rate0(struct dram_info *dram)
2898*4882a593Smuzhiyun {
2899*4882a593Smuzhiyun 	u32 ctl_fn;
2900*4882a593Smuzhiyun 	u32 phy_fn;
2901*4882a593Smuzhiyun 
2902*4882a593Smuzhiyun 	ctl_fn = 0;
2903*4882a593Smuzhiyun 	phy_fn = get_phy_fn(g_sdram_params, ctl_fn);
2904*4882a593Smuzhiyun 	dram_set_phy_fn(dram, g_sdram_params, phy_fn, &dfs_configs[ctl_fn]);
2905*4882a593Smuzhiyun 	dram_set_rate(dram, g_sdram_params, ctl_fn,
2906*4882a593Smuzhiyun 		      dfs_configs[ctl_fn].base.ddr_freq);
2907*4882a593Smuzhiyun 	printf("change freq to %d MHz %d, %d\n",
2908*4882a593Smuzhiyun 	       dfs_configs[ctl_fn].base.ddr_freq / MHZ, ctl_fn, phy_fn);
2909*4882a593Smuzhiyun }
2910*4882a593Smuzhiyun 
set_rate1(struct dram_info * dram)2911*4882a593Smuzhiyun static void set_rate1(struct dram_info *dram)
2912*4882a593Smuzhiyun {
2913*4882a593Smuzhiyun 	u32 ctl_fn;
2914*4882a593Smuzhiyun 	u32 phy_fn;
2915*4882a593Smuzhiyun 
2916*4882a593Smuzhiyun 	ctl_fn = 1;
2917*4882a593Smuzhiyun 	phy_fn = get_phy_fn(g_sdram_params, ctl_fn);
2918*4882a593Smuzhiyun 	dram_set_phy_fn(dram, g_sdram_params, phy_fn, &dfs_configs[ctl_fn]);
2919*4882a593Smuzhiyun 	dram_set_rate(dram, g_sdram_params, ctl_fn,
2920*4882a593Smuzhiyun 		      dfs_configs[ctl_fn].base.ddr_freq);
2921*4882a593Smuzhiyun 	printf("change freq to %d MHz %d, %d\n",
2922*4882a593Smuzhiyun 	       dfs_configs[ctl_fn].base.ddr_freq / MHZ, ctl_fn, phy_fn);
2923*4882a593Smuzhiyun }
2924*4882a593Smuzhiyun 
sdram_init(struct dram_info * dram,struct rk3399_sdram_params * sdram_params)2925*4882a593Smuzhiyun static int sdram_init(struct dram_info *dram,
2926*4882a593Smuzhiyun 		      struct rk3399_sdram_params *sdram_params)
2927*4882a593Smuzhiyun {
2928*4882a593Smuzhiyun 	unsigned char dramtype = sdram_params->base.dramtype;
2929*4882a593Smuzhiyun 	unsigned int ddr_freq = sdram_params->base.ddr_freq;
2930*4882a593Smuzhiyun 	int channel;
2931*4882a593Smuzhiyun 	u32 rank;
2932*4882a593Smuzhiyun 	int ch;
2933*4882a593Smuzhiyun 	u32 tmp;
2934*4882a593Smuzhiyun 	u32 training_flag;
2935*4882a593Smuzhiyun 
2936*4882a593Smuzhiyun 	debug("Starting SDRAM initialization...\n");
2937*4882a593Smuzhiyun 
2938*4882a593Smuzhiyun 	if ((dramtype == DDR3 && ddr_freq > 933) ||
2939*4882a593Smuzhiyun 	    (dramtype == LPDDR3 && ddr_freq > 933) ||
2940*4882a593Smuzhiyun 	    (dramtype == LPDDR4 && ddr_freq > 800)) {
2941*4882a593Smuzhiyun 		debug("SDRAM frequency is to high!");
2942*4882a593Smuzhiyun 		return -E2BIG;
2943*4882a593Smuzhiyun 	}
2944*4882a593Smuzhiyun 
2945*4882a593Smuzhiyun 	/* detect rank */
2946*4882a593Smuzhiyun 	for (ch = 0; ch < 2; ch++) {
2947*4882a593Smuzhiyun 		sdram_params->ch[ch].cap_info.rank = 2;
2948*4882a593Smuzhiyun 		for (rank = 2; rank != 0; rank--) {
2949*4882a593Smuzhiyun 			for (channel = 0; channel < 2; channel++) {
2950*4882a593Smuzhiyun 				const struct chan_info *chan =
2951*4882a593Smuzhiyun 					&dram->chan[channel];
2952*4882a593Smuzhiyun 				struct rk3399_cru *cru = dram->cru;
2953*4882a593Smuzhiyun 				struct rk3399_ddr_publ_regs *publ = chan->publ;
2954*4882a593Smuzhiyun 
2955*4882a593Smuzhiyun 				phy_pctrl_reset(cru, channel);
2956*4882a593Smuzhiyun 				phy_dll_bypass_set(publ, ddr_freq);
2957*4882a593Smuzhiyun 				pctl_cfg(chan, channel, sdram_params);
2958*4882a593Smuzhiyun 			}
2959*4882a593Smuzhiyun 
2960*4882a593Smuzhiyun 			/* start to trigger initialization */
2961*4882a593Smuzhiyun 			pctl_start(dram, sdram_params, 3);
2962*4882a593Smuzhiyun 
2963*4882a593Smuzhiyun 			/* LPDDR2/LPDDR3 need to wait DAI complete, max 10us */
2964*4882a593Smuzhiyun 			if (dramtype == LPDDR3)
2965*4882a593Smuzhiyun 				udelay(10);
2966*4882a593Smuzhiyun 
2967*4882a593Smuzhiyun 			tmp = (rank == 2) ? 3 : 1;
2968*4882a593Smuzhiyun 			dram_set_cs(&dram->chan[ch], tmp, 2048,
2969*4882a593Smuzhiyun 				    sdram_params->base.dramtype);
2970*4882a593Smuzhiyun 			sdram_params->ch[ch].cap_info.rank = rank;
2971*4882a593Smuzhiyun 			if (sdram_params->base.dramtype == LPDDR4) {
2972*4882a593Smuzhiyun 				/* two rank, then read_mr(cs1)
2973*4882a593Smuzhiyun 				 * one rank, then read_mr(cs0)
2974*4882a593Smuzhiyun 				 */
2975*4882a593Smuzhiyun 				if (!read_mr_for_detect(dram, ch, rank,
2976*4882a593Smuzhiyun 							sdram_params))
2977*4882a593Smuzhiyun 					break;
2978*4882a593Smuzhiyun 			} else {
2979*4882a593Smuzhiyun 				/*
2980*4882a593Smuzhiyun 				 * LPDDR3 CA training msut be trigger before
2981*4882a593Smuzhiyun 				 * other training.
2982*4882a593Smuzhiyun 				 * DDR3 is not have CA training.
2983*4882a593Smuzhiyun 				 * LPDDR4 need confirm here!
2984*4882a593Smuzhiyun 				 */
2985*4882a593Smuzhiyun 				if (sdram_params->base.dramtype == LPDDR3)
2986*4882a593Smuzhiyun 					training_flag = PI_CA_TRAINING |
2987*4882a593Smuzhiyun 							PI_READ_GATE_TRAINING;
2988*4882a593Smuzhiyun 				else
2989*4882a593Smuzhiyun 					training_flag = PI_READ_GATE_TRAINING;
2990*4882a593Smuzhiyun 				if (!(data_training(&dram->chan[ch], ch,
2991*4882a593Smuzhiyun 						    sdram_params,
2992*4882a593Smuzhiyun 						    training_flag)))
2993*4882a593Smuzhiyun 					break;
2994*4882a593Smuzhiyun 			}
2995*4882a593Smuzhiyun 		}
2996*4882a593Smuzhiyun 		sdram_params->ch[ch].cap_info.rank = rank;
2997*4882a593Smuzhiyun 	}
2998*4882a593Smuzhiyun 
2999*4882a593Smuzhiyun 	sdram_params->base.num_channels = 0;
3000*4882a593Smuzhiyun 	for (channel = 0; channel < 2; channel++) {
3001*4882a593Smuzhiyun 		const struct chan_info *chan = &dram->chan[channel];
3002*4882a593Smuzhiyun 		struct sdram_cap_info *cap_info =
3003*4882a593Smuzhiyun 			&sdram_params->ch[channel].cap_info;
3004*4882a593Smuzhiyun 
3005*4882a593Smuzhiyun 		if (cap_info->rank == 0) {
3006*4882a593Smuzhiyun 			clear_channel_params(sdram_params, 1);
3007*4882a593Smuzhiyun 			continue;
3008*4882a593Smuzhiyun 		} else {
3009*4882a593Smuzhiyun 			sdram_params->base.num_channels++;
3010*4882a593Smuzhiyun 		}
3011*4882a593Smuzhiyun 
3012*4882a593Smuzhiyun 		printf("Channel ");
3013*4882a593Smuzhiyun 		printf(channel ? "1: " : "0: ");
3014*4882a593Smuzhiyun 
3015*4882a593Smuzhiyun 		if (channel == 0)
3016*4882a593Smuzhiyun 			set_ddr_stride(dram->pmusgrf, 0x17);
3017*4882a593Smuzhiyun 		else
3018*4882a593Smuzhiyun 			set_ddr_stride(dram->pmusgrf, 0x18);
3019*4882a593Smuzhiyun 
3020*4882a593Smuzhiyun 		if (dram_detect_cap(dram, sdram_params, channel)) {
3021*4882a593Smuzhiyun 			printf("Cap error!\n");
3022*4882a593Smuzhiyun 			continue;
3023*4882a593Smuzhiyun 		}
3024*4882a593Smuzhiyun 
3025*4882a593Smuzhiyun 		sdram_print_ddr_info(cap_info, &sdram_params->base, 0);
3026*4882a593Smuzhiyun 		set_memory_map(chan, channel, sdram_params);
3027*4882a593Smuzhiyun 		cap_info->ddrconfig =
3028*4882a593Smuzhiyun 			calculate_ddrconfig(sdram_params, channel);
3029*4882a593Smuzhiyun 		if (-1 == cap_info->ddrconfig) {
3030*4882a593Smuzhiyun 			printf("no ddrconfig find, Cap not support!\n");
3031*4882a593Smuzhiyun 			continue;
3032*4882a593Smuzhiyun 		}
3033*4882a593Smuzhiyun 		set_ddrconfig(chan, sdram_params, channel, cap_info->ddrconfig);
3034*4882a593Smuzhiyun 		set_cap_relate_config(chan, sdram_params, channel);
3035*4882a593Smuzhiyun 	}
3036*4882a593Smuzhiyun 
3037*4882a593Smuzhiyun 	if (sdram_params->base.num_channels == 0) {
3038*4882a593Smuzhiyun 		sdram_print_dram_type(sdram_params->base.dramtype);
3039*4882a593Smuzhiyun 		printf(" %dMHz\n", sdram_params->base.ddr_freq);
3040*4882a593Smuzhiyun 		return -1;
3041*4882a593Smuzhiyun 	}
3042*4882a593Smuzhiyun 
3043*4882a593Smuzhiyun 	sdram_params->base.stride = calculate_stride(sdram_params);
3044*4882a593Smuzhiyun 	dram_all_config(dram, sdram_params);
3045*4882a593Smuzhiyun 
3046*4882a593Smuzhiyun 	if (sdram_params->base.dramtype != LPDDR4)
3047*4882a593Smuzhiyun 		switch_to_phy_index1(dram, sdram_params);
3048*4882a593Smuzhiyun 
3049*4882a593Smuzhiyun 	if (sdram_params->base.dramtype == LPDDR4) {
3050*4882a593Smuzhiyun 		g_sdram_params = sdram_params;
3051*4882a593Smuzhiyun 		set_rate0(dram);
3052*4882a593Smuzhiyun 		set_rate1(dram);
3053*4882a593Smuzhiyun 	}
3054*4882a593Smuzhiyun 
3055*4882a593Smuzhiyun 	debug("Finish SDRAM initialization...\n");
3056*4882a593Smuzhiyun 	return 0;
3057*4882a593Smuzhiyun }
3058*4882a593Smuzhiyun 
rk3399_dmc_ofdata_to_platdata(struct udevice * dev)3059*4882a593Smuzhiyun static int rk3399_dmc_ofdata_to_platdata(struct udevice *dev)
3060*4882a593Smuzhiyun {
3061*4882a593Smuzhiyun #if !CONFIG_IS_ENABLED(OF_PLATDATA)
3062*4882a593Smuzhiyun 	struct rockchip_dmc_plat *plat = dev_get_platdata(dev);
3063*4882a593Smuzhiyun 	int ret;
3064*4882a593Smuzhiyun 
3065*4882a593Smuzhiyun 	ret = dev_read_u32_array(dev, "rockchip,sdram-params",
3066*4882a593Smuzhiyun 				 (u32 *)&plat->sdram_params,
3067*4882a593Smuzhiyun 				 sizeof(plat->sdram_params) / sizeof(u32));
3068*4882a593Smuzhiyun 	if (ret) {
3069*4882a593Smuzhiyun 		printf("%s: Cannot read rockchip,sdram-params %d\n",
3070*4882a593Smuzhiyun 		       __func__, ret);
3071*4882a593Smuzhiyun 		return ret;
3072*4882a593Smuzhiyun 	}
3073*4882a593Smuzhiyun 	ret = regmap_init_mem(dev, &plat->map);
3074*4882a593Smuzhiyun 	if (ret)
3075*4882a593Smuzhiyun 		printf("%s: regmap failed %d\n", __func__, ret);
3076*4882a593Smuzhiyun 
3077*4882a593Smuzhiyun #endif
3078*4882a593Smuzhiyun 	return 0;
3079*4882a593Smuzhiyun }
3080*4882a593Smuzhiyun 
3081*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(OF_PLATDATA)
conv_of_platdata(struct udevice * dev)3082*4882a593Smuzhiyun static int conv_of_platdata(struct udevice *dev)
3083*4882a593Smuzhiyun {
3084*4882a593Smuzhiyun 	struct rockchip_dmc_plat *plat = dev_get_platdata(dev);
3085*4882a593Smuzhiyun 	struct dtd_rockchip_rk3399_dmc *dtplat = &plat->dtplat;
3086*4882a593Smuzhiyun 	int ret;
3087*4882a593Smuzhiyun 
3088*4882a593Smuzhiyun 	ret = regmap_init_mem_platdata(dev, dtplat->reg,
3089*4882a593Smuzhiyun 				       ARRAY_SIZE(dtplat->reg) / 2,
3090*4882a593Smuzhiyun 				       &plat->map);
3091*4882a593Smuzhiyun 	if (ret)
3092*4882a593Smuzhiyun 		return ret;
3093*4882a593Smuzhiyun 
3094*4882a593Smuzhiyun 	return 0;
3095*4882a593Smuzhiyun }
3096*4882a593Smuzhiyun #endif
3097*4882a593Smuzhiyun 
rk3399_dmc_init(struct udevice * dev)3098*4882a593Smuzhiyun static int rk3399_dmc_init(struct udevice *dev)
3099*4882a593Smuzhiyun {
3100*4882a593Smuzhiyun 	struct dram_info *priv = dev_get_priv(dev);
3101*4882a593Smuzhiyun 	struct rockchip_dmc_plat *plat = dev_get_platdata(dev);
3102*4882a593Smuzhiyun 	int ret;
3103*4882a593Smuzhiyun #if !CONFIG_IS_ENABLED(OF_PLATDATA)
3104*4882a593Smuzhiyun 	struct rk3399_sdram_params *params = &plat->sdram_params;
3105*4882a593Smuzhiyun #else
3106*4882a593Smuzhiyun 	struct dtd_rockchip_rk3399_dmc *dtplat = &plat->dtplat;
3107*4882a593Smuzhiyun 	struct rk3399_sdram_params *params =
3108*4882a593Smuzhiyun 					(void *)dtplat->rockchip_sdram_params;
3109*4882a593Smuzhiyun 
3110*4882a593Smuzhiyun 	ret = conv_of_platdata(dev);
3111*4882a593Smuzhiyun 	if (ret)
3112*4882a593Smuzhiyun 		return ret;
3113*4882a593Smuzhiyun #endif
3114*4882a593Smuzhiyun 
3115*4882a593Smuzhiyun 	priv->cic = syscon_get_first_range(ROCKCHIP_SYSCON_CIC);
3116*4882a593Smuzhiyun 	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
3117*4882a593Smuzhiyun 	priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
3118*4882a593Smuzhiyun 	priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
3119*4882a593Smuzhiyun 	priv->pmusgrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUSGRF);
3120*4882a593Smuzhiyun 	priv->pmucru = rockchip_get_pmucru();
3121*4882a593Smuzhiyun 	priv->cru = rockchip_get_cru();
3122*4882a593Smuzhiyun 	priv->chan[0].pctl = regmap_get_range(plat->map, 0);
3123*4882a593Smuzhiyun 	priv->chan[0].pi = regmap_get_range(plat->map, 1);
3124*4882a593Smuzhiyun 	priv->chan[0].publ = regmap_get_range(plat->map, 2);
3125*4882a593Smuzhiyun 	priv->chan[0].msch = regmap_get_range(plat->map, 3);
3126*4882a593Smuzhiyun 	priv->chan[1].pctl = regmap_get_range(plat->map, 4);
3127*4882a593Smuzhiyun 	priv->chan[1].pi = regmap_get_range(plat->map, 5);
3128*4882a593Smuzhiyun 	priv->chan[1].publ = regmap_get_range(plat->map, 6);
3129*4882a593Smuzhiyun 	priv->chan[1].msch = regmap_get_range(plat->map, 7);
3130*4882a593Smuzhiyun 
3131*4882a593Smuzhiyun 	debug("con reg %p %p %p %p %p %p %p %p\n",
3132*4882a593Smuzhiyun 	      priv->chan[0].pctl, priv->chan[0].pi,
3133*4882a593Smuzhiyun 	      priv->chan[0].publ, priv->chan[0].msch,
3134*4882a593Smuzhiyun 	      priv->chan[1].pctl, priv->chan[1].pi,
3135*4882a593Smuzhiyun 	      priv->chan[1].publ, priv->chan[1].msch);
3136*4882a593Smuzhiyun 	debug("cru %p, cic %p, grf %p, sgrf %p, pmucru %p, pmu %p\n", priv->cru,
3137*4882a593Smuzhiyun 	      priv->cic, priv->pmugrf, priv->pmusgrf, priv->pmucru, priv->pmu);
3138*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(OF_PLATDATA)
3139*4882a593Smuzhiyun 	ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->ddr_clk);
3140*4882a593Smuzhiyun #else
3141*4882a593Smuzhiyun 	ret = clk_get_by_index(dev, 0, &priv->ddr_clk);
3142*4882a593Smuzhiyun #endif
3143*4882a593Smuzhiyun 	if (ret) {
3144*4882a593Smuzhiyun 		printf("%s clk get failed %d\n", __func__, ret);
3145*4882a593Smuzhiyun 		return ret;
3146*4882a593Smuzhiyun 	}
3147*4882a593Smuzhiyun 	ret = clk_set_rate(&priv->ddr_clk, params->base.ddr_freq * MHz);
3148*4882a593Smuzhiyun 	if (ret < 0) {
3149*4882a593Smuzhiyun 		printf("%s clk set failed %d\n", __func__, ret);
3150*4882a593Smuzhiyun 		return ret;
3151*4882a593Smuzhiyun 	}
3152*4882a593Smuzhiyun 	ret = sdram_init(priv, params);
3153*4882a593Smuzhiyun 	if (ret < 0) {
3154*4882a593Smuzhiyun 		printf("%s DRAM init failed %d\n", __func__, ret);
3155*4882a593Smuzhiyun 		return ret;
3156*4882a593Smuzhiyun 	}
3157*4882a593Smuzhiyun 
3158*4882a593Smuzhiyun 	return 0;
3159*4882a593Smuzhiyun }
3160*4882a593Smuzhiyun #endif
3161*4882a593Smuzhiyun 
rk3399_dmc_probe(struct udevice * dev)3162*4882a593Smuzhiyun static int rk3399_dmc_probe(struct udevice *dev)
3163*4882a593Smuzhiyun {
3164*4882a593Smuzhiyun #ifdef CONFIG_TPL_BUILD
3165*4882a593Smuzhiyun 	if (rk3399_dmc_init(dev))
3166*4882a593Smuzhiyun 		return 0;
3167*4882a593Smuzhiyun #else
3168*4882a593Smuzhiyun 	struct dram_info *priv = dev_get_priv(dev);
3169*4882a593Smuzhiyun 
3170*4882a593Smuzhiyun 	priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
3171*4882a593Smuzhiyun 	debug("%s: pmugrf=%p\n", __func__, priv->pmugrf);
3172*4882a593Smuzhiyun 	priv->info.base = CONFIG_SYS_SDRAM_BASE;
3173*4882a593Smuzhiyun 	priv->info.size =
3174*4882a593Smuzhiyun 		rockchip_sdram_size((phys_addr_t)&priv->pmugrf->os_reg2);
3175*4882a593Smuzhiyun #ifdef CONFIG_SPL_BUILD
3176*4882a593Smuzhiyun 	struct ddr_param ddr_parem;
3177*4882a593Smuzhiyun 
3178*4882a593Smuzhiyun 	ddr_parem.count = 1;
3179*4882a593Smuzhiyun 	ddr_parem.para[0] = priv->info.base;
3180*4882a593Smuzhiyun 	ddr_parem.para[1] = priv->info.size;
3181*4882a593Smuzhiyun 	rockchip_setup_ddr_param(&ddr_parem);
3182*4882a593Smuzhiyun #endif
3183*4882a593Smuzhiyun 
3184*4882a593Smuzhiyun #endif
3185*4882a593Smuzhiyun 	return 0;
3186*4882a593Smuzhiyun }
3187*4882a593Smuzhiyun 
rk3399_dmc_get_info(struct udevice * dev,struct ram_info * info)3188*4882a593Smuzhiyun static int rk3399_dmc_get_info(struct udevice *dev, struct ram_info *info)
3189*4882a593Smuzhiyun {
3190*4882a593Smuzhiyun 	struct dram_info *priv = dev_get_priv(dev);
3191*4882a593Smuzhiyun 
3192*4882a593Smuzhiyun 	*info = priv->info;
3193*4882a593Smuzhiyun 
3194*4882a593Smuzhiyun 	return 0;
3195*4882a593Smuzhiyun }
3196*4882a593Smuzhiyun 
3197*4882a593Smuzhiyun static struct ram_ops rk3399_dmc_ops = {
3198*4882a593Smuzhiyun 	.get_info = rk3399_dmc_get_info,
3199*4882a593Smuzhiyun };
3200*4882a593Smuzhiyun 
3201*4882a593Smuzhiyun static const struct udevice_id rk3399_dmc_ids[] = {
3202*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3399-dmc" },
3203*4882a593Smuzhiyun 	{ }
3204*4882a593Smuzhiyun };
3205*4882a593Smuzhiyun 
3206*4882a593Smuzhiyun U_BOOT_DRIVER(dmc_rk3399) = {
3207*4882a593Smuzhiyun 	.name = "rockchip_rk3399_dmc",
3208*4882a593Smuzhiyun 	.id = UCLASS_RAM,
3209*4882a593Smuzhiyun 	.of_match = rk3399_dmc_ids,
3210*4882a593Smuzhiyun 	.ops = &rk3399_dmc_ops,
3211*4882a593Smuzhiyun #ifdef CONFIG_TPL_BUILD
3212*4882a593Smuzhiyun 	.ofdata_to_platdata = rk3399_dmc_ofdata_to_platdata,
3213*4882a593Smuzhiyun #endif
3214*4882a593Smuzhiyun 	.probe = rk3399_dmc_probe,
3215*4882a593Smuzhiyun 	.priv_auto_alloc_size = sizeof(struct dram_info),
3216*4882a593Smuzhiyun #ifdef CONFIG_TPL_BUILD
3217*4882a593Smuzhiyun 	.platdata_auto_alloc_size = sizeof(struct rockchip_dmc_plat),
3218*4882a593Smuzhiyun #endif
3219*4882a593Smuzhiyun };
3220