xref: /rk3399_rockchip-uboot/drivers/ram/rockchip/sdram_rk3399.c (revision e1652d3918b182e107addd5e6f451655f239efbc)
1d0b1becdSKever Yang /*
2d0b1becdSKever Yang  * (C) Copyright 2016-2017 Rockchip Inc.
3d0b1becdSKever Yang  *
4d0b1becdSKever Yang  * SPDX-License-Identifier:     GPL-2.0
5d0b1becdSKever Yang  *
6d0b1becdSKever Yang  * Adapted from coreboot.
7d0b1becdSKever Yang  */
8d0b1becdSKever Yang 
9d0b1becdSKever Yang #include <common.h>
10d0b1becdSKever Yang #include <clk.h>
11d0b1becdSKever Yang #include <dm.h>
12d0b1becdSKever Yang #include <dt-structs.h>
13d0b1becdSKever Yang #include <ram.h>
14d0b1becdSKever Yang #include <regmap.h>
15d0b1becdSKever Yang #include <syscon.h>
16d0b1becdSKever Yang #include <asm/io.h>
17d0b1becdSKever Yang #include <asm/arch/clock.h>
18e1f97ec3SYouMin Chen #include <asm/arch/sdram.h>
19d0b1becdSKever Yang #include <asm/arch/sdram_rk3399.h>
20d0b1becdSKever Yang #include <asm/arch/cru_rk3399.h>
21d0b1becdSKever Yang #include <asm/arch/grf_rk3399.h>
228b36ec9fSYouMin Chen #include <asm/arch/pmu_rk3399.h>
23d0b1becdSKever Yang #include <asm/arch/hardware.h>
24d0b1becdSKever Yang #include <linux/err.h>
25d0b1becdSKever Yang #include <time.h>
26d0b1becdSKever Yang 
27d0b1becdSKever Yang DECLARE_GLOBAL_DATA_PTR;
288b36ec9fSYouMin Chen 
29d0b1becdSKever Yang struct chan_info {
30d0b1becdSKever Yang 	struct rk3399_ddr_pctl_regs *pctl;
31d0b1becdSKever Yang 	struct rk3399_ddr_pi_regs *pi;
32d0b1becdSKever Yang 	struct rk3399_ddr_publ_regs *publ;
3331d8c61dSYouMin Chen 	struct msch_regs *msch;
34d0b1becdSKever Yang };
35d0b1becdSKever Yang 
36d0b1becdSKever Yang struct dram_info {
37ca77381eSKever Yang #ifdef CONFIG_TPL_BUILD
38d0b1becdSKever Yang 	struct chan_info chan[2];
39d0b1becdSKever Yang 	struct clk ddr_clk;
40d0b1becdSKever Yang 	struct rk3399_cru *cru;
418b36ec9fSYouMin Chen 	struct rk3399_grf_regs *grf;
428b36ec9fSYouMin Chen 	struct rk3399_pmu_regs *pmu;
43d0b1becdSKever Yang 	struct rk3399_pmucru *pmucru;
44d0b1becdSKever Yang 	struct rk3399_pmusgrf_regs *pmusgrf;
45d0b1becdSKever Yang 	struct rk3399_ddr_cic_regs *cic;
46d0b1becdSKever Yang #endif
47d0b1becdSKever Yang 	struct ram_info info;
48d0b1becdSKever Yang 	struct rk3399_pmugrf_regs *pmugrf;
49d0b1becdSKever Yang };
50d0b1becdSKever Yang 
51d0b1becdSKever Yang #define PRESET_SGRF_HOLD(n)	((0x1 << (6 + 16)) | ((n) << 6))
52d0b1becdSKever Yang #define PRESET_GPIO0_HOLD(n)	((0x1 << (7 + 16)) | ((n) << 7))
53d0b1becdSKever Yang #define PRESET_GPIO1_HOLD(n)	((0x1 << (8 + 16)) | ((n) << 8))
54d0b1becdSKever Yang 
558b36ec9fSYouMin Chen #define PHY_DRV_ODT_HI_Z	0x0
56d0b1becdSKever Yang #define PHY_DRV_ODT_240		0x1
57d0b1becdSKever Yang #define PHY_DRV_ODT_120		0x8
58d0b1becdSKever Yang #define PHY_DRV_ODT_80		0x9
59d0b1becdSKever Yang #define PHY_DRV_ODT_60		0xc
60d0b1becdSKever Yang #define PHY_DRV_ODT_48		0xd
61d0b1becdSKever Yang #define PHY_DRV_ODT_40		0xe
62d0b1becdSKever Yang #define PHY_DRV_ODT_34_3	0xf
63d0b1becdSKever Yang 
64ca77381eSKever Yang #ifdef CONFIG_TPL_BUILD
65d0b1becdSKever Yang 
66d0b1becdSKever Yang struct rockchip_dmc_plat {
67d0b1becdSKever Yang #if CONFIG_IS_ENABLED(OF_PLATDATA)
68d0b1becdSKever Yang 	struct dtd_rockchip_rk3399_dmc dtplat;
69d0b1becdSKever Yang #else
70d0b1becdSKever Yang 	struct rk3399_sdram_params sdram_params;
71d0b1becdSKever Yang #endif
72d0b1becdSKever Yang 	struct regmap *map;
73d0b1becdSKever Yang };
74d0b1becdSKever Yang 
758b36ec9fSYouMin Chen u32 g_pwrup_srefresh_exit[2];
768b36ec9fSYouMin Chen 
778b36ec9fSYouMin Chen struct rk3399_sdram_params dfs_configs[] = {
788b36ec9fSYouMin Chen #include "sdram-rk3399-lpddr4-400.inc"
798b36ec9fSYouMin Chen #include "sdram-rk3399-lpddr4-800.inc"
808b36ec9fSYouMin Chen };
818b36ec9fSYouMin Chen 
8231d8c61dSYouMin Chen #define CRU_SFTRST_DDR_CTRL(ch, n)	((0x1 << (8 + 16 + (ch) * 4)) | \
8331d8c61dSYouMin Chen 						((n) << (8 + (ch) * 4)))
8431d8c61dSYouMin Chen #define CRU_SFTRST_DDR_PHY(ch, n)	((0x1 << (9 + 16 + (ch) * 4)) | \
8531d8c61dSYouMin Chen 						((n) << (9 + (ch) * 4)))
rkclk_ddr_reset(struct rk3399_cru * cru,u32 channel,u32 ctl,u32 phy)8631d8c61dSYouMin Chen static void rkclk_ddr_reset(struct rk3399_cru *cru, u32 channel, u32 ctl,
8731d8c61dSYouMin Chen 			    u32 phy)
88d0b1becdSKever Yang {
8931d8c61dSYouMin Chen 	channel &= 0x1;
9031d8c61dSYouMin Chen 	ctl &= 0x1;
9131d8c61dSYouMin Chen 	phy &= 0x1;
9231d8c61dSYouMin Chen 	writel(CRU_SFTRST_DDR_CTRL(channel, ctl) |
9331d8c61dSYouMin Chen 					CRU_SFTRST_DDR_PHY(channel, phy),
9431d8c61dSYouMin Chen 					&cru->softrst_con[4]);
95d0b1becdSKever Yang }
9631d8c61dSYouMin Chen 
phy_pctrl_reset(struct rk3399_cru * cru,u32 channel)9731d8c61dSYouMin Chen static void phy_pctrl_reset(struct rk3399_cru *cru,
9831d8c61dSYouMin Chen 			    u32 channel)
9931d8c61dSYouMin Chen {
10031d8c61dSYouMin Chen 	rkclk_ddr_reset(cru, channel, 1, 1);
10131d8c61dSYouMin Chen 	udelay(10);
10231d8c61dSYouMin Chen 	rkclk_ddr_reset(cru, channel, 1, 0);
10331d8c61dSYouMin Chen 	udelay(10);
10431d8c61dSYouMin Chen 	rkclk_ddr_reset(cru, channel, 0, 0);
10531d8c61dSYouMin Chen 	udelay(10);
106d0b1becdSKever Yang }
107d0b1becdSKever Yang 
phy_dll_bypass_set(struct rk3399_ddr_publ_regs * ddr_publ_regs,u32 freq)108d0b1becdSKever Yang static void phy_dll_bypass_set(struct rk3399_ddr_publ_regs *ddr_publ_regs,
109d0b1becdSKever Yang 			       u32 freq)
110d0b1becdSKever Yang {
111d0b1becdSKever Yang 	u32 *denali_phy = ddr_publ_regs->denali_phy;
112d0b1becdSKever Yang 
113d0b1becdSKever Yang 	/* From IP spec, only freq small than 125 can enter dll bypass mode */
114d0b1becdSKever Yang 	if (freq <= 125) {
115d0b1becdSKever Yang 		/* phy_sw_master_mode_X PHY_86/214/342/470 4bits offset_8 */
116d0b1becdSKever Yang 		setbits_le32(&denali_phy[86], (0x3 << 2) << 8);
117d0b1becdSKever Yang 		setbits_le32(&denali_phy[214], (0x3 << 2) << 8);
118d0b1becdSKever Yang 		setbits_le32(&denali_phy[342], (0x3 << 2) << 8);
119d0b1becdSKever Yang 		setbits_le32(&denali_phy[470], (0x3 << 2) << 8);
120d0b1becdSKever Yang 
121d0b1becdSKever Yang 		/* phy_adrctl_sw_master_mode PHY_547/675/803 4bits offset_16 */
122d0b1becdSKever Yang 		setbits_le32(&denali_phy[547], (0x3 << 2) << 16);
123d0b1becdSKever Yang 		setbits_le32(&denali_phy[675], (0x3 << 2) << 16);
124d0b1becdSKever Yang 		setbits_le32(&denali_phy[803], (0x3 << 2) << 16);
125d0b1becdSKever Yang 	} else {
126d0b1becdSKever Yang 		/* phy_sw_master_mode_X PHY_86/214/342/470 4bits offset_8 */
127d0b1becdSKever Yang 		clrbits_le32(&denali_phy[86], (0x3 << 2) << 8);
128d0b1becdSKever Yang 		clrbits_le32(&denali_phy[214], (0x3 << 2) << 8);
129d0b1becdSKever Yang 		clrbits_le32(&denali_phy[342], (0x3 << 2) << 8);
130d0b1becdSKever Yang 		clrbits_le32(&denali_phy[470], (0x3 << 2) << 8);
131d0b1becdSKever Yang 
132d0b1becdSKever Yang 		/* phy_adrctl_sw_master_mode PHY_547/675/803 4bits offset_16 */
133d0b1becdSKever Yang 		clrbits_le32(&denali_phy[547], (0x3 << 2) << 16);
134d0b1becdSKever Yang 		clrbits_le32(&denali_phy[675], (0x3 << 2) << 16);
135d0b1becdSKever Yang 		clrbits_le32(&denali_phy[803], (0x3 << 2) << 16);
136d0b1becdSKever Yang 	}
137d0b1becdSKever Yang }
138d0b1becdSKever Yang 
set_memory_map(const struct chan_info * chan,u32 channel,const struct rk3399_sdram_params * sdram_params)139d0b1becdSKever Yang static void set_memory_map(const struct chan_info *chan, u32 channel,
140d0b1becdSKever Yang 			   const struct rk3399_sdram_params *sdram_params)
141d0b1becdSKever Yang {
142d0b1becdSKever Yang 	const struct rk3399_sdram_channel *sdram_ch =
143d0b1becdSKever Yang 		&sdram_params->ch[channel];
144d0b1becdSKever Yang 	u32 *denali_ctl = chan->pctl->denali_ctl;
145d0b1becdSKever Yang 	u32 *denali_pi = chan->pi->denali_pi;
146d0b1becdSKever Yang 	u32 cs_map;
147d0b1becdSKever Yang 	u32 reduc;
148d0b1becdSKever Yang 	u32 row;
149d0b1becdSKever Yang 
150d0b1becdSKever Yang 	/* Get row number from ddrconfig setting */
15131d8c61dSYouMin Chen 	if (sdram_ch->cap_info.ddrconfig < 2 ||
15231d8c61dSYouMin Chen 	    sdram_ch->cap_info.ddrconfig == 4)
153d0b1becdSKever Yang 		row = 16;
1548b36ec9fSYouMin Chen 	else if (sdram_ch->cap_info.ddrconfig == 3 ||
1558b36ec9fSYouMin Chen 		 sdram_ch->cap_info.ddrconfig == 5)
156d0b1becdSKever Yang 		row = 14;
157d0b1becdSKever Yang 	else
158d0b1becdSKever Yang 		row = 15;
159d0b1becdSKever Yang 
16031d8c61dSYouMin Chen 	cs_map = (sdram_ch->cap_info.rank > 1) ? 3 : 1;
16131d8c61dSYouMin Chen 	reduc = (sdram_ch->cap_info.bw == 2) ? 0 : 1;
162d0b1becdSKever Yang 
163d0b1becdSKever Yang 	/* Set the dram configuration to ctrl */
16431d8c61dSYouMin Chen 	clrsetbits_le32(&denali_ctl[191], 0xF, (12 - sdram_ch->cap_info.col));
165d0b1becdSKever Yang 	clrsetbits_le32(&denali_ctl[190], (0x3 << 16) | (0x7 << 24),
16631d8c61dSYouMin Chen 			((3 - sdram_ch->cap_info.bk) << 16) |
167d0b1becdSKever Yang 			((16 - row) << 24));
168d0b1becdSKever Yang 
169d0b1becdSKever Yang 	clrsetbits_le32(&denali_ctl[196], 0x3 | (1 << 16),
170d0b1becdSKever Yang 			cs_map | (reduc << 16));
171d0b1becdSKever Yang 
172d0b1becdSKever Yang 	/* PI_199 PI_COL_DIFF:RW:0:4 */
17331d8c61dSYouMin Chen 	clrsetbits_le32(&denali_pi[199], 0xF, (12 - sdram_ch->cap_info.col));
174d0b1becdSKever Yang 
175d0b1becdSKever Yang 	/* PI_155 PI_ROW_DIFF:RW:24:3 PI_BANK_DIFF:RW:16:2 */
176d0b1becdSKever Yang 	clrsetbits_le32(&denali_pi[155], (0x3 << 16) | (0x7 << 24),
17731d8c61dSYouMin Chen 			((3 - sdram_ch->cap_info.bk) << 16) |
178d0b1becdSKever Yang 			((16 - row) << 24));
1798b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4) {
1808b36ec9fSYouMin Chen 		if (cs_map == 1)
1818b36ec9fSYouMin Chen 			cs_map = 0x5;
1828b36ec9fSYouMin Chen 		else if (cs_map == 2)
1838b36ec9fSYouMin Chen 			cs_map = 0xa;
1848b36ec9fSYouMin Chen 		else
1858b36ec9fSYouMin Chen 			cs_map = 0xF;
1868b36ec9fSYouMin Chen 	}
1878b36ec9fSYouMin Chen 
188d0b1becdSKever Yang 	/* PI_41 PI_CS_MAP:RW:24:4 */
189d0b1becdSKever Yang 	clrsetbits_le32(&denali_pi[41], 0xf << 24, cs_map << 24);
19031d8c61dSYouMin Chen 	if (sdram_ch->cap_info.rank == 1 &&
19131d8c61dSYouMin Chen 	    sdram_params->base.dramtype == DDR3)
192d0b1becdSKever Yang 		writel(0x2EC7FFFF, &denali_pi[34]);
193d0b1becdSKever Yang }
194d0b1becdSKever Yang 
phy_io_config(const struct chan_info * chan,struct rk3399_sdram_params * sdram_params,u32 rd_vref,u32 b_reg,u32 channel)1958b36ec9fSYouMin Chen static void phy_io_config(const struct chan_info *chan,
1968b36ec9fSYouMin Chen 			  struct rk3399_sdram_params *sdram_params, u32 rd_vref,
1978b36ec9fSYouMin Chen 			  u32 b_reg, u32 channel)
198d0b1becdSKever Yang {
1998b36ec9fSYouMin Chen 	u32 *denali_phy;
2008b36ec9fSYouMin Chen 	u32 *denali_ctl;
2018b36ec9fSYouMin Chen 	u32 vref_mode_dq = 0, vref_value_dq = 0;
2028b36ec9fSYouMin Chen 	u32 vref_mode_ac = 0, vref_value_ac = 0;
2038b36ec9fSYouMin Chen 	u32 mode_sel = 0;
2048b36ec9fSYouMin Chen 	u32 boostp, boostn;
2058b36ec9fSYouMin Chen 	u32 slewp, slewn;
2068b36ec9fSYouMin Chen 	u32 speed;
2078b36ec9fSYouMin Chen 	u32 rx_cm_input;
208d0b1becdSKever Yang 	u32 reg_value;
2098b36ec9fSYouMin Chen 	u32 ds_value, odt_value;
210d0b1becdSKever Yang 
2118b36ec9fSYouMin Chen 	if (b_reg) {
2128b36ec9fSYouMin Chen 		denali_phy = chan->publ->denali_phy;
2138b36ec9fSYouMin Chen 		denali_ctl = chan->pctl->denali_ctl;
214d0b1becdSKever Yang 	} else {
2158b36ec9fSYouMin Chen 		denali_phy = sdram_params->phy_regs.denali_phy;
2168b36ec9fSYouMin Chen 		denali_ctl = sdram_params->pctl_regs.denali_ctl;
2178b36ec9fSYouMin Chen 	}
2188b36ec9fSYouMin Chen 	rd_vref *= 1000;
2198b36ec9fSYouMin Chen 	/* vref setting & mode setting */
2208b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4) {
2218b36ec9fSYouMin Chen 		if (rd_vref < 36700) {
2228b36ec9fSYouMin Chen 			/* MODE_LV[2:0] = LPDDR4 (Range 2)*/
2238b36ec9fSYouMin Chen 			vref_mode_dq = 0x7;
2248b36ec9fSYouMin Chen 			/* MODE[2:0]= LPDDR4 Range 2(0.4*VDDQ) */
2258b36ec9fSYouMin Chen 			mode_sel = 0x5;
2268b36ec9fSYouMin Chen 			vref_value_dq = (rd_vref - 3300) / 521;
2278b36ec9fSYouMin Chen 		} else {
2288b36ec9fSYouMin Chen 			/* MODE_LV[2:0] = LPDDR4 (Range 1)*/
2298b36ec9fSYouMin Chen 			vref_mode_dq = 0x6;
2308b36ec9fSYouMin Chen 			/* MODE[2:0]= LPDDR4 Range 1(0.33*VDDQ) */
2318b36ec9fSYouMin Chen 			mode_sel = 0x4;
2328b36ec9fSYouMin Chen 			vref_value_dq = (rd_vref - 15300) / 521;
2338b36ec9fSYouMin Chen 		}
2348b36ec9fSYouMin Chen 		vref_mode_ac = 0x6;
2358b36ec9fSYouMin Chen 		/* VDDQ/3/2=16.8% */
2368b36ec9fSYouMin Chen 		vref_value_ac = 0x3;
2378b36ec9fSYouMin Chen 	} else if (sdram_params->base.dramtype == LPDDR3) {
2388b36ec9fSYouMin Chen 		/* LPDDR3 */
2398b36ec9fSYouMin Chen 		if (sdram_params->base.odt == 1) {
2408b36ec9fSYouMin Chen 			vref_mode_dq = 0x5;  /*LPDDR3 ODT*/
2418b36ec9fSYouMin Chen 			ds_value = readl(&denali_ctl[138]) & 0xf;
2428b36ec9fSYouMin Chen 			odt_value = (readl(&denali_phy[6]) >> 4) & 0xf;
2438b36ec9fSYouMin Chen 			if (ds_value == 0x3) {	/* 48ohm */
2448b36ec9fSYouMin Chen 				switch (odt_value) {
2458b36ec9fSYouMin Chen 				case PHY_DRV_ODT_240:
2468b36ec9fSYouMin Chen 					vref_value_dq = 0x1B;
2478b36ec9fSYouMin Chen 					break;
2488b36ec9fSYouMin Chen 				case PHY_DRV_ODT_120:
2498b36ec9fSYouMin Chen 					vref_value_dq = 0x26;
2508b36ec9fSYouMin Chen 					break;
2518b36ec9fSYouMin Chen 				case PHY_DRV_ODT_60:
2528b36ec9fSYouMin Chen 					vref_value_dq = 0x36;
2538b36ec9fSYouMin Chen 					break;
2548b36ec9fSYouMin Chen 				}
2558b36ec9fSYouMin Chen 			} else if (ds_value == 0x2) {  /* 40ohm */
2568b36ec9fSYouMin Chen 				switch (odt_value) {
2578b36ec9fSYouMin Chen 				case PHY_DRV_ODT_240:
2588b36ec9fSYouMin Chen 					vref_value_dq = 0x19;
2598b36ec9fSYouMin Chen 					break;
2608b36ec9fSYouMin Chen 				case PHY_DRV_ODT_120:
2618b36ec9fSYouMin Chen 					vref_value_dq = 0x23;
2628b36ec9fSYouMin Chen 					break;
2638b36ec9fSYouMin Chen 				case PHY_DRV_ODT_60:
2648b36ec9fSYouMin Chen 					vref_value_dq = 0x31;
2658b36ec9fSYouMin Chen 					break;
2668b36ec9fSYouMin Chen 				}
2678b36ec9fSYouMin Chen 			} else if (ds_value == 0x1) {  /*34.3ohm*/
2688b36ec9fSYouMin Chen 				switch (odt_value) {
2698b36ec9fSYouMin Chen 				case PHY_DRV_ODT_240:
2708b36ec9fSYouMin Chen 					vref_value_dq = 0x17;
2718b36ec9fSYouMin Chen 					break;
2728b36ec9fSYouMin Chen 				case PHY_DRV_ODT_120:
2738b36ec9fSYouMin Chen 					vref_value_dq = 0x20;
2748b36ec9fSYouMin Chen 					break;
2758b36ec9fSYouMin Chen 				case PHY_DRV_ODT_60:
2768b36ec9fSYouMin Chen 					vref_value_dq = 0x2e;
2778b36ec9fSYouMin Chen 					break;
2788b36ec9fSYouMin Chen 				}
2798b36ec9fSYouMin Chen 			}
2808b36ec9fSYouMin Chen 		} else {
2818b36ec9fSYouMin Chen 			vref_mode_dq = 0x2;
2828b36ec9fSYouMin Chen 			vref_value_dq = 0x1f;
2838b36ec9fSYouMin Chen 		}
2848b36ec9fSYouMin Chen 		vref_mode_ac = 0x2;
2858b36ec9fSYouMin Chen 		vref_value_ac = 0x1f;
2868b36ec9fSYouMin Chen 		mode_sel = 0x0;
2878b36ec9fSYouMin Chen 	} else if (sdram_params->base.dramtype == DDR3) {
2888b36ec9fSYouMin Chen 		vref_mode_dq = 0x1;
2898b36ec9fSYouMin Chen 		vref_value_dq = 0x1f;
2908b36ec9fSYouMin Chen 		vref_mode_ac = 0x1;
2918b36ec9fSYouMin Chen 		vref_value_ac = 0x1f;
2928b36ec9fSYouMin Chen 		mode_sel = 0x1;
293d0b1becdSKever Yang 	}
294d0b1becdSKever Yang 
2958b36ec9fSYouMin Chen 	reg_value = (vref_mode_dq << 9) | (0x1 << 8) | vref_value_dq;
2968b36ec9fSYouMin Chen 	/* PHY_913 PHY_PAD_VREF_CTRL_DQ_0 12bits offset_8 */
2978b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[913], 0xfff << 8, reg_value << 8);
2988b36ec9fSYouMin Chen 	/* PHY_914 PHY_PAD_VREF_CTRL_DQ_1 12bits offset_0 */
2998b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[914], 0xfff, reg_value);
3008b36ec9fSYouMin Chen 	/* PHY_914 PHY_PAD_VREF_CTRL_DQ_2 12bits offset_16 */
3018b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[914], 0xfff << 16, reg_value << 16);
3028b36ec9fSYouMin Chen 	/* PHY_915 PHY_PAD_VREF_CTRL_DQ_3 12bits offset_0 */
3038b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[915], 0xfff, reg_value);
304d0b1becdSKever Yang 
3058b36ec9fSYouMin Chen 	reg_value = (vref_mode_ac << 9) | (0x1 << 8) | vref_value_ac;
3068b36ec9fSYouMin Chen 	/* PHY_915 PHY_PAD_VREF_CTRL_AC 12bits offset_16 */
3078b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[915], 0xfff << 16, reg_value << 16);
3088b36ec9fSYouMin Chen 
3098b36ec9fSYouMin Chen 	/* PHY_924 PHY_PAD_FDBK_DRIVE */
3108b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[924], 0x7 << 15, mode_sel << 15);
3118b36ec9fSYouMin Chen 	/* PHY_926 PHY_PAD_DATA_DRIVE */
3128b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[926], 0x7 << 6, mode_sel << 6);
3138b36ec9fSYouMin Chen 	/* PHY_927 PHY_PAD_DQS_DRIVE */
3148b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[927], 0x7 << 6, mode_sel << 6);
3158b36ec9fSYouMin Chen 	/* PHY_928 PHY_PAD_ADDR_DRIVE */
3168b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[928], 0x7 << 14, mode_sel << 14);
3178b36ec9fSYouMin Chen 	/* PHY_929 PHY_PAD_CLK_DRIVE */
3188b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[929], 0x7 << 14, mode_sel << 14);
3198b36ec9fSYouMin Chen 	/* PHY_935 PHY_PAD_CKE_DRIVE */
3208b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[935], 0x7 << 14, mode_sel << 14);
3218b36ec9fSYouMin Chen 	/* PHY_937 PHY_PAD_RST_DRIVE */
3228b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[937], 0x7 << 14, mode_sel << 14);
3238b36ec9fSYouMin Chen 	/* PHY_939 PHY_PAD_CS_DRIVE */
3248b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[939], 0x7 << 14, mode_sel << 14);
3258b36ec9fSYouMin Chen 
3268b36ec9fSYouMin Chen 	/* BOOSTP_EN & BOOSTn_EN */
3278b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4) {
3288b36ec9fSYouMin Chen 		boostp = 0x1;
3298b36ec9fSYouMin Chen 		boostn = 0x1;
3308b36ec9fSYouMin Chen 		reg_value = ((boostp << 4) | boostn);
3318b36ec9fSYouMin Chen 		/* PHY_925 PHY_PAD_FDBK_DRIVE2 */
3328b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[925], 0xff << 8, reg_value << 8);
3338b36ec9fSYouMin Chen 		/* PHY_926 PHY_PAD_DATA_DRIVE */
3348b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[926], 0xff << 12, reg_value << 12);
3358b36ec9fSYouMin Chen 		/* PHY_927 PHY_PAD_DQS_DRIVE */
3368b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[927], 0xff << 14, reg_value << 14);
3378b36ec9fSYouMin Chen 		/* PHY_928 PHY_PAD_ADDR_DRIVE */
3388b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[928], 0xff << 20, reg_value << 20);
3398b36ec9fSYouMin Chen 		/* PHY_929 PHY_PAD_CLK_DRIVE */
3408b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[929], 0xff << 22, reg_value << 22);
3418b36ec9fSYouMin Chen 		/* PHY_935 PHY_PAD_CKE_DRIVE */
3428b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[935], 0xff << 20, reg_value << 20);
3438b36ec9fSYouMin Chen 		/* PHY_937 PHY_PAD_RST_DRIVE */
3448b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[937], 0xff << 20, reg_value << 20);
3458b36ec9fSYouMin Chen 		/* PHY_939 PHY_PAD_CS_DRIVE */
3468b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[939], 0xff << 20, reg_value << 20);
3478b36ec9fSYouMin Chen 	}
3488b36ec9fSYouMin Chen 
3498b36ec9fSYouMin Chen 	/* SLEWP & SLEWN */
3508b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4) {
3518b36ec9fSYouMin Chen 		slewp = 0x1;
3528b36ec9fSYouMin Chen 		slewn = 0x1;
3538b36ec9fSYouMin Chen 		reg_value = ((slewp << 3) | slewn);
3548b36ec9fSYouMin Chen 		/* PHY_924 PHY_PAD_FDBK_DRIVE */
3558b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[924], 0x3f << 8, reg_value << 8);
3568b36ec9fSYouMin Chen 		/* PHY_926 PHY_PAD_DATA_DRIVE */
3578b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[926], 0x3f, reg_value);
3588b36ec9fSYouMin Chen 		/* PHY_927 PHY_PAD_DQS_DRIVE */
3598b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[927], 0x3f, reg_value);
3608b36ec9fSYouMin Chen 		/* PHY_928 PHY_PAD_ADDR_DRIVE */
3618b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[928], 0x3f << 8, reg_value << 8);
3628b36ec9fSYouMin Chen 		/* PHY_929 PHY_PAD_CLK_DRIVE */
3638b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[929], 0x3f << 8, reg_value << 8);
3648b36ec9fSYouMin Chen 		/* PHY_935 PHY_PAD_CKE_DRIVE */
3658b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[935], 0x3f << 8, reg_value << 8);
3668b36ec9fSYouMin Chen 		/* PHY_937 PHY_PAD_RST_DRIVE */
3678b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[937], 0x3f << 8, reg_value << 8);
3688b36ec9fSYouMin Chen 		/* PHY_939 PHY_PAD_CS_DRIVE */
3698b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[939], 0x3f << 8, reg_value << 8);
3708b36ec9fSYouMin Chen 	}
3718b36ec9fSYouMin Chen 
3728b36ec9fSYouMin Chen 	/* speed setting */
3738b36ec9fSYouMin Chen 	if (sdram_params->base.ddr_freq < 400 * MHz)
3748b36ec9fSYouMin Chen 		speed = 0x0;
3758b36ec9fSYouMin Chen 	else if (sdram_params->base.ddr_freq < 800 * MHz)
3768b36ec9fSYouMin Chen 		speed = 0x1;
3778b36ec9fSYouMin Chen 	else if (sdram_params->base.ddr_freq < 1200 * MHz)
3788b36ec9fSYouMin Chen 		speed = 0x2;
3798b36ec9fSYouMin Chen 	speed = 0x2;
3808b36ec9fSYouMin Chen 
3818b36ec9fSYouMin Chen 	/* PHY_924 PHY_PAD_FDBK_DRIVE */
3828b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[924], 0x3 << 21, speed << 21);
3838b36ec9fSYouMin Chen 	/* PHY_926 PHY_PAD_DATA_DRIVE */
3848b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[926], 0x3 << 9, speed << 9);
3858b36ec9fSYouMin Chen 	/* PHY_927 PHY_PAD_DQS_DRIVE */
3868b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[927], 0x3 << 9, speed << 9);
3878b36ec9fSYouMin Chen 	/* PHY_928 PHY_PAD_ADDR_DRIVE */
3888b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[928], 0x3 << 17, speed << 17);
3898b36ec9fSYouMin Chen 	/* PHY_929 PHY_PAD_CLK_DRIVE */
3908b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[929], 0x3 << 17, speed << 17);
3918b36ec9fSYouMin Chen 	/* PHY_935 PHY_PAD_CKE_DRIVE */
3928b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[935], 0x3 << 17, speed << 17);
3938b36ec9fSYouMin Chen 	/* PHY_937 PHY_PAD_RST_DRIVE */
3948b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[937], 0x3 << 17, speed << 17);
3958b36ec9fSYouMin Chen 	/* PHY_939 PHY_PAD_CS_DRIVE */
3968b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[939], 0x3 << 17, speed << 17);
3978b36ec9fSYouMin Chen 
3988b36ec9fSYouMin Chen 	/* RX_CM_INPUT */
3998b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4) {
4008b36ec9fSYouMin Chen 		rx_cm_input = 0x1;
4018b36ec9fSYouMin Chen 		/* PHY_924 PHY_PAD_FDBK_DRIVE */
4028b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[924], 0x1 << 14, rx_cm_input << 14);
4038b36ec9fSYouMin Chen 		/* PHY_926 PHY_PAD_DATA_DRIVE */
4048b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[926], 0x1 << 11, rx_cm_input << 11);
4058b36ec9fSYouMin Chen 		/* PHY_927 PHY_PAD_DQS_DRIVE */
4068b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[927], 0x1 << 13, rx_cm_input << 13);
4078b36ec9fSYouMin Chen 		/* PHY_928 PHY_PAD_ADDR_DRIVE */
4088b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[928], 0x1 << 19, rx_cm_input << 19);
4098b36ec9fSYouMin Chen 		/* PHY_929 PHY_PAD_CLK_DRIVE */
4108b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[929], 0x1 << 21, rx_cm_input << 21);
4118b36ec9fSYouMin Chen 		/* PHY_935 PHY_PAD_CKE_DRIVE */
4128b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[935], 0x1 << 19, rx_cm_input << 19);
4138b36ec9fSYouMin Chen 		/* PHY_937 PHY_PAD_RST_DRIVE */
4148b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[937], 0x1 << 19, rx_cm_input << 19);
4158b36ec9fSYouMin Chen 		/* PHY_939 PHY_PAD_CS_DRIVE */
4168b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy[939], 0x1 << 19, rx_cm_input << 19);
4178b36ec9fSYouMin Chen 	}
4188b36ec9fSYouMin Chen }
4198b36ec9fSYouMin Chen 
4208b36ec9fSYouMin Chen struct io_setting {
4218b36ec9fSYouMin Chen 	u32 mhz;
4228b36ec9fSYouMin Chen 	u32 mr5;
4238b36ec9fSYouMin Chen 	/* dram side */
4248b36ec9fSYouMin Chen 	u32 dq_odt;
4258b36ec9fSYouMin Chen 	u32 ca_odt;
4268b36ec9fSYouMin Chen 	u32 pdds;
4278b36ec9fSYouMin Chen 	u32 dq_vref;
4288b36ec9fSYouMin Chen 	u32 ca_vref;
4298b36ec9fSYouMin Chen 	/* phy side */
4308b36ec9fSYouMin Chen 	u32 rd_odt;
4318b36ec9fSYouMin Chen 	u32 wr_dq_drv;
4328b36ec9fSYouMin Chen 	u32 wr_ca_drv;
4338b36ec9fSYouMin Chen 	u32 wr_ckcs_drv;
4348b36ec9fSYouMin Chen 	u32 rd_odt_en;
4358b36ec9fSYouMin Chen 	u32 rd_vref;
4368b36ec9fSYouMin Chen };
4378b36ec9fSYouMin Chen 
4388b36ec9fSYouMin Chen struct io_setting lp4_io_set[] = {
4398b36ec9fSYouMin Chen 	{
4408b36ec9fSYouMin Chen 		50 * MHz,
4418b36ec9fSYouMin Chen 		0,
4428b36ec9fSYouMin Chen 		/* dram side */
4438b36ec9fSYouMin Chen 		0,	/* dq_odt; */
4448b36ec9fSYouMin Chen 		0,	/* ca_odt; */
4458b36ec9fSYouMin Chen 		6,	/* pdds; */
4468b36ec9fSYouMin Chen 		0x72,	/* dq_vref; */
4478b36ec9fSYouMin Chen 		0x72,	/* ca_vref; */
4488b36ec9fSYouMin Chen 		/* phy side */
4498b36ec9fSYouMin Chen 		PHY_DRV_ODT_HI_Z,	/* rd_odt; */
4508b36ec9fSYouMin Chen 		PHY_DRV_ODT_40,	/* wr_dq_drv; */
4518b36ec9fSYouMin Chen 		PHY_DRV_ODT_40,	/* wr_ca_drv; */
4528b36ec9fSYouMin Chen 		PHY_DRV_ODT_40,	/* wr_ckcs_drv; */
4538b36ec9fSYouMin Chen 		0,	/* rd_odt_en;*/
4548b36ec9fSYouMin Chen 		41,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
4558b36ec9fSYouMin Chen 	},
4568b36ec9fSYouMin Chen 	{
4578b36ec9fSYouMin Chen 		400 * MHz,
4588b36ec9fSYouMin Chen 		0,
4598b36ec9fSYouMin Chen 		/* dram side */
4608b36ec9fSYouMin Chen 		0,	/* dq_odt; */
4618b36ec9fSYouMin Chen 		0,	/* ca_odt; */
4628b36ec9fSYouMin Chen 		6,	/* pdds; */
4638b36ec9fSYouMin Chen 		0x72,	/* dq_vref; */
4648b36ec9fSYouMin Chen 		0x72,	/* ca_vref; */
4658b36ec9fSYouMin Chen 		/* phy side */
4668b36ec9fSYouMin Chen 		PHY_DRV_ODT_HI_Z,	/* rd_odt; */
4678b36ec9fSYouMin Chen 		PHY_DRV_ODT_40,	/* wr_dq_drv; */
4688b36ec9fSYouMin Chen 		PHY_DRV_ODT_40,	/* wr_ca_drv; */
4698b36ec9fSYouMin Chen 		PHY_DRV_ODT_40,	/* wr_ckcs_drv; */
4708b36ec9fSYouMin Chen 		0,	/* rd_odt_en; */
4718b36ec9fSYouMin Chen 		/* shmoo result, read signal 41% is the best */
4728b36ec9fSYouMin Chen 		41,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
4738b36ec9fSYouMin Chen 	},
4748b36ec9fSYouMin Chen 	{
4758b36ec9fSYouMin Chen 		800 * MHz,
4768b36ec9fSYouMin Chen 		0,
4778b36ec9fSYouMin Chen 		/* dram side */
4788b36ec9fSYouMin Chen 		0,	/* dq_odt; */
4798b36ec9fSYouMin Chen 		0,	/* ca_odt; */
4808b36ec9fSYouMin Chen 		1,	/* pdds; */
4818b36ec9fSYouMin Chen 		0x72,	/* dq_vref; */
4828b36ec9fSYouMin Chen 		0x72,	/* ca_vref; */
4838b36ec9fSYouMin Chen 		/* phy side */
4848b36ec9fSYouMin Chen 		PHY_DRV_ODT_40,	/* rd_odt; */
4858b36ec9fSYouMin Chen 		PHY_DRV_ODT_40,	/* wr_dq_drv; */
4868b36ec9fSYouMin Chen 		PHY_DRV_ODT_40,	/* wr_ca_drv; */
4878b36ec9fSYouMin Chen 		PHY_DRV_ODT_40,	/* wr_ckcs_drv; */
4888b36ec9fSYouMin Chen 		1,	/* rd_odt_en; */
4898b36ec9fSYouMin Chen 		17,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
4908b36ec9fSYouMin Chen 	},
4918b36ec9fSYouMin Chen 	{
4928b36ec9fSYouMin Chen 		1066 * MHz,
4938b36ec9fSYouMin Chen 		0,
4948b36ec9fSYouMin Chen 		/* dram side */
4958b36ec9fSYouMin Chen 		6,	/* dq_odt; */
4968b36ec9fSYouMin Chen 		0,	/* ca_odt; */
4978b36ec9fSYouMin Chen 		1,	/* pdds; */
4988b36ec9fSYouMin Chen 		0x10,	/* dq_vref; */
4998b36ec9fSYouMin Chen 		0x72,	/* ca_vref; */
5008b36ec9fSYouMin Chen 		/* phy side */
5018b36ec9fSYouMin Chen 		PHY_DRV_ODT_40,	/* rd_odt; */
5028b36ec9fSYouMin Chen 		PHY_DRV_ODT_60,	/* wr_dq_drv; */
5038b36ec9fSYouMin Chen 		PHY_DRV_ODT_40,	/* wr_ca_drv; */
5048b36ec9fSYouMin Chen 		PHY_DRV_ODT_40,	/* wr_ckcs_drv; */
5058b36ec9fSYouMin Chen 		1,	/* rd_odt_en; */
5068b36ec9fSYouMin Chen 		17,	/* rd_vref; (unit %, range 3.3% - 48.7%) */
5078b36ec9fSYouMin Chen 	},
5088b36ec9fSYouMin Chen };
5098b36ec9fSYouMin Chen 
get_io_set(struct rk3399_sdram_params * sdram_params,u32 mr5)5108b36ec9fSYouMin Chen static struct io_setting *get_io_set(struct rk3399_sdram_params *sdram_params,
5118b36ec9fSYouMin Chen 				     u32 mr5)
5128b36ec9fSYouMin Chen {
5138b36ec9fSYouMin Chen 	struct io_setting *io = NULL;
5148b36ec9fSYouMin Chen 	u32 n;
5158b36ec9fSYouMin Chen 
5168b36ec9fSYouMin Chen 	for (n = 0; n < ARRAY_SIZE(lp4_io_set); n++) {
5178b36ec9fSYouMin Chen 		io = &lp4_io_set[n];
5188b36ec9fSYouMin Chen 		if (io->mr5 != 0) {
5198b36ec9fSYouMin Chen 			if (io->mhz >= sdram_params->base.ddr_freq &&
5208b36ec9fSYouMin Chen 			    io->mr5 == mr5)
5218b36ec9fSYouMin Chen 				break;
5228b36ec9fSYouMin Chen 		} else {
5238b36ec9fSYouMin Chen 			if (io->mhz >= sdram_params->base.ddr_freq)
5248b36ec9fSYouMin Chen 				break;
5258b36ec9fSYouMin Chen 		}
5268b36ec9fSYouMin Chen 	}
5278b36ec9fSYouMin Chen 	return io;
5288b36ec9fSYouMin Chen }
5298b36ec9fSYouMin Chen 
5308b36ec9fSYouMin Chen /*
5318b36ec9fSYouMin Chen  * b_reg: indicate whether set phy register
5328b36ec9fSYouMin Chen  * or just set sdram_params.
5338b36ec9fSYouMin Chen  * if b_reg = 0, channel, mr5 are not care
5348b36ec9fSYouMin Chen  */
set_ds_odt(const struct chan_info * chan,struct rk3399_sdram_params * sdram_params,u32 b_reg,u32 channel,u32 mr5)5358b36ec9fSYouMin Chen static void set_ds_odt(const struct chan_info *chan,
5368b36ec9fSYouMin Chen 		       struct rk3399_sdram_params *sdram_params, u32 b_reg,
5378b36ec9fSYouMin Chen 		       u32 channel, u32 mr5)
5388b36ec9fSYouMin Chen {
5398b36ec9fSYouMin Chen 	u32 *denali_phy;
5408b36ec9fSYouMin Chen 	u32 *denali_ctl;
5418b36ec9fSYouMin Chen 	u32 tsel_idle_en, tsel_wr_en, tsel_rd_en;
5428b36ec9fSYouMin Chen 	u32 tsel_idle_select_p, tsel_rd_select_p;
5438b36ec9fSYouMin Chen 	u32 tsel_idle_select_n, tsel_rd_select_n;
5448b36ec9fSYouMin Chen 	u32 tsel_wr_select_dq_p, tsel_wr_select_ca_p;
5458b36ec9fSYouMin Chen 	u32 tsel_wr_select_dq_n, tsel_wr_select_ca_n;
5468b36ec9fSYouMin Chen 	u32 soc_odt = 0;
5478b36ec9fSYouMin Chen 	u32 tsel_ckcs_select_p, tsel_ckcs_select_n;
5488b36ec9fSYouMin Chen 	u32 reg_value;
5498b36ec9fSYouMin Chen 	struct io_setting *io = NULL;
5508b36ec9fSYouMin Chen 
5518b36ec9fSYouMin Chen 	if (b_reg) {
5528b36ec9fSYouMin Chen 		denali_phy = chan->publ->denali_phy;
5538b36ec9fSYouMin Chen 		denali_ctl = chan->pctl->denali_ctl;
5548b36ec9fSYouMin Chen 	} else {
5558b36ec9fSYouMin Chen 		denali_phy = sdram_params->phy_regs.denali_phy;
5568b36ec9fSYouMin Chen 		denali_ctl = sdram_params->pctl_regs.denali_ctl;
5578b36ec9fSYouMin Chen 	}
5588b36ec9fSYouMin Chen 
5598b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4) {
5608b36ec9fSYouMin Chen 		io = get_io_set(sdram_params, mr5);
5618b36ec9fSYouMin Chen 
5628b36ec9fSYouMin Chen 		tsel_rd_select_p = PHY_DRV_ODT_HI_Z;
5638b36ec9fSYouMin Chen 		tsel_rd_select_n = io->rd_odt;
5648b36ec9fSYouMin Chen 
5658b36ec9fSYouMin Chen 		tsel_idle_select_p = PHY_DRV_ODT_HI_Z;
5668b36ec9fSYouMin Chen 		tsel_idle_select_n = PHY_DRV_ODT_HI_Z;
5678b36ec9fSYouMin Chen 
5688b36ec9fSYouMin Chen 		tsel_wr_select_dq_p = io->wr_dq_drv;
5698b36ec9fSYouMin Chen 		tsel_wr_select_dq_n = PHY_DRV_ODT_34_3;
5708b36ec9fSYouMin Chen 
5718b36ec9fSYouMin Chen 		tsel_wr_select_ca_p = io->wr_ca_drv;
5728b36ec9fSYouMin Chen 		tsel_wr_select_ca_n = PHY_DRV_ODT_34_3;
5738b36ec9fSYouMin Chen 
5748b36ec9fSYouMin Chen 		tsel_ckcs_select_p = io->wr_ckcs_drv;
5758b36ec9fSYouMin Chen 		tsel_ckcs_select_n = PHY_DRV_ODT_34_3;
5768b36ec9fSYouMin Chen 
5778b36ec9fSYouMin Chen 		switch (tsel_rd_select_n) {
5788b36ec9fSYouMin Chen 		case PHY_DRV_ODT_240:
5798b36ec9fSYouMin Chen 			soc_odt = 1;
5808b36ec9fSYouMin Chen 			break;
5818b36ec9fSYouMin Chen 		case PHY_DRV_ODT_120:
5828b36ec9fSYouMin Chen 			soc_odt = 2;
5838b36ec9fSYouMin Chen 			break;
5848b36ec9fSYouMin Chen 		case PHY_DRV_ODT_80:
5858b36ec9fSYouMin Chen 			soc_odt = 3;
5868b36ec9fSYouMin Chen 			break;
5878b36ec9fSYouMin Chen 		case PHY_DRV_ODT_60:
5888b36ec9fSYouMin Chen 			soc_odt = 4;
5898b36ec9fSYouMin Chen 			break;
5908b36ec9fSYouMin Chen 		case PHY_DRV_ODT_48:
5918b36ec9fSYouMin Chen 			soc_odt = 5;
5928b36ec9fSYouMin Chen 			break;
5938b36ec9fSYouMin Chen 		case PHY_DRV_ODT_40:
5948b36ec9fSYouMin Chen 			soc_odt = 6;
5958b36ec9fSYouMin Chen 			break;
5968b36ec9fSYouMin Chen 		case PHY_DRV_ODT_34_3:
5978b36ec9fSYouMin Chen 			soc_odt = 6;
5988b36ec9fSYouMin Chen 			printf("LPDDR4 MR22 Soc ODT not support\n");
5998b36ec9fSYouMin Chen 			break;
6008b36ec9fSYouMin Chen 		case PHY_DRV_ODT_HI_Z:
6018b36ec9fSYouMin Chen 		default:
6028b36ec9fSYouMin Chen 			soc_odt = 0;
6038b36ec9fSYouMin Chen 			break;
6048b36ec9fSYouMin Chen 		}
6058b36ec9fSYouMin Chen 	} else if (sdram_params->base.dramtype == LPDDR3) {
6068b36ec9fSYouMin Chen 		tsel_rd_select_p = PHY_DRV_ODT_240;
6078b36ec9fSYouMin Chen 		tsel_rd_select_n = PHY_DRV_ODT_HI_Z;
6088b36ec9fSYouMin Chen 
6098b36ec9fSYouMin Chen 		tsel_idle_select_p = PHY_DRV_ODT_240;
6108b36ec9fSYouMin Chen 		tsel_idle_select_n = PHY_DRV_ODT_HI_Z;
6118b36ec9fSYouMin Chen 
6128b36ec9fSYouMin Chen 		tsel_wr_select_dq_p = PHY_DRV_ODT_34_3;
6138b36ec9fSYouMin Chen 		tsel_wr_select_dq_n = PHY_DRV_ODT_34_3;
6148b36ec9fSYouMin Chen 
6158b36ec9fSYouMin Chen 		tsel_wr_select_ca_p = PHY_DRV_ODT_34_3;
6168b36ec9fSYouMin Chen 		tsel_wr_select_ca_n = PHY_DRV_ODT_34_3;
6178b36ec9fSYouMin Chen 
6188b36ec9fSYouMin Chen 		tsel_ckcs_select_p = PHY_DRV_ODT_34_3;
6198b36ec9fSYouMin Chen 		tsel_ckcs_select_n = PHY_DRV_ODT_34_3;
6208b36ec9fSYouMin Chen 	} else {
6218b36ec9fSYouMin Chen 		tsel_rd_select_p = PHY_DRV_ODT_240;
6228b36ec9fSYouMin Chen 		tsel_rd_select_n = PHY_DRV_ODT_240;
6238b36ec9fSYouMin Chen 
6248b36ec9fSYouMin Chen 		tsel_idle_select_p = PHY_DRV_ODT_240;
6258b36ec9fSYouMin Chen 		tsel_idle_select_n = PHY_DRV_ODT_240;
6268b36ec9fSYouMin Chen 
6278b36ec9fSYouMin Chen 		tsel_wr_select_dq_p = PHY_DRV_ODT_34_3;
6288b36ec9fSYouMin Chen 		tsel_wr_select_dq_n = PHY_DRV_ODT_34_3;
6298b36ec9fSYouMin Chen 
6308b36ec9fSYouMin Chen 		tsel_wr_select_ca_p = PHY_DRV_ODT_34_3;
6318b36ec9fSYouMin Chen 		tsel_wr_select_ca_n = PHY_DRV_ODT_34_3;
6328b36ec9fSYouMin Chen 
6338b36ec9fSYouMin Chen 		tsel_ckcs_select_p = PHY_DRV_ODT_34_3;
6348b36ec9fSYouMin Chen 		tsel_ckcs_select_n = PHY_DRV_ODT_34_3;
6358b36ec9fSYouMin Chen 	}
6368b36ec9fSYouMin Chen 
6378b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4) {
6388b36ec9fSYouMin Chen 		if (sdram_params->base.odt == 1) {
6398b36ec9fSYouMin Chen 			tsel_rd_en = io->rd_odt_en;
640d0b1becdSKever Yang 			tsel_idle_en = 0;
6418b36ec9fSYouMin Chen 		} else {
6428b36ec9fSYouMin Chen 			tsel_rd_en = 0;
6438b36ec9fSYouMin Chen 			tsel_idle_en = 0;
6448b36ec9fSYouMin Chen 		}
6458b36ec9fSYouMin Chen 	} else {
6468b36ec9fSYouMin Chen 		tsel_rd_en = sdram_params->base.odt;
6478b36ec9fSYouMin Chen 		tsel_idle_en = 0;
6488b36ec9fSYouMin Chen 	}
6498b36ec9fSYouMin Chen 	tsel_wr_en = 0;
6508b36ec9fSYouMin Chen 
6518b36ec9fSYouMin Chen #define CS0_MR22_VAL (0)
6528b36ec9fSYouMin Chen #define CS1_MR22_VAL (3)
6538b36ec9fSYouMin Chen 	/* F0_0 */
6548b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_ctl[145], 0xFF << 16,
6558b36ec9fSYouMin Chen 			(soc_odt | (CS0_MR22_VAL << 3)) << 16);
6568b36ec9fSYouMin Chen 	/* F2_0, F1_0 */
6578b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_ctl[146], 0xFF00FF,
6588b36ec9fSYouMin Chen 			((soc_odt | (CS0_MR22_VAL << 3)) << 16) |
6598b36ec9fSYouMin Chen 			(soc_odt | (CS0_MR22_VAL << 3)));
6608b36ec9fSYouMin Chen 	/* F0_1 */
6618b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_ctl[159], 0xFF << 16,
6628b36ec9fSYouMin Chen 			(soc_odt | (CS1_MR22_VAL << 3)) << 16);
6638b36ec9fSYouMin Chen 	/* F2_1, F1_1 */
6648b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_ctl[160], 0xFF00FF,
6658b36ec9fSYouMin Chen 			((soc_odt | (CS1_MR22_VAL << 3)) << 16) |
6668b36ec9fSYouMin Chen 			(soc_odt | (CS1_MR22_VAL << 3)));
667d0b1becdSKever Yang 
668d0b1becdSKever Yang 	/*
669d0b1becdSKever Yang 	 * phy_dq_tsel_select_X 24bits DENALI_PHY_6/134/262/390 offset_0
670d0b1becdSKever Yang 	 * sets termination values for read/idle cycles and drive strength
671d0b1becdSKever Yang 	 * for write cycles for DQ/DM
672d0b1becdSKever Yang 	 */
673d0b1becdSKever Yang 	reg_value = tsel_rd_select_n | (tsel_rd_select_p << 0x4) |
6748b36ec9fSYouMin Chen 		(tsel_wr_select_dq_n << 8) | (tsel_wr_select_dq_p << 12) |
675d0b1becdSKever Yang 		(tsel_idle_select_n << 16) | (tsel_idle_select_p << 20);
676d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[6], 0xffffff, reg_value);
677d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[134], 0xffffff, reg_value);
678d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[262], 0xffffff, reg_value);
679d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[390], 0xffffff, reg_value);
680d0b1becdSKever Yang 
681d0b1becdSKever Yang 	/*
682d0b1becdSKever Yang 	 * phy_dqs_tsel_select_X 24bits DENALI_PHY_7/135/263/391 offset_0
683d0b1becdSKever Yang 	 * sets termination values for read/idle cycles and drive strength
684d0b1becdSKever Yang 	 * for write cycles for DQS
685d0b1becdSKever Yang 	 */
686d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[7], 0xffffff, reg_value);
687d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[135], 0xffffff, reg_value);
688d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[263], 0xffffff, reg_value);
689d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[391], 0xffffff, reg_value);
690d0b1becdSKever Yang 
691d0b1becdSKever Yang 	/* phy_adr_tsel_select_ 8bits DENALI_PHY_544/672/800 offset_0 */
6928b36ec9fSYouMin Chen 	reg_value = tsel_wr_select_ca_n | (tsel_wr_select_ca_p << 0x4);
6938b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4) {
6948b36ec9fSYouMin Chen 		/* LPDDR4 these register read always return 0, so
6958b36ec9fSYouMin Chen 		 * can not use clrsetbits_le32(), need to write32
6968b36ec9fSYouMin Chen 		 */
6978b36ec9fSYouMin Chen 		writel((0x300 << 8) | reg_value, &denali_phy[544]);
6988b36ec9fSYouMin Chen 		writel((0x300 << 8) | reg_value, &denali_phy[672]);
6998b36ec9fSYouMin Chen 		writel((0x300 << 8) | reg_value, &denali_phy[800]);
7008b36ec9fSYouMin Chen 	} else {
701d0b1becdSKever Yang 		clrsetbits_le32(&denali_phy[544], 0xff, reg_value);
702d0b1becdSKever Yang 		clrsetbits_le32(&denali_phy[672], 0xff, reg_value);
703d0b1becdSKever Yang 		clrsetbits_le32(&denali_phy[800], 0xff, reg_value);
7048b36ec9fSYouMin Chen 	}
705d0b1becdSKever Yang 
706d0b1becdSKever Yang 	/* phy_pad_addr_drive 8bits DENALI_PHY_928 offset_0 */
707d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[928], 0xff, reg_value);
708d0b1becdSKever Yang 
709d0b1becdSKever Yang 	/* phy_pad_rst_drive 8bits DENALI_PHY_937 offset_0 */
7108b36ec9fSYouMin Chen 	if (!b_reg)
711d0b1becdSKever Yang 		clrsetbits_le32(&denali_phy[937], 0xff, reg_value);
712d0b1becdSKever Yang 
713d0b1becdSKever Yang 	/* phy_pad_cke_drive 8bits DENALI_PHY_935 offset_0 */
714d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[935], 0xff, reg_value);
715d0b1becdSKever Yang 
716d0b1becdSKever Yang 	/* phy_pad_cs_drive 8bits DENALI_PHY_939 offset_0 */
7178b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[939], 0xff,
7188b36ec9fSYouMin Chen 			tsel_ckcs_select_n | (tsel_ckcs_select_p << 0x4));
719d0b1becdSKever Yang 
720d0b1becdSKever Yang 	/* phy_pad_clk_drive 8bits DENALI_PHY_929 offset_0 */
7218b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[929], 0xff,
7228b36ec9fSYouMin Chen 			tsel_ckcs_select_n | (tsel_ckcs_select_p << 0x4));
723d0b1becdSKever Yang 
724d0b1becdSKever Yang 	/* phy_pad_fdbk_drive 23bit DENALI_PHY_924/925 */
725d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[924], 0xff,
7268b36ec9fSYouMin Chen 			tsel_wr_select_ca_n | (tsel_wr_select_ca_p << 4));
727d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[925], 0xff,
7288b36ec9fSYouMin Chen 			tsel_wr_select_dq_n | (tsel_wr_select_dq_p << 4));
729d0b1becdSKever Yang 
730d0b1becdSKever Yang 	/* phy_dq_tsel_enable_X 3bits DENALI_PHY_5/133/261/389 offset_16 */
731d0b1becdSKever Yang 	reg_value = (tsel_rd_en | (tsel_wr_en << 1) | (tsel_idle_en << 2))
732d0b1becdSKever Yang 		<< 16;
733d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[5], 0x7 << 16, reg_value);
734d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[133], 0x7 << 16, reg_value);
735d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[261], 0x7 << 16, reg_value);
736d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[389], 0x7 << 16, reg_value);
737d0b1becdSKever Yang 
738d0b1becdSKever Yang 	/* phy_dqs_tsel_enable_X 3bits DENALI_PHY_6/134/262/390 offset_24 */
739d0b1becdSKever Yang 	reg_value = (tsel_rd_en | (tsel_wr_en << 1) | (tsel_idle_en << 2))
740d0b1becdSKever Yang 		<< 24;
741d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[6], 0x7 << 24, reg_value);
742d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[134], 0x7 << 24, reg_value);
743d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[262], 0x7 << 24, reg_value);
744d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[390], 0x7 << 24, reg_value);
745d0b1becdSKever Yang 
746d0b1becdSKever Yang 	/* phy_adr_tsel_enable_ 1bit DENALI_PHY_518/646/774 offset_8 */
747d0b1becdSKever Yang 	reg_value = tsel_wr_en << 8;
748d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[518], 0x1 << 8, reg_value);
749d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[646], 0x1 << 8, reg_value);
750d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[774], 0x1 << 8, reg_value);
751d0b1becdSKever Yang 
752d0b1becdSKever Yang 	/* phy_pad_addr_term tsel 1bit DENALI_PHY_933 offset_17 */
753d0b1becdSKever Yang 	reg_value = tsel_wr_en << 17;
754d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[933], 0x1 << 17, reg_value);
755d0b1becdSKever Yang 	/*
756d0b1becdSKever Yang 	 * pad_rst/cke/cs/clk_term tsel 1bits
757d0b1becdSKever Yang 	 * DENALI_PHY_938/936/940/934 offset_17
758d0b1becdSKever Yang 	 */
759d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[938], 0x1 << 17, reg_value);
760d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[936], 0x1 << 17, reg_value);
761d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[940], 0x1 << 17, reg_value);
762d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[934], 0x1 << 17, reg_value);
763d0b1becdSKever Yang 
764d0b1becdSKever Yang 	/* phy_pad_fdbk_term 1bit DENALI_PHY_930 offset_17 */
765d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[930], 0x1 << 17, reg_value);
766d0b1becdSKever Yang 
767d0b1becdSKever Yang 	if (sdram_params->base.dramtype == LPDDR4)
7688b36ec9fSYouMin Chen 		phy_io_config(chan, sdram_params, io->rd_vref, b_reg, channel);
769d0b1becdSKever Yang 	else
7708b36ec9fSYouMin Chen 		phy_io_config(chan, sdram_params, 0, b_reg, channel);
7718b36ec9fSYouMin Chen }
772d0b1becdSKever Yang 
pctl_start(struct dram_info * dram,struct rk3399_sdram_params * sdram_params,u32 channel_mask)7738b36ec9fSYouMin Chen static void pctl_start(struct dram_info *dram,
7748b36ec9fSYouMin Chen 		       struct rk3399_sdram_params *sdram_params,
7758b36ec9fSYouMin Chen 		       u32 channel_mask)
7768b36ec9fSYouMin Chen {
7778b36ec9fSYouMin Chen 	const struct chan_info *chan_0 = &dram->chan[0];
7788b36ec9fSYouMin Chen 	const struct chan_info *chan_1 = &dram->chan[1];
779d0b1becdSKever Yang 
7808b36ec9fSYouMin Chen 	u32 *denali_ctl_0 = chan_0->pctl->denali_ctl;
7818b36ec9fSYouMin Chen 	u32 *denali_phy_0 = chan_0->publ->denali_phy;
7828b36ec9fSYouMin Chen 	u32 *denali_ctl_1 = chan_1->pctl->denali_ctl;
7838b36ec9fSYouMin Chen 	u32 *denali_phy_1 = chan_1->publ->denali_phy;
7848b36ec9fSYouMin Chen 	u32 count, byte, tmp;
7858b36ec9fSYouMin Chen 
7868b36ec9fSYouMin Chen 	/* PHY_DLL_RST_EN */
7878b36ec9fSYouMin Chen 	if (channel_mask & 1) {
7888b36ec9fSYouMin Chen 		writel(0x01000000, &dram->grf->ddrc0_con0);
7898b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy_0[957], 0x3 << 24, 0x2 << 24);
7908b36ec9fSYouMin Chen 	}
7918b36ec9fSYouMin Chen 
7928b36ec9fSYouMin Chen 	if (channel_mask & 1) {
7938b36ec9fSYouMin Chen 		count = 0;
7948b36ec9fSYouMin Chen 		while (!(readl(&denali_ctl_0[203]) & (1 << 3))) {
7958b36ec9fSYouMin Chen 			if (count > 1000) {
7968b36ec9fSYouMin Chen 				printf("channel 0 init err!\n");
7978b36ec9fSYouMin Chen 				while (1)
7988b36ec9fSYouMin Chen 					;
7998b36ec9fSYouMin Chen 			}
8008b36ec9fSYouMin Chen 			udelay(1);
8018b36ec9fSYouMin Chen 			count++;
8028b36ec9fSYouMin Chen 		}
8038b36ec9fSYouMin Chen 
8048b36ec9fSYouMin Chen 		writel(0x01000100, &dram->grf->ddrc0_con0);
8058b36ec9fSYouMin Chen 		for (byte = 0; byte < 4; byte++)	{
8068b36ec9fSYouMin Chen 			tmp = 0x820;
8078b36ec9fSYouMin Chen 			writel((tmp << 16) | tmp,
8088b36ec9fSYouMin Chen 			       &denali_phy_0[53 + (128 * byte)]);
8098b36ec9fSYouMin Chen 			writel((tmp << 16) | tmp,
8108b36ec9fSYouMin Chen 			       &denali_phy_0[54 + (128 * byte)]);
8118b36ec9fSYouMin Chen 			writel((tmp << 16) | tmp,
8128b36ec9fSYouMin Chen 			       &denali_phy_0[55 + (128 * byte)]);
8138b36ec9fSYouMin Chen 			writel((tmp << 16) | tmp,
8148b36ec9fSYouMin Chen 			       &denali_phy_0[56 + (128 * byte)]);
8158b36ec9fSYouMin Chen 			writel((tmp << 16) | tmp,
8168b36ec9fSYouMin Chen 			       &denali_phy_0[57 + (128 * byte)]);
8178b36ec9fSYouMin Chen 			clrsetbits_le32(&denali_phy_0[58 + (128 * byte)],
8188b36ec9fSYouMin Chen 					0xffff, tmp);
8198b36ec9fSYouMin Chen 		}
8208b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl_0[68], PWRUP_SREFRESH_EXIT,
8218b36ec9fSYouMin Chen 				g_pwrup_srefresh_exit[0]);
8228b36ec9fSYouMin Chen 	}
8238b36ec9fSYouMin Chen 
8248b36ec9fSYouMin Chen 	if (channel_mask & 2) {
8258b36ec9fSYouMin Chen 		writel(0x01000000, &dram->grf->ddrc1_con0);
8268b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy_1[957], 0x3 << 24, 0x2 << 24);
8278b36ec9fSYouMin Chen 	}
8288b36ec9fSYouMin Chen 	if (channel_mask & 2) {
8298b36ec9fSYouMin Chen 		count = 0;
8308b36ec9fSYouMin Chen 		while (!(readl(&denali_ctl_1[203]) & (1 << 3))) {
8318b36ec9fSYouMin Chen 			if (count > 1000) {
8328b36ec9fSYouMin Chen 				printf("channel 1 init err!\n");
8338b36ec9fSYouMin Chen 				while (1)
8348b36ec9fSYouMin Chen 					;
8358b36ec9fSYouMin Chen 			}
8368b36ec9fSYouMin Chen 			udelay(1);
8378b36ec9fSYouMin Chen 			count++;
8388b36ec9fSYouMin Chen 		}
8398b36ec9fSYouMin Chen 
8408b36ec9fSYouMin Chen 		writel(0x01000100, &dram->grf->ddrc1_con0);
8418b36ec9fSYouMin Chen 		for (byte = 0; byte < 4; byte++)	{
8428b36ec9fSYouMin Chen 			tmp = 0x820;
8438b36ec9fSYouMin Chen 			writel((tmp << 16) | tmp,
8448b36ec9fSYouMin Chen 			       &denali_phy_1[53 + (128 * byte)]);
8458b36ec9fSYouMin Chen 			writel((tmp << 16) | tmp,
8468b36ec9fSYouMin Chen 			       &denali_phy_1[54 + (128 * byte)]);
8478b36ec9fSYouMin Chen 			writel((tmp << 16) | tmp,
8488b36ec9fSYouMin Chen 			       &denali_phy_1[55 + (128 * byte)]);
8498b36ec9fSYouMin Chen 			writel((tmp << 16) | tmp,
8508b36ec9fSYouMin Chen 			       &denali_phy_1[56 + (128 * byte)]);
8518b36ec9fSYouMin Chen 			writel((tmp << 16) | tmp,
8528b36ec9fSYouMin Chen 			       &denali_phy_1[57 + (128 * byte)]);
8538b36ec9fSYouMin Chen 			clrsetbits_le32(&denali_phy_1[58 + (128 * byte)],
8548b36ec9fSYouMin Chen 					0xffff, tmp);
8558b36ec9fSYouMin Chen 		}
8568b36ec9fSYouMin Chen 
8578b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl_1[68], PWRUP_SREFRESH_EXIT,
8588b36ec9fSYouMin Chen 				g_pwrup_srefresh_exit[1]);
8598b36ec9fSYouMin Chen 
8608b36ec9fSYouMin Chen 		/*
8618b36ec9fSYouMin Chen 		 * restore channel 1 RESET original setting
8628b36ec9fSYouMin Chen 		 * to avoid 240ohm too weak to prevent ESD test
8638b36ec9fSYouMin Chen 		 */
8648b36ec9fSYouMin Chen 		if (sdram_params->base.dramtype == LPDDR4)
8658b36ec9fSYouMin Chen 			clrsetbits_le32(&denali_phy_1[937], 0xff,
8668b36ec9fSYouMin Chen 					sdram_params->phy_regs.denali_phy[937] &
8678b36ec9fSYouMin Chen 					0xFF);
8688b36ec9fSYouMin Chen 	}
8698b36ec9fSYouMin Chen }
8708b36ec9fSYouMin Chen 
8718b36ec9fSYouMin Chen /* phy_fn = 0, PHY boot freq
8728b36ec9fSYouMin Chen  * phy_fn = 1, PHY index 0
8738b36ec9fSYouMin Chen  * phy_fn = 2, PHY index 1
8748b36ec9fSYouMin Chen  */
8758b36ec9fSYouMin Chen static struct rk3399_sdram_params
get_phy_index_params(u32 phy_fn,struct rk3399_sdram_params * sdram_params)8768b36ec9fSYouMin Chen 	*get_phy_index_params(u32 phy_fn,
8778b36ec9fSYouMin Chen 			      struct rk3399_sdram_params *sdram_params)
8788b36ec9fSYouMin Chen {
8798b36ec9fSYouMin Chen 	if (phy_fn == 0)
8808b36ec9fSYouMin Chen 		return sdram_params;
8818b36ec9fSYouMin Chen 	else if (phy_fn == 1)
8828b36ec9fSYouMin Chen 		return &dfs_configs[1];
8838b36ec9fSYouMin Chen 	else if (phy_fn == 2)
8848b36ec9fSYouMin Chen 		return &dfs_configs[0];
885d0b1becdSKever Yang 	else
8868b36ec9fSYouMin Chen 		return NULL;
8878b36ec9fSYouMin Chen }
888d0b1becdSKever Yang 
8898b36ec9fSYouMin Chen /*
8908b36ec9fSYouMin Chen  * b_reg: indicate whether set phy register
8918b36ec9fSYouMin Chen  * or just set sdram_params.
8928b36ec9fSYouMin Chen  * if b_reg = 0, channel, mr5 are not care
8938b36ec9fSYouMin Chen  */
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)8948b36ec9fSYouMin Chen static void set_lp4_dq_odt(const struct chan_info *chan,
8958b36ec9fSYouMin Chen 			   struct rk3399_sdram_params *sdram_params, u32 ctl_fn,
8968b36ec9fSYouMin Chen 			   u32 en, u32 b_reg, u32 channel, u32 mr5)
8978b36ec9fSYouMin Chen {
8988b36ec9fSYouMin Chen 	u32 *denali_ctl;
8998b36ec9fSYouMin Chen 	u32 *denali_pi;
9008b36ec9fSYouMin Chen 	u32 reg_value;
9018b36ec9fSYouMin Chen 	struct io_setting *io;
902d0b1becdSKever Yang 
9038b36ec9fSYouMin Chen 	if (b_reg) {
9048b36ec9fSYouMin Chen 		denali_pi = chan->pi->denali_pi;
9058b36ec9fSYouMin Chen 		denali_ctl = chan->pctl->denali_ctl;
9068b36ec9fSYouMin Chen 	} else {
9078b36ec9fSYouMin Chen 		denali_pi = sdram_params->pi_regs.denali_pi;
9088b36ec9fSYouMin Chen 		denali_ctl = sdram_params->pctl_regs.denali_ctl;
9098b36ec9fSYouMin Chen 	}
9108b36ec9fSYouMin Chen 	io = get_io_set(sdram_params, mr5);
9118b36ec9fSYouMin Chen 	if (en)
9128b36ec9fSYouMin Chen 		reg_value = io->dq_odt;
9138b36ec9fSYouMin Chen 	else
9148b36ec9fSYouMin Chen 		reg_value = 0;
9158b36ec9fSYouMin Chen 
9168b36ec9fSYouMin Chen 	switch (ctl_fn) {
9178b36ec9fSYouMin Chen 	case 0:
9188b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[139], 0x7 << 24, reg_value << 24);
9198b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[153], 0x7 << 24, reg_value << 24);
9208b36ec9fSYouMin Chen 
9218b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[132], 0x7 << 0, (reg_value << 0));
9228b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[139], 0x7 << 16, (reg_value << 16));
9238b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[147], 0x7 << 0, (reg_value << 0));
9248b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[154], 0x7 << 16, (reg_value << 16));
9258b36ec9fSYouMin Chen 		break;
9268b36ec9fSYouMin Chen 	case 1:
9278b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[140], 0x7 << 0, reg_value << 0);
9288b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[154], 0x7 << 0, reg_value << 0);
9298b36ec9fSYouMin Chen 
9308b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[129], 0x7 << 16, (reg_value << 16));
9318b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[137], 0x7 << 0, (reg_value << 0));
9328b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[144], 0x7 << 16, (reg_value << 16));
9338b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[152], 0x7 << 0, (reg_value << 0));
9348b36ec9fSYouMin Chen 		break;
9358b36ec9fSYouMin Chen 	case 2:
9368b36ec9fSYouMin Chen 	default:
9378b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[140], 0x7 << 8, (reg_value << 8));
9388b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[154], 0x7 << 8, (reg_value << 8));
9398b36ec9fSYouMin Chen 
9408b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[127], 0x7 << 0, (reg_value << 0));
9418b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[134], 0x7 << 16, (reg_value << 16));
9428b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[142], 0x7 << 0, (reg_value << 0));
9438b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[149], 0x7 << 16, (reg_value << 16));
9448b36ec9fSYouMin Chen 		break;
9458b36ec9fSYouMin Chen 	}
9468b36ec9fSYouMin Chen }
9478b36ec9fSYouMin Chen 
9488b36ec9fSYouMin Chen /*
9498b36ec9fSYouMin Chen  * b_reg: indicate whether set phy register
9508b36ec9fSYouMin Chen  * or just set sdram_params.
9518b36ec9fSYouMin Chen  * if b_reg = 0, channel, mr5 are not care
9528b36ec9fSYouMin Chen  */
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)9538b36ec9fSYouMin Chen static void set_lp4_ca_odt(const struct chan_info *chan,
9548b36ec9fSYouMin Chen 			   struct rk3399_sdram_params *sdram_params, u32 ctl_fn,
9558b36ec9fSYouMin Chen 			   u32 en, u32 b_reg, u32 channel, u32 mr5)
9568b36ec9fSYouMin Chen {
9578b36ec9fSYouMin Chen 	u32 *denali_ctl;
9588b36ec9fSYouMin Chen 	u32 *denali_pi;
9598b36ec9fSYouMin Chen 	u32 reg_value;
9608b36ec9fSYouMin Chen 	struct io_setting *io;
9618b36ec9fSYouMin Chen 
9628b36ec9fSYouMin Chen 	if (b_reg) {
9638b36ec9fSYouMin Chen 		denali_pi = chan->pi->denali_pi;
9648b36ec9fSYouMin Chen 		denali_ctl = chan->pctl->denali_ctl;
9658b36ec9fSYouMin Chen 	} else {
9668b36ec9fSYouMin Chen 		denali_pi = sdram_params->pi_regs.denali_pi;
9678b36ec9fSYouMin Chen 		denali_ctl = sdram_params->pctl_regs.denali_ctl;
9688b36ec9fSYouMin Chen 	}
9698b36ec9fSYouMin Chen 	io = get_io_set(sdram_params, mr5);
9708b36ec9fSYouMin Chen 	if (en)
9718b36ec9fSYouMin Chen 		reg_value = io->ca_odt;
9728b36ec9fSYouMin Chen 	else
9738b36ec9fSYouMin Chen 		reg_value = 0;
9748b36ec9fSYouMin Chen 
9758b36ec9fSYouMin Chen 	switch (ctl_fn) {
9768b36ec9fSYouMin Chen 	case 0:
9778b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[139], 0x7 << 28, reg_value << 28);
9788b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[153], 0x7 << 28, reg_value << 28);
9798b36ec9fSYouMin Chen 
9808b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[132], 0x7 << 4, reg_value << 4);
9818b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[139], 0x7 << 20, reg_value << 20);
9828b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[147], 0x7 << 4, reg_value << 4);
9838b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[154], 0x7 << 20, reg_value << 20);
9848b36ec9fSYouMin Chen 		break;
9858b36ec9fSYouMin Chen 	case 1:
9868b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[140], 0x7 << 4, reg_value << 4);
9878b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[154], 0x7 << 4, reg_value << 4);
9888b36ec9fSYouMin Chen 
9898b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[129], 0x7 << 20, reg_value << 20);
9908b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[137], 0x7 << 4, reg_value << 4);
9918b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[144], 0x7 << 20, reg_value << 20);
9928b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[152], 0x7 << 4, reg_value << 4);
9938b36ec9fSYouMin Chen 		break;
9948b36ec9fSYouMin Chen 	case 2:
9958b36ec9fSYouMin Chen 	default:
9968b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[140], 0x7 << 12, (reg_value << 12));
9978b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[154], 0x7 << 12, (reg_value << 12));
9988b36ec9fSYouMin Chen 
9998b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[127], 0x7 << 4, reg_value << 4);
10008b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[134], 0x7 << 20, reg_value << 20);
10018b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[142], 0x7 << 4, reg_value << 4);
10028b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[149], 0x7 << 20, reg_value << 20);
10038b36ec9fSYouMin Chen 		break;
10048b36ec9fSYouMin Chen 	}
10058b36ec9fSYouMin Chen }
10068b36ec9fSYouMin Chen 
10078b36ec9fSYouMin Chen /*
10088b36ec9fSYouMin Chen  * b_reg: indicate whether set phy register
10098b36ec9fSYouMin Chen  * or just set sdram_params.
10108b36ec9fSYouMin Chen  * if b_reg = 0, channel, mr5 are not care
10118b36ec9fSYouMin Chen  */
set_lp4_MR3(const struct chan_info * chan,struct rk3399_sdram_params * sdram_params,u32 ctl_fn,u32 b_reg,u32 channel,u32 mr5)10128b36ec9fSYouMin Chen static void set_lp4_MR3(const struct chan_info *chan,
10138b36ec9fSYouMin Chen 			struct rk3399_sdram_params *sdram_params, u32 ctl_fn,
10148b36ec9fSYouMin Chen 			u32 b_reg, u32 channel, u32 mr5)
10158b36ec9fSYouMin Chen {
10168b36ec9fSYouMin Chen 	u32 *denali_ctl;
10178b36ec9fSYouMin Chen 	u32 *denali_pi;
10188b36ec9fSYouMin Chen 	u32 reg_value;
10198b36ec9fSYouMin Chen 	struct io_setting *io;
10208b36ec9fSYouMin Chen 
10218b36ec9fSYouMin Chen 	if (b_reg) {
10228b36ec9fSYouMin Chen 		denali_pi = chan->pi->denali_pi;
10238b36ec9fSYouMin Chen 		denali_ctl = chan->pctl->denali_ctl;
10248b36ec9fSYouMin Chen 	} else {
10258b36ec9fSYouMin Chen 		denali_pi = sdram_params->pi_regs.denali_pi;
10268b36ec9fSYouMin Chen 		denali_ctl = sdram_params->pctl_regs.denali_ctl;
10278b36ec9fSYouMin Chen 	}
10288b36ec9fSYouMin Chen 	io = get_io_set(sdram_params, mr5);
10298b36ec9fSYouMin Chen 
10308b36ec9fSYouMin Chen 	reg_value = ((io->pdds << 3) | 1);
10318b36ec9fSYouMin Chen 	switch (ctl_fn) {
10328b36ec9fSYouMin Chen 	case 0:
10338b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[138], 0xFFFF, reg_value);
10348b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[152], 0xFFFF, reg_value);
10358b36ec9fSYouMin Chen 
10368b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[131], 0xFFFF << 16, reg_value << 16);
10378b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[139], 0xFFFF, reg_value);
10388b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[146], 0xFFFF << 16, reg_value << 16);
10398b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[154], 0xFFFF, reg_value);
10408b36ec9fSYouMin Chen 		break;
10418b36ec9fSYouMin Chen 	case 1:
10428b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[138], 0xFFFF << 16,
10438b36ec9fSYouMin Chen 				reg_value << 16);
10448b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[152], 0xFFFF << 16,
10458b36ec9fSYouMin Chen 				reg_value << 16);
10468b36ec9fSYouMin Chen 
10478b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[129], 0xFFFF, reg_value);
10488b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[136], 0xFFFF << 16, reg_value << 16);
10498b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[144], 0xFFFF, reg_value);
10508b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[151], 0xFFFF << 16, reg_value << 16);
10518b36ec9fSYouMin Chen 		break;
10528b36ec9fSYouMin Chen 	case 2:
10538b36ec9fSYouMin Chen 	default:
10548b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[139], 0xFFFF, reg_value);
10558b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[153], 0xFFFF, reg_value);
10568b36ec9fSYouMin Chen 
10578b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[126], 0xFFFF << 16, reg_value << 16);
10588b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[134], 0xFFFF, reg_value);
10598b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[141], 0xFFFF << 16, reg_value << 16);
10608b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[149], 0xFFFF, reg_value);
10618b36ec9fSYouMin Chen 		break;
10628b36ec9fSYouMin Chen 	}
10638b36ec9fSYouMin Chen }
10648b36ec9fSYouMin Chen 
10658b36ec9fSYouMin Chen /*
10668b36ec9fSYouMin Chen  * b_reg: indicate whether set phy register
10678b36ec9fSYouMin Chen  * or just set sdram_params.
10688b36ec9fSYouMin Chen  * if b_reg = 0, channel, mr5 are not care
10698b36ec9fSYouMin Chen  */
set_lp4_MR12(const struct chan_info * chan,struct rk3399_sdram_params * sdram_params,u32 ctl_fn,u32 b_reg,u32 channel,u32 mr5)10708b36ec9fSYouMin Chen static void set_lp4_MR12(const struct chan_info *chan,
10718b36ec9fSYouMin Chen 			 struct rk3399_sdram_params *sdram_params, u32 ctl_fn,
10728b36ec9fSYouMin Chen 			 u32 b_reg, u32 channel, u32 mr5)
10738b36ec9fSYouMin Chen {
10748b36ec9fSYouMin Chen 	u32 *denali_ctl;
10758b36ec9fSYouMin Chen 	u32 *denali_pi;
10768b36ec9fSYouMin Chen 	u32 reg_value;
10778b36ec9fSYouMin Chen 	struct io_setting *io;
10788b36ec9fSYouMin Chen 
10798b36ec9fSYouMin Chen 	if (b_reg) {
10808b36ec9fSYouMin Chen 		denali_pi = chan->pi->denali_pi;
10818b36ec9fSYouMin Chen 		denali_ctl = chan->pctl->denali_ctl;
10828b36ec9fSYouMin Chen 	} else {
10838b36ec9fSYouMin Chen 		denali_pi = sdram_params->pi_regs.denali_pi;
10848b36ec9fSYouMin Chen 		denali_ctl = sdram_params->pctl_regs.denali_ctl;
10858b36ec9fSYouMin Chen 	}
10868b36ec9fSYouMin Chen 	io = get_io_set(sdram_params, mr5);
10878b36ec9fSYouMin Chen 
10888b36ec9fSYouMin Chen 	reg_value = io->ca_vref;
10898b36ec9fSYouMin Chen 	switch (ctl_fn) {
10908b36ec9fSYouMin Chen 	case 0:
10918b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[140], 0xFFFF << 16,
10928b36ec9fSYouMin Chen 				reg_value << 16);
10938b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[154], 0xFFFF << 16,
10948b36ec9fSYouMin Chen 				reg_value << 16);
10958b36ec9fSYouMin Chen 
10968b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[132], 0xFF << 8, reg_value << 8);
10978b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[139], 0xFF << 24, reg_value << 24);
10988b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[147], 0xFF << 8, reg_value << 8);
10998b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[154], 0xFF << 24, reg_value << 24);
11008b36ec9fSYouMin Chen 		break;
11018b36ec9fSYouMin Chen 	case 1:
11028b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[141], 0xFFFF, reg_value);
11038b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[155], 0xFFFF, reg_value);
11048b36ec9fSYouMin Chen 
11058b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[129], 0xFF << 24, reg_value << 24);
11068b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[137], 0xFF << 8, reg_value << 8);
11078b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[144], 0xFF << 24, reg_value << 24);
11088b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[152], 0xFF << 8, reg_value << 8);
11098b36ec9fSYouMin Chen 		break;
11108b36ec9fSYouMin Chen 	case 2:
11118b36ec9fSYouMin Chen 	default:
11128b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[141], 0xFFFF << 16,
11138b36ec9fSYouMin Chen 				reg_value << 16);
11148b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[155], 0xFFFF << 16,
11158b36ec9fSYouMin Chen 				reg_value << 16);
11168b36ec9fSYouMin Chen 
11178b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[127], 0xFF << 8, reg_value << 8);
11188b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[134], 0xFF << 24, reg_value << 24);
11198b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[142], 0xFF << 8, reg_value << 8);
11208b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[149], 0xFF << 24, reg_value << 24);
11218b36ec9fSYouMin Chen 		break;
11228b36ec9fSYouMin Chen 	}
11238b36ec9fSYouMin Chen }
11248b36ec9fSYouMin Chen 
11258b36ec9fSYouMin Chen /*
11268b36ec9fSYouMin Chen  * b_reg: indicate whether set phy register
11278b36ec9fSYouMin Chen  * or just set sdram_params.
11288b36ec9fSYouMin Chen  * if b_reg = 0, channel, mr5 are not care
11298b36ec9fSYouMin Chen  */
set_lp4_MR14(const struct chan_info * chan,struct rk3399_sdram_params * sdram_params,u32 ctl_fn,u32 b_reg,u32 channel,u32 mr5)11308b36ec9fSYouMin Chen static void set_lp4_MR14(const struct chan_info *chan,
11318b36ec9fSYouMin Chen 			 struct rk3399_sdram_params *sdram_params, u32 ctl_fn,
11328b36ec9fSYouMin Chen 			 u32 b_reg, u32 channel, u32 mr5)
11338b36ec9fSYouMin Chen {
11348b36ec9fSYouMin Chen 	u32 *denali_ctl;
11358b36ec9fSYouMin Chen 	u32 *denali_pi;
11368b36ec9fSYouMin Chen 	u32 reg_value;
11378b36ec9fSYouMin Chen 	struct io_setting *io;
11388b36ec9fSYouMin Chen 
11398b36ec9fSYouMin Chen 	if (b_reg) {
11408b36ec9fSYouMin Chen 		denali_pi = chan->pi->denali_pi;
11418b36ec9fSYouMin Chen 		denali_ctl = chan->pctl->denali_ctl;
11428b36ec9fSYouMin Chen 	} else {
11438b36ec9fSYouMin Chen 		denali_pi = sdram_params->pi_regs.denali_pi;
11448b36ec9fSYouMin Chen 		denali_ctl = sdram_params->pctl_regs.denali_ctl;
11458b36ec9fSYouMin Chen 	}
11468b36ec9fSYouMin Chen 	io = get_io_set(sdram_params, mr5);
11478b36ec9fSYouMin Chen 
11488b36ec9fSYouMin Chen 	reg_value = io->dq_vref;
11498b36ec9fSYouMin Chen 	switch (ctl_fn) {
11508b36ec9fSYouMin Chen 	case 0:
11518b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[142], 0xFFFF << 16,
11528b36ec9fSYouMin Chen 				reg_value << 16);
11538b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[156], 0xFFFF << 16,
11548b36ec9fSYouMin Chen 				reg_value << 16);
11558b36ec9fSYouMin Chen 
11568b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[132], 0xFF << 16, reg_value << 16);
11578b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[140], 0xFF << 0, reg_value << 0);
11588b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[147], 0xFF << 16, reg_value << 16);
11598b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[155], 0xFF << 0, reg_value << 0);
11608b36ec9fSYouMin Chen 		break;
11618b36ec9fSYouMin Chen 	case 1:
11628b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[143], 0xFFFF, reg_value);
11638b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[157], 0xFFFF, reg_value);
11648b36ec9fSYouMin Chen 
11658b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[130], 0xFF << 0, reg_value << 0);
11668b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[137], 0xFF << 16, reg_value << 16);
11678b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[145], 0xFF << 0, reg_value << 0);
11688b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[152], 0xFF << 16, reg_value << 16);
11698b36ec9fSYouMin Chen 		break;
11708b36ec9fSYouMin Chen 	case 2:
11718b36ec9fSYouMin Chen 	default:
11728b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[143], 0xFFFF << 16,
11738b36ec9fSYouMin Chen 				reg_value << 16);
11748b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl[157], 0xFFFF << 16,
11758b36ec9fSYouMin Chen 				reg_value << 16);
11768b36ec9fSYouMin Chen 
11778b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[127], 0xFF << 16, reg_value << 16);
11788b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[135], 0xFF << 0, reg_value << 0);
11798b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[142], 0xFF << 16, reg_value << 16);
11808b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi[150], 0xFF << 0, reg_value << 0);
11818b36ec9fSYouMin Chen 		break;
11828b36ec9fSYouMin Chen 	}
11838b36ec9fSYouMin Chen }
11848b36ec9fSYouMin Chen 
modify_param(const struct chan_info * chan,struct rk3399_sdram_params * sdram_params)11858b36ec9fSYouMin Chen static void modify_param(const struct chan_info *chan,
11868b36ec9fSYouMin Chen 			 struct rk3399_sdram_params *sdram_params)
11878b36ec9fSYouMin Chen {
11888b36ec9fSYouMin Chen 	struct rk3399_sdram_params *params;
11898b36ec9fSYouMin Chen 	u32 *denali_ctl_params;
11908b36ec9fSYouMin Chen 	u32 *denali_pi_params;
11918b36ec9fSYouMin Chen 	u32 *denali_phy_params;
11928b36ec9fSYouMin Chen 
11938b36ec9fSYouMin Chen 	denali_ctl_params = sdram_params->pctl_regs.denali_ctl;
11948b36ec9fSYouMin Chen 	denali_pi_params = sdram_params->pi_regs.denali_pi;
11958b36ec9fSYouMin Chen 	denali_phy_params = sdram_params->phy_regs.denali_phy;
11968b36ec9fSYouMin Chen 
11978b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4) {
11988b36ec9fSYouMin Chen 		set_lp4_dq_odt(chan, sdram_params, 2, 1, 0, 0, 0);
11998b36ec9fSYouMin Chen 		set_lp4_ca_odt(chan, sdram_params, 2, 1, 0, 0, 0);
12008b36ec9fSYouMin Chen 		set_lp4_MR3(chan, sdram_params, 2, 0, 0, 0);
12018b36ec9fSYouMin Chen 		set_lp4_MR12(chan, sdram_params, 2, 0, 0, 0);
12028b36ec9fSYouMin Chen 		set_lp4_MR14(chan, sdram_params, 2, 0, 0, 0);
12038b36ec9fSYouMin Chen 		params = get_phy_index_params(0, sdram_params);
12048b36ec9fSYouMin Chen 		set_ds_odt(chan, params, 0, 0, 0);
12058b36ec9fSYouMin Chen 		/* read two cycle preamble */
12068b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_ctl_params[200], 0x3 << 24, 0x3 << 24);
12078b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy_params[7], 0x3 << 24, 0x3 << 24);
12088b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy_params[135], 0x3 << 24, 0x3 << 24);
12098b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy_params[263], 0x3 << 24, 0x3 << 24);
12108b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy_params[391], 0x3 << 24, 0x3 << 24);
12118b36ec9fSYouMin Chen 
12128b36ec9fSYouMin Chen 		/* boot frequency two cycle preamble */
12138b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy_params[2], 0x3 << 16, 0x3 << 16);
12148b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy_params[130], 0x3 << 16, 0x3 << 16);
12158b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy_params[258], 0x3 << 16, 0x3 << 16);
12168b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_phy_params[386], 0x3 << 16, 0x3 << 16);
12178b36ec9fSYouMin Chen 
12188b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi_params[45], 0x3 << 8, 0x3 << 8);
12198b36ec9fSYouMin Chen 		clrsetbits_le32(&denali_pi_params[58], 0x1, 0x1);
12208b36ec9fSYouMin Chen 
12218b36ec9fSYouMin Chen 		/*
12228b36ec9fSYouMin Chen 		 * bypass mode need PHY_SLICE_PWR_RDC_DISABLE_x = 1,
12238b36ec9fSYouMin Chen 		 * boot frequency mode use bypass mode
12248b36ec9fSYouMin Chen 		 */
12258b36ec9fSYouMin Chen 		setbits_le32(&denali_phy_params[10], 1 << 16);
12268b36ec9fSYouMin Chen 		setbits_le32(&denali_phy_params[138], 1 << 16);
12278b36ec9fSYouMin Chen 		setbits_le32(&denali_phy_params[266], 1 << 16);
12288b36ec9fSYouMin Chen 		setbits_le32(&denali_phy_params[394], 1 << 16);
12298b36ec9fSYouMin Chen 	} else {
12308b36ec9fSYouMin Chen 		/* modify PHY F0/F1/F2 params */
12318b36ec9fSYouMin Chen 		params = get_phy_index_params(0, sdram_params);
12328b36ec9fSYouMin Chen 		set_ds_odt(chan, params, 0, 0, 0);
12338b36ec9fSYouMin Chen 	}
12348b36ec9fSYouMin Chen 
12358b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_pi_params[45], 0x1 << 24, 0x1 << 24);
12368b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_pi_params[61], 0x1 << 24, 0x1 << 24);
12378b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_pi_params[76], 0x1 << 24, 0x1 << 24);
12388b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_pi_params[77], 0x1, 0x1);
1239d0b1becdSKever Yang }
1240d0b1becdSKever Yang 
pctl_cfg(const struct chan_info * chan,u32 channel,struct rk3399_sdram_params * sdram_params)1241d0b1becdSKever Yang static int pctl_cfg(const struct chan_info *chan, u32 channel,
12428b36ec9fSYouMin Chen 		    struct rk3399_sdram_params *sdram_params)
1243d0b1becdSKever Yang {
1244d0b1becdSKever Yang 	u32 *denali_ctl = chan->pctl->denali_ctl;
1245d0b1becdSKever Yang 	u32 *denali_pi = chan->pi->denali_pi;
1246d0b1becdSKever Yang 	u32 *denali_phy = chan->publ->denali_phy;
1247d0b1becdSKever Yang 	const u32 *params_ctl = sdram_params->pctl_regs.denali_ctl;
1248d0b1becdSKever Yang 	const u32 *params_phy = sdram_params->phy_regs.denali_phy;
1249d0b1becdSKever Yang 	u32 tmp, tmp1, tmp2;
12508b36ec9fSYouMin Chen 	struct rk3399_sdram_params *params;
12518b36ec9fSYouMin Chen 	u32 byte;
1252d0b1becdSKever Yang 
12538b36ec9fSYouMin Chen 	modify_param(chan, sdram_params);
1254d0b1becdSKever Yang 	/*
1255d0b1becdSKever Yang 	 * work around controller bug:
1256d0b1becdSKever Yang 	 * Do not program DRAM_CLASS until NO_PHY_IND_TRAIN_INT is programmed
1257d0b1becdSKever Yang 	 */
125831d8c61dSYouMin Chen 	sdram_copy_to_reg(&denali_ctl[1], &params_ctl[1],
1259d0b1becdSKever Yang 			  sizeof(struct rk3399_ddr_pctl_regs) - 4);
1260d0b1becdSKever Yang 	writel(params_ctl[0], &denali_ctl[0]);
12618b36ec9fSYouMin Chen 
12628b36ec9fSYouMin Chen 	/*
12638b36ec9fSYouMin Chen 	 * two channel init at the same time, then ZQ Cal Start
12648b36ec9fSYouMin Chen 	 * at the same time, it will use the same RZQ.
12658b36ec9fSYouMin Chen 	 * to fix it: increase tINIT3 for channel 1, will avoid two
12668b36ec9fSYouMin Chen 	 * channel ZQ Cal Start at the same time
12678b36ec9fSYouMin Chen 	 */
12688b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4 && channel == 1) {
12698b36ec9fSYouMin Chen 		tmp = ((1000000 * (sdram_params->base.ddr_freq / MHz) + 999) /
12708b36ec9fSYouMin Chen 		       1000);
12718b36ec9fSYouMin Chen 		tmp1 = readl(&denali_ctl[14]);
12728b36ec9fSYouMin Chen 		writel(tmp + tmp1, &denali_ctl[14]);
12738b36ec9fSYouMin Chen 	}
12748b36ec9fSYouMin Chen 
127531d8c61dSYouMin Chen 	sdram_copy_to_reg(denali_pi, &sdram_params->pi_regs.denali_pi[0],
1276d0b1becdSKever Yang 			  sizeof(struct rk3399_ddr_pi_regs));
1277d0b1becdSKever Yang 	/* rank count need to set for init */
1278d0b1becdSKever Yang 	set_memory_map(chan, channel, sdram_params);
1279d0b1becdSKever Yang 
1280d0b1becdSKever Yang 	writel(sdram_params->phy_regs.denali_phy[910], &denali_phy[910]);
1281d0b1becdSKever Yang 	writel(sdram_params->phy_regs.denali_phy[911], &denali_phy[911]);
1282d0b1becdSKever Yang 	writel(sdram_params->phy_regs.denali_phy[912], &denali_phy[912]);
1283d0b1becdSKever Yang 
12848b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4) {
12858b36ec9fSYouMin Chen 		writel(sdram_params->phy_regs.denali_phy[898],
12868b36ec9fSYouMin Chen 		       &denali_phy[898]);
12878b36ec9fSYouMin Chen 		writel(sdram_params->phy_regs.denali_phy[919],
12888b36ec9fSYouMin Chen 		       &denali_phy[919]);
12898b36ec9fSYouMin Chen 	}
12908b36ec9fSYouMin Chen 
12918b36ec9fSYouMin Chen 	g_pwrup_srefresh_exit[channel] = readl(&denali_ctl[68]) &
12928b36ec9fSYouMin Chen 					 PWRUP_SREFRESH_EXIT;
1293d0b1becdSKever Yang 	clrbits_le32(&denali_ctl[68], PWRUP_SREFRESH_EXIT);
1294d0b1becdSKever Yang 
1295d0b1becdSKever Yang 	/* PHY_DLL_RST_EN */
1296d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[957], 0x3 << 24, 1 << 24);
1297d0b1becdSKever Yang 
1298d0b1becdSKever Yang 	setbits_le32(&denali_pi[0], START);
1299d0b1becdSKever Yang 	setbits_le32(&denali_ctl[0], START);
1300d0b1becdSKever Yang 
13018b36ec9fSYouMin Chen 	/* because LPDDR4 use PLL bypass mode for init
13028b36ec9fSYouMin Chen 	 * not need to wait for the PLL to lock
13038b36ec9fSYouMin Chen 	 */
13048b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype != LPDDR4) {
13058b36ec9fSYouMin Chen 		/* wait lock */
1306d0b1becdSKever Yang 		while (1) {
1307d0b1becdSKever Yang 			tmp = readl(&denali_phy[920]);
1308d0b1becdSKever Yang 			tmp1 = readl(&denali_phy[921]);
1309d0b1becdSKever Yang 			tmp2 = readl(&denali_phy[922]);
1310d0b1becdSKever Yang 			if ((((tmp >> 16) & 0x1) == 0x1) &&
1311d0b1becdSKever Yang 			    (((tmp1 >> 16) & 0x1) == 0x1) &&
1312d0b1becdSKever Yang 			    (((tmp1 >> 0) & 0x1) == 0x1) &&
1313d0b1becdSKever Yang 			    (((tmp2 >> 0) & 0x1) == 0x1))
1314d0b1becdSKever Yang 				break;
1315d0b1becdSKever Yang 		}
13168b36ec9fSYouMin Chen 	}
1317d0b1becdSKever Yang 
131831d8c61dSYouMin Chen 	sdram_copy_to_reg(&denali_phy[896], &params_phy[896], (958 - 895) * 4);
131931d8c61dSYouMin Chen 	sdram_copy_to_reg(&denali_phy[0], &params_phy[0], (90 - 0 + 1) * 4);
132031d8c61dSYouMin Chen 	sdram_copy_to_reg(&denali_phy[128],
132131d8c61dSYouMin Chen 			  &params_phy[128], (218 - 128 + 1) * 4);
132231d8c61dSYouMin Chen 	sdram_copy_to_reg(&denali_phy[256],
132331d8c61dSYouMin Chen 			  &params_phy[256], (346 - 256 + 1) * 4);
132431d8c61dSYouMin Chen 	sdram_copy_to_reg(&denali_phy[384],
132531d8c61dSYouMin Chen 			  &params_phy[384], (474 - 384 + 1) * 4);
132631d8c61dSYouMin Chen 	sdram_copy_to_reg(&denali_phy[512],
132731d8c61dSYouMin Chen 			  &params_phy[512], (549 - 512 + 1) * 4);
132831d8c61dSYouMin Chen 	sdram_copy_to_reg(&denali_phy[640],
132931d8c61dSYouMin Chen 			  &params_phy[640], (677 - 640 + 1) * 4);
133031d8c61dSYouMin Chen 	sdram_copy_to_reg(&denali_phy[768],
133131d8c61dSYouMin Chen 			  &params_phy[768], (805 - 768 + 1) * 4);
1332d0b1becdSKever Yang 
13338b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4)
13348b36ec9fSYouMin Chen 		params = get_phy_index_params(1, sdram_params);
13358b36ec9fSYouMin Chen 	else
13368b36ec9fSYouMin Chen 		params = get_phy_index_params(0, sdram_params);
13378b36ec9fSYouMin Chen 
13388b36ec9fSYouMin Chen 	clrsetbits_le32(&params->phy_regs.denali_phy[896], 0x3 << 8,
13398b36ec9fSYouMin Chen 			0 << 8);
13408b36ec9fSYouMin Chen 	writel(params->phy_regs.denali_phy[896], &denali_phy[896]);
13418b36ec9fSYouMin Chen 
13428b36ec9fSYouMin Chen 	writel(sdram_params->phy_regs.denali_phy[83] + (0x10 << 16),
13438b36ec9fSYouMin Chen 	       &denali_phy[83]);
13448b36ec9fSYouMin Chen 	writel(sdram_params->phy_regs.denali_phy[84] + (0x10 << 8),
13458b36ec9fSYouMin Chen 	       &denali_phy[84]);
13468b36ec9fSYouMin Chen 	writel(sdram_params->phy_regs.denali_phy[211] + (0x10 << 16),
13478b36ec9fSYouMin Chen 	       &denali_phy[211]);
13488b36ec9fSYouMin Chen 	writel(sdram_params->phy_regs.denali_phy[212] + (0x10 << 8),
13498b36ec9fSYouMin Chen 	       &denali_phy[212]);
13508b36ec9fSYouMin Chen 	writel(sdram_params->phy_regs.denali_phy[339] + (0x10 << 16),
13518b36ec9fSYouMin Chen 	       &denali_phy[339]);
13528b36ec9fSYouMin Chen 	writel(sdram_params->phy_regs.denali_phy[340] + (0x10 << 8),
13538b36ec9fSYouMin Chen 	       &denali_phy[340]);
13548b36ec9fSYouMin Chen 	writel(sdram_params->phy_regs.denali_phy[467] + (0x10 << 16),
13558b36ec9fSYouMin Chen 	       &denali_phy[467]);
13568b36ec9fSYouMin Chen 	writel(sdram_params->phy_regs.denali_phy[468] + (0x10 << 8),
13578b36ec9fSYouMin Chen 	       &denali_phy[468]);
13588b36ec9fSYouMin Chen 
13598b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4) {
1360d0b1becdSKever Yang 		/*
13618b36ec9fSYouMin Chen 		 * to improve write dqs and dq phase from 1.5ns to 3.5ns
13628b36ec9fSYouMin Chen 		 * at 50MHz.
1363d0b1becdSKever Yang 		 */
13648b36ec9fSYouMin Chen 		for (byte = 0; byte < 4; byte++) {
13658b36ec9fSYouMin Chen 			tmp = 0x680;
13668b36ec9fSYouMin Chen 			clrsetbits_le32(&denali_phy[1 + (128 * byte)],
13678b36ec9fSYouMin Chen 					0xfff << 8, tmp << 8);
1368d0b1becdSKever Yang 		}
13698b36ec9fSYouMin Chen 		/*
13708b36ec9fSYouMin Chen 		 * to workaround 366ball two channel's RESET connect to
13718b36ec9fSYouMin Chen 		 * one RESET signal of die
13728b36ec9fSYouMin Chen 		 */
13738b36ec9fSYouMin Chen 		if (channel == 1)
13748b36ec9fSYouMin Chen 			clrsetbits_le32(&denali_phy[937], 0xff,
13758b36ec9fSYouMin Chen 					PHY_DRV_ODT_240 |
13768b36ec9fSYouMin Chen 					(PHY_DRV_ODT_240 << 0x4));
13778b36ec9fSYouMin Chen 	}
1378d0b1becdSKever Yang 
1379d0b1becdSKever Yang 	return 0;
1380d0b1becdSKever Yang }
1381d0b1becdSKever Yang 
select_per_cs_training_index(const struct chan_info * chan,u32 rank)1382d0b1becdSKever Yang static void select_per_cs_training_index(const struct chan_info *chan,
1383d0b1becdSKever Yang 					 u32 rank)
1384d0b1becdSKever Yang {
1385d0b1becdSKever Yang 	u32 *denali_phy = chan->publ->denali_phy;
1386d0b1becdSKever Yang 
1387d0b1becdSKever Yang 	/* PHY_84 PHY_PER_CS_TRAINING_EN_0 1bit offset_16 */
1388d0b1becdSKever Yang 	if ((readl(&denali_phy[84]) >> 16) & 1) {
1389d0b1becdSKever Yang 		/*
1390d0b1becdSKever Yang 		 * PHY_8/136/264/392
1391d0b1becdSKever Yang 		 * phy_per_cs_training_index_X 1bit offset_24
1392d0b1becdSKever Yang 		 */
1393d0b1becdSKever Yang 		clrsetbits_le32(&denali_phy[8], 0x1 << 24, rank << 24);
1394d0b1becdSKever Yang 		clrsetbits_le32(&denali_phy[136], 0x1 << 24, rank << 24);
1395d0b1becdSKever Yang 		clrsetbits_le32(&denali_phy[264], 0x1 << 24, rank << 24);
1396d0b1becdSKever Yang 		clrsetbits_le32(&denali_phy[392], 0x1 << 24, rank << 24);
1397d0b1becdSKever Yang 	}
1398d0b1becdSKever Yang }
1399d0b1becdSKever Yang 
override_write_leveling_value(const struct chan_info * chan)1400d0b1becdSKever Yang static void override_write_leveling_value(const struct chan_info *chan)
1401d0b1becdSKever Yang {
1402d0b1becdSKever Yang 	u32 *denali_ctl = chan->pctl->denali_ctl;
1403d0b1becdSKever Yang 	u32 *denali_phy = chan->publ->denali_phy;
1404d0b1becdSKever Yang 	u32 byte;
1405d0b1becdSKever Yang 
1406d0b1becdSKever Yang 	/* PHY_896 PHY_FREQ_SEL_MULTICAST_EN 1bit offset_0 */
1407d0b1becdSKever Yang 	setbits_le32(&denali_phy[896], 1);
1408d0b1becdSKever Yang 
1409d0b1becdSKever Yang 	/*
1410d0b1becdSKever Yang 	 * PHY_8/136/264/392
1411d0b1becdSKever Yang 	 * phy_per_cs_training_multicast_en_X 1bit offset_16
1412d0b1becdSKever Yang 	 */
1413d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[8], 0x1 << 16, 1 << 16);
1414d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[136], 0x1 << 16, 1 << 16);
1415d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[264], 0x1 << 16, 1 << 16);
1416d0b1becdSKever Yang 	clrsetbits_le32(&denali_phy[392], 0x1 << 16, 1 << 16);
1417d0b1becdSKever Yang 
1418d0b1becdSKever Yang 	for (byte = 0; byte < 4; byte++)
1419d0b1becdSKever Yang 		clrsetbits_le32(&denali_phy[63 + (128 * byte)], 0xffff << 16,
1420d0b1becdSKever Yang 				0x200 << 16);
1421d0b1becdSKever Yang 
1422d0b1becdSKever Yang 	/* PHY_896 PHY_FREQ_SEL_MULTICAST_EN 1bit offset_0 */
1423d0b1becdSKever Yang 	clrbits_le32(&denali_phy[896], 1);
1424d0b1becdSKever Yang 
1425d0b1becdSKever Yang 	/* CTL_200 ctrlupd_req 1bit offset_8 */
1426d0b1becdSKever Yang 	clrsetbits_le32(&denali_ctl[200], 0x1 << 8, 0x1 << 8);
1427d0b1becdSKever Yang }
1428d0b1becdSKever Yang 
data_training_ca(const struct chan_info * chan,u32 channel,const struct rk3399_sdram_params * sdram_params)1429d0b1becdSKever Yang static int data_training_ca(const struct chan_info *chan, u32 channel,
1430d0b1becdSKever Yang 			    const struct rk3399_sdram_params *sdram_params)
1431d0b1becdSKever Yang {
1432d0b1becdSKever Yang 	u32 *denali_pi = chan->pi->denali_pi;
1433d0b1becdSKever Yang 	u32 *denali_phy = chan->publ->denali_phy;
1434d0b1becdSKever Yang 	u32 i, tmp;
1435d0b1becdSKever Yang 	u32 obs_0, obs_1, obs_2, obs_err = 0;
143631d8c61dSYouMin Chen 	u32 rank = sdram_params->ch[channel].cap_info.rank;
14378b36ec9fSYouMin Chen 	u32 rank_mask;
1438d0b1becdSKever Yang 
143900e55222SYouMin Chen 	/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
144000e55222SYouMin Chen 	writel(0x00003f7c, (&denali_pi[175]));
144100e55222SYouMin Chen 
14428b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4)
14438b36ec9fSYouMin Chen 		rank_mask = (rank == 1) ? 0x5 : 0xf;
14448b36ec9fSYouMin Chen 	else
14458b36ec9fSYouMin Chen 		rank_mask = (rank == 1) ? 0x1 : 0x3;
14468b36ec9fSYouMin Chen 
14478b36ec9fSYouMin Chen 	for (i = 0; i < 4; i++) {
14488b36ec9fSYouMin Chen 		if (!(rank_mask & (1 << i)))
14498b36ec9fSYouMin Chen 			continue;
1450d0b1becdSKever Yang 		select_per_cs_training_index(chan, i);
1451d0b1becdSKever Yang 		/* PI_100 PI_CALVL_EN:RW:8:2 */
1452d0b1becdSKever Yang 		clrsetbits_le32(&denali_pi[100], 0x3 << 8, 0x2 << 8);
1453d0b1becdSKever Yang 		/* PI_92 PI_CALVL_REQ:WR:16:1,PI_CALVL_CS:RW:24:2 */
1454d0b1becdSKever Yang 		clrsetbits_le32(&denali_pi[92],
1455d0b1becdSKever Yang 				(0x1 << 16) | (0x3 << 24),
1456d0b1becdSKever Yang 				(0x1 << 16) | (i << 24));
1457d0b1becdSKever Yang 
1458d0b1becdSKever Yang 		/* Waiting for training complete */
1459d0b1becdSKever Yang 		while (1) {
1460d0b1becdSKever Yang 			/* PI_174 PI_INT_STATUS:RD:8:18 */
1461d0b1becdSKever Yang 			tmp = readl(&denali_pi[174]) >> 8;
1462d0b1becdSKever Yang 			/*
1463d0b1becdSKever Yang 			 * check status obs
1464d0b1becdSKever Yang 			 * PHY_532/660/789 phy_adr_calvl_obs1_:0:32
1465d0b1becdSKever Yang 			 */
1466d0b1becdSKever Yang 			obs_0 = readl(&denali_phy[532]);
1467d0b1becdSKever Yang 			obs_1 = readl(&denali_phy[660]);
1468d0b1becdSKever Yang 			obs_2 = readl(&denali_phy[788]);
1469d0b1becdSKever Yang 			if (((obs_0 >> 30) & 0x3) ||
1470d0b1becdSKever Yang 			    ((obs_1 >> 30) & 0x3) ||
1471d0b1becdSKever Yang 			    ((obs_2 >> 30) & 0x3))
1472d0b1becdSKever Yang 				obs_err = 1;
1473d0b1becdSKever Yang 			if ((((tmp >> 11) & 0x1) == 0x1) &&
1474d0b1becdSKever Yang 			    (((tmp >> 13) & 0x1) == 0x1) &&
1475d0b1becdSKever Yang 			    (((tmp >> 5) & 0x1) == 0x0) &&
14768b36ec9fSYouMin Chen 			    obs_err == 0)
1477d0b1becdSKever Yang 				break;
1478d0b1becdSKever Yang 			else if ((((tmp >> 5) & 0x1) == 0x1) ||
1479d0b1becdSKever Yang 				 (obs_err == 1))
1480d0b1becdSKever Yang 				return -EIO;
1481d0b1becdSKever Yang 		}
1482d0b1becdSKever Yang 		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
1483d0b1becdSKever Yang 		writel(0x00003f7c, (&denali_pi[175]));
1484d0b1becdSKever Yang 	}
1485d0b1becdSKever Yang 	clrbits_le32(&denali_pi[100], 0x3 << 8);
1486d0b1becdSKever Yang 
1487d0b1becdSKever Yang 	return 0;
1488d0b1becdSKever Yang }
1489d0b1becdSKever Yang 
data_training_wl(const struct chan_info * chan,u32 channel,const struct rk3399_sdram_params * sdram_params)1490d0b1becdSKever Yang static int data_training_wl(const struct chan_info *chan, u32 channel,
1491d0b1becdSKever Yang 			    const struct rk3399_sdram_params *sdram_params)
1492d0b1becdSKever Yang {
1493d0b1becdSKever Yang 	u32 *denali_pi = chan->pi->denali_pi;
1494d0b1becdSKever Yang 	u32 *denali_phy = chan->publ->denali_phy;
1495d0b1becdSKever Yang 	u32 i, tmp;
1496d0b1becdSKever Yang 	u32 obs_0, obs_1, obs_2, obs_3, obs_err = 0;
149731d8c61dSYouMin Chen 	u32 rank = sdram_params->ch[channel].cap_info.rank;
1498d0b1becdSKever Yang 
149900e55222SYouMin Chen 	/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
150000e55222SYouMin Chen 	writel(0x00003f7c, (&denali_pi[175]));
150100e55222SYouMin Chen 
1502d0b1becdSKever Yang 	for (i = 0; i < rank; i++) {
1503d0b1becdSKever Yang 		select_per_cs_training_index(chan, i);
1504d0b1becdSKever Yang 		/* PI_60 PI_WRLVL_EN:RW:8:2 */
1505d0b1becdSKever Yang 		clrsetbits_le32(&denali_pi[60], 0x3 << 8, 0x2 << 8);
1506d0b1becdSKever Yang 		/* PI_59 PI_WRLVL_REQ:WR:8:1,PI_WRLVL_CS:RW:16:2 */
1507d0b1becdSKever Yang 		clrsetbits_le32(&denali_pi[59],
1508d0b1becdSKever Yang 				(0x1 << 8) | (0x3 << 16),
1509d0b1becdSKever Yang 				(0x1 << 8) | (i << 16));
1510d0b1becdSKever Yang 
1511d0b1becdSKever Yang 		/* Waiting for training complete */
1512d0b1becdSKever Yang 		while (1) {
1513d0b1becdSKever Yang 			/* PI_174 PI_INT_STATUS:RD:8:18 */
1514d0b1becdSKever Yang 			tmp = readl(&denali_pi[174]) >> 8;
1515d0b1becdSKever Yang 
1516d0b1becdSKever Yang 			/*
1517d0b1becdSKever Yang 			 * check status obs, if error maybe can not
1518d0b1becdSKever Yang 			 * get leveling done PHY_40/168/296/424
1519d0b1becdSKever Yang 			 * phy_wrlvl_status_obs_X:0:13
1520d0b1becdSKever Yang 			 */
1521d0b1becdSKever Yang 			obs_0 = readl(&denali_phy[40]);
1522d0b1becdSKever Yang 			obs_1 = readl(&denali_phy[168]);
1523d0b1becdSKever Yang 			obs_2 = readl(&denali_phy[296]);
1524d0b1becdSKever Yang 			obs_3 = readl(&denali_phy[424]);
1525d0b1becdSKever Yang 			if (((obs_0 >> 12) & 0x1) ||
1526d0b1becdSKever Yang 			    ((obs_1 >> 12) & 0x1) ||
1527d0b1becdSKever Yang 			    ((obs_2 >> 12) & 0x1) ||
1528d0b1becdSKever Yang 			    ((obs_3 >> 12) & 0x1))
1529d0b1becdSKever Yang 				obs_err = 1;
1530d0b1becdSKever Yang 			if ((((tmp >> 10) & 0x1) == 0x1) &&
1531d0b1becdSKever Yang 			    (((tmp >> 13) & 0x1) == 0x1) &&
1532d0b1becdSKever Yang 			    (((tmp >> 4) & 0x1) == 0x0) &&
15338b36ec9fSYouMin Chen 			    obs_err == 0)
1534d0b1becdSKever Yang 				break;
1535d0b1becdSKever Yang 			else if ((((tmp >> 4) & 0x1) == 0x1) ||
1536d0b1becdSKever Yang 				 (obs_err == 1))
1537d0b1becdSKever Yang 				return -EIO;
1538d0b1becdSKever Yang 		}
1539d0b1becdSKever Yang 		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
1540d0b1becdSKever Yang 		writel(0x00003f7c, (&denali_pi[175]));
1541d0b1becdSKever Yang 	}
1542d0b1becdSKever Yang 
1543d0b1becdSKever Yang 	override_write_leveling_value(chan);
1544d0b1becdSKever Yang 	clrbits_le32(&denali_pi[60], 0x3 << 8);
1545d0b1becdSKever Yang 
1546d0b1becdSKever Yang 	return 0;
1547d0b1becdSKever Yang }
1548d0b1becdSKever Yang 
data_training_rg(const struct chan_info * chan,u32 channel,const struct rk3399_sdram_params * sdram_params)1549d0b1becdSKever Yang static int data_training_rg(const struct chan_info *chan, u32 channel,
1550d0b1becdSKever Yang 			    const struct rk3399_sdram_params *sdram_params)
1551d0b1becdSKever Yang {
1552d0b1becdSKever Yang 	u32 *denali_pi = chan->pi->denali_pi;
1553d0b1becdSKever Yang 	u32 *denali_phy = chan->publ->denali_phy;
1554d0b1becdSKever Yang 	u32 i, tmp;
1555d0b1becdSKever Yang 	u32 obs_0, obs_1, obs_2, obs_3, obs_err = 0;
155631d8c61dSYouMin Chen 	u32 rank = sdram_params->ch[channel].cap_info.rank;
1557d0b1becdSKever Yang 
155800e55222SYouMin Chen 	/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
155900e55222SYouMin Chen 	writel(0x00003f7c, (&denali_pi[175]));
156000e55222SYouMin Chen 
1561d0b1becdSKever Yang 	for (i = 0; i < rank; i++) {
1562d0b1becdSKever Yang 		select_per_cs_training_index(chan, i);
1563d0b1becdSKever Yang 		/* PI_80 PI_RDLVL_GATE_EN:RW:24:2 */
1564d0b1becdSKever Yang 		clrsetbits_le32(&denali_pi[80], 0x3 << 24, 0x2 << 24);
1565d0b1becdSKever Yang 		/*
1566d0b1becdSKever Yang 		 * PI_74 PI_RDLVL_GATE_REQ:WR:16:1
1567d0b1becdSKever Yang 		 * PI_RDLVL_CS:RW:24:2
1568d0b1becdSKever Yang 		 */
1569d0b1becdSKever Yang 		clrsetbits_le32(&denali_pi[74],
1570d0b1becdSKever Yang 				(0x1 << 16) | (0x3 << 24),
1571d0b1becdSKever Yang 				(0x1 << 16) | (i << 24));
1572d0b1becdSKever Yang 
1573d0b1becdSKever Yang 		/* Waiting for training complete */
1574d0b1becdSKever Yang 		while (1) {
1575d0b1becdSKever Yang 			/* PI_174 PI_INT_STATUS:RD:8:18 */
1576d0b1becdSKever Yang 			tmp = readl(&denali_pi[174]) >> 8;
1577d0b1becdSKever Yang 
1578d0b1becdSKever Yang 			/*
1579d0b1becdSKever Yang 			 * check status obs
1580d0b1becdSKever Yang 			 * PHY_43/171/299/427
1581d0b1becdSKever Yang 			 *     PHY_GTLVL_STATUS_OBS_x:16:8
1582d0b1becdSKever Yang 			 */
1583d0b1becdSKever Yang 			obs_0 = readl(&denali_phy[43]);
1584d0b1becdSKever Yang 			obs_1 = readl(&denali_phy[171]);
1585d0b1becdSKever Yang 			obs_2 = readl(&denali_phy[299]);
1586d0b1becdSKever Yang 			obs_3 = readl(&denali_phy[427]);
1587d0b1becdSKever Yang 			if (((obs_0 >> (16 + 6)) & 0x3) ||
1588d0b1becdSKever Yang 			    ((obs_1 >> (16 + 6)) & 0x3) ||
1589d0b1becdSKever Yang 			    ((obs_2 >> (16 + 6)) & 0x3) ||
1590d0b1becdSKever Yang 			    ((obs_3 >> (16 + 6)) & 0x3))
1591d0b1becdSKever Yang 				obs_err = 1;
1592d0b1becdSKever Yang 			if ((((tmp >> 9) & 0x1) == 0x1) &&
1593d0b1becdSKever Yang 			    (((tmp >> 13) & 0x1) == 0x1) &&
1594d0b1becdSKever Yang 			    (((tmp >> 3) & 0x1) == 0x0) &&
15958b36ec9fSYouMin Chen 			    obs_err == 0)
1596d0b1becdSKever Yang 				break;
1597d0b1becdSKever Yang 			else if ((((tmp >> 3) & 0x1) == 0x1) ||
1598d0b1becdSKever Yang 				 (obs_err == 1))
1599d0b1becdSKever Yang 				return -EIO;
1600d0b1becdSKever Yang 		}
1601d0b1becdSKever Yang 		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
1602d0b1becdSKever Yang 		writel(0x00003f7c, (&denali_pi[175]));
1603d0b1becdSKever Yang 	}
1604d0b1becdSKever Yang 	clrbits_le32(&denali_pi[80], 0x3 << 24);
1605d0b1becdSKever Yang 
1606d0b1becdSKever Yang 	return 0;
1607d0b1becdSKever Yang }
1608d0b1becdSKever Yang 
data_training_rl(const struct chan_info * chan,u32 channel,const struct rk3399_sdram_params * sdram_params)1609d0b1becdSKever Yang static int data_training_rl(const struct chan_info *chan, u32 channel,
1610d0b1becdSKever Yang 			    const struct rk3399_sdram_params *sdram_params)
1611d0b1becdSKever Yang {
1612d0b1becdSKever Yang 	u32 *denali_pi = chan->pi->denali_pi;
1613d0b1becdSKever Yang 	u32 i, tmp;
161431d8c61dSYouMin Chen 	u32 rank = sdram_params->ch[channel].cap_info.rank;
1615d0b1becdSKever Yang 
161600e55222SYouMin Chen 	/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
161700e55222SYouMin Chen 	writel(0x00003f7c, (&denali_pi[175]));
161800e55222SYouMin Chen 
1619d0b1becdSKever Yang 	for (i = 0; i < rank; i++) {
1620d0b1becdSKever Yang 		select_per_cs_training_index(chan, i);
1621d0b1becdSKever Yang 		/* PI_80 PI_RDLVL_EN:RW:16:2 */
1622d0b1becdSKever Yang 		clrsetbits_le32(&denali_pi[80], 0x3 << 16, 0x2 << 16);
1623d0b1becdSKever Yang 		/* PI_74 PI_RDLVL_REQ:WR:8:1,PI_RDLVL_CS:RW:24:2 */
1624d0b1becdSKever Yang 		clrsetbits_le32(&denali_pi[74],
1625d0b1becdSKever Yang 				(0x1 << 8) | (0x3 << 24),
1626d0b1becdSKever Yang 				(0x1 << 8) | (i << 24));
1627d0b1becdSKever Yang 
1628d0b1becdSKever Yang 		/* Waiting for training complete */
1629d0b1becdSKever Yang 		while (1) {
1630d0b1becdSKever Yang 			/* PI_174 PI_INT_STATUS:RD:8:18 */
1631d0b1becdSKever Yang 			tmp = readl(&denali_pi[174]) >> 8;
1632d0b1becdSKever Yang 
1633d0b1becdSKever Yang 			/*
1634d0b1becdSKever Yang 			 * make sure status obs not report error bit
1635d0b1becdSKever Yang 			 * PHY_46/174/302/430
1636d0b1becdSKever Yang 			 *     phy_rdlvl_status_obs_X:16:8
1637d0b1becdSKever Yang 			 */
1638d0b1becdSKever Yang 			if ((((tmp >> 8) & 0x1) == 0x1) &&
1639d0b1becdSKever Yang 			    (((tmp >> 13) & 0x1) == 0x1) &&
1640d0b1becdSKever Yang 			    (((tmp >> 2) & 0x1) == 0x0))
1641d0b1becdSKever Yang 				break;
1642d0b1becdSKever Yang 			else if (((tmp >> 2) & 0x1) == 0x1)
1643d0b1becdSKever Yang 				return -EIO;
1644d0b1becdSKever Yang 		}
1645d0b1becdSKever Yang 		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
1646d0b1becdSKever Yang 		writel(0x00003f7c, (&denali_pi[175]));
1647d0b1becdSKever Yang 	}
1648d0b1becdSKever Yang 	clrbits_le32(&denali_pi[80], 0x3 << 16);
1649d0b1becdSKever Yang 
1650d0b1becdSKever Yang 	return 0;
1651d0b1becdSKever Yang }
1652d0b1becdSKever Yang 
data_training_wdql(const struct chan_info * chan,u32 channel,const struct rk3399_sdram_params * sdram_params)1653d0b1becdSKever Yang static int data_training_wdql(const struct chan_info *chan, u32 channel,
1654d0b1becdSKever Yang 			      const struct rk3399_sdram_params *sdram_params)
1655d0b1becdSKever Yang {
1656d0b1becdSKever Yang 	u32 *denali_pi = chan->pi->denali_pi;
1657d0b1becdSKever Yang 	u32 i, tmp;
165831d8c61dSYouMin Chen 	u32 rank = sdram_params->ch[channel].cap_info.rank;
16598b36ec9fSYouMin Chen 	u32 rank_mask;
1660d0b1becdSKever Yang 
166100e55222SYouMin Chen 	/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
166200e55222SYouMin Chen 	writel(0x00003f7c, (&denali_pi[175]));
166300e55222SYouMin Chen 
16648b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4)
16658b36ec9fSYouMin Chen 		rank_mask = (rank == 1) ? 0x5 : 0xf;
16668b36ec9fSYouMin Chen 	else
16678b36ec9fSYouMin Chen 		rank_mask = (rank == 1) ? 0x1 : 0x3;
16688b36ec9fSYouMin Chen 
16698b36ec9fSYouMin Chen 	for (i = 0; i < 4; i++) {
16708b36ec9fSYouMin Chen 		if (!(rank_mask & (1 << i)))
16718b36ec9fSYouMin Chen 			continue;
16728b36ec9fSYouMin Chen 
1673d0b1becdSKever Yang 		select_per_cs_training_index(chan, i);
1674d0b1becdSKever Yang 		/*
1675d0b1becdSKever Yang 		 * disable PI_WDQLVL_VREF_EN before wdq leveling?
16768b36ec9fSYouMin Chen 		 * PI_117 PI_WDQLVL_VREF_EN:RW:8:1
1677d0b1becdSKever Yang 		 */
16788b36ec9fSYouMin Chen 		clrbits_le32(&denali_pi[117], 0x1 << 8);
1679d0b1becdSKever Yang 		/* PI_124 PI_WDQLVL_EN:RW:16:2 */
1680d0b1becdSKever Yang 		clrsetbits_le32(&denali_pi[124], 0x3 << 16, 0x2 << 16);
1681d0b1becdSKever Yang 		/* PI_121 PI_WDQLVL_REQ:WR:8:1,PI_WDQLVL_CS:RW:16:2 */
1682d0b1becdSKever Yang 		clrsetbits_le32(&denali_pi[121],
1683d0b1becdSKever Yang 				(0x1 << 8) | (0x3 << 16),
1684d0b1becdSKever Yang 				(0x1 << 8) | (i << 16));
1685d0b1becdSKever Yang 
1686d0b1becdSKever Yang 		/* Waiting for training complete */
1687d0b1becdSKever Yang 		while (1) {
1688d0b1becdSKever Yang 			/* PI_174 PI_INT_STATUS:RD:8:18 */
1689d0b1becdSKever Yang 			tmp = readl(&denali_pi[174]) >> 8;
1690d0b1becdSKever Yang 			if ((((tmp >> 12) & 0x1) == 0x1) &&
1691d0b1becdSKever Yang 			    (((tmp >> 13) & 0x1) == 0x1) &&
1692d0b1becdSKever Yang 			    (((tmp >> 6) & 0x1) == 0x0))
1693d0b1becdSKever Yang 				break;
1694d0b1becdSKever Yang 			else if (((tmp >> 6) & 0x1) == 0x1)
1695d0b1becdSKever Yang 				return -EIO;
1696d0b1becdSKever Yang 		}
1697d0b1becdSKever Yang 		/* clear interrupt,PI_175 PI_INT_ACK:WR:0:17 */
1698d0b1becdSKever Yang 		writel(0x00003f7c, (&denali_pi[175]));
1699d0b1becdSKever Yang 	}
1700d0b1becdSKever Yang 	clrbits_le32(&denali_pi[124], 0x3 << 16);
1701d0b1becdSKever Yang 
1702d0b1becdSKever Yang 	return 0;
1703d0b1becdSKever Yang }
1704d0b1becdSKever Yang 
data_training(const struct chan_info * chan,u32 channel,const struct rk3399_sdram_params * sdram_params,u32 training_flag)1705d0b1becdSKever Yang static int data_training(const struct chan_info *chan, u32 channel,
1706d0b1becdSKever Yang 			 const struct rk3399_sdram_params *sdram_params,
1707d0b1becdSKever Yang 			 u32 training_flag)
1708d0b1becdSKever Yang {
1709d0b1becdSKever Yang 	u32 *denali_phy = chan->publ->denali_phy;
171031d8c61dSYouMin Chen 	int ret = 0;
1711d0b1becdSKever Yang 
1712d0b1becdSKever Yang 	/* PHY_927 PHY_PAD_DQS_DRIVE  RPULL offset_22 */
1713d0b1becdSKever Yang 	setbits_le32(&denali_phy[927], (1 << 22));
1714d0b1becdSKever Yang 
1715d0b1becdSKever Yang 	if (training_flag == PI_FULL_TRAINING) {
1716d0b1becdSKever Yang 		if (sdram_params->base.dramtype == LPDDR4) {
17178b36ec9fSYouMin Chen 			training_flag = PI_WRITE_LEVELING |
1718d0b1becdSKever Yang 					PI_READ_GATE_TRAINING |
1719d0b1becdSKever Yang 					PI_READ_LEVELING | PI_WDQ_LEVELING;
1720d0b1becdSKever Yang 		} else if (sdram_params->base.dramtype == LPDDR3) {
1721d0b1becdSKever Yang 			training_flag = PI_CA_TRAINING | PI_WRITE_LEVELING |
1722d0b1becdSKever Yang 					PI_READ_GATE_TRAINING;
1723d0b1becdSKever Yang 		} else if (sdram_params->base.dramtype == DDR3) {
1724d0b1becdSKever Yang 			training_flag = PI_WRITE_LEVELING |
1725d0b1becdSKever Yang 					PI_READ_GATE_TRAINING |
1726d0b1becdSKever Yang 					PI_READ_LEVELING;
1727d0b1becdSKever Yang 		}
1728d0b1becdSKever Yang 	}
1729d0b1becdSKever Yang 
1730d0b1becdSKever Yang 	/* ca training(LPDDR4,LPDDR3 support) */
173131d8c61dSYouMin Chen 	if ((training_flag & PI_CA_TRAINING) == PI_CA_TRAINING) {
173231d8c61dSYouMin Chen 		ret = data_training_ca(chan, channel, sdram_params);
173331d8c61dSYouMin Chen 		if (ret != 0)
173431d8c61dSYouMin Chen 			goto out;
173531d8c61dSYouMin Chen 	}
1736d0b1becdSKever Yang 
1737d0b1becdSKever Yang 	/* write leveling(LPDDR4,LPDDR3,DDR3 support) */
173831d8c61dSYouMin Chen 	if ((training_flag & PI_WRITE_LEVELING) == PI_WRITE_LEVELING) {
173931d8c61dSYouMin Chen 		ret = data_training_wl(chan, channel, sdram_params);
174031d8c61dSYouMin Chen 		if (ret != 0)
174131d8c61dSYouMin Chen 			goto out;
174231d8c61dSYouMin Chen 	}
1743d0b1becdSKever Yang 
1744d0b1becdSKever Yang 	/* read gate training(LPDDR4,LPDDR3,DDR3 support) */
174531d8c61dSYouMin Chen 	if ((training_flag & PI_READ_GATE_TRAINING) == PI_READ_GATE_TRAINING) {
174631d8c61dSYouMin Chen 		ret = data_training_rg(chan, channel, sdram_params);
174731d8c61dSYouMin Chen 		if (ret != 0)
174831d8c61dSYouMin Chen 			goto out;
174931d8c61dSYouMin Chen 	}
1750d0b1becdSKever Yang 
1751d0b1becdSKever Yang 	/* read leveling(LPDDR4,LPDDR3,DDR3 support) */
175231d8c61dSYouMin Chen 	if ((training_flag & PI_READ_LEVELING) == PI_READ_LEVELING) {
175331d8c61dSYouMin Chen 		ret = data_training_rl(chan, channel, sdram_params);
175431d8c61dSYouMin Chen 		if (ret != 0)
175531d8c61dSYouMin Chen 			goto out;
175631d8c61dSYouMin Chen 	}
1757d0b1becdSKever Yang 
1758d0b1becdSKever Yang 	/* wdq leveling(LPDDR4 support) */
175931d8c61dSYouMin Chen 	if ((training_flag & PI_WDQ_LEVELING) == PI_WDQ_LEVELING) {
176031d8c61dSYouMin Chen 		ret = data_training_wdql(chan, channel, sdram_params);
176131d8c61dSYouMin Chen 		if (ret != 0)
176231d8c61dSYouMin Chen 			goto out;
176331d8c61dSYouMin Chen 	}
1764d0b1becdSKever Yang 
1765d0b1becdSKever Yang 	/* PHY_927 PHY_PAD_DQS_DRIVE  RPULL offset_22 */
1766d0b1becdSKever Yang 	clrbits_le32(&denali_phy[927], (1 << 22));
1767d0b1becdSKever Yang 
176831d8c61dSYouMin Chen out:
176931d8c61dSYouMin Chen 	return ret;
1770d0b1becdSKever Yang }
1771d0b1becdSKever Yang 
set_ddrconfig(const struct chan_info * chan,const struct rk3399_sdram_params * sdram_params,unsigned char channel,u32 ddrconfig)1772d0b1becdSKever Yang static void set_ddrconfig(const struct chan_info *chan,
1773d0b1becdSKever Yang 			  const struct rk3399_sdram_params *sdram_params,
1774d0b1becdSKever Yang 			  unsigned char channel, u32 ddrconfig)
1775d0b1becdSKever Yang {
1776d0b1becdSKever Yang 	/* only need to set ddrconfig */
177731d8c61dSYouMin Chen 	struct msch_regs *ddr_msch_regs = chan->msch;
1778d0b1becdSKever Yang 	unsigned int cs0_cap = 0;
1779d0b1becdSKever Yang 	unsigned int cs1_cap = 0;
1780d0b1becdSKever Yang 
178131d8c61dSYouMin Chen 	cs0_cap = (1 << (sdram_params->ch[channel].cap_info.cs0_row
178231d8c61dSYouMin Chen 			+ sdram_params->ch[channel].cap_info.col
178331d8c61dSYouMin Chen 			+ sdram_params->ch[channel].cap_info.bk
178431d8c61dSYouMin Chen 			+ sdram_params->ch[channel].cap_info.bw - 20));
178531d8c61dSYouMin Chen 	if (sdram_params->ch[channel].cap_info.rank > 1)
178631d8c61dSYouMin Chen 		cs1_cap = cs0_cap >> (sdram_params->ch[channel].cap_info.cs0_row
178731d8c61dSYouMin Chen 				- sdram_params->ch[channel].cap_info.cs1_row);
178831d8c61dSYouMin Chen 	if (sdram_params->ch[channel].cap_info.row_3_4) {
1789d0b1becdSKever Yang 		cs0_cap = cs0_cap * 3 / 4;
1790d0b1becdSKever Yang 		cs1_cap = cs1_cap * 3 / 4;
1791d0b1becdSKever Yang 	}
1792d0b1becdSKever Yang 
1793d0b1becdSKever Yang 	writel(ddrconfig | (ddrconfig << 8), &ddr_msch_regs->ddrconf);
1794d0b1becdSKever Yang 	writel(((cs0_cap / 32) & 0xff) | (((cs1_cap / 32) & 0xff) << 8),
1795d0b1becdSKever Yang 	       &ddr_msch_regs->ddrsize);
1796d0b1becdSKever Yang }
1797d0b1becdSKever Yang 
sdram_msch_config(struct msch_regs * msch,struct sdram_msch_timings * noc_timings)17985e6e8f2dSYouMin Chen static void sdram_msch_config(struct msch_regs *msch,
17995e6e8f2dSYouMin Chen 			      struct sdram_msch_timings *noc_timings)
18005e6e8f2dSYouMin Chen {
18015e6e8f2dSYouMin Chen 	writel(noc_timings->ddrtiminga0.d32,
18025e6e8f2dSYouMin Chen 	       &msch->ddrtiminga0.d32);
18035e6e8f2dSYouMin Chen 	writel(noc_timings->ddrtimingb0.d32,
18045e6e8f2dSYouMin Chen 	       &msch->ddrtimingb0.d32);
18055e6e8f2dSYouMin Chen 	writel(noc_timings->ddrtimingc0.d32,
18065e6e8f2dSYouMin Chen 	       &msch->ddrtimingc0.d32);
18075e6e8f2dSYouMin Chen 	writel(noc_timings->devtodev0.d32,
18085e6e8f2dSYouMin Chen 	       &msch->devtodev0.d32);
18095e6e8f2dSYouMin Chen 	writel(noc_timings->ddrmode.d32,
18105e6e8f2dSYouMin Chen 	       &msch->ddrmode.d32);
18115e6e8f2dSYouMin Chen }
18125e6e8f2dSYouMin Chen 
dram_all_config(struct dram_info * dram,struct rk3399_sdram_params * sdram_params)1813d0b1becdSKever Yang static void dram_all_config(struct dram_info *dram,
181431d8c61dSYouMin Chen 			    struct rk3399_sdram_params *sdram_params)
1815d0b1becdSKever Yang {
181631d8c61dSYouMin Chen 	u32 sys_reg2 = 0;
181731d8c61dSYouMin Chen 	u32 sys_reg3 = 0;
1818d0b1becdSKever Yang 	unsigned int channel, idx;
1819d0b1becdSKever Yang 
1820d0b1becdSKever Yang 	for (channel = 0, idx = 0;
1821d0b1becdSKever Yang 	     (idx < sdram_params->base.num_channels) && (channel < 2);
1822d0b1becdSKever Yang 	     channel++) {
182331d8c61dSYouMin Chen 		struct msch_regs *ddr_msch_regs;
182431d8c61dSYouMin Chen 		struct sdram_msch_timings *noc_timing;
1825d0b1becdSKever Yang 
182631d8c61dSYouMin Chen 		if (sdram_params->ch[channel].cap_info.col == 0)
1827d0b1becdSKever Yang 			continue;
1828d0b1becdSKever Yang 		idx++;
182931d8c61dSYouMin Chen 		sdram_org_config(&sdram_params->ch[channel].cap_info,
183031d8c61dSYouMin Chen 				 &sdram_params->base, &sys_reg2,
183131d8c61dSYouMin Chen 				 &sys_reg3, channel);
1832d0b1becdSKever Yang 		ddr_msch_regs = dram->chan[channel].msch;
1833d0b1becdSKever Yang 		noc_timing = &sdram_params->ch[channel].noc_timings;
183431d8c61dSYouMin Chen 		sdram_msch_config(ddr_msch_regs, noc_timing);
1835d0b1becdSKever Yang 
1836d0b1becdSKever Yang 		/* rank 1 memory clock disable (dfi_dram_clk_disable = 1) */
183731d8c61dSYouMin Chen 		if (sdram_params->ch[channel].cap_info.rank == 1)
1838d0b1becdSKever Yang 			setbits_le32(&dram->chan[channel].pctl->denali_ctl[276],
1839d0b1becdSKever Yang 				     1 << 17);
1840d0b1becdSKever Yang 	}
1841d0b1becdSKever Yang 
184231d8c61dSYouMin Chen 	writel(sys_reg2, &dram->pmugrf->os_reg2);
184331d8c61dSYouMin Chen 	writel(sys_reg3, &dram->pmugrf->os_reg3);
1844d0b1becdSKever Yang 	rk_clrsetreg(&dram->pmusgrf->soc_con4, 0x1f << 10,
1845d0b1becdSKever Yang 		     sdram_params->base.stride << 10);
1846d0b1becdSKever Yang 
1847d0b1becdSKever Yang 	/* reboot hold register set */
1848d0b1becdSKever Yang 	writel(PRESET_SGRF_HOLD(0) | PRESET_GPIO0_HOLD(1) |
1849d0b1becdSKever Yang 		PRESET_GPIO1_HOLD(1),
1850d0b1becdSKever Yang 		&dram->pmucru->pmucru_rstnhold_con[1]);
1851d0b1becdSKever Yang 	clrsetbits_le32(&dram->cru->glb_rst_con, 0x3, 0x3);
1852d0b1becdSKever Yang }
1853d0b1becdSKever Yang 
switch_to_phy_index1(struct dram_info * dram,const struct rk3399_sdram_params * sdram_params)1854d0b1becdSKever Yang static int switch_to_phy_index1(struct dram_info *dram,
1855d0b1becdSKever Yang 				const struct rk3399_sdram_params *sdram_params)
1856d0b1becdSKever Yang {
1857d0b1becdSKever Yang 	u32 channel;
1858d0b1becdSKever Yang 	u32 *denali_phy;
1859d0b1becdSKever Yang 	u32 ch_count = sdram_params->base.num_channels;
1860d0b1becdSKever Yang 	int ret;
1861d0b1becdSKever Yang 	int i = 0;
1862d0b1becdSKever Yang 
1863d0b1becdSKever Yang 	writel(RK_CLRSETBITS(0x03 << 4 | 1 << 2 | 1,
1864d0b1becdSKever Yang 			     1 << 4 | 1 << 2 | 1),
1865d0b1becdSKever Yang 			&dram->cic->cic_ctrl0);
1866d0b1becdSKever Yang 	while (!(readl(&dram->cic->cic_status0) & (1 << 2))) {
1867d0b1becdSKever Yang 		mdelay(10);
1868d0b1becdSKever Yang 		i++;
1869d0b1becdSKever Yang 		if (i > 10) {
1870d0b1becdSKever Yang 			debug("index1 frequency change overtime\n");
1871d0b1becdSKever Yang 			return -ETIME;
1872d0b1becdSKever Yang 		}
1873d0b1becdSKever Yang 	}
1874d0b1becdSKever Yang 
1875d0b1becdSKever Yang 	i = 0;
1876d0b1becdSKever Yang 	writel(RK_CLRSETBITS(1 << 1, 1 << 1), &dram->cic->cic_ctrl0);
1877d0b1becdSKever Yang 	while (!(readl(&dram->cic->cic_status0) & (1 << 0))) {
1878d0b1becdSKever Yang 		mdelay(10);
1879d0b1becdSKever Yang 		if (i > 10) {
1880d0b1becdSKever Yang 			debug("index1 frequency done overtime\n");
1881d0b1becdSKever Yang 			return -ETIME;
1882d0b1becdSKever Yang 		}
1883d0b1becdSKever Yang 	}
1884d0b1becdSKever Yang 
1885d0b1becdSKever Yang 	for (channel = 0; channel < ch_count; channel++) {
1886d0b1becdSKever Yang 		denali_phy = dram->chan[channel].publ->denali_phy;
1887d0b1becdSKever Yang 		clrsetbits_le32(&denali_phy[896], (0x3 << 8) | 1, 1 << 8);
1888d0b1becdSKever Yang 		ret = data_training(&dram->chan[channel], channel,
1889d0b1becdSKever Yang 				    sdram_params, PI_FULL_TRAINING);
1890d0b1becdSKever Yang 		if (ret) {
1891d0b1becdSKever Yang 			debug("index1 training failed\n");
1892d0b1becdSKever Yang 			return ret;
1893d0b1becdSKever Yang 		}
1894d0b1becdSKever Yang 	}
1895d0b1becdSKever Yang 
1896d0b1becdSKever Yang 	return 0;
1897d0b1becdSKever Yang }
1898d0b1becdSKever Yang 
189931d8c61dSYouMin Chen u16  ddr_cfg_2_rbc[] = {
190031d8c61dSYouMin Chen 		/*
190131d8c61dSYouMin Chen 		 * [6]	  highest bit col
190231d8c61dSYouMin Chen 		 * [5:3]  max row(14+n)
190331d8c61dSYouMin Chen 		 * [2]    insertion row
190431d8c61dSYouMin Chen 		 * [1:0]  col(9+n),col, data bus 32bit
190531d8c61dSYouMin Chen 		 *
190631d8c61dSYouMin Chen 		 * highbitcol, max_row, insertion_row,  col
190731d8c61dSYouMin Chen 		 */
190831d8c61dSYouMin Chen 		((0 << 6) | (2 << 3) | (0 << 2) | 0), /* 0 */
190931d8c61dSYouMin Chen 		((0 << 6) | (2 << 3) | (0 << 2) | 1), /* 1 */
191031d8c61dSYouMin Chen 		((0 << 6) | (1 << 3) | (0 << 2) | 2), /* 2 */
191131d8c61dSYouMin Chen 		((0 << 6) | (0 << 3) | (0 << 2) | 3), /* 3 */
191231d8c61dSYouMin Chen 		((0 << 6) | (2 << 3) | (1 << 2) | 1), /* 4 */
191331d8c61dSYouMin Chen 		((0 << 6) | (1 << 3) | (1 << 2) | 2), /* 5 */
191431d8c61dSYouMin Chen 		((1 << 6) | (0 << 3) | (0 << 2) | 2), /* 6 */
191531d8c61dSYouMin Chen 		((1 << 6) | (1 << 3) | (0 << 2) | 2), /* 7 */
191631d8c61dSYouMin Chen };
191731d8c61dSYouMin Chen 
calculate_ddrconfig(struct rk3399_sdram_params * sdram_params,u32 channel)19188b36ec9fSYouMin Chen static u32 calculate_ddrconfig(struct rk3399_sdram_params *sdram_params,
19198b36ec9fSYouMin Chen 			       u32 channel)
192031d8c61dSYouMin Chen {
192131d8c61dSYouMin Chen 	unsigned int i;
192231d8c61dSYouMin Chen 	unsigned int cs0_row = sdram_params->ch[channel].cap_info.cs0_row;
192331d8c61dSYouMin Chen 	unsigned int col = sdram_params->ch[channel].cap_info.col;
192431d8c61dSYouMin Chen 	unsigned int bw = sdram_params->ch[channel].cap_info.bw;
192531d8c61dSYouMin Chen 
192631d8c61dSYouMin Chen 	col -= (bw == 2) ? 0 : 1;
192731d8c61dSYouMin Chen 	col -= 9;
192831d8c61dSYouMin Chen 
192931d8c61dSYouMin Chen 	for (i = 0; i < 4; i++) {
193031d8c61dSYouMin Chen 		if ((col == (ddr_cfg_2_rbc[i] & 0x3)) &&
193131d8c61dSYouMin Chen 		    (cs0_row <= (((ddr_cfg_2_rbc[i] >> 3) & 0x7) + 14)))
193231d8c61dSYouMin Chen 			break;
193331d8c61dSYouMin Chen 	}
193431d8c61dSYouMin Chen 
193531d8c61dSYouMin Chen 	if (i >= 4)
193631d8c61dSYouMin Chen 		i = -1;
193731d8c61dSYouMin Chen 
193831d8c61dSYouMin Chen 	return i;
193931d8c61dSYouMin Chen }
194031d8c61dSYouMin Chen 
calculate_stride(struct rk3399_sdram_params * sdram_params)19418b36ec9fSYouMin Chen static unsigned char calculate_stride(struct rk3399_sdram_params *sdram_params)
194231d8c61dSYouMin Chen {
194331d8c61dSYouMin Chen 	unsigned int gstride_type;
194431d8c61dSYouMin Chen 	unsigned int channel;
194531d8c61dSYouMin Chen 	unsigned int chinfo = 0;
194631d8c61dSYouMin Chen 	unsigned int cap = 0;
194731d8c61dSYouMin Chen 	unsigned int stride = -1;
194831d8c61dSYouMin Chen 	unsigned int ch_cap[2] = {0, 0};
194931d8c61dSYouMin Chen 
195031d8c61dSYouMin Chen 	gstride_type = STRIDE_256B;
195131d8c61dSYouMin Chen 
195231d8c61dSYouMin Chen 	for (channel = 0; channel < 2; channel++) {
195331d8c61dSYouMin Chen 		unsigned int cs0_cap = 0;
195431d8c61dSYouMin Chen 		unsigned int cs1_cap = 0;
195531d8c61dSYouMin Chen 		struct sdram_cap_info *cap_info =
195631d8c61dSYouMin Chen 			&sdram_params->ch[channel].cap_info;
195731d8c61dSYouMin Chen 
195831d8c61dSYouMin Chen 		if (cap_info->col == 0)
195931d8c61dSYouMin Chen 			continue;
196031d8c61dSYouMin Chen 
196131d8c61dSYouMin Chen 		cs0_cap = (1 << (cap_info->cs0_row + cap_info->col +
196231d8c61dSYouMin Chen 				 cap_info->bk + cap_info->bw - 20));
196331d8c61dSYouMin Chen 		if (cap_info->rank > 1)
196431d8c61dSYouMin Chen 			cs1_cap = cs0_cap >> (cap_info->cs0_row
196531d8c61dSYouMin Chen 					      - cap_info->cs1_row);
196631d8c61dSYouMin Chen 		if (cap_info->row_3_4) {
196731d8c61dSYouMin Chen 			cs0_cap = cs0_cap * 3 / 4;
196831d8c61dSYouMin Chen 			cs1_cap = cs1_cap * 3 / 4;
196931d8c61dSYouMin Chen 		}
197031d8c61dSYouMin Chen 		ch_cap[channel] = cs0_cap + cs1_cap;
197131d8c61dSYouMin Chen 		chinfo |= 1 << channel;
197231d8c61dSYouMin Chen 	}
197331d8c61dSYouMin Chen 
197431d8c61dSYouMin Chen 	cap = ch_cap[0] + ch_cap[1];
197531d8c61dSYouMin Chen 	if (sdram_params->base.num_channels == 1) {
197631d8c61dSYouMin Chen 		if (chinfo & 1) /* channel a only */
197731d8c61dSYouMin Chen 			stride = 0x17;
197831d8c61dSYouMin Chen 		else /* channel b only */
197931d8c61dSYouMin Chen 			stride = 0x18;
198031d8c61dSYouMin Chen 	} else {/* 2 channel */
198131d8c61dSYouMin Chen 		if (ch_cap[0] == ch_cap[1]) {
198231d8c61dSYouMin Chen 			/* interleaved */
198331d8c61dSYouMin Chen 			if (gstride_type == PART_STRIDE) {
198431d8c61dSYouMin Chen 			/*
198531d8c61dSYouMin Chen 			 * first 64MB no interleaved other 256B interleaved
198631d8c61dSYouMin Chen 			 * if 786M+768M.useful space from 0-1280MB and
198731d8c61dSYouMin Chen 			 * 1536MB-1792MB
198831d8c61dSYouMin Chen 			 * if 1.5G+1.5G(continuous).useful space from 0-2560MB
198931d8c61dSYouMin Chen 			 * and 3072MB-3584MB
199031d8c61dSYouMin Chen 			 */
199131d8c61dSYouMin Chen 				stride = 0x1F;
199231d8c61dSYouMin Chen 			} else {
199331d8c61dSYouMin Chen 				switch (cap) {
199431d8c61dSYouMin Chen 				/* 512MB */
199531d8c61dSYouMin Chen 				case 512:
199631d8c61dSYouMin Chen 					stride = 0;
199731d8c61dSYouMin Chen 					break;
199831d8c61dSYouMin Chen 				/* 1GB unstride or 256B stride*/
199931d8c61dSYouMin Chen 				case 1024:
200031d8c61dSYouMin Chen 					stride = (gstride_type == UN_STRIDE) ?
200131d8c61dSYouMin Chen 						0x1 : 0x5;
200231d8c61dSYouMin Chen 					break;
200331d8c61dSYouMin Chen 				/*
200431d8c61dSYouMin Chen 				 * 768MB + 768MB same as total 2GB memory
200531d8c61dSYouMin Chen 				 * useful space: 0-768MB 1GB-1792MB
200631d8c61dSYouMin Chen 				 */
200731d8c61dSYouMin Chen 				case 1536:
200831d8c61dSYouMin Chen 				/* 2GB unstride or 256B or 512B stride */
200931d8c61dSYouMin Chen 				case 2048:
201031d8c61dSYouMin Chen 					stride = (gstride_type == UN_STRIDE) ?
201131d8c61dSYouMin Chen 						0x2 :
201231d8c61dSYouMin Chen 						((gstride_type == STRIDE_512B) ?
201331d8c61dSYouMin Chen 						 0xA : 0x9);
201431d8c61dSYouMin Chen 					break;
201531d8c61dSYouMin Chen 				/* 1536MB + 1536MB */
201631d8c61dSYouMin Chen 				case 3072:
201731d8c61dSYouMin Chen 					stride = (gstride_type == UN_STRIDE) ?
201831d8c61dSYouMin Chen 						0x3 :
201931d8c61dSYouMin Chen 						((gstride_type == STRIDE_512B) ?
202031d8c61dSYouMin Chen 						 0x12 : 0x11);
202131d8c61dSYouMin Chen 					break;
202231d8c61dSYouMin Chen 				/* 4GB  unstride or 128B,256B,512B,4KB stride */
202331d8c61dSYouMin Chen 				case 4096:
202431d8c61dSYouMin Chen 					stride = (gstride_type == UN_STRIDE) ?
202531d8c61dSYouMin Chen 						0x3 : (0xC + gstride_type);
202631d8c61dSYouMin Chen 					break;
202731d8c61dSYouMin Chen 				}
202831d8c61dSYouMin Chen 			}
202931d8c61dSYouMin Chen 		}
203031d8c61dSYouMin Chen 		if (ch_cap[0] == 2048 && ch_cap[1] == 1024) {
203131d8c61dSYouMin Chen 			/* 2GB + 1GB */
203231d8c61dSYouMin Chen 			stride = (gstride_type == UN_STRIDE) ? 0x3 : 0x19;
203331d8c61dSYouMin Chen 		}
203431d8c61dSYouMin Chen 		/*
203531d8c61dSYouMin Chen 		 * remain two channel capability not equal OR capability
203631d8c61dSYouMin Chen 		 * power function of 2
203731d8c61dSYouMin Chen 		 */
203831d8c61dSYouMin Chen 		if (stride == (-1)) {
203931d8c61dSYouMin Chen 			switch ((ch_cap[0] > ch_cap[1]) ?
204031d8c61dSYouMin Chen 				ch_cap[0] : ch_cap[1]) {
204131d8c61dSYouMin Chen 			case 256: /* 256MB + 128MB */
204231d8c61dSYouMin Chen 				stride = 0;
204331d8c61dSYouMin Chen 				break;
204431d8c61dSYouMin Chen 			case 512: /* 512MB + 256MB */
204531d8c61dSYouMin Chen 				stride = 1;
204631d8c61dSYouMin Chen 				break;
204731d8c61dSYouMin Chen 			case 1024:/* 1GB + 128MB/256MB/384MB/512MB/768MB */
204831d8c61dSYouMin Chen 				stride = 2;
204931d8c61dSYouMin Chen 				break;
205031d8c61dSYouMin Chen 			case 2048: /* 2GB + 128MB/256MB/384MB/512MB/768MB/1GB */
205131d8c61dSYouMin Chen 				stride = 3;
205231d8c61dSYouMin Chen 				break;
205331d8c61dSYouMin Chen 			default:
205431d8c61dSYouMin Chen 				break;
205531d8c61dSYouMin Chen 			}
205631d8c61dSYouMin Chen 		}
205731d8c61dSYouMin Chen 		if (stride == (-1))
205831d8c61dSYouMin Chen 			goto error;
205931d8c61dSYouMin Chen 	}
206031d8c61dSYouMin Chen 	switch (stride) {
206131d8c61dSYouMin Chen 	case 0xc:
206231d8c61dSYouMin Chen 		printf("128B stride\n");
206331d8c61dSYouMin Chen 		break;
206431d8c61dSYouMin Chen 	case 5:
206531d8c61dSYouMin Chen 	case 9:
206631d8c61dSYouMin Chen 	case 0xd:
206731d8c61dSYouMin Chen 	case 0x11:
206831d8c61dSYouMin Chen 	case 0x19:
206931d8c61dSYouMin Chen 		printf("256B stride\n");
207031d8c61dSYouMin Chen 		break;
207131d8c61dSYouMin Chen 	case 0xa:
207231d8c61dSYouMin Chen 	case 0xe:
207331d8c61dSYouMin Chen 	case 0x12:
207431d8c61dSYouMin Chen 		printf("512B stride\n");
207531d8c61dSYouMin Chen 		break;
207631d8c61dSYouMin Chen 	case 0xf:
207731d8c61dSYouMin Chen 		printf("4K stride\n");
207831d8c61dSYouMin Chen 		break;
207931d8c61dSYouMin Chen 	case 0x1f:
208031d8c61dSYouMin Chen 		printf("32MB + 256B stride\n");
208131d8c61dSYouMin Chen 		break;
208231d8c61dSYouMin Chen 	default:
208331d8c61dSYouMin Chen 		printf("no stride\n");
208431d8c61dSYouMin Chen 	}
208531d8c61dSYouMin Chen 
208631d8c61dSYouMin Chen 	return stride;
208731d8c61dSYouMin Chen error:
208831d8c61dSYouMin Chen 	printf("Cap not support!\n");
208931d8c61dSYouMin Chen 	return (-1);
209031d8c61dSYouMin Chen }
209131d8c61dSYouMin Chen 
get_ddr_stride(struct rk3399_pmusgrf_regs * pmusgrf)20928b36ec9fSYouMin Chen static u32 get_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf)
20938b36ec9fSYouMin Chen {
20948b36ec9fSYouMin Chen 	u32 val;
20958b36ec9fSYouMin Chen 
20968b36ec9fSYouMin Chen 	val = (readl(&pmusgrf->soc_con4) >> 10) & 0x1F;
20978b36ec9fSYouMin Chen 
20988b36ec9fSYouMin Chen 	return val;
20998b36ec9fSYouMin Chen }
21008b36ec9fSYouMin Chen 
set_ddr_stride(struct rk3399_pmusgrf_regs * pmusgrf,u32 stride)210131d8c61dSYouMin Chen static void set_ddr_stride(struct rk3399_pmusgrf_regs *pmusgrf, u32 stride)
210231d8c61dSYouMin Chen {
210331d8c61dSYouMin Chen 	rk_clrsetreg(&pmusgrf->soc_con4, 0x1f << 10,
210431d8c61dSYouMin Chen 		     stride << 10);
210531d8c61dSYouMin Chen }
210631d8c61dSYouMin Chen 
set_cap_relate_config(const struct chan_info * chan,struct rk3399_sdram_params * sdram_params,unsigned int channel)21078b36ec9fSYouMin Chen static void set_cap_relate_config(const struct chan_info *chan,
210831d8c61dSYouMin Chen 				  struct rk3399_sdram_params *sdram_params,
210931d8c61dSYouMin Chen 				  unsigned int channel)
211031d8c61dSYouMin Chen {
211131d8c61dSYouMin Chen 	u32 *denali_ctl = chan->pctl->denali_ctl;
211231d8c61dSYouMin Chen 	u32 tmp;
211331d8c61dSYouMin Chen 	struct sdram_msch_timings *noc_timing;
211431d8c61dSYouMin Chen 
211531d8c61dSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR3) {
211631d8c61dSYouMin Chen 		tmp = (8 << sdram_params->ch[channel].cap_info.bw) /
211731d8c61dSYouMin Chen 			(8 << sdram_params->ch[channel].cap_info.dbw);
211831d8c61dSYouMin Chen 		/* memdata_ratio
211931d8c61dSYouMin Chen 		 * 1 -> 0, 2 -> 1, 4 -> 2
212031d8c61dSYouMin Chen 		 */
212131d8c61dSYouMin Chen 		clrsetbits_le32(&denali_ctl[197], 0x7,
212231d8c61dSYouMin Chen 				(tmp >> 1));
212331d8c61dSYouMin Chen 		clrsetbits_le32(&denali_ctl[198], 0x7 << 8,
212431d8c61dSYouMin Chen 				(tmp >> 1) << 8);
212531d8c61dSYouMin Chen 	}
212631d8c61dSYouMin Chen 	noc_timing = &sdram_params->ch[channel].noc_timings;
212731d8c61dSYouMin Chen 	/*
212831d8c61dSYouMin Chen 	 * noc timing bw relate timing is 32 bit, and real bw is 16bit
212931d8c61dSYouMin Chen 	 * actually noc reg is setting at function dram_all_config
213031d8c61dSYouMin Chen 	 */
213131d8c61dSYouMin Chen 	if (sdram_params->ch[channel].cap_info.bw == 16 &&
213231d8c61dSYouMin Chen 	    noc_timing->ddrmode.b.mwrsize == 2) {
213331d8c61dSYouMin Chen 		if (noc_timing->ddrmode.b.burstsize)
213431d8c61dSYouMin Chen 			noc_timing->ddrmode.b.burstsize -= 1;
213531d8c61dSYouMin Chen 		noc_timing->ddrmode.b.mwrsize -= 1;
213631d8c61dSYouMin Chen 		noc_timing->ddrtimingc0.b.burstpenalty *= 2;
213731d8c61dSYouMin Chen 		noc_timing->ddrtimingc0.b.wrtomwr *= 2;
213831d8c61dSYouMin Chen 	}
213931d8c61dSYouMin Chen }
214031d8c61dSYouMin Chen 
clear_channel_params(struct rk3399_sdram_params * sdram_params,unsigned int channel)21418b36ec9fSYouMin Chen static void clear_channel_params(struct rk3399_sdram_params *sdram_params,
214231d8c61dSYouMin Chen 				 unsigned int channel)
214331d8c61dSYouMin Chen {
214431d8c61dSYouMin Chen 	sdram_params->ch[channel].cap_info.rank = 0;
214531d8c61dSYouMin Chen 	sdram_params->ch[channel].cap_info.col = 0;
214631d8c61dSYouMin Chen 	sdram_params->ch[channel].cap_info.bk = 0;
214731d8c61dSYouMin Chen 	sdram_params->ch[channel].cap_info.bw = 32;
214831d8c61dSYouMin Chen 	sdram_params->ch[channel].cap_info.dbw = 32;
214931d8c61dSYouMin Chen 	sdram_params->ch[channel].cap_info.row_3_4 = 0;
215031d8c61dSYouMin Chen 	sdram_params->ch[channel].cap_info.cs0_row = 0;
215131d8c61dSYouMin Chen 	sdram_params->ch[channel].cap_info.cs1_row = 0;
215231d8c61dSYouMin Chen 	sdram_params->ch[channel].cap_info.ddrconfig = 0;
215331d8c61dSYouMin Chen }
215431d8c61dSYouMin Chen 
215531d8c61dSYouMin Chen /* CS0,n=1
215631d8c61dSYouMin Chen  * CS1,n=2
215731d8c61dSYouMin Chen  * CS0 & CS1, n=3
215831d8c61dSYouMin Chen  * cs0_cap: MB unit
215931d8c61dSYouMin Chen  */
dram_set_cs(const struct chan_info * chan,u32 cs_map,u32 cs0_cap,unsigned char dramtype)21608b36ec9fSYouMin Chen static void dram_set_cs(const struct chan_info *chan, u32 cs_map, u32 cs0_cap,
216131d8c61dSYouMin Chen 			unsigned char dramtype)
216231d8c61dSYouMin Chen {
216331d8c61dSYouMin Chen 	u32 *denali_ctl = chan->pctl->denali_ctl;
216431d8c61dSYouMin Chen 	u32 *denali_pi = chan->pi->denali_pi;
216531d8c61dSYouMin Chen 	struct msch_regs *ddr_msch_regs = chan->msch;
216631d8c61dSYouMin Chen 
216731d8c61dSYouMin Chen 	clrsetbits_le32(&denali_ctl[196], 0x3, cs_map);
216831d8c61dSYouMin Chen 	writel((cs0_cap / 32) | (((4096 - cs0_cap) / 32) << 8),
216931d8c61dSYouMin Chen 	       &ddr_msch_regs->ddrsize);
217031d8c61dSYouMin Chen 	if (dramtype == LPDDR4) {
217131d8c61dSYouMin Chen 		if (cs_map == 1)
217231d8c61dSYouMin Chen 			cs_map = 0x5;
217331d8c61dSYouMin Chen 		else if (cs_map == 2)
217431d8c61dSYouMin Chen 			cs_map = 0xa;
217531d8c61dSYouMin Chen 		else
217631d8c61dSYouMin Chen 			cs_map = 0xF;
217731d8c61dSYouMin Chen 	}
217831d8c61dSYouMin Chen 	/*PI_41 PI_CS_MAP:RW:24:4*/
217931d8c61dSYouMin Chen 	clrsetbits_le32(&denali_pi[41],
218031d8c61dSYouMin Chen 			0xf << 24, cs_map << 24);
218131d8c61dSYouMin Chen 	if (cs_map == 1 && dramtype == DDR3)
218231d8c61dSYouMin Chen 		writel(0x2EC7FFFF, &denali_pi[34]);
218331d8c61dSYouMin Chen }
218431d8c61dSYouMin Chen 
dram_set_bw(const struct chan_info * chan,u32 bw)21858b36ec9fSYouMin Chen static void dram_set_bw(const struct chan_info *chan, u32 bw)
218631d8c61dSYouMin Chen {
218731d8c61dSYouMin Chen 	u32 *denali_ctl = chan->pctl->denali_ctl;
218831d8c61dSYouMin Chen 
218931d8c61dSYouMin Chen 	if (bw == 2)
219031d8c61dSYouMin Chen 		clrbits_le32(&denali_ctl[196], 1 << 16);
219131d8c61dSYouMin Chen 	else
219231d8c61dSYouMin Chen 		setbits_le32(&denali_ctl[196], 1 << 16);
219331d8c61dSYouMin Chen }
219431d8c61dSYouMin Chen 
dram_set_max_col(const struct chan_info * chan,u32 bw,u32 * pcol)21958b36ec9fSYouMin Chen static void dram_set_max_col(const struct chan_info *chan, u32 bw, u32 *pcol)
219631d8c61dSYouMin Chen {
219731d8c61dSYouMin Chen 	u32 *denali_ctl = chan->pctl->denali_ctl;
219831d8c61dSYouMin Chen 	struct msch_regs *ddr_msch_regs = chan->msch;
219931d8c61dSYouMin Chen 	u32 *denali_pi = chan->pi->denali_pi;
220031d8c61dSYouMin Chen 	u32 ddrconfig;
220131d8c61dSYouMin Chen 
220231d8c61dSYouMin Chen 	clrbits_le32(&denali_ctl[191], 0xf);
220331d8c61dSYouMin Chen 	clrsetbits_le32(&denali_ctl[190],
220431d8c61dSYouMin Chen 			(7 << 24),
220531d8c61dSYouMin Chen 			((16 - ((bw == 2) ? 14 : 15)) << 24));
220631d8c61dSYouMin Chen 	/*PI_199 PI_COL_DIFF:RW:0:4*/
220731d8c61dSYouMin Chen 	clrbits_le32(&denali_pi[199], 0xf);
220831d8c61dSYouMin Chen 	/*PI_155 PI_ROW_DIFF:RW:24:3*/
220931d8c61dSYouMin Chen 	clrsetbits_le32(&denali_pi[155],
221031d8c61dSYouMin Chen 			(7 << 24),
221131d8c61dSYouMin Chen 			((16 - 12) << 24));
221231d8c61dSYouMin Chen 	ddrconfig = (bw == 2) ? 3 : 2;
221331d8c61dSYouMin Chen 	writel(ddrconfig | (ddrconfig << 8), &ddr_msch_regs->ddrconf);
221431d8c61dSYouMin Chen 	/* set max cs0 size */
221531d8c61dSYouMin Chen 	writel((4096 / 32) | ((0 / 32) << 8),
221631d8c61dSYouMin Chen 	       &ddr_msch_regs->ddrsize);
221731d8c61dSYouMin Chen 
221831d8c61dSYouMin Chen 	*pcol = 12;
221931d8c61dSYouMin Chen }
222031d8c61dSYouMin Chen 
dram_set_max_bank(const struct chan_info * chan,u32 bw,u32 * pbank,u32 * pcol)22218b36ec9fSYouMin Chen static void dram_set_max_bank(const struct chan_info *chan, u32 bw, u32 *pbank,
222231d8c61dSYouMin Chen 			      u32 *pcol)
222331d8c61dSYouMin Chen {
222431d8c61dSYouMin Chen 	u32 *denali_ctl = chan->pctl->denali_ctl;
222531d8c61dSYouMin Chen 	u32 *denali_pi = chan->pi->denali_pi;
222631d8c61dSYouMin Chen 
222731d8c61dSYouMin Chen 	clrbits_le32(&denali_ctl[191], 0xf);
222831d8c61dSYouMin Chen 	clrbits_le32(&denali_ctl[190], (3 << 16));
222931d8c61dSYouMin Chen 	/*PI_199 PI_COL_DIFF:RW:0:4*/
223031d8c61dSYouMin Chen 	clrbits_le32(&denali_pi[199], 0xf);
223131d8c61dSYouMin Chen 	/*PI_155 PI_BANK_DIFF:RW:16:2*/
223231d8c61dSYouMin Chen 	clrbits_le32(&denali_pi[155], (3 << 16));
223331d8c61dSYouMin Chen 
223431d8c61dSYouMin Chen 	*pbank = 3;
223531d8c61dSYouMin Chen 	*pcol = 12;
223631d8c61dSYouMin Chen }
223731d8c61dSYouMin Chen 
dram_set_max_row(const struct chan_info * chan,u32 bw,u32 * prow,u32 * pbank,u32 * pcol)22388b36ec9fSYouMin Chen static void dram_set_max_row(const struct chan_info *chan, u32 bw, u32 *prow,
223931d8c61dSYouMin Chen 			     u32 *pbank, u32 *pcol)
224031d8c61dSYouMin Chen {
224131d8c61dSYouMin Chen 	u32 *denali_ctl = chan->pctl->denali_ctl;
224231d8c61dSYouMin Chen 	u32 *denali_pi = chan->pi->denali_pi;
224331d8c61dSYouMin Chen 	struct msch_regs *ddr_msch_regs = chan->msch;
224431d8c61dSYouMin Chen 
224531d8c61dSYouMin Chen 	clrsetbits_le32(&denali_ctl[191], 0xf, 12 - 10);
224631d8c61dSYouMin Chen 	clrbits_le32(&denali_ctl[190],
224731d8c61dSYouMin Chen 		     (0x3 << 16) | (0x7 << 24));
224831d8c61dSYouMin Chen 	/*PI_199 PI_COL_DIFF:RW:0:4*/
224931d8c61dSYouMin Chen 	clrsetbits_le32(&denali_pi[199], 0xf, 12 - 10);
225031d8c61dSYouMin Chen 	/*PI_155 PI_ROW_DIFF:RW:24:3 PI_BANK_DIFF:RW:16:2*/
225131d8c61dSYouMin Chen 	clrbits_le32(&denali_pi[155],
225231d8c61dSYouMin Chen 		     (0x3 << 16) | (0x7 << 24));
225331d8c61dSYouMin Chen 	writel(1 | (1 << 8), &ddr_msch_regs->ddrconf);
225431d8c61dSYouMin Chen 	/* set max cs0 size */
225531d8c61dSYouMin Chen 	writel((4096 / 32) | ((0 / 32) << 8),
225631d8c61dSYouMin Chen 	       &ddr_msch_regs->ddrsize);
225731d8c61dSYouMin Chen 
225831d8c61dSYouMin Chen 	*prow = 16;
225931d8c61dSYouMin Chen 	*pbank = 3;
226031d8c61dSYouMin Chen 	*pcol = (bw == 2) ? 10 : 11;
226131d8c61dSYouMin Chen }
226231d8c61dSYouMin Chen 
dram_detect_cap(struct dram_info * dram,struct rk3399_sdram_params * sdram_params,unsigned char channel)226331d8c61dSYouMin Chen static u64 dram_detect_cap(struct dram_info *dram,
226431d8c61dSYouMin Chen 			   struct rk3399_sdram_params *sdram_params,
226531d8c61dSYouMin Chen 			   unsigned char channel)
226631d8c61dSYouMin Chen {
226731d8c61dSYouMin Chen 	const struct chan_info *chan = &dram->chan[channel];
226831d8c61dSYouMin Chen 	struct sdram_cap_info *cap_info = &sdram_params->ch[channel].cap_info;
226931d8c61dSYouMin Chen 	u32 bw;
227031d8c61dSYouMin Chen 	u32 col_tmp;
227131d8c61dSYouMin Chen 	u32 bk_tmp;
227231d8c61dSYouMin Chen 	u32 row_tmp;
227331d8c61dSYouMin Chen 	u32 cs0_cap;
227431d8c61dSYouMin Chen 	u32 training_flag;
227531d8c61dSYouMin Chen 	u32 ddrconfig;
227631d8c61dSYouMin Chen 
227731d8c61dSYouMin Chen 	/* detect bw */
227831d8c61dSYouMin Chen 	bw = 2;
22798b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype != LPDDR4) {
228031d8c61dSYouMin Chen 		dram_set_bw(chan, bw);
228131d8c61dSYouMin Chen 		cap_info->bw = bw;
22828b36ec9fSYouMin Chen 		if (data_training(chan, channel, sdram_params,
22838b36ec9fSYouMin Chen 				  PI_READ_GATE_TRAINING)) {
228431d8c61dSYouMin Chen 			bw = 1;
228531d8c61dSYouMin Chen 			dram_set_bw(chan, 1);
228631d8c61dSYouMin Chen 			cap_info->bw = bw;
228731d8c61dSYouMin Chen 			if (data_training(chan, channel, sdram_params,
228831d8c61dSYouMin Chen 					  PI_READ_GATE_TRAINING)) {
228931d8c61dSYouMin Chen 				printf("16bit error!!!\n");
229031d8c61dSYouMin Chen 				goto error;
229131d8c61dSYouMin Chen 			}
229231d8c61dSYouMin Chen 		}
22938b36ec9fSYouMin Chen 	}
229431d8c61dSYouMin Chen 	/*
229531d8c61dSYouMin Chen 	 * LPDDR3 CA training msut be trigger before other training.
229631d8c61dSYouMin Chen 	 * DDR3 is not have CA training.
229731d8c61dSYouMin Chen 	 */
229831d8c61dSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR3)
229931d8c61dSYouMin Chen 		training_flag = PI_WRITE_LEVELING;
230031d8c61dSYouMin Chen 	else
230131d8c61dSYouMin Chen 		training_flag = PI_FULL_TRAINING;
230231d8c61dSYouMin Chen 
230331d8c61dSYouMin Chen 	if (sdram_params->base.dramtype != LPDDR4) {
230431d8c61dSYouMin Chen 		if (data_training(chan, channel, sdram_params, training_flag)) {
230531d8c61dSYouMin Chen 			printf("full training error!!!\n");
230631d8c61dSYouMin Chen 			goto error;
230731d8c61dSYouMin Chen 		}
230831d8c61dSYouMin Chen 	}
230931d8c61dSYouMin Chen 
231031d8c61dSYouMin Chen 	/* detect col */
231131d8c61dSYouMin Chen 	dram_set_max_col(chan, bw, &col_tmp);
231231d8c61dSYouMin Chen 	if (sdram_detect_col(cap_info, col_tmp) != 0)
231331d8c61dSYouMin Chen 		goto error;
231431d8c61dSYouMin Chen 
231531d8c61dSYouMin Chen 	/* detect bank */
231631d8c61dSYouMin Chen 	dram_set_max_bank(chan, bw, &bk_tmp, &col_tmp);
2317*e1652d39SZhihuan He 	sdram_detect_bank(cap_info, chan->pctl, col_tmp, bk_tmp);
231831d8c61dSYouMin Chen 
231931d8c61dSYouMin Chen 	/* detect row */
232031d8c61dSYouMin Chen 	dram_set_max_row(chan, bw, &row_tmp, &bk_tmp, &col_tmp);
232131d8c61dSYouMin Chen 	if (sdram_detect_row(cap_info, col_tmp, bk_tmp, row_tmp) != 0)
232231d8c61dSYouMin Chen 		goto error;
232331d8c61dSYouMin Chen 
232431d8c61dSYouMin Chen 	/* detect row_3_4 */
232531d8c61dSYouMin Chen 	sdram_detect_row_3_4(cap_info, col_tmp, bk_tmp);
232631d8c61dSYouMin Chen 
232731d8c61dSYouMin Chen 	/* set ddrconfig */
232831d8c61dSYouMin Chen 	cs0_cap = (1 << (cap_info->cs0_row + cap_info->col + cap_info->bk +
232931d8c61dSYouMin Chen 			 cap_info->bw - 20));
233031d8c61dSYouMin Chen 	if (cap_info->row_3_4)
233131d8c61dSYouMin Chen 		cs0_cap = cs0_cap * 3 / 4;
233231d8c61dSYouMin Chen 
233331d8c61dSYouMin Chen 	cap_info->cs1_row = cap_info->cs0_row;
233431d8c61dSYouMin Chen 	set_memory_map(chan, channel, sdram_params);
233531d8c61dSYouMin Chen 	ddrconfig = calculate_ddrconfig(sdram_params, channel);
233631d8c61dSYouMin Chen 	if (-1 == ddrconfig)
233731d8c61dSYouMin Chen 		goto error;
233831d8c61dSYouMin Chen 	set_ddrconfig(chan, sdram_params, channel,
233931d8c61dSYouMin Chen 		      cap_info->ddrconfig);
234031d8c61dSYouMin Chen 
234131d8c61dSYouMin Chen 	/* detect cs1 row */
234231d8c61dSYouMin Chen 	sdram_detect_cs1_row(cap_info, sdram_params->base.dramtype);
234331d8c61dSYouMin Chen 
234431d8c61dSYouMin Chen 	/* detect die bw */
234531d8c61dSYouMin Chen 	sdram_detect_dbw(cap_info, sdram_params->base.dramtype);
234631d8c61dSYouMin Chen 
234731d8c61dSYouMin Chen 	return 0;
234831d8c61dSYouMin Chen error:
234931d8c61dSYouMin Chen 	return (-1);
235031d8c61dSYouMin Chen }
235131d8c61dSYouMin Chen 
23528b36ec9fSYouMin Chen /* read mr_num mode register
23538b36ec9fSYouMin Chen  * input: rank = 1: cs0, rank = 2: cs1
23548b36ec9fSYouMin Chen  *        mr_num: mode register number
23558b36ec9fSYouMin Chen  * output: buf
23568b36ec9fSYouMin Chen  */
read_mr(struct rk3399_ddr_pctl_regs * ddr_pctl_regs,u32 rank,u32 mr_num,u32 * buf)23578b36ec9fSYouMin Chen static int read_mr(struct rk3399_ddr_pctl_regs *ddr_pctl_regs, u32 rank,
23588b36ec9fSYouMin Chen 		   u32 mr_num, u32 *buf)
23598b36ec9fSYouMin Chen {
23608b36ec9fSYouMin Chen 	s32 timeout = 100;
23618b36ec9fSYouMin Chen 
23628b36ec9fSYouMin Chen 	writel(((1 << 16) |
23638b36ec9fSYouMin Chen 			(((rank == 2) ? 1 : 0) << 8) |
23648b36ec9fSYouMin Chen 			mr_num) << 8,
23658b36ec9fSYouMin Chen 			&ddr_pctl_regs->denali_ctl[118]);
23668b36ec9fSYouMin Chen 	while (0 == (readl(&ddr_pctl_regs->denali_ctl[203]) &
23678b36ec9fSYouMin Chen 			((1 << 21) | (1 << 12)))) {
23688b36ec9fSYouMin Chen 		udelay(1);
23698b36ec9fSYouMin Chen 		if (timeout <= 0)
23708b36ec9fSYouMin Chen 			goto error;
23718b36ec9fSYouMin Chen 		timeout--;
23728b36ec9fSYouMin Chen 	}
23738b36ec9fSYouMin Chen 	if (!(readl(&ddr_pctl_regs->denali_ctl[203]) & (1 << 12))) {
23748b36ec9fSYouMin Chen 		*buf = readl(&ddr_pctl_regs->denali_ctl[119]) & 0xFF;
23758b36ec9fSYouMin Chen 	} else {
23768b36ec9fSYouMin Chen 		printf("read mr error\n");
23778b36ec9fSYouMin Chen 		printf("MRR_ERROR_STATUS = 0x%x\n",
23788b36ec9fSYouMin Chen 		       readl(&ddr_pctl_regs->denali_ctl[17]) & 0x3);
23798b36ec9fSYouMin Chen 		*buf = 0;
23808b36ec9fSYouMin Chen 	}
23818b36ec9fSYouMin Chen 	setbits_le32(&ddr_pctl_regs->denali_ctl[205], (1 << 21) | (1 << 12));
23828b36ec9fSYouMin Chen 	return 0;
23838b36ec9fSYouMin Chen error:
23848b36ec9fSYouMin Chen 	return (-1);
23858b36ec9fSYouMin Chen }
23868b36ec9fSYouMin Chen 
read_mr_for_detect(struct dram_info * dram,u32 channel,u32 rank,struct rk3399_sdram_params * sdram_params)23878b36ec9fSYouMin Chen static int read_mr_for_detect(struct dram_info *dram, u32 channel, u32 rank,
23888b36ec9fSYouMin Chen 			      struct rk3399_sdram_params *sdram_params)
23898b36ec9fSYouMin Chen {
23908b36ec9fSYouMin Chen 	u64 cs0_cap;
23918b36ec9fSYouMin Chen 	u32 stride;
23928b36ec9fSYouMin Chen 	u32 cs = 0, col = 0, bk = 0, bw = 0, row_3_4 = 0;
23938b36ec9fSYouMin Chen 	u32 cs0_row = 0, cs1_row = 0, ddrconfig = 0;
23948b36ec9fSYouMin Chen 	u32 mr5, mr12, mr14;
23958b36ec9fSYouMin Chen 	struct chan_info *chan =
23968b36ec9fSYouMin Chen 		&dram->chan[channel];
23978b36ec9fSYouMin Chen 	struct rk3399_ddr_pctl_regs *ddr_pctl_regs = chan->pctl;
23988b36ec9fSYouMin Chen 	int ret = 0;
23998b36ec9fSYouMin Chen 	u32 val;
24008b36ec9fSYouMin Chen 	void __iomem *addr = NULL;
24018b36ec9fSYouMin Chen 
24028b36ec9fSYouMin Chen 	stride = get_ddr_stride(dram->pmusgrf);
24038b36ec9fSYouMin Chen 
24048b36ec9fSYouMin Chen 	if (sdram_params->ch[channel].cap_info.col == 0) {
24058b36ec9fSYouMin Chen 		ret = -1;
24068b36ec9fSYouMin Chen 		goto end;
24078b36ec9fSYouMin Chen 	}
24088b36ec9fSYouMin Chen 
24098b36ec9fSYouMin Chen 	cs = sdram_params->ch[channel].cap_info.rank;
24108b36ec9fSYouMin Chen 	col = sdram_params->ch[channel].cap_info.col;
24118b36ec9fSYouMin Chen 	bk = sdram_params->ch[channel].cap_info.bk;
24128b36ec9fSYouMin Chen 	bw = sdram_params->ch[channel].cap_info.bw;
24138b36ec9fSYouMin Chen 	row_3_4 = sdram_params->ch[channel].cap_info.row_3_4;
24148b36ec9fSYouMin Chen 	cs0_row = sdram_params->ch[channel].cap_info.cs0_row;
24158b36ec9fSYouMin Chen 	cs1_row = sdram_params->ch[channel].cap_info.cs1_row;
24168b36ec9fSYouMin Chen 	ddrconfig = sdram_params->ch[channel].cap_info.ddrconfig;
24178b36ec9fSYouMin Chen 
24188b36ec9fSYouMin Chen 	/* 2GB */
24198b36ec9fSYouMin Chen 	sdram_params->ch[channel].cap_info.rank = 2;
24208b36ec9fSYouMin Chen 	sdram_params->ch[channel].cap_info.col = 10;
24218b36ec9fSYouMin Chen 	sdram_params->ch[channel].cap_info.bk = 3;
24228b36ec9fSYouMin Chen 	sdram_params->ch[channel].cap_info.bw = 2;
24238b36ec9fSYouMin Chen 	sdram_params->ch[channel].cap_info.row_3_4 = 0;
24248b36ec9fSYouMin Chen 	sdram_params->ch[channel].cap_info.cs0_row = 15;
24258b36ec9fSYouMin Chen 	sdram_params->ch[channel].cap_info.cs1_row = 15;
24268b36ec9fSYouMin Chen 	sdram_params->ch[channel].cap_info.ddrconfig = 1;
24278b36ec9fSYouMin Chen 
24288b36ec9fSYouMin Chen 	set_memory_map(chan, channel, sdram_params);
24298b36ec9fSYouMin Chen 	sdram_params->ch[channel].cap_info.ddrconfig =
24308b36ec9fSYouMin Chen 			calculate_ddrconfig(sdram_params, channel);
24318b36ec9fSYouMin Chen 	set_ddrconfig(chan, sdram_params, channel,
24328b36ec9fSYouMin Chen 		      sdram_params->ch[channel].cap_info.ddrconfig);
24338b36ec9fSYouMin Chen 	set_cap_relate_config(chan, sdram_params, channel);
24348b36ec9fSYouMin Chen 
24358b36ec9fSYouMin Chen 	cs0_cap = (1 << (sdram_params->ch[channel].cap_info.bw
24368b36ec9fSYouMin Chen 			+ sdram_params->ch[channel].cap_info.col
24378b36ec9fSYouMin Chen 			+ sdram_params->ch[channel].cap_info.bk
24388b36ec9fSYouMin Chen 			+ sdram_params->ch[channel].cap_info.cs0_row));
24398b36ec9fSYouMin Chen 
24408b36ec9fSYouMin Chen 	if (sdram_params->ch[channel].cap_info.row_3_4)
24418b36ec9fSYouMin Chen 		cs0_cap = cs0_cap * 3 / 4;
24428b36ec9fSYouMin Chen 
24438b36ec9fSYouMin Chen 	if (channel == 0)
24448b36ec9fSYouMin Chen 		set_ddr_stride(dram->pmusgrf, 0x17);
24458b36ec9fSYouMin Chen 	else
24468b36ec9fSYouMin Chen 		set_ddr_stride(dram->pmusgrf, 0x18);
24478b36ec9fSYouMin Chen 
24488b36ec9fSYouMin Chen 	/* !will soiled DRAM space here!
24498b36ec9fSYouMin Chen 	 * read and write data to DRAM, avoid be optimized by compiler.
24508b36ec9fSYouMin Chen 	 */
24518b36ec9fSYouMin Chen 	if (rank == 1)
24528b36ec9fSYouMin Chen 		addr = (void __iomem *)0x100;
24538b36ec9fSYouMin Chen 	else if (rank == 2)
24548b36ec9fSYouMin Chen 		addr = (void __iomem *)(cs0_cap + 0x100);
24558b36ec9fSYouMin Chen 
24568b36ec9fSYouMin Chen 	val = readl(addr);
24578b36ec9fSYouMin Chen 	writel(val + 1, addr);
24588b36ec9fSYouMin Chen 
24598b36ec9fSYouMin Chen 	read_mr(ddr_pctl_regs, rank, 5, &mr5);
24608b36ec9fSYouMin Chen 	read_mr(ddr_pctl_regs, rank, 12, &mr12);
24618b36ec9fSYouMin Chen 	read_mr(ddr_pctl_regs, rank, 14, &mr14);
24628b36ec9fSYouMin Chen 
24638b36ec9fSYouMin Chen 	if (mr5 == 0 || mr12 != 0x4d || mr14 != 0x4d) {
24648b36ec9fSYouMin Chen 		ret = -1;
24658b36ec9fSYouMin Chen 		goto end;
24668b36ec9fSYouMin Chen 	}
24678b36ec9fSYouMin Chen end:
24688b36ec9fSYouMin Chen 	sdram_params->ch[channel].cap_info.rank = cs;
24698b36ec9fSYouMin Chen 	sdram_params->ch[channel].cap_info.col = col;
24708b36ec9fSYouMin Chen 	sdram_params->ch[channel].cap_info.bk = bk;
24718b36ec9fSYouMin Chen 	sdram_params->ch[channel].cap_info.bw = bw;
24728b36ec9fSYouMin Chen 	sdram_params->ch[channel].cap_info.row_3_4 = row_3_4;
24738b36ec9fSYouMin Chen 	sdram_params->ch[channel].cap_info.cs0_row = cs0_row;
24748b36ec9fSYouMin Chen 	sdram_params->ch[channel].cap_info.cs1_row = cs1_row;
24758b36ec9fSYouMin Chen 	sdram_params->ch[channel].cap_info.ddrconfig = ddrconfig;
24768b36ec9fSYouMin Chen 
24778b36ec9fSYouMin Chen 	set_ddr_stride(dram->pmusgrf, stride);
24788b36ec9fSYouMin Chen 	return ret;
24798b36ec9fSYouMin Chen }
24808b36ec9fSYouMin Chen 
get_phy_fn(struct rk3399_sdram_params * sdram_params,u32 ctl_fn)24818b36ec9fSYouMin Chen static u32 get_phy_fn(struct rk3399_sdram_params *sdram_params, u32 ctl_fn)
24828b36ec9fSYouMin Chen {
24838b36ec9fSYouMin Chen 	u32 lp4_phy_fn[] = {1, 0, 0xb};
24848b36ec9fSYouMin Chen 
24858b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4)
24868b36ec9fSYouMin Chen 		return lp4_phy_fn[ctl_fn];
24878b36ec9fSYouMin Chen 	else
24888b36ec9fSYouMin Chen 		return ctl_fn;
24898b36ec9fSYouMin Chen }
24908b36ec9fSYouMin Chen 
get_ctl_fn(struct rk3399_sdram_params * sdram_params,u32 phy_fn)24918b36ec9fSYouMin Chen static u32 get_ctl_fn(struct rk3399_sdram_params *sdram_params, u32 phy_fn)
24928b36ec9fSYouMin Chen {
24938b36ec9fSYouMin Chen 	u32 lp4_ctl_fn[] = {1, 0, 2};
24948b36ec9fSYouMin Chen 
24958b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4)
24968b36ec9fSYouMin Chen 		return lp4_ctl_fn[phy_fn];
24978b36ec9fSYouMin Chen 	else
24988b36ec9fSYouMin Chen 		return phy_fn;
24998b36ec9fSYouMin Chen }
25008b36ec9fSYouMin Chen 
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)25018b36ec9fSYouMin Chen static void dram_copy_phy_fn(struct dram_info *dram,
25028b36ec9fSYouMin Chen 			     struct rk3399_sdram_params *sdram_params, u32 fn,
25038b36ec9fSYouMin Chen 			     struct rk3399_sdram_params *f1_sdram_params,
25048b36ec9fSYouMin Chen 			     u32 channel)
25058b36ec9fSYouMin Chen {
25068b36ec9fSYouMin Chen 	u32 *denali_ctl;
25078b36ec9fSYouMin Chen 	u32 *denali_phy;
25088b36ec9fSYouMin Chen 	u32 *denali_phy_params;
25098b36ec9fSYouMin Chen 	u32 speed = 0;
25108b36ec9fSYouMin Chen 	u32 mr5;
25118b36ec9fSYouMin Chen 	u32 ctl_fn;
25128b36ec9fSYouMin Chen 
25138b36ec9fSYouMin Chen 	denali_ctl = dram->chan[channel].pctl->denali_ctl;
25148b36ec9fSYouMin Chen 	denali_phy = dram->chan[channel].publ->denali_phy;
25158b36ec9fSYouMin Chen 	denali_phy_params = f1_sdram_params->phy_regs.denali_phy;
25168b36ec9fSYouMin Chen 
25178b36ec9fSYouMin Chen 	/* switch index */
25188b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy_params[896], 0x3 << 8,
25198b36ec9fSYouMin Chen 			fn << 8);
25208b36ec9fSYouMin Chen 	writel(denali_phy_params[896], &denali_phy[896]);
25218b36ec9fSYouMin Chen 
25228b36ec9fSYouMin Chen 	/* phy_pll_ctrl_ca, phy_pll_ctrl */
25238b36ec9fSYouMin Chen 	writel(denali_phy_params[911], &denali_phy[911]);
25248b36ec9fSYouMin Chen 	/* phy_low_freq_sel */
25258b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[913], 0x1,
25268b36ec9fSYouMin Chen 			denali_phy_params[913] & 0x1);
25278b36ec9fSYouMin Chen 	/* PHY_GRP_SLAVE_DELAY_X, phy_cslvl_dly_step */
25288b36ec9fSYouMin Chen 	writel(denali_phy_params[916], &denali_phy[916]);
25298b36ec9fSYouMin Chen 	writel(denali_phy_params[917], &denali_phy[917]);
25308b36ec9fSYouMin Chen 	writel(denali_phy_params[918], &denali_phy[918]);
25318b36ec9fSYouMin Chen 	/* phy_adrZ_sw_wraddr_shift_X  */
25328b36ec9fSYouMin Chen 	writel(denali_phy_params[512], &denali_phy[512]);
25338b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[513], 0xFFFF,
25348b36ec9fSYouMin Chen 			denali_phy_params[513] & 0xFFFF);
25358b36ec9fSYouMin Chen 	writel(denali_phy_params[640], &denali_phy[640]);
25368b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[641], 0xFFFF,
25378b36ec9fSYouMin Chen 			denali_phy_params[641] & 0xFFFF);
25388b36ec9fSYouMin Chen 	writel(denali_phy_params[768], &denali_phy[768]);
25398b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[769], 0xFFFF,
25408b36ec9fSYouMin Chen 			denali_phy_params[769] & 0xFFFF);
25418b36ec9fSYouMin Chen 
25428b36ec9fSYouMin Chen 	writel(denali_phy_params[544], &denali_phy[544]);
25438b36ec9fSYouMin Chen 	writel(denali_phy_params[545], &denali_phy[545]);
25448b36ec9fSYouMin Chen 	writel(denali_phy_params[546], &denali_phy[546]);
25458b36ec9fSYouMin Chen 	writel(denali_phy_params[547], &denali_phy[547]);
25468b36ec9fSYouMin Chen 
25478b36ec9fSYouMin Chen 	writel(denali_phy_params[672], &denali_phy[672]);
25488b36ec9fSYouMin Chen 	writel(denali_phy_params[673], &denali_phy[673]);
25498b36ec9fSYouMin Chen 	writel(denali_phy_params[674], &denali_phy[674]);
25508b36ec9fSYouMin Chen 	writel(denali_phy_params[675], &denali_phy[675]);
25518b36ec9fSYouMin Chen 
25528b36ec9fSYouMin Chen 	writel(denali_phy_params[800], &denali_phy[800]);
25538b36ec9fSYouMin Chen 	writel(denali_phy_params[801], &denali_phy[801]);
25548b36ec9fSYouMin Chen 	writel(denali_phy_params[802], &denali_phy[802]);
25558b36ec9fSYouMin Chen 	writel(denali_phy_params[803], &denali_phy[803]);
25568b36ec9fSYouMin Chen 
25578b36ec9fSYouMin Chen 	/*
25588b36ec9fSYouMin Chen 	 * phy_adr_master_delay_start_X
25598b36ec9fSYouMin Chen 	 * phy_adr_master_delay_step_X
25608b36ec9fSYouMin Chen 	 * phy_adr_master_delay_wait_X
25618b36ec9fSYouMin Chen 	 */
25628b36ec9fSYouMin Chen 	writel(denali_phy_params[548], &denali_phy[548]);
25638b36ec9fSYouMin Chen 	writel(denali_phy_params[676], &denali_phy[676]);
25648b36ec9fSYouMin Chen 	writel(denali_phy_params[804], &denali_phy[804]);
25658b36ec9fSYouMin Chen 
25668b36ec9fSYouMin Chen 	/* phy_adr_calvl_dly_step_X */
25678b36ec9fSYouMin Chen 	writel(denali_phy_params[549], &denali_phy[549]);
25688b36ec9fSYouMin Chen 	writel(denali_phy_params[677], &denali_phy[677]);
25698b36ec9fSYouMin Chen 	writel(denali_phy_params[805], &denali_phy[805]);
25708b36ec9fSYouMin Chen 
25718b36ec9fSYouMin Chen 	/*
25728b36ec9fSYouMin Chen 	 * phy_clk_wrdm_slave_delay_X
25738b36ec9fSYouMin Chen 	 * phy_clk_wrdqZ_slave_delay_X
25748b36ec9fSYouMin Chen 	 * phy_clk_wrdqs_slave_delay_X
25758b36ec9fSYouMin Chen 	 */
25768b36ec9fSYouMin Chen 	sdram_copy_to_reg((u32 *)&denali_phy[59],
25778b36ec9fSYouMin Chen 			  (u32 *)&denali_phy_params[59],
25788b36ec9fSYouMin Chen 			  (63 - 58) * 4);
25798b36ec9fSYouMin Chen 	sdram_copy_to_reg((u32 *)&denali_phy[187],
25808b36ec9fSYouMin Chen 			  (u32 *)&denali_phy_params[187],
25818b36ec9fSYouMin Chen 			  (191 - 186) * 4);
25828b36ec9fSYouMin Chen 	sdram_copy_to_reg((u32 *)&denali_phy[315],
25838b36ec9fSYouMin Chen 			  (u32 *)&denali_phy_params[315],
25848b36ec9fSYouMin Chen 			  (319 - 314) * 4);
25858b36ec9fSYouMin Chen 	sdram_copy_to_reg((u32 *)&denali_phy[443],
25868b36ec9fSYouMin Chen 			  (u32 *)&denali_phy_params[443],
25878b36ec9fSYouMin Chen 			  (447 - 442) * 4);
25888b36ec9fSYouMin Chen 
25898b36ec9fSYouMin Chen 	/*
25908b36ec9fSYouMin Chen 	 * phy_dqs_tsel_wr_timing_X 8bits DENALI_PHY_84/212/340/468 offset_8
25918b36ec9fSYouMin Chen 	 * dqs_tsel_wr_end[7:4] add Half cycle
25928b36ec9fSYouMin Chen 	 * phy_dq_tsel_wr_timing_X 8bits DENALI_PHY_83/211/339/467 offset_8
25938b36ec9fSYouMin Chen 	 * dq_tsel_wr_end[7:4] add Half cycle
25948b36ec9fSYouMin Chen 	 */
25958b36ec9fSYouMin Chen 	writel(denali_phy_params[83] + (0x10 << 16), &denali_phy[83]);
25968b36ec9fSYouMin Chen 	writel(denali_phy_params[84] + (0x10 << 8), &denali_phy[84]);
25978b36ec9fSYouMin Chen 	writel(denali_phy_params[85], &denali_phy[85]);
25988b36ec9fSYouMin Chen 
25998b36ec9fSYouMin Chen 	writel(denali_phy_params[211] + (0x10 << 16), &denali_phy[211]);
26008b36ec9fSYouMin Chen 	writel(denali_phy_params[212] + (0x10 << 8), &denali_phy[212]);
26018b36ec9fSYouMin Chen 	writel(denali_phy_params[213], &denali_phy[213]);
26028b36ec9fSYouMin Chen 
26038b36ec9fSYouMin Chen 	writel(denali_phy_params[339] + (0x10 << 16), &denali_phy[339]);
26048b36ec9fSYouMin Chen 	writel(denali_phy_params[340] + (0x10 << 8), &denali_phy[340]);
26058b36ec9fSYouMin Chen 	writel(denali_phy_params[341], &denali_phy[341]);
26068b36ec9fSYouMin Chen 
26078b36ec9fSYouMin Chen 	writel(denali_phy_params[467] + (0x10 << 16), &denali_phy[467]);
26088b36ec9fSYouMin Chen 	writel(denali_phy_params[468] + (0x10 << 8), &denali_phy[468]);
26098b36ec9fSYouMin Chen 	writel(denali_phy_params[469], &denali_phy[469]);
26108b36ec9fSYouMin Chen 
26118b36ec9fSYouMin Chen 	/*
26128b36ec9fSYouMin Chen 	 * phy_gtlvl_resp_wait_cnt_X
26138b36ec9fSYouMin Chen 	 * phy_gtlvl_dly_step_X
26148b36ec9fSYouMin Chen 	 * phy_wrlvl_resp_wait_cnt_X
26158b36ec9fSYouMin Chen 	 * phy_gtlvl_final_step_X
26168b36ec9fSYouMin Chen 	 * phy_gtlvl_back_step_X
26178b36ec9fSYouMin Chen 	 * phy_rdlvl_dly_step_X
26188b36ec9fSYouMin Chen 	 *
26198b36ec9fSYouMin Chen 	 * phy_master_delay_step_X
26208b36ec9fSYouMin Chen 	 * phy_master_delay_wait_X
26218b36ec9fSYouMin Chen 	 * phy_wrlvl_dly_step_X
26228b36ec9fSYouMin Chen 	 * phy_rptr_update_X
26238b36ec9fSYouMin Chen 	 * phy_wdqlvl_dly_step_X
26248b36ec9fSYouMin Chen 	 */
26258b36ec9fSYouMin Chen 	writel(denali_phy_params[87], &denali_phy[87]);
26268b36ec9fSYouMin Chen 	writel(denali_phy_params[88], &denali_phy[88]);
26278b36ec9fSYouMin Chen 	writel(denali_phy_params[89], &denali_phy[89]);
26288b36ec9fSYouMin Chen 	writel(denali_phy_params[90], &denali_phy[90]);
26298b36ec9fSYouMin Chen 
26308b36ec9fSYouMin Chen 	writel(denali_phy_params[215], &denali_phy[215]);
26318b36ec9fSYouMin Chen 	writel(denali_phy_params[216], &denali_phy[216]);
26328b36ec9fSYouMin Chen 	writel(denali_phy_params[217], &denali_phy[217]);
26338b36ec9fSYouMin Chen 	writel(denali_phy_params[218], &denali_phy[218]);
26348b36ec9fSYouMin Chen 
26358b36ec9fSYouMin Chen 	writel(denali_phy_params[343], &denali_phy[343]);
26368b36ec9fSYouMin Chen 	writel(denali_phy_params[344], &denali_phy[344]);
26378b36ec9fSYouMin Chen 	writel(denali_phy_params[345], &denali_phy[345]);
26388b36ec9fSYouMin Chen 	writel(denali_phy_params[346], &denali_phy[346]);
26398b36ec9fSYouMin Chen 
26408b36ec9fSYouMin Chen 	writel(denali_phy_params[471], &denali_phy[471]);
26418b36ec9fSYouMin Chen 	writel(denali_phy_params[472], &denali_phy[472]);
26428b36ec9fSYouMin Chen 	writel(denali_phy_params[473], &denali_phy[473]);
26438b36ec9fSYouMin Chen 	writel(denali_phy_params[474], &denali_phy[474]);
26448b36ec9fSYouMin Chen 
26458b36ec9fSYouMin Chen 	/*
26468b36ec9fSYouMin Chen 	 * phy_gtlvl_lat_adj_start_X
26478b36ec9fSYouMin Chen 	 * phy_gtlvl_rddqs_slv_dly_start_X
26488b36ec9fSYouMin Chen 	 * phy_rdlvl_rddqs_dq_slv_dly_start_X
26498b36ec9fSYouMin Chen 	 * phy_wdqlvl_dqdm_slv_dly_start_X
26508b36ec9fSYouMin Chen 	 */
26518b36ec9fSYouMin Chen 	writel(denali_phy_params[80], &denali_phy[80]);
26528b36ec9fSYouMin Chen 	writel(denali_phy_params[81], &denali_phy[81]);
26538b36ec9fSYouMin Chen 
26548b36ec9fSYouMin Chen 	writel(denali_phy_params[208], &denali_phy[208]);
26558b36ec9fSYouMin Chen 	writel(denali_phy_params[209], &denali_phy[209]);
26568b36ec9fSYouMin Chen 
26578b36ec9fSYouMin Chen 	writel(denali_phy_params[336], &denali_phy[336]);
26588b36ec9fSYouMin Chen 	writel(denali_phy_params[337], &denali_phy[337]);
26598b36ec9fSYouMin Chen 
26608b36ec9fSYouMin Chen 	writel(denali_phy_params[464], &denali_phy[464]);
26618b36ec9fSYouMin Chen 	writel(denali_phy_params[465], &denali_phy[465]);
26628b36ec9fSYouMin Chen 
26638b36ec9fSYouMin Chen 	/*
26648b36ec9fSYouMin Chen 	 * phy_master_delay_start_X
26658b36ec9fSYouMin Chen 	 * phy_sw_master_mode_X
26668b36ec9fSYouMin Chen 	 * phy_rddata_en_tsel_dly_X
26678b36ec9fSYouMin Chen 	 */
26688b36ec9fSYouMin Chen 	writel(denali_phy_params[86], &denali_phy[86]);
26698b36ec9fSYouMin Chen 	writel(denali_phy_params[214], &denali_phy[214]);
26708b36ec9fSYouMin Chen 	writel(denali_phy_params[342], &denali_phy[342]);
26718b36ec9fSYouMin Chen 	writel(denali_phy_params[470], &denali_phy[470]);
26728b36ec9fSYouMin Chen 
26738b36ec9fSYouMin Chen 	/*
26748b36ec9fSYouMin Chen 	 * phy_rddqZ_slave_delay_X
26758b36ec9fSYouMin Chen 	 * phy_rddqs_dqZ_fall_slave_delay_X
26768b36ec9fSYouMin Chen 	 * phy_rddqs_dqZ_rise_slave_delay_X
26778b36ec9fSYouMin Chen 	 * phy_rddqs_dm_fall_slave_delay_X
26788b36ec9fSYouMin Chen 	 * phy_rddqs_dm_rise_slave_delay_X
26798b36ec9fSYouMin Chen 	 * phy_rddqs_gate_slave_delay_X
26808b36ec9fSYouMin Chen 	 * phy_wrlvl_delay_early_threshold_X
26818b36ec9fSYouMin Chen 	 * phy_write_path_lat_add_X
26828b36ec9fSYouMin Chen 	 * phy_rddqs_latency_adjust_X
26838b36ec9fSYouMin Chen 	 * phy_wrlvl_delay_period_threshold_X
26848b36ec9fSYouMin Chen 	 * phy_wrlvl_early_force_zero_X
26858b36ec9fSYouMin Chen 	 */
26868b36ec9fSYouMin Chen 	sdram_copy_to_reg((u32 *)&denali_phy[64],
26878b36ec9fSYouMin Chen 			  (u32 *)&denali_phy_params[64],
26888b36ec9fSYouMin Chen 			  (67 - 63) * 4);
26898b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[68], 0xFFFFFC00,
26908b36ec9fSYouMin Chen 			denali_phy_params[68] & 0xFFFFFC00);
26918b36ec9fSYouMin Chen 	sdram_copy_to_reg((u32 *)&denali_phy[69],
26928b36ec9fSYouMin Chen 			  (u32 *)&denali_phy_params[69],
26938b36ec9fSYouMin Chen 			  (79 - 68) * 4);
26948b36ec9fSYouMin Chen 
26958b36ec9fSYouMin Chen 	sdram_copy_to_reg((u32 *)&denali_phy[192],
26968b36ec9fSYouMin Chen 			  (u32 *)&denali_phy_params[192],
26978b36ec9fSYouMin Chen 			  (195 - 191) * 4);
26988b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[196], 0xFFFFFC00,
26998b36ec9fSYouMin Chen 			denali_phy_params[196] & 0xFFFFFC00);
27008b36ec9fSYouMin Chen 	sdram_copy_to_reg((u32 *)&denali_phy[197],
27018b36ec9fSYouMin Chen 			  (u32 *)&denali_phy_params[197],
27028b36ec9fSYouMin Chen 			  (207 - 196) * 4);
27038b36ec9fSYouMin Chen 
27048b36ec9fSYouMin Chen 	sdram_copy_to_reg((u32 *)&denali_phy[320],
27058b36ec9fSYouMin Chen 			  (u32 *)&denali_phy_params[320],
27068b36ec9fSYouMin Chen 			  (323 - 319) * 4);
27078b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[324], 0xFFFFFC00,
27088b36ec9fSYouMin Chen 			denali_phy_params[324] & 0xFFFFFC00);
27098b36ec9fSYouMin Chen 	sdram_copy_to_reg((u32 *)&denali_phy[325],
27108b36ec9fSYouMin Chen 			  (u32 *)&denali_phy_params[325],
27118b36ec9fSYouMin Chen 			  (335 - 324) * 4);
27128b36ec9fSYouMin Chen 
27138b36ec9fSYouMin Chen 	sdram_copy_to_reg((u32 *)&denali_phy[448],
27148b36ec9fSYouMin Chen 			  (u32 *)&denali_phy_params[448],
27158b36ec9fSYouMin Chen 			  (451 - 447) * 4);
27168b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[452], 0xFFFFFC00,
27178b36ec9fSYouMin Chen 			denali_phy_params[452] & 0xFFFFFC00);
27188b36ec9fSYouMin Chen 	sdram_copy_to_reg((u32 *)&denali_phy[453],
27198b36ec9fSYouMin Chen 			  (u32 *)&denali_phy_params[453],
27208b36ec9fSYouMin Chen 			  (463 - 452) * 4);
27218b36ec9fSYouMin Chen 
27228b36ec9fSYouMin Chen 	/* phy_two_cyc_preamble_X */
27238b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[7], 0x3 << 24,
27248b36ec9fSYouMin Chen 			denali_phy_params[7] & (0x3 << 24));
27258b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[135], 0x3 << 24,
27268b36ec9fSYouMin Chen 			denali_phy_params[135] & (0x3 << 24));
27278b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[263], 0x3 << 24,
27288b36ec9fSYouMin Chen 			denali_phy_params[263] & (0x3 << 24));
27298b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[391], 0x3 << 24,
27308b36ec9fSYouMin Chen 			denali_phy_params[391] & (0x3 << 24));
27318b36ec9fSYouMin Chen 
27328b36ec9fSYouMin Chen 	/* speed */
27338b36ec9fSYouMin Chen 	if (f1_sdram_params->base.ddr_freq < 400 * MHz)
27348b36ec9fSYouMin Chen 		speed = 0x0;
27358b36ec9fSYouMin Chen 	else if (f1_sdram_params->base.ddr_freq < 800 * MHz)
27368b36ec9fSYouMin Chen 		speed = 0x1;
27378b36ec9fSYouMin Chen 	else if (f1_sdram_params->base.ddr_freq < 1200 * MHz)
27388b36ec9fSYouMin Chen 		speed = 0x2;
27398b36ec9fSYouMin Chen 
27408b36ec9fSYouMin Chen 	/* PHY_924 PHY_PAD_FDBK_DRIVE */
27418b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[924],
27428b36ec9fSYouMin Chen 			0x3 << 21, speed << 21);
27438b36ec9fSYouMin Chen 	/* PHY_926 PHY_PAD_DATA_DRIVE */
27448b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[926],
27458b36ec9fSYouMin Chen 			0x3 << 9, speed << 9);
27468b36ec9fSYouMin Chen 	/* PHY_927 PHY_PAD_DQS_DRIVE */
27478b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[927],
27488b36ec9fSYouMin Chen 			0x3 << 9, speed << 9);
27498b36ec9fSYouMin Chen 	/* PHY_928 PHY_PAD_ADDR_DRIVE */
27508b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[928],
27518b36ec9fSYouMin Chen 			0x3 << 17, speed << 17);
27528b36ec9fSYouMin Chen 	/* PHY_929 PHY_PAD_CLK_DRIVE */
27538b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[929],
27548b36ec9fSYouMin Chen 			0x3 << 17, speed << 17);
27558b36ec9fSYouMin Chen 	/* PHY_935 PHY_PAD_CKE_DRIVE */
27568b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[935],
27578b36ec9fSYouMin Chen 			0x3 << 17, speed << 17);
27588b36ec9fSYouMin Chen 	/* PHY_937 PHY_PAD_RST_DRIVE */
27598b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[937],
27608b36ec9fSYouMin Chen 			0x3 << 17, speed << 17);
27618b36ec9fSYouMin Chen 	/* PHY_939 PHY_PAD_CS_DRIVE */
27628b36ec9fSYouMin Chen 	clrsetbits_le32(&denali_phy[939],
27638b36ec9fSYouMin Chen 			0x3 << 17, speed << 17);
27648b36ec9fSYouMin Chen 
27658b36ec9fSYouMin Chen 	if (f1_sdram_params->base.dramtype == LPDDR4) {
27668b36ec9fSYouMin Chen 		read_mr(dram->chan[channel].pctl, 1, 5, &mr5);
27678b36ec9fSYouMin Chen 		set_ds_odt(&dram->chan[channel], f1_sdram_params, 1, 0, mr5);
27688b36ec9fSYouMin Chen 		set_ds_odt(&dram->chan[channel], f1_sdram_params, 1, 1, mr5);
27698b36ec9fSYouMin Chen 
27708b36ec9fSYouMin Chen 		ctl_fn = get_ctl_fn(f1_sdram_params, fn);
27718b36ec9fSYouMin Chen 		set_lp4_dq_odt(&dram->chan[channel], f1_sdram_params,
27728b36ec9fSYouMin Chen 			       ctl_fn, 1, 1, 0, mr5);
27738b36ec9fSYouMin Chen 		set_lp4_ca_odt(&dram->chan[channel], f1_sdram_params,
27748b36ec9fSYouMin Chen 			       ctl_fn, 1, 1, 0, mr5);
27758b36ec9fSYouMin Chen 		set_lp4_MR3(&dram->chan[channel], f1_sdram_params,
27768b36ec9fSYouMin Chen 			    ctl_fn, 1, 0, mr5);
27778b36ec9fSYouMin Chen 		set_lp4_MR12(&dram->chan[channel], f1_sdram_params,
27788b36ec9fSYouMin Chen 			     ctl_fn, 1, 0, mr5);
27798b36ec9fSYouMin Chen 		set_lp4_MR14(&dram->chan[channel], f1_sdram_params,
27808b36ec9fSYouMin Chen 			     ctl_fn, 1, 0, mr5);
27818b36ec9fSYouMin Chen 
27828b36ec9fSYouMin Chen 		set_lp4_dq_odt(&dram->chan[channel], f1_sdram_params,
27838b36ec9fSYouMin Chen 			       ctl_fn, 1, 1, 1, mr5);
27848b36ec9fSYouMin Chen 		set_lp4_ca_odt(&dram->chan[channel], f1_sdram_params,
27858b36ec9fSYouMin Chen 			       ctl_fn, 1, 1, 1, mr5);
27868b36ec9fSYouMin Chen 		set_lp4_MR3(&dram->chan[channel], f1_sdram_params,
27878b36ec9fSYouMin Chen 			    ctl_fn, 1, 1, mr5);
27888b36ec9fSYouMin Chen 		set_lp4_MR12(&dram->chan[channel], f1_sdram_params,
27898b36ec9fSYouMin Chen 			     ctl_fn, 1, 1, mr5);
27908b36ec9fSYouMin Chen 		set_lp4_MR14(&dram->chan[channel], f1_sdram_params,
27918b36ec9fSYouMin Chen 			     ctl_fn, 1, 1, mr5);
27928b36ec9fSYouMin Chen 
27938b36ec9fSYouMin Chen 		/*
27948b36ec9fSYouMin Chen 		 * if phy_sw_master_mode_X not bypass mode,
27958b36ec9fSYouMin Chen 		 * clear PHY_SLICE_PWR_RDC_DISABLE.
27968b36ec9fSYouMin Chen 		 * NOTE: need use f1_sdram_params, not ddr_publ_regs
27978b36ec9fSYouMin Chen 		 */
27988b36ec9fSYouMin Chen 		if (!((denali_phy_params[86] >> 8)
27998b36ec9fSYouMin Chen 			& (1 << 2))) {
28008b36ec9fSYouMin Chen 			clrbits_le32(&denali_phy[10], 1 << 16);
28018b36ec9fSYouMin Chen 			clrbits_le32(&denali_phy[138], 1 << 16);
28028b36ec9fSYouMin Chen 			clrbits_le32(&denali_phy[266], 1 << 16);
28038b36ec9fSYouMin Chen 			clrbits_le32(&denali_phy[394], 1 << 16);
28048b36ec9fSYouMin Chen 		}
28058b36ec9fSYouMin Chen 
28068b36ec9fSYouMin Chen 		/*
28078b36ec9fSYouMin Chen 		 * when PHY_PER_CS_TRAINING_EN=1, W2W_DIFFCS_DLY_Fx can't
28088b36ec9fSYouMin Chen 		 * smaller than 8
28098b36ec9fSYouMin Chen 		 * NOTE: need use f1_sdram_params, not ddr_publ_regs
28108b36ec9fSYouMin Chen 		 */
28118b36ec9fSYouMin Chen 		if ((denali_phy_params[84] >> 16) & 1) {
28128b36ec9fSYouMin Chen 			if (((readl(&denali_ctl[217 + ctl_fn]) >>
28138b36ec9fSYouMin Chen 				16) & 0x1f) < 8)
28148b36ec9fSYouMin Chen 				clrsetbits_le32(&denali_ctl[217 + ctl_fn],
28158b36ec9fSYouMin Chen 						0x1f << 16,
28168b36ec9fSYouMin Chen 						8 << 16);
28178b36ec9fSYouMin Chen 		}
28188b36ec9fSYouMin Chen 	}
28198b36ec9fSYouMin Chen }
28208b36ec9fSYouMin Chen 
dram_set_phy_fn(struct dram_info * dram,struct rk3399_sdram_params * sdram_params,u32 fn,struct rk3399_sdram_params * f1_sdram_params)28218b36ec9fSYouMin Chen static void dram_set_phy_fn(struct dram_info *dram,
28228b36ec9fSYouMin Chen 			    struct rk3399_sdram_params *sdram_params, u32 fn,
28238b36ec9fSYouMin Chen 			    struct rk3399_sdram_params *f1_sdram_params)
28248b36ec9fSYouMin Chen {
28258b36ec9fSYouMin Chen 	u32 channel;
28268b36ec9fSYouMin Chen 
28278b36ec9fSYouMin Chen 	for (channel = 0; channel < 2; channel++)
28288b36ec9fSYouMin Chen 		dram_copy_phy_fn(dram, sdram_params, fn, f1_sdram_params,
28298b36ec9fSYouMin Chen 				 channel);
28308b36ec9fSYouMin Chen }
28318b36ec9fSYouMin Chen 
dram_set_rate(struct dram_info * dram,struct rk3399_sdram_params * sdram_params,u32 fn,u32 hz)28328b36ec9fSYouMin Chen static int dram_set_rate(struct dram_info *dram,
28338b36ec9fSYouMin Chen 			 struct rk3399_sdram_params *sdram_params,
28348b36ec9fSYouMin Chen 			 u32 fn, u32 hz)
28358b36ec9fSYouMin Chen {
28368b36ec9fSYouMin Chen 	u32 channel;
28378b36ec9fSYouMin Chen 	int ret_clk, ret[2];
28388b36ec9fSYouMin Chen 
28398b36ec9fSYouMin Chen 	/* cci idle req stall */
28408b36ec9fSYouMin Chen 	writel(0x70007, &dram->grf->soc_con0);
28418b36ec9fSYouMin Chen 	/* enable all clk */
28428b36ec9fSYouMin Chen 	setbits_le32(&dram->pmu->pmu_noc_auto_ena, (0x3 << 7));
28438b36ec9fSYouMin Chen 	/* idle */
28448b36ec9fSYouMin Chen 	setbits_le32(&dram->pmu->pmu_bus_idle_req, (0x3 << 18));
28458b36ec9fSYouMin Chen 	while ((readl(&dram->pmu->pmu_bus_idle_st) & (0x3 << 18))
28468b36ec9fSYouMin Chen 	       != (0x3 << 18))
28478b36ec9fSYouMin Chen 		;
28488b36ec9fSYouMin Chen 
28498b36ec9fSYouMin Chen 	/* change freq */
28508b36ec9fSYouMin Chen 	writel((((0x3 << 4) | (1 << 2) | 1) << 16) |
28518b36ec9fSYouMin Chen 		(fn << 4) | (1 << 2) | 1, &dram->cic->cic_ctrl0);
28528b36ec9fSYouMin Chen 	while (!(readl(&dram->cic->cic_status0) & (1 << 2)))
28538b36ec9fSYouMin Chen 		;
28548b36ec9fSYouMin Chen 
28558b36ec9fSYouMin Chen 	ret_clk = clk_set_rate(&dram->ddr_clk, hz);
28568b36ec9fSYouMin Chen 	if (ret_clk < 0) {
28578b36ec9fSYouMin Chen 		printf("%s clk set failed %d\n", __func__, ret_clk);
28588b36ec9fSYouMin Chen 		return ret_clk;
28598b36ec9fSYouMin Chen 	}
28608b36ec9fSYouMin Chen 
28618b36ec9fSYouMin Chen 	writel(0x20002, &dram->cic->cic_ctrl0);
28628b36ec9fSYouMin Chen 	while (!(readl(&dram->cic->cic_status0) & (1 << 0)))
28638b36ec9fSYouMin Chen 		;
28648b36ec9fSYouMin Chen 
28658b36ec9fSYouMin Chen 	/* deidle */
28668b36ec9fSYouMin Chen 	clrbits_le32(&dram->pmu->pmu_bus_idle_req, (0x3 << 18));
28678b36ec9fSYouMin Chen 	while (readl(&dram->pmu->pmu_bus_idle_st) & (0x3 << 18))
28688b36ec9fSYouMin Chen 		;
28698b36ec9fSYouMin Chen 
28708b36ec9fSYouMin Chen 	/* clear enable all clk */
28718b36ec9fSYouMin Chen 	clrbits_le32(&dram->pmu->pmu_noc_auto_ena, (0x3 << 7));
28728b36ec9fSYouMin Chen 
28738b36ec9fSYouMin Chen 	/* LPDDR4 f2 can not do training, all training will fail */
28748b36ec9fSYouMin Chen 	if (!(sdram_params->base.dramtype == LPDDR4 && fn == 2)) {
28758b36ec9fSYouMin Chen 		for (channel = 0; channel < 2; channel++) {
28768b36ec9fSYouMin Chen 			if (!(sdram_params->ch[channel].cap_info.col))
28778b36ec9fSYouMin Chen 				continue;
28788b36ec9fSYouMin Chen 			ret[channel] = data_training(&dram->chan[channel],
28798b36ec9fSYouMin Chen 						     channel, sdram_params,
28808b36ec9fSYouMin Chen 						     PI_FULL_TRAINING);
28818b36ec9fSYouMin Chen 		}
28828b36ec9fSYouMin Chen 		for (channel = 0; channel < 2; channel++) {
28838b36ec9fSYouMin Chen 			if (!(sdram_params->ch[channel].cap_info.col))
28848b36ec9fSYouMin Chen 				continue;
28858b36ec9fSYouMin Chen 			if (ret[channel])
28868b36ec9fSYouMin Chen 				printf("channel %d training failed!\n",
28878b36ec9fSYouMin Chen 				       channel);
28888b36ec9fSYouMin Chen 			else
28898b36ec9fSYouMin Chen 				printf("channel %d training pass\n", channel);
28908b36ec9fSYouMin Chen 		}
28918b36ec9fSYouMin Chen 	}
28928b36ec9fSYouMin Chen 
28938b36ec9fSYouMin Chen 	return 0;
28948b36ec9fSYouMin Chen }
28958b36ec9fSYouMin Chen 
28968b36ec9fSYouMin Chen static struct rk3399_sdram_params *g_sdram_params;
set_rate0(struct dram_info * dram)28978b36ec9fSYouMin Chen static void set_rate0(struct dram_info *dram)
28988b36ec9fSYouMin Chen {
28998b36ec9fSYouMin Chen 	u32 ctl_fn;
29008b36ec9fSYouMin Chen 	u32 phy_fn;
29018b36ec9fSYouMin Chen 
29028b36ec9fSYouMin Chen 	ctl_fn = 0;
29038b36ec9fSYouMin Chen 	phy_fn = get_phy_fn(g_sdram_params, ctl_fn);
29048b36ec9fSYouMin Chen 	dram_set_phy_fn(dram, g_sdram_params, phy_fn, &dfs_configs[ctl_fn]);
29058b36ec9fSYouMin Chen 	dram_set_rate(dram, g_sdram_params, ctl_fn,
29068b36ec9fSYouMin Chen 		      dfs_configs[ctl_fn].base.ddr_freq);
29078b36ec9fSYouMin Chen 	printf("change freq to %d MHz %d, %d\n",
29088b36ec9fSYouMin Chen 	       dfs_configs[ctl_fn].base.ddr_freq / MHZ, ctl_fn, phy_fn);
29098b36ec9fSYouMin Chen }
29108b36ec9fSYouMin Chen 
set_rate1(struct dram_info * dram)29118b36ec9fSYouMin Chen static void set_rate1(struct dram_info *dram)
29128b36ec9fSYouMin Chen {
29138b36ec9fSYouMin Chen 	u32 ctl_fn;
29148b36ec9fSYouMin Chen 	u32 phy_fn;
29158b36ec9fSYouMin Chen 
29168b36ec9fSYouMin Chen 	ctl_fn = 1;
29178b36ec9fSYouMin Chen 	phy_fn = get_phy_fn(g_sdram_params, ctl_fn);
29188b36ec9fSYouMin Chen 	dram_set_phy_fn(dram, g_sdram_params, phy_fn, &dfs_configs[ctl_fn]);
29198b36ec9fSYouMin Chen 	dram_set_rate(dram, g_sdram_params, ctl_fn,
29208b36ec9fSYouMin Chen 		      dfs_configs[ctl_fn].base.ddr_freq);
29218b36ec9fSYouMin Chen 	printf("change freq to %d MHz %d, %d\n",
29228b36ec9fSYouMin Chen 	       dfs_configs[ctl_fn].base.ddr_freq / MHZ, ctl_fn, phy_fn);
29238b36ec9fSYouMin Chen }
29248b36ec9fSYouMin Chen 
sdram_init(struct dram_info * dram,struct rk3399_sdram_params * sdram_params)2925d0b1becdSKever Yang static int sdram_init(struct dram_info *dram,
292631d8c61dSYouMin Chen 		      struct rk3399_sdram_params *sdram_params)
2927d0b1becdSKever Yang {
2928d0b1becdSKever Yang 	unsigned char dramtype = sdram_params->base.dramtype;
2929d0b1becdSKever Yang 	unsigned int ddr_freq = sdram_params->base.ddr_freq;
2930d0b1becdSKever Yang 	int channel;
293131d8c61dSYouMin Chen 	u32 rank;
293231d8c61dSYouMin Chen 	int ch;
293331d8c61dSYouMin Chen 	u32 tmp;
293431d8c61dSYouMin Chen 	u32 training_flag;
2935d0b1becdSKever Yang 
2936d0b1becdSKever Yang 	debug("Starting SDRAM initialization...\n");
2937d0b1becdSKever Yang 
2938d0b1becdSKever Yang 	if ((dramtype == DDR3 && ddr_freq > 933) ||
2939d0b1becdSKever Yang 	    (dramtype == LPDDR3 && ddr_freq > 933) ||
2940d0b1becdSKever Yang 	    (dramtype == LPDDR4 && ddr_freq > 800)) {
2941d0b1becdSKever Yang 		debug("SDRAM frequency is to high!");
2942d0b1becdSKever Yang 		return -E2BIG;
2943d0b1becdSKever Yang 	}
2944d0b1becdSKever Yang 
294531d8c61dSYouMin Chen 	/* detect rank */
294631d8c61dSYouMin Chen 	for (ch = 0; ch < 2; ch++) {
294731d8c61dSYouMin Chen 		sdram_params->ch[ch].cap_info.rank = 2;
294831d8c61dSYouMin Chen 		for (rank = 2; rank != 0; rank--) {
2949d0b1becdSKever Yang 			for (channel = 0; channel < 2; channel++) {
295031d8c61dSYouMin Chen 				const struct chan_info *chan =
295131d8c61dSYouMin Chen 					&dram->chan[channel];
295231d8c61dSYouMin Chen 				struct rk3399_cru *cru = dram->cru;
2953d0b1becdSKever Yang 				struct rk3399_ddr_publ_regs *publ = chan->publ;
2954d0b1becdSKever Yang 
295531d8c61dSYouMin Chen 				phy_pctrl_reset(cru, channel);
2956d0b1becdSKever Yang 				phy_dll_bypass_set(publ, ddr_freq);
29578b36ec9fSYouMin Chen 				pctl_cfg(chan, channel, sdram_params);
2958d0b1becdSKever Yang 			}
2959d0b1becdSKever Yang 
29608b36ec9fSYouMin Chen 			/* start to trigger initialization */
29618b36ec9fSYouMin Chen 			pctl_start(dram, sdram_params, 3);
29628b36ec9fSYouMin Chen 
2963d0b1becdSKever Yang 			/* LPDDR2/LPDDR3 need to wait DAI complete, max 10us */
2964d0b1becdSKever Yang 			if (dramtype == LPDDR3)
2965d0b1becdSKever Yang 				udelay(10);
2966d0b1becdSKever Yang 
296731d8c61dSYouMin Chen 			tmp = (rank == 2) ? 3 : 1;
296831d8c61dSYouMin Chen 			dram_set_cs(&dram->chan[ch], tmp, 2048,
296931d8c61dSYouMin Chen 				    sdram_params->base.dramtype);
297031d8c61dSYouMin Chen 			sdram_params->ch[ch].cap_info.rank = rank;
29718b36ec9fSYouMin Chen 			if (sdram_params->base.dramtype == LPDDR4) {
29728b36ec9fSYouMin Chen 				/* two rank, then read_mr(cs1)
29738b36ec9fSYouMin Chen 				 * one rank, then read_mr(cs0)
29748b36ec9fSYouMin Chen 				 */
29758b36ec9fSYouMin Chen 				if (!read_mr_for_detect(dram, ch, rank,
29768b36ec9fSYouMin Chen 							sdram_params))
29778b36ec9fSYouMin Chen 					break;
29788b36ec9fSYouMin Chen 			} else {
297931d8c61dSYouMin Chen 				/*
298031d8c61dSYouMin Chen 				 * LPDDR3 CA training msut be trigger before
298131d8c61dSYouMin Chen 				 * other training.
298231d8c61dSYouMin Chen 				 * DDR3 is not have CA training.
298331d8c61dSYouMin Chen 				 * LPDDR4 need confirm here!
298431d8c61dSYouMin Chen 				 */
298531d8c61dSYouMin Chen 				if (sdram_params->base.dramtype == LPDDR3)
298631d8c61dSYouMin Chen 					training_flag = PI_CA_TRAINING |
298731d8c61dSYouMin Chen 							PI_READ_GATE_TRAINING;
298831d8c61dSYouMin Chen 				else
298931d8c61dSYouMin Chen 					training_flag = PI_READ_GATE_TRAINING;
29908b36ec9fSYouMin Chen 				if (!(data_training(&dram->chan[ch], ch,
29918b36ec9fSYouMin Chen 						    sdram_params,
299231d8c61dSYouMin Chen 						    training_flag)))
299331d8c61dSYouMin Chen 					break;
299431d8c61dSYouMin Chen 			}
29958b36ec9fSYouMin Chen 		}
299631d8c61dSYouMin Chen 		sdram_params->ch[ch].cap_info.rank = rank;
2997d0b1becdSKever Yang 	}
2998d0b1becdSKever Yang 
299931d8c61dSYouMin Chen 	sdram_params->base.num_channels = 0;
300031d8c61dSYouMin Chen 	for (channel = 0; channel < 2; channel++) {
300131d8c61dSYouMin Chen 		const struct chan_info *chan = &dram->chan[channel];
300231d8c61dSYouMin Chen 		struct sdram_cap_info *cap_info =
300331d8c61dSYouMin Chen 			&sdram_params->ch[channel].cap_info;
300431d8c61dSYouMin Chen 
300531d8c61dSYouMin Chen 		if (cap_info->rank == 0) {
300631d8c61dSYouMin Chen 			clear_channel_params(sdram_params, 1);
300731d8c61dSYouMin Chen 			continue;
300831d8c61dSYouMin Chen 		} else {
300931d8c61dSYouMin Chen 			sdram_params->base.num_channels++;
3010d0b1becdSKever Yang 		}
301131d8c61dSYouMin Chen 
301231d8c61dSYouMin Chen 		printf("Channel ");
301331d8c61dSYouMin Chen 		printf(channel ? "1: " : "0: ");
301431d8c61dSYouMin Chen 
301531d8c61dSYouMin Chen 		if (channel == 0)
301631d8c61dSYouMin Chen 			set_ddr_stride(dram->pmusgrf, 0x17);
301731d8c61dSYouMin Chen 		else
301831d8c61dSYouMin Chen 			set_ddr_stride(dram->pmusgrf, 0x18);
301931d8c61dSYouMin Chen 
302031d8c61dSYouMin Chen 		if (dram_detect_cap(dram, sdram_params, channel)) {
302131d8c61dSYouMin Chen 			printf("Cap error!\n");
302231d8c61dSYouMin Chen 			continue;
302331d8c61dSYouMin Chen 		}
302431d8c61dSYouMin Chen 
302531d8c61dSYouMin Chen 		sdram_print_ddr_info(cap_info, &sdram_params->base, 0);
302631d8c61dSYouMin Chen 		set_memory_map(chan, channel, sdram_params);
302731d8c61dSYouMin Chen 		cap_info->ddrconfig =
302831d8c61dSYouMin Chen 			calculate_ddrconfig(sdram_params, channel);
302931d8c61dSYouMin Chen 		if (-1 == cap_info->ddrconfig) {
303031d8c61dSYouMin Chen 			printf("no ddrconfig find, Cap not support!\n");
303131d8c61dSYouMin Chen 			continue;
303231d8c61dSYouMin Chen 		}
303331d8c61dSYouMin Chen 		set_ddrconfig(chan, sdram_params, channel, cap_info->ddrconfig);
303431d8c61dSYouMin Chen 		set_cap_relate_config(chan, sdram_params, channel);
303531d8c61dSYouMin Chen 	}
303631d8c61dSYouMin Chen 
30378b36ec9fSYouMin Chen 	if (sdram_params->base.num_channels == 0) {
30388b36ec9fSYouMin Chen 		sdram_print_dram_type(sdram_params->base.dramtype);
30398b36ec9fSYouMin Chen 		printf(" %dMHz\n", sdram_params->base.ddr_freq);
30408b36ec9fSYouMin Chen 		return -1;
30418b36ec9fSYouMin Chen 	}
30428b36ec9fSYouMin Chen 
304331d8c61dSYouMin Chen 	sdram_params->base.stride = calculate_stride(sdram_params);
3044d0b1becdSKever Yang 	dram_all_config(dram, sdram_params);
30458b36ec9fSYouMin Chen 
30468b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype != LPDDR4)
3047d0b1becdSKever Yang 		switch_to_phy_index1(dram, sdram_params);
3048d0b1becdSKever Yang 
30498b36ec9fSYouMin Chen 	if (sdram_params->base.dramtype == LPDDR4) {
30508b36ec9fSYouMin Chen 		g_sdram_params = sdram_params;
30518b36ec9fSYouMin Chen 		set_rate0(dram);
30528b36ec9fSYouMin Chen 		set_rate1(dram);
30538b36ec9fSYouMin Chen 	}
30548b36ec9fSYouMin Chen 
3055d0b1becdSKever Yang 	debug("Finish SDRAM initialization...\n");
3056d0b1becdSKever Yang 	return 0;
3057d0b1becdSKever Yang }
3058d0b1becdSKever Yang 
rk3399_dmc_ofdata_to_platdata(struct udevice * dev)3059d0b1becdSKever Yang static int rk3399_dmc_ofdata_to_platdata(struct udevice *dev)
3060d0b1becdSKever Yang {
3061d0b1becdSKever Yang #if !CONFIG_IS_ENABLED(OF_PLATDATA)
3062d0b1becdSKever Yang 	struct rockchip_dmc_plat *plat = dev_get_platdata(dev);
3063d0b1becdSKever Yang 	int ret;
3064d0b1becdSKever Yang 
3065d0b1becdSKever Yang 	ret = dev_read_u32_array(dev, "rockchip,sdram-params",
3066d0b1becdSKever Yang 				 (u32 *)&plat->sdram_params,
3067d0b1becdSKever Yang 				 sizeof(plat->sdram_params) / sizeof(u32));
3068d0b1becdSKever Yang 	if (ret) {
3069d0b1becdSKever Yang 		printf("%s: Cannot read rockchip,sdram-params %d\n",
3070d0b1becdSKever Yang 		       __func__, ret);
3071d0b1becdSKever Yang 		return ret;
3072d0b1becdSKever Yang 	}
3073d0b1becdSKever Yang 	ret = regmap_init_mem(dev, &plat->map);
3074d0b1becdSKever Yang 	if (ret)
3075d0b1becdSKever Yang 		printf("%s: regmap failed %d\n", __func__, ret);
3076d0b1becdSKever Yang 
3077d0b1becdSKever Yang #endif
3078d0b1becdSKever Yang 	return 0;
3079d0b1becdSKever Yang }
3080d0b1becdSKever Yang 
3081d0b1becdSKever Yang #if CONFIG_IS_ENABLED(OF_PLATDATA)
conv_of_platdata(struct udevice * dev)3082d0b1becdSKever Yang static int conv_of_platdata(struct udevice *dev)
3083d0b1becdSKever Yang {
3084d0b1becdSKever Yang 	struct rockchip_dmc_plat *plat = dev_get_platdata(dev);
3085d0b1becdSKever Yang 	struct dtd_rockchip_rk3399_dmc *dtplat = &plat->dtplat;
3086d0b1becdSKever Yang 	int ret;
3087d0b1becdSKever Yang 
3088d0b1becdSKever Yang 	ret = regmap_init_mem_platdata(dev, dtplat->reg,
30897dfddccfSKever Yang 				       ARRAY_SIZE(dtplat->reg) / 2,
3090d0b1becdSKever Yang 				       &plat->map);
3091d0b1becdSKever Yang 	if (ret)
3092d0b1becdSKever Yang 		return ret;
3093d0b1becdSKever Yang 
3094d0b1becdSKever Yang 	return 0;
3095d0b1becdSKever Yang }
3096d0b1becdSKever Yang #endif
3097d0b1becdSKever Yang 
rk3399_dmc_init(struct udevice * dev)3098d0b1becdSKever Yang static int rk3399_dmc_init(struct udevice *dev)
3099d0b1becdSKever Yang {
3100d0b1becdSKever Yang 	struct dram_info *priv = dev_get_priv(dev);
3101d0b1becdSKever Yang 	struct rockchip_dmc_plat *plat = dev_get_platdata(dev);
3102d0b1becdSKever Yang 	int ret;
3103d0b1becdSKever Yang #if !CONFIG_IS_ENABLED(OF_PLATDATA)
3104d0b1becdSKever Yang 	struct rk3399_sdram_params *params = &plat->sdram_params;
3105d0b1becdSKever Yang #else
3106d0b1becdSKever Yang 	struct dtd_rockchip_rk3399_dmc *dtplat = &plat->dtplat;
3107d0b1becdSKever Yang 	struct rk3399_sdram_params *params =
3108d0b1becdSKever Yang 					(void *)dtplat->rockchip_sdram_params;
3109d0b1becdSKever Yang 
3110d0b1becdSKever Yang 	ret = conv_of_platdata(dev);
3111d0b1becdSKever Yang 	if (ret)
3112d0b1becdSKever Yang 		return ret;
3113d0b1becdSKever Yang #endif
3114d0b1becdSKever Yang 
3115d0b1becdSKever Yang 	priv->cic = syscon_get_first_range(ROCKCHIP_SYSCON_CIC);
31168b36ec9fSYouMin Chen 	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
31178b36ec9fSYouMin Chen 	priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
3118d0b1becdSKever Yang 	priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
3119d0b1becdSKever Yang 	priv->pmusgrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUSGRF);
3120d0b1becdSKever Yang 	priv->pmucru = rockchip_get_pmucru();
3121d0b1becdSKever Yang 	priv->cru = rockchip_get_cru();
3122d0b1becdSKever Yang 	priv->chan[0].pctl = regmap_get_range(plat->map, 0);
3123d0b1becdSKever Yang 	priv->chan[0].pi = regmap_get_range(plat->map, 1);
3124d0b1becdSKever Yang 	priv->chan[0].publ = regmap_get_range(plat->map, 2);
3125d0b1becdSKever Yang 	priv->chan[0].msch = regmap_get_range(plat->map, 3);
3126d0b1becdSKever Yang 	priv->chan[1].pctl = regmap_get_range(plat->map, 4);
3127d0b1becdSKever Yang 	priv->chan[1].pi = regmap_get_range(plat->map, 5);
3128d0b1becdSKever Yang 	priv->chan[1].publ = regmap_get_range(plat->map, 6);
3129d0b1becdSKever Yang 	priv->chan[1].msch = regmap_get_range(plat->map, 7);
3130d0b1becdSKever Yang 
3131d0b1becdSKever Yang 	debug("con reg %p %p %p %p %p %p %p %p\n",
3132d0b1becdSKever Yang 	      priv->chan[0].pctl, priv->chan[0].pi,
3133d0b1becdSKever Yang 	      priv->chan[0].publ, priv->chan[0].msch,
3134d0b1becdSKever Yang 	      priv->chan[1].pctl, priv->chan[1].pi,
3135d0b1becdSKever Yang 	      priv->chan[1].publ, priv->chan[1].msch);
31368b36ec9fSYouMin Chen 	debug("cru %p, cic %p, grf %p, sgrf %p, pmucru %p, pmu %p\n", priv->cru,
31378b36ec9fSYouMin Chen 	      priv->cic, priv->pmugrf, priv->pmusgrf, priv->pmucru, priv->pmu);
3138d0b1becdSKever Yang #if CONFIG_IS_ENABLED(OF_PLATDATA)
3139d0b1becdSKever Yang 	ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->ddr_clk);
3140d0b1becdSKever Yang #else
3141d0b1becdSKever Yang 	ret = clk_get_by_index(dev, 0, &priv->ddr_clk);
3142d0b1becdSKever Yang #endif
3143d0b1becdSKever Yang 	if (ret) {
3144d0b1becdSKever Yang 		printf("%s clk get failed %d\n", __func__, ret);
3145d0b1becdSKever Yang 		return ret;
3146d0b1becdSKever Yang 	}
3147d0b1becdSKever Yang 	ret = clk_set_rate(&priv->ddr_clk, params->base.ddr_freq * MHz);
3148d0b1becdSKever Yang 	if (ret < 0) {
3149d0b1becdSKever Yang 		printf("%s clk set failed %d\n", __func__, ret);
3150d0b1becdSKever Yang 		return ret;
3151d0b1becdSKever Yang 	}
3152d0b1becdSKever Yang 	ret = sdram_init(priv, params);
3153d0b1becdSKever Yang 	if (ret < 0) {
3154d0b1becdSKever Yang 		printf("%s DRAM init failed %d\n", __func__, ret);
3155d0b1becdSKever Yang 		return ret;
3156d0b1becdSKever Yang 	}
3157d0b1becdSKever Yang 
3158d0b1becdSKever Yang 	return 0;
3159d0b1becdSKever Yang }
3160d0b1becdSKever Yang #endif
3161d0b1becdSKever Yang 
rk3399_dmc_probe(struct udevice * dev)3162d0b1becdSKever Yang static int rk3399_dmc_probe(struct udevice *dev)
3163d0b1becdSKever Yang {
3164ca77381eSKever Yang #ifdef CONFIG_TPL_BUILD
3165d0b1becdSKever Yang 	if (rk3399_dmc_init(dev))
3166d0b1becdSKever Yang 		return 0;
3167d0b1becdSKever Yang #else
3168d0b1becdSKever Yang 	struct dram_info *priv = dev_get_priv(dev);
3169d0b1becdSKever Yang 
3170d0b1becdSKever Yang 	priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
3171d0b1becdSKever Yang 	debug("%s: pmugrf=%p\n", __func__, priv->pmugrf);
3172d0b1becdSKever Yang 	priv->info.base = CONFIG_SYS_SDRAM_BASE;
31738b36ec9fSYouMin Chen 	priv->info.size =
31748b36ec9fSYouMin Chen 		rockchip_sdram_size((phys_addr_t)&priv->pmugrf->os_reg2);
3175ca77381eSKever Yang #ifdef CONFIG_SPL_BUILD
3176ca77381eSKever Yang 	struct ddr_param ddr_parem;
3177ca77381eSKever Yang 
3178ca77381eSKever Yang 	ddr_parem.count = 1;
3179ca77381eSKever Yang 	ddr_parem.para[0] = priv->info.base;
3180ca77381eSKever Yang 	ddr_parem.para[1] = priv->info.size;
3181ca77381eSKever Yang 	rockchip_setup_ddr_param(&ddr_parem);
3182ca77381eSKever Yang #endif
3183ca77381eSKever Yang 
3184d0b1becdSKever Yang #endif
3185d0b1becdSKever Yang 	return 0;
3186d0b1becdSKever Yang }
3187d0b1becdSKever Yang 
rk3399_dmc_get_info(struct udevice * dev,struct ram_info * info)3188d0b1becdSKever Yang static int rk3399_dmc_get_info(struct udevice *dev, struct ram_info *info)
3189d0b1becdSKever Yang {
3190d0b1becdSKever Yang 	struct dram_info *priv = dev_get_priv(dev);
3191d0b1becdSKever Yang 
3192d0b1becdSKever Yang 	*info = priv->info;
3193d0b1becdSKever Yang 
3194d0b1becdSKever Yang 	return 0;
3195d0b1becdSKever Yang }
3196d0b1becdSKever Yang 
3197d0b1becdSKever Yang static struct ram_ops rk3399_dmc_ops = {
3198d0b1becdSKever Yang 	.get_info = rk3399_dmc_get_info,
3199d0b1becdSKever Yang };
3200d0b1becdSKever Yang 
3201d0b1becdSKever Yang static const struct udevice_id rk3399_dmc_ids[] = {
3202d0b1becdSKever Yang 	{ .compatible = "rockchip,rk3399-dmc" },
3203d0b1becdSKever Yang 	{ }
3204d0b1becdSKever Yang };
3205d0b1becdSKever Yang 
3206d0b1becdSKever Yang U_BOOT_DRIVER(dmc_rk3399) = {
3207d0b1becdSKever Yang 	.name = "rockchip_rk3399_dmc",
3208d0b1becdSKever Yang 	.id = UCLASS_RAM,
3209d0b1becdSKever Yang 	.of_match = rk3399_dmc_ids,
3210d0b1becdSKever Yang 	.ops = &rk3399_dmc_ops,
3211ca77381eSKever Yang #ifdef CONFIG_TPL_BUILD
3212d0b1becdSKever Yang 	.ofdata_to_platdata = rk3399_dmc_ofdata_to_platdata,
3213d0b1becdSKever Yang #endif
3214d0b1becdSKever Yang 	.probe = rk3399_dmc_probe,
3215d0b1becdSKever Yang 	.priv_auto_alloc_size = sizeof(struct dram_info),
3216ca77381eSKever Yang #ifdef CONFIG_TPL_BUILD
3217d0b1becdSKever Yang 	.platdata_auto_alloc_size = sizeof(struct rockchip_dmc_plat),
3218d0b1becdSKever Yang #endif
3219d0b1becdSKever Yang };
3220