xref: /openbmc/u-boot/arch/arm/mach-rockchip/rk3036/sdram_rk3036.c (revision 53c45f0ca27cbf6acd840e87beaa1ba1be74399b)
1*53c45f0cShuang lin /*
2*53c45f0cShuang lin  * (C) Copyright 2015 Google, Inc
3*53c45f0cShuang lin  *
4*53c45f0cShuang lin  * SPDX-License-Identifier:     GPL-2.0+
5*53c45f0cShuang lin  */
6*53c45f0cShuang lin #include <common.h>
7*53c45f0cShuang lin #include <asm/io.h>
8*53c45f0cShuang lin #include <asm/types.h>
9*53c45f0cShuang lin #include <asm/arch/cru_rk3036.h>
10*53c45f0cShuang lin #include <asm/arch/grf_rk3036.h>
11*53c45f0cShuang lin #include <asm/arch/hardware.h>
12*53c45f0cShuang lin #include <asm/arch/sdram_rk3036.h>
13*53c45f0cShuang lin #include <asm/arch/timer.h>
14*53c45f0cShuang lin #include <asm/arch/uart.h>
15*53c45f0cShuang lin 
16*53c45f0cShuang lin /*
17*53c45f0cShuang lin  * we can not fit the code to access the device tree in SPL
18*53c45f0cShuang lin  * (due to 4K SRAM size limits), so these are hard-coded
19*53c45f0cShuang lin  */
20*53c45f0cShuang lin #define CRU_BASE	0x20000000
21*53c45f0cShuang lin #define GRF_BASE	0x20008000
22*53c45f0cShuang lin #define DDR_PHY_BASE	0x2000a000
23*53c45f0cShuang lin #define DDR_PCTL_BASE	0x20004000
24*53c45f0cShuang lin #define CPU_AXI_BUS_BASE	0x10128000
25*53c45f0cShuang lin 
26*53c45f0cShuang lin struct rk3036_sdram_priv {
27*53c45f0cShuang lin 	struct rk3036_cru *cru;
28*53c45f0cShuang lin 	struct rk3036_grf *grf;
29*53c45f0cShuang lin 	struct rk3036_ddr_phy *phy;
30*53c45f0cShuang lin 	struct rk3036_ddr_pctl *pctl;
31*53c45f0cShuang lin 	struct rk3036_service_sys *axi_bus;
32*53c45f0cShuang lin 
33*53c45f0cShuang lin 	/* ddr die config */
34*53c45f0cShuang lin 	struct rk3036_ddr_config ddr_config;
35*53c45f0cShuang lin };
36*53c45f0cShuang lin 
37*53c45f0cShuang lin /* use integer mode, 396MHz dpll setting
38*53c45f0cShuang lin  * refdiv, fbdiv, postdiv1, postdiv2
39*53c45f0cShuang lin  */
40*53c45f0cShuang lin const struct pll_div dpll_init_cfg = {1, 66, 4, 1};
41*53c45f0cShuang lin 
42*53c45f0cShuang lin /* 396Mhz ddr timing */
43*53c45f0cShuang lin const struct rk3036_ddr_timing ddr_timing = {0x18c,
44*53c45f0cShuang lin 	{0x18c, 0xc8, 0x1f4, 0x27, 0x4e,
45*53c45f0cShuang lin 	0x4, 0x8b, 0x06, 0x03, 0x0, 0x06, 0x05, 0x0f, 0x15, 0x06, 0x04, 0x04,
46*53c45f0cShuang lin 	0x06, 0x04, 0x200, 0x03, 0x0a, 0x40, 0x2710, 0x01, 0x05, 0x05, 0x03,
47*53c45f0cShuang lin 	0x0c, 0x28, 0x100, 0x0, 0x04, 0x0},
48*53c45f0cShuang lin 	{{0x420, 0x42, 0x0, 0x0}, 0x01, 0x60},
49*53c45f0cShuang lin 	{0x24717315} };
50*53c45f0cShuang lin 
51*53c45f0cShuang lin /*
52*53c45f0cShuang lin  * [7:6]  bank(n:n bit bank)
53*53c45f0cShuang lin  * [5:4]  row(13+n)
54*53c45f0cShuang lin  * [3]    cs(0:1 cs, 1:2 cs)
55*53c45f0cShuang lin  * [2:1]  bank(n:n bit bank)
56*53c45f0cShuang lin  * [0]    col(10+n)
57*53c45f0cShuang lin  */
58*53c45f0cShuang lin const char ddr_cfg_2_rbc[] = {
59*53c45f0cShuang lin 	((3 << 6) | (3 << 4) | (0 << 3) | (0 << 1) | 1),
60*53c45f0cShuang lin 	((0 << 6) | (1 << 4) | (0 << 3) | (3 << 1) | 0),
61*53c45f0cShuang lin 	((0 << 6) | (2 << 4) | (0 << 3) | (3 << 1) | 0),
62*53c45f0cShuang lin 	((0 << 6) | (3 << 4) | (0 << 3) | (3 << 1) | 0),
63*53c45f0cShuang lin 	((0 << 6) | (1 << 4) | (0 << 3) | (3 << 1) | 1),
64*53c45f0cShuang lin 	((0 << 6) | (2 << 4) | (0 << 3) | (3 << 1) | 1),
65*53c45f0cShuang lin 	((0 << 6) | (3 << 4) | (0 << 3) | (3 << 1) | 1),
66*53c45f0cShuang lin 	((0 << 6) | (0 << 4) | (0 << 3) | (3 << 1) | 0),
67*53c45f0cShuang lin 	((0 << 6) | (0 << 4) | (0 << 3) | (3 << 1) | 1),
68*53c45f0cShuang lin 	((0 << 6) | (3 << 4) | (1 << 3) | (3 << 1) | 0),
69*53c45f0cShuang lin 	((0 << 6) | (3 << 4) | (1 << 3) | (3 << 1) | 1),
70*53c45f0cShuang lin 	((1 << 6) | (2 << 4) | (0 << 3) | (2 << 1) | 0),
71*53c45f0cShuang lin 	((3 << 6) | (2 << 4) | (0 << 3) | (0 << 1) | 1),
72*53c45f0cShuang lin 	((3 << 6) | (3 << 4) | (0 << 3) | (0 << 1) | 0),
73*53c45f0cShuang lin };
74*53c45f0cShuang lin 
75*53c45f0cShuang lin /* DDRPHY REG */
76*53c45f0cShuang lin enum {
77*53c45f0cShuang lin 	/* DDRPHY_REG1 */
78*53c45f0cShuang lin 	SOFT_RESET_MASK				= 3,
79*53c45f0cShuang lin 	SOFT_RESET_SHIFT			= 2,
80*53c45f0cShuang lin 
81*53c45f0cShuang lin 	/* DDRPHY_REG2 */
82*53c45f0cShuang lin 	MEMORY_SELECT_DDR3			= 0 << 6,
83*53c45f0cShuang lin 	DQS_SQU_CAL_NORMAL_MODE			= 0 << 1,
84*53c45f0cShuang lin 	DQS_SQU_CAL_START			= 1 << 0,
85*53c45f0cShuang lin 	DQS_SQU_NO_CAL				= 0 << 0,
86*53c45f0cShuang lin 
87*53c45f0cShuang lin 	/* DDRPHY_REG2A */
88*53c45f0cShuang lin 	CMD_DLL_BYPASS				= 1 << 4,
89*53c45f0cShuang lin 	CMD_DLL_BYPASS_DISABLE			= 0 << 4,
90*53c45f0cShuang lin 	HIGH_8BIT_DLL_BYPASS			= 1 << 3,
91*53c45f0cShuang lin 	HIGH_8BIT_DLL_BYPASS_DISABLE		= 0 << 3,
92*53c45f0cShuang lin 	LOW_8BIT_DLL_BYPASS			= 1 << 2,
93*53c45f0cShuang lin 	LOW_8BIT_DLL_BYPASS_DISABLE		= 0 << 2,
94*53c45f0cShuang lin 
95*53c45f0cShuang lin 	/* DDRPHY_REG19 */
96*53c45f0cShuang lin 	CMD_FEEDBACK_ENABLE			= 1 << 5,
97*53c45f0cShuang lin 	CMD_SLAVE_DLL_INVERSE_MODE		= 1 << 4,
98*53c45f0cShuang lin 	CMD_SLAVE_DLL_NO_INVERSE_MODE		= 0 << 4,
99*53c45f0cShuang lin 	CMD_SLAVE_DLL_ENALBE			= 1 << 3,
100*53c45f0cShuang lin 	CMD_TX_SLAVE_DLL_DELAY_MASK		= 7,
101*53c45f0cShuang lin 	CMD_TX_SLAVE_DLL_DELAY_SHIFT		= 0,
102*53c45f0cShuang lin 
103*53c45f0cShuang lin 	/* DDRPHY_REG6 */
104*53c45f0cShuang lin 	LEFT_CHN_TX_DQ_PHASE_BYPASS_90		= 1 << 4,
105*53c45f0cShuang lin 	LEFT_CHN_TX_DQ_PHASE_BYPASS_0		= 0 << 4,
106*53c45f0cShuang lin 	LEFT_CHN_TX_DQ_DLL_ENABLE		= 1 << 3,
107*53c45f0cShuang lin 	LEFT_CHN_TX_DQ_DLL_DELAY_MASK		= 7,
108*53c45f0cShuang lin 	LEFT_CHN_TX_DQ_DLL_DELAY_SHIFT		= 0,
109*53c45f0cShuang lin 
110*53c45f0cShuang lin 	/* DDRPHY_REG8 */
111*53c45f0cShuang lin 	LEFT_CHN_RX_DQS_DELAY_TAP_MASK		= 3,
112*53c45f0cShuang lin 	LEFT_CHN_RX_DQS_DELAY_TAP_SHIFT		= 0,
113*53c45f0cShuang lin 
114*53c45f0cShuang lin 	/* DDRPHY_REG9 */
115*53c45f0cShuang lin 	RIGHT_CHN_TX_DQ_PHASE_BYPASS_90		= 1 << 4,
116*53c45f0cShuang lin 	RIGHT_CHN_TX_DQ_PHASE_BYPASS_0		= 0 << 4,
117*53c45f0cShuang lin 	RIGHT_CHN_TX_DQ_DLL_ENABLE		= 1 << 3,
118*53c45f0cShuang lin 	RIGHT_CHN_TX_DQ_DLL_DELAY_MASK		= 7,
119*53c45f0cShuang lin 	RIGHT_CHN_TX_DQ_DLL_DELAY_SHIFT		= 0,
120*53c45f0cShuang lin 
121*53c45f0cShuang lin 	/* DDRPHY_REG11 */
122*53c45f0cShuang lin 	RIGHT_CHN_RX_DQS_DELAY_TAP_MASK		= 3,
123*53c45f0cShuang lin 	RIGHT_CHN_RX_DQS_DELAY_TAP_SHIFT	= 0,
124*53c45f0cShuang lin 
125*53c45f0cShuang lin 	/* DDRPHY_REG62 */
126*53c45f0cShuang lin 	CAL_DONE_MASK				= 3,
127*53c45f0cShuang lin 	HIGH_8BIT_CAL_DONE			= 1 << 1,
128*53c45f0cShuang lin 	LOW_8BIT_CAL_DONE			= 1 << 0,
129*53c45f0cShuang lin };
130*53c45f0cShuang lin 
131*53c45f0cShuang lin /* PTCL */
132*53c45f0cShuang lin enum {
133*53c45f0cShuang lin 	/* PCTL_DFISTCFG0 */
134*53c45f0cShuang lin 	DFI_INIT_START			= 1 << 0,
135*53c45f0cShuang lin 	DFI_DATA_BYTE_DISABLE_EN	= 1 << 2,
136*53c45f0cShuang lin 
137*53c45f0cShuang lin 	/* PCTL_DFISTCFG1 */
138*53c45f0cShuang lin 	DFI_DRAM_CLK_SR_EN		= 1 << 0,
139*53c45f0cShuang lin 	DFI_DRAM_CLK_DPD_EN		= 1 << 1,
140*53c45f0cShuang lin 
141*53c45f0cShuang lin 	/* PCTL_DFISTCFG2 */
142*53c45f0cShuang lin 	DFI_PARITY_INTR_EN		= 1 << 0,
143*53c45f0cShuang lin 	DFI_PARITY_EN			= 1 << 1,
144*53c45f0cShuang lin 
145*53c45f0cShuang lin 	/* PCTL_DFILPCFG0 */
146*53c45f0cShuang lin 	TLP_RESP_TIME_SHIFT		= 16,
147*53c45f0cShuang lin 	LP_SR_EN			= 1 << 8,
148*53c45f0cShuang lin 	LP_PD_EN			= 1 << 0,
149*53c45f0cShuang lin 
150*53c45f0cShuang lin 	/* PCTL_DFIODTCFG */
151*53c45f0cShuang lin 	RANK0_ODT_WRITE_SEL		= 1 << 3,
152*53c45f0cShuang lin 	RANK1_ODT_WRITE_SEL		= 1 << 11,
153*53c45f0cShuang lin 
154*53c45f0cShuang lin 	/* PCTL_DFIODTCFG1 */
155*53c45f0cShuang lin 	ODT_LEN_BL8_W_SHIFT		= 16,
156*53c45f0cShuang lin 
157*53c45f0cShuang lin 	/* PCTL_MCFG */
158*53c45f0cShuang lin 	TFAW_CFG_MASK			= 3,
159*53c45f0cShuang lin 	TFAW_CFG_SHIFT			= 18,
160*53c45f0cShuang lin 	PD_EXIT_SLOW_MODE		= 0 << 17,
161*53c45f0cShuang lin 	PD_ACTIVE_POWER_DOWN		= 1 << 16,
162*53c45f0cShuang lin 	PD_IDLE_MASK			= 0xff,
163*53c45f0cShuang lin 	PD_IDLE_SHIFT			= 8,
164*53c45f0cShuang lin 	MEM_BL4				= 0 << 0,
165*53c45f0cShuang lin 	MEM_BL8				= 1 << 0,
166*53c45f0cShuang lin 
167*53c45f0cShuang lin 	/* PCTL_MCFG1 */
168*53c45f0cShuang lin 	HW_EXIT_IDLE_EN_MASK		= 1,
169*53c45f0cShuang lin 	HW_EXIT_IDLE_EN_SHIFT		= 31,
170*53c45f0cShuang lin 	SR_IDLE_MASK			= 0x1ff,
171*53c45f0cShuang lin 	SR_IDLE_SHIFT			= 0,
172*53c45f0cShuang lin 
173*53c45f0cShuang lin 	/* PCTL_SCFG */
174*53c45f0cShuang lin 	HW_LOW_POWER_EN			= 1 << 0,
175*53c45f0cShuang lin 
176*53c45f0cShuang lin 	/* PCTL_POWCTL */
177*53c45f0cShuang lin 	POWER_UP_START			= 1 << 0,
178*53c45f0cShuang lin 
179*53c45f0cShuang lin 	/* PCTL_POWSTAT */
180*53c45f0cShuang lin 	POWER_UP_DONE			= 1 << 0,
181*53c45f0cShuang lin 
182*53c45f0cShuang lin 	/* PCTL_MCMD */
183*53c45f0cShuang lin 	START_CMD			= 1 << 31,
184*53c45f0cShuang lin 	BANK_ADDR_MASK			= 7,
185*53c45f0cShuang lin 	BANK_ADDR_SHIFT			= 17,
186*53c45f0cShuang lin 	CMD_ADDR_MASK			= 0x1fff,
187*53c45f0cShuang lin 	CMD_ADDR_SHIFT			= 4,
188*53c45f0cShuang lin 	DESELECT_CMD			= 0,
189*53c45f0cShuang lin 	PREA_CMD,
190*53c45f0cShuang lin 	REF_CMD,
191*53c45f0cShuang lin 	MRS_CMD,
192*53c45f0cShuang lin 	ZQCS_CMD,
193*53c45f0cShuang lin 	ZQCL_CMD,
194*53c45f0cShuang lin 	RSTL_CMD,
195*53c45f0cShuang lin 	MRR_CMD				= 8,
196*53c45f0cShuang lin 
197*53c45f0cShuang lin 	/* PCTL_STAT */
198*53c45f0cShuang lin 	INIT_MEM			= 0,
199*53c45f0cShuang lin 	CONFIG,
200*53c45f0cShuang lin 	CONFIG_REQ,
201*53c45f0cShuang lin 	ACCESS,
202*53c45f0cShuang lin 	ACCESS_REQ,
203*53c45f0cShuang lin 	LOW_POWER,
204*53c45f0cShuang lin 	LOW_POWER_ENTRY_REQ,
205*53c45f0cShuang lin 	LOW_POWER_EXIT_REQ,
206*53c45f0cShuang lin 	PCTL_STAT_MASK			= 7,
207*53c45f0cShuang lin 
208*53c45f0cShuang lin 	/* PCTL_SCTL */
209*53c45f0cShuang lin 	INIT_STATE			= 0,
210*53c45f0cShuang lin 	CFG_STATE			= 1,
211*53c45f0cShuang lin 	GO_STATE			= 2,
212*53c45f0cShuang lin 	SLEEP_STATE			= 3,
213*53c45f0cShuang lin 	WAKEUP_STATE			= 4,
214*53c45f0cShuang lin };
215*53c45f0cShuang lin 
216*53c45f0cShuang lin /* GRF_SOC_CON2 */
217*53c45f0cShuang lin #define	MSCH4_MAINDDR3		(1 << 7)
218*53c45f0cShuang lin #define PHY_DRV_ODT_SET(n)	((n << 4) | n)
219*53c45f0cShuang lin #define DDR3_DLL_RESET		(1 << 8)
220*53c45f0cShuang lin 
221*53c45f0cShuang lin /* CK pull up/down driver strength control */
222*53c45f0cShuang lin enum {
223*53c45f0cShuang lin 	PHY_RON_DISABLE		= 0,
224*53c45f0cShuang lin 	PHY_RON_309OHM		= 1,
225*53c45f0cShuang lin 	PHY_RON_155OHM,
226*53c45f0cShuang lin 	PHY_RON_103OHM		= 3,
227*53c45f0cShuang lin 	PHY_RON_63OHM		= 5,
228*53c45f0cShuang lin 	PHY_RON_45OHM		= 7,
229*53c45f0cShuang lin 	PHY_RON_77OHM,
230*53c45f0cShuang lin 	PHY_RON_62OHM,
231*53c45f0cShuang lin 	PHY_RON_52OHM,
232*53c45f0cShuang lin 	PHY_RON_44OHM,
233*53c45f0cShuang lin 	PHY_RON_39OHM,
234*53c45f0cShuang lin 	PHY_RON_34OHM,
235*53c45f0cShuang lin 	PHY_RON_31OHM,
236*53c45f0cShuang lin 	PHY_RON_28OHM,
237*53c45f0cShuang lin };
238*53c45f0cShuang lin 
239*53c45f0cShuang lin /* DQ pull up/down control */
240*53c45f0cShuang lin enum {
241*53c45f0cShuang lin 	PHY_RTT_DISABLE		= 0,
242*53c45f0cShuang lin 	PHY_RTT_861OHM		= 1,
243*53c45f0cShuang lin 	PHY_RTT_431OHM,
244*53c45f0cShuang lin 	PHY_RTT_287OHM,
245*53c45f0cShuang lin 	PHY_RTT_216OHM,
246*53c45f0cShuang lin 	PHY_RTT_172OHM,
247*53c45f0cShuang lin 	PHY_RTT_145OHM,
248*53c45f0cShuang lin 	PHY_RTT_124OHM,
249*53c45f0cShuang lin 	PHY_RTT_215OHM,
250*53c45f0cShuang lin 	PHY_RTT_144OHM		= 0xa,
251*53c45f0cShuang lin 	PHY_RTT_123OHM,
252*53c45f0cShuang lin 	PHY_RTT_108OHM,
253*53c45f0cShuang lin 	PHY_RTT_96OHM,
254*53c45f0cShuang lin 	PHY_RTT_86OHM,
255*53c45f0cShuang lin 	PHY_RTT_78OHM,
256*53c45f0cShuang lin };
257*53c45f0cShuang lin 
258*53c45f0cShuang lin /* DQS squelch DLL delay */
259*53c45f0cShuang lin enum {
260*53c45f0cShuang lin 	DQS_DLL_NO_DELAY	= 0,
261*53c45f0cShuang lin 	DQS_DLL_22P5_DELAY,
262*53c45f0cShuang lin 	DQS_DLL_45_DELAY,
263*53c45f0cShuang lin 	DQS_DLL_67P5_DELAY,
264*53c45f0cShuang lin 	DQS_DLL_90_DELAY,
265*53c45f0cShuang lin 	DQS_DLL_112P5_DELAY,
266*53c45f0cShuang lin 	DQS_DLL_135_DELAY,
267*53c45f0cShuang lin 	DQS_DLL_157P5_DELAY,
268*53c45f0cShuang lin };
269*53c45f0cShuang lin 
270*53c45f0cShuang lin /* GRF_OS_REG1 */
271*53c45f0cShuang lin enum {
272*53c45f0cShuang lin 	/*
273*53c45f0cShuang lin 	 * 000: lpddr
274*53c45f0cShuang lin 	 * 001: ddr
275*53c45f0cShuang lin 	 * 010: ddr2
276*53c45f0cShuang lin 	 * 011: ddr3
277*53c45f0cShuang lin 	 * 100: lpddr2-s2
278*53c45f0cShuang lin 	 * 101: lpddr2-s4
279*53c45f0cShuang lin 	 * 110: lpddr3
280*53c45f0cShuang lin 	 */
281*53c45f0cShuang lin 	DDR_TYPE_MASK		= 7,
282*53c45f0cShuang lin 	DDR_TYPE_SHIFT		= 13,
283*53c45f0cShuang lin 
284*53c45f0cShuang lin 	/* 0: 1 chn, 1: 2 chn */
285*53c45f0cShuang lin 	DDR_CHN_CNT_SHIFT	= 12,
286*53c45f0cShuang lin 
287*53c45f0cShuang lin 	/* 0: 1 rank, 1: 2 rank */
288*53c45f0cShuang lin 	DDR_RANK_CNT_MASK	= 1,
289*53c45f0cShuang lin 	DDR_RANK_CNT_SHIFT	= 11,
290*53c45f0cShuang lin 
291*53c45f0cShuang lin 	/*
292*53c45f0cShuang lin 	 * 00: 9col
293*53c45f0cShuang lin 	 * 01: 10col
294*53c45f0cShuang lin 	 * 10: 11col
295*53c45f0cShuang lin 	 * 11: 12col
296*53c45f0cShuang lin 	 */
297*53c45f0cShuang lin 	DDR_COL_MASK		= 3,
298*53c45f0cShuang lin 	DDR_COL_SHIFT		= 9,
299*53c45f0cShuang lin 
300*53c45f0cShuang lin 	/* 0: 8 bank, 1: 4 bank*/
301*53c45f0cShuang lin 	DDR_BANK_MASK		= 1,
302*53c45f0cShuang lin 	DDR_BANK_SHIFT		= 8,
303*53c45f0cShuang lin 
304*53c45f0cShuang lin 	/*
305*53c45f0cShuang lin 	 * 00: 13 row
306*53c45f0cShuang lin 	 * 01: 14 row
307*53c45f0cShuang lin 	 * 10: 15 row
308*53c45f0cShuang lin 	 * 11: 16 row
309*53c45f0cShuang lin 	 */
310*53c45f0cShuang lin 	DDR_CS0_ROW_MASK	= 3,
311*53c45f0cShuang lin 	DDR_CS0_ROW_SHIFT	= 6,
312*53c45f0cShuang lin 	DDR_CS1_ROW_MASK	= 3,
313*53c45f0cShuang lin 	DDR_CS1_ROW_SHIFT	= 4,
314*53c45f0cShuang lin 
315*53c45f0cShuang lin 	/*
316*53c45f0cShuang lin 	 * 00: 32 bit
317*53c45f0cShuang lin 	 * 01: 16 bit
318*53c45f0cShuang lin 	 * 10: 8 bit
319*53c45f0cShuang lin 	 * rk3036 only support 16bit
320*53c45f0cShuang lin 	 */
321*53c45f0cShuang lin 	DDR_BW_MASK		= 3,
322*53c45f0cShuang lin 	DDR_BW_SHIFT		= 2,
323*53c45f0cShuang lin 	DDR_DIE_BW_MASK		= 3,
324*53c45f0cShuang lin 	DDR_DIE_BW_SHIFT	= 0,
325*53c45f0cShuang lin };
326*53c45f0cShuang lin 
327*53c45f0cShuang lin static void rkdclk_init(struct rk3036_sdram_priv *priv)
328*53c45f0cShuang lin {
329*53c45f0cShuang lin 	struct rk3036_pll *pll = &priv->cru->pll[1];
330*53c45f0cShuang lin 
331*53c45f0cShuang lin 	/* pll enter slow-mode */
332*53c45f0cShuang lin 	rk_clrsetreg(&priv->cru->cru_mode_con,
333*53c45f0cShuang lin 		     DPLL_MODE_MASK << DPLL_MODE_SHIFT,
334*53c45f0cShuang lin 		     DPLL_MODE_SLOW << DPLL_MODE_SHIFT);
335*53c45f0cShuang lin 
336*53c45f0cShuang lin 	/* use integer mode */
337*53c45f0cShuang lin 	rk_clrreg(&pll->con1, 1 << PLL_DSMPD_SHIFT);
338*53c45f0cShuang lin 
339*53c45f0cShuang lin 	rk_clrsetreg(&pll->con0,
340*53c45f0cShuang lin 		     PLL_POSTDIV1_MASK << PLL_POSTDIV1_SHIFT | PLL_FBDIV_MASK,
341*53c45f0cShuang lin 		     (dpll_init_cfg.postdiv1 << PLL_POSTDIV1_SHIFT) |
342*53c45f0cShuang lin 			dpll_init_cfg.fbdiv);
343*53c45f0cShuang lin 	rk_clrsetreg(&pll->con1, PLL_POSTDIV2_MASK << PLL_POSTDIV2_SHIFT |
344*53c45f0cShuang lin 			PLL_REFDIV_MASK << PLL_REFDIV_SHIFT,
345*53c45f0cShuang lin 			(dpll_init_cfg.postdiv2 << PLL_POSTDIV2_SHIFT |
346*53c45f0cShuang lin 			 dpll_init_cfg.refdiv << PLL_REFDIV_SHIFT));
347*53c45f0cShuang lin 
348*53c45f0cShuang lin 	/* waiting for pll lock */
349*53c45f0cShuang lin 	while (readl(&pll->con1) & (1 << PLL_LOCK_STATUS_SHIFT))
350*53c45f0cShuang lin 		rockchip_udelay(1);
351*53c45f0cShuang lin 
352*53c45f0cShuang lin 	/* PLL enter normal-mode */
353*53c45f0cShuang lin 	rk_clrsetreg(&priv->cru->cru_mode_con,
354*53c45f0cShuang lin 		     DPLL_MODE_MASK << DPLL_MODE_SHIFT,
355*53c45f0cShuang lin 		     DPLL_MODE_NORM << DPLL_MODE_SHIFT);
356*53c45f0cShuang lin }
357*53c45f0cShuang lin 
358*53c45f0cShuang lin static void copy_to_reg(u32 *dest, const u32 *src, u32 n)
359*53c45f0cShuang lin {
360*53c45f0cShuang lin 	int i;
361*53c45f0cShuang lin 
362*53c45f0cShuang lin 	for (i = 0; i < n / sizeof(u32); i++) {
363*53c45f0cShuang lin 		writel(*src, dest);
364*53c45f0cShuang lin 		src++;
365*53c45f0cShuang lin 		dest++;
366*53c45f0cShuang lin 	}
367*53c45f0cShuang lin }
368*53c45f0cShuang lin 
369*53c45f0cShuang lin void phy_pctrl_reset(struct rk3036_sdram_priv *priv)
370*53c45f0cShuang lin {
371*53c45f0cShuang lin 	struct rk3036_ddr_phy *ddr_phy = priv->phy;
372*53c45f0cShuang lin 
373*53c45f0cShuang lin 	rk_clrsetreg(&priv->cru->cru_softrst_con[5], 1 << DDRCTRL_PSRST_SHIFT |
374*53c45f0cShuang lin 			1 << DDRCTRL_SRST_SHIFT | 1 << DDRPHY_PSRST_SHIFT |
375*53c45f0cShuang lin 			1 << DDRPHY_SRST_SHIFT,
376*53c45f0cShuang lin 			1 << DDRCTRL_PSRST_SHIFT | 1 << DDRCTRL_SRST_SHIFT |
377*53c45f0cShuang lin 			1 << DDRPHY_PSRST_SHIFT | 1 << DDRPHY_SRST_SHIFT);
378*53c45f0cShuang lin 
379*53c45f0cShuang lin 	rockchip_udelay(10);
380*53c45f0cShuang lin 
381*53c45f0cShuang lin 	rk_clrreg(&priv->cru->cru_softrst_con[5], 1 << DDRPHY_PSRST_SHIFT |
382*53c45f0cShuang lin 						  1 << DDRPHY_SRST_SHIFT);
383*53c45f0cShuang lin 	rockchip_udelay(10);
384*53c45f0cShuang lin 
385*53c45f0cShuang lin 	rk_clrreg(&priv->cru->cru_softrst_con[5], 1 << DDRCTRL_PSRST_SHIFT |
386*53c45f0cShuang lin 						  1 << DDRCTRL_SRST_SHIFT);
387*53c45f0cShuang lin 	rockchip_udelay(10);
388*53c45f0cShuang lin 
389*53c45f0cShuang lin 	clrsetbits_le32(&ddr_phy->ddrphy_reg1,
390*53c45f0cShuang lin 			SOFT_RESET_MASK << SOFT_RESET_SHIFT,
391*53c45f0cShuang lin 			0 << SOFT_RESET_SHIFT);
392*53c45f0cShuang lin 	rockchip_udelay(10);
393*53c45f0cShuang lin 	clrsetbits_le32(&ddr_phy->ddrphy_reg1,
394*53c45f0cShuang lin 			SOFT_RESET_MASK << SOFT_RESET_SHIFT,
395*53c45f0cShuang lin 			3 << SOFT_RESET_SHIFT);
396*53c45f0cShuang lin 
397*53c45f0cShuang lin 	rockchip_udelay(1);
398*53c45f0cShuang lin }
399*53c45f0cShuang lin 
400*53c45f0cShuang lin void phy_dll_bypass_set(struct rk3036_sdram_priv *priv, unsigned int freq)
401*53c45f0cShuang lin {
402*53c45f0cShuang lin 	struct rk3036_ddr_phy *ddr_phy = priv->phy;
403*53c45f0cShuang lin 
404*53c45f0cShuang lin 	if (freq < ddr_timing.freq) {
405*53c45f0cShuang lin 		writel(CMD_DLL_BYPASS | HIGH_8BIT_DLL_BYPASS |
406*53c45f0cShuang lin 			LOW_8BIT_DLL_BYPASS, &ddr_phy->ddrphy_reg2a);
407*53c45f0cShuang lin 
408*53c45f0cShuang lin 		writel(LEFT_CHN_TX_DQ_PHASE_BYPASS_90 |
409*53c45f0cShuang lin 			LEFT_CHN_TX_DQ_DLL_ENABLE |
410*53c45f0cShuang lin 			(0 & LEFT_CHN_TX_DQ_DLL_DELAY_MASK) <<
411*53c45f0cShuang lin 			 LEFT_CHN_TX_DQ_DLL_DELAY_SHIFT, &ddr_phy->ddrphy_reg6);
412*53c45f0cShuang lin 
413*53c45f0cShuang lin 		writel(RIGHT_CHN_TX_DQ_PHASE_BYPASS_90 |
414*53c45f0cShuang lin 			RIGHT_CHN_TX_DQ_DLL_ENABLE |
415*53c45f0cShuang lin 			(0 & RIGHT_CHN_TX_DQ_DLL_DELAY_MASK) <<
416*53c45f0cShuang lin 			 RIGHT_CHN_TX_DQ_DLL_DELAY_SHIFT,
417*53c45f0cShuang lin 			&ddr_phy->ddrphy_reg9);
418*53c45f0cShuang lin 	} else {
419*53c45f0cShuang lin 		writel(CMD_DLL_BYPASS_DISABLE | HIGH_8BIT_DLL_BYPASS_DISABLE |
420*53c45f0cShuang lin 			LOW_8BIT_DLL_BYPASS_DISABLE, &ddr_phy->ddrphy_reg2a);
421*53c45f0cShuang lin 
422*53c45f0cShuang lin 		writel(LEFT_CHN_TX_DQ_PHASE_BYPASS_0 |
423*53c45f0cShuang lin 			LEFT_CHN_TX_DQ_DLL_ENABLE |
424*53c45f0cShuang lin 			(4 & LEFT_CHN_TX_DQ_DLL_DELAY_MASK) <<
425*53c45f0cShuang lin 			 LEFT_CHN_TX_DQ_DLL_DELAY_SHIFT,
426*53c45f0cShuang lin 			&ddr_phy->ddrphy_reg6);
427*53c45f0cShuang lin 
428*53c45f0cShuang lin 		writel(RIGHT_CHN_TX_DQ_PHASE_BYPASS_0 |
429*53c45f0cShuang lin 			RIGHT_CHN_TX_DQ_DLL_ENABLE |
430*53c45f0cShuang lin 			(4 & RIGHT_CHN_TX_DQ_DLL_DELAY_MASK) <<
431*53c45f0cShuang lin 			 RIGHT_CHN_TX_DQ_DLL_DELAY_SHIFT,
432*53c45f0cShuang lin 			&ddr_phy->ddrphy_reg9);
433*53c45f0cShuang lin 	}
434*53c45f0cShuang lin 
435*53c45f0cShuang lin 	writel(CMD_SLAVE_DLL_NO_INVERSE_MODE | CMD_SLAVE_DLL_ENALBE |
436*53c45f0cShuang lin 			(0 & CMD_TX_SLAVE_DLL_DELAY_MASK) <<
437*53c45f0cShuang lin 			CMD_TX_SLAVE_DLL_DELAY_SHIFT, &ddr_phy->ddrphy_reg19);
438*53c45f0cShuang lin 
439*53c45f0cShuang lin 	/* 45 degree delay */
440*53c45f0cShuang lin 	writel((DQS_DLL_45_DELAY & LEFT_CHN_RX_DQS_DELAY_TAP_MASK) <<
441*53c45f0cShuang lin 		LEFT_CHN_RX_DQS_DELAY_TAP_SHIFT, &ddr_phy->ddrphy_reg8);
442*53c45f0cShuang lin 	writel((DQS_DLL_45_DELAY & RIGHT_CHN_RX_DQS_DELAY_TAP_MASK) <<
443*53c45f0cShuang lin 		RIGHT_CHN_RX_DQS_DELAY_TAP_SHIFT, &ddr_phy->ddrphy_reg11);
444*53c45f0cShuang lin }
445*53c45f0cShuang lin 
446*53c45f0cShuang lin static void send_command(struct rk3036_ddr_pctl *pctl,
447*53c45f0cShuang lin 			 u32 rank, u32 cmd, u32 arg)
448*53c45f0cShuang lin {
449*53c45f0cShuang lin 	writel((START_CMD | (rank << 20) | arg | cmd), &pctl->mcmd);
450*53c45f0cShuang lin 	rockchip_udelay(1);
451*53c45f0cShuang lin 	while (readl(&pctl->mcmd) & START_CMD)
452*53c45f0cShuang lin 		;
453*53c45f0cShuang lin }
454*53c45f0cShuang lin 
455*53c45f0cShuang lin static void memory_init(struct rk3036_sdram_priv *priv)
456*53c45f0cShuang lin {
457*53c45f0cShuang lin 	struct rk3036_ddr_pctl *pctl = priv->pctl;
458*53c45f0cShuang lin 
459*53c45f0cShuang lin 	send_command(pctl, 3, DESELECT_CMD, 0);
460*53c45f0cShuang lin 	rockchip_udelay(1);
461*53c45f0cShuang lin 	send_command(pctl, 3, PREA_CMD, 0);
462*53c45f0cShuang lin 	send_command(pctl, 3, MRS_CMD,
463*53c45f0cShuang lin 		     (0x02 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT |
464*53c45f0cShuang lin 		     (ddr_timing.phy_timing.mr[2] & CMD_ADDR_MASK) <<
465*53c45f0cShuang lin 		     CMD_ADDR_SHIFT);
466*53c45f0cShuang lin 
467*53c45f0cShuang lin 	send_command(pctl, 3, MRS_CMD,
468*53c45f0cShuang lin 		     (0x03 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT |
469*53c45f0cShuang lin 		     (ddr_timing.phy_timing.mr[3] & CMD_ADDR_MASK) <<
470*53c45f0cShuang lin 		     CMD_ADDR_SHIFT);
471*53c45f0cShuang lin 
472*53c45f0cShuang lin 	send_command(pctl, 3, MRS_CMD,
473*53c45f0cShuang lin 		     (0x01 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT |
474*53c45f0cShuang lin 		     (ddr_timing.phy_timing.mr[1] & CMD_ADDR_MASK) <<
475*53c45f0cShuang lin 		     CMD_ADDR_SHIFT);
476*53c45f0cShuang lin 
477*53c45f0cShuang lin 	send_command(pctl, 3, MRS_CMD,
478*53c45f0cShuang lin 		     (0x00 & BANK_ADDR_MASK) << BANK_ADDR_SHIFT |
479*53c45f0cShuang lin 		     (ddr_timing.phy_timing.mr[0] & CMD_ADDR_MASK) <<
480*53c45f0cShuang lin 		     CMD_ADDR_SHIFT | DDR3_DLL_RESET);
481*53c45f0cShuang lin 
482*53c45f0cShuang lin 	send_command(pctl, 3, ZQCL_CMD, 0);
483*53c45f0cShuang lin }
484*53c45f0cShuang lin 
485*53c45f0cShuang lin static void data_training(struct rk3036_sdram_priv *priv)
486*53c45f0cShuang lin {
487*53c45f0cShuang lin 	struct rk3036_ddr_phy *ddr_phy = priv->phy;
488*53c45f0cShuang lin 	struct rk3036_ddr_pctl *pctl = priv->pctl;
489*53c45f0cShuang lin 	u32 value;
490*53c45f0cShuang lin 
491*53c45f0cShuang lin 	/* disable auto refresh */
492*53c45f0cShuang lin 	value = readl(&pctl->trefi),
493*53c45f0cShuang lin 	writel(0, &pctl->trefi);
494*53c45f0cShuang lin 
495*53c45f0cShuang lin 	clrsetbits_le32(&ddr_phy->ddrphy_reg2, 0x03,
496*53c45f0cShuang lin 			DQS_SQU_CAL_NORMAL_MODE | DQS_SQU_CAL_START);
497*53c45f0cShuang lin 
498*53c45f0cShuang lin 	rockchip_udelay(1);
499*53c45f0cShuang lin 	while ((readl(&ddr_phy->ddrphy_reg62) & CAL_DONE_MASK) !=
500*53c45f0cShuang lin 		(HIGH_8BIT_CAL_DONE | LOW_8BIT_CAL_DONE)) {
501*53c45f0cShuang lin 		;
502*53c45f0cShuang lin 	}
503*53c45f0cShuang lin 
504*53c45f0cShuang lin 	clrsetbits_le32(&ddr_phy->ddrphy_reg2, 0x03,
505*53c45f0cShuang lin 			DQS_SQU_CAL_NORMAL_MODE | DQS_SQU_NO_CAL);
506*53c45f0cShuang lin 
507*53c45f0cShuang lin 	/*
508*53c45f0cShuang lin 	 * since data training will take about 20us, so send some auto
509*53c45f0cShuang lin 	 * refresh(about 7.8us) to complement the lost time
510*53c45f0cShuang lin 	 */
511*53c45f0cShuang lin 	send_command(pctl, 3, REF_CMD, 0);
512*53c45f0cShuang lin 	send_command(pctl, 3, REF_CMD, 0);
513*53c45f0cShuang lin 	send_command(pctl, 3, REF_CMD, 0);
514*53c45f0cShuang lin 
515*53c45f0cShuang lin 	writel(value, &pctl->trefi);
516*53c45f0cShuang lin }
517*53c45f0cShuang lin 
518*53c45f0cShuang lin static void move_to_config_state(struct rk3036_sdram_priv *priv)
519*53c45f0cShuang lin {
520*53c45f0cShuang lin 	unsigned int state;
521*53c45f0cShuang lin 	struct rk3036_ddr_pctl *pctl = priv->pctl;
522*53c45f0cShuang lin 
523*53c45f0cShuang lin 	while (1) {
524*53c45f0cShuang lin 		state = readl(&pctl->stat) & PCTL_STAT_MASK;
525*53c45f0cShuang lin 		switch (state) {
526*53c45f0cShuang lin 		case LOW_POWER:
527*53c45f0cShuang lin 			writel(WAKEUP_STATE, &pctl->sctl);
528*53c45f0cShuang lin 			while ((readl(&pctl->stat) & PCTL_STAT_MASK)
529*53c45f0cShuang lin 				!= ACCESS)
530*53c45f0cShuang lin 				;
531*53c45f0cShuang lin 			/*
532*53c45f0cShuang lin 			 * If at low power state, need wakeup first, and then
533*53c45f0cShuang lin 			 * enter the config, so fallthrough
534*53c45f0cShuang lin 			 */
535*53c45f0cShuang lin 		case ACCESS:
536*53c45f0cShuang lin 			/* fallthrough */
537*53c45f0cShuang lin 		case INIT_MEM:
538*53c45f0cShuang lin 			writel(CFG_STATE, &pctl->sctl);
539*53c45f0cShuang lin 			while ((readl(&pctl->stat) & PCTL_STAT_MASK) != CONFIG)
540*53c45f0cShuang lin 				;
541*53c45f0cShuang lin 			break;
542*53c45f0cShuang lin 		case CONFIG:
543*53c45f0cShuang lin 			return;
544*53c45f0cShuang lin 		default:
545*53c45f0cShuang lin 			break;
546*53c45f0cShuang lin 		}
547*53c45f0cShuang lin 	}
548*53c45f0cShuang lin }
549*53c45f0cShuang lin 
550*53c45f0cShuang lin static void move_to_access_state(struct rk3036_sdram_priv *priv)
551*53c45f0cShuang lin {
552*53c45f0cShuang lin 	unsigned int state;
553*53c45f0cShuang lin 	struct rk3036_ddr_pctl *pctl = priv->pctl;
554*53c45f0cShuang lin 
555*53c45f0cShuang lin 	while (1) {
556*53c45f0cShuang lin 		state = readl(&pctl->stat) & PCTL_STAT_MASK;
557*53c45f0cShuang lin 		switch (state) {
558*53c45f0cShuang lin 		case LOW_POWER:
559*53c45f0cShuang lin 			writel(WAKEUP_STATE, &pctl->sctl);
560*53c45f0cShuang lin 			while ((readl(&pctl->stat) & PCTL_STAT_MASK) != ACCESS)
561*53c45f0cShuang lin 				;
562*53c45f0cShuang lin 			break;
563*53c45f0cShuang lin 		case INIT_MEM:
564*53c45f0cShuang lin 			writel(CFG_STATE, &pctl->sctl);
565*53c45f0cShuang lin 			while ((readl(&pctl->stat) & PCTL_STAT_MASK) != CONFIG)
566*53c45f0cShuang lin 				;
567*53c45f0cShuang lin 			/* fallthrough */
568*53c45f0cShuang lin 		case CONFIG:
569*53c45f0cShuang lin 			writel(GO_STATE, &pctl->sctl);
570*53c45f0cShuang lin 			while ((readl(&pctl->stat) & PCTL_STAT_MASK) != ACCESS)
571*53c45f0cShuang lin 				;
572*53c45f0cShuang lin 			break;
573*53c45f0cShuang lin 		case ACCESS:
574*53c45f0cShuang lin 			return;
575*53c45f0cShuang lin 		default:
576*53c45f0cShuang lin 			break;
577*53c45f0cShuang lin 		}
578*53c45f0cShuang lin 	}
579*53c45f0cShuang lin }
580*53c45f0cShuang lin 
581*53c45f0cShuang lin static void pctl_cfg(struct rk3036_sdram_priv *priv)
582*53c45f0cShuang lin {
583*53c45f0cShuang lin 	struct rk3036_ddr_pctl *pctl = priv->pctl;
584*53c45f0cShuang lin 	u32 burst_len;
585*53c45f0cShuang lin 	u32 reg;
586*53c45f0cShuang lin 
587*53c45f0cShuang lin 	writel(DFI_INIT_START | DFI_DATA_BYTE_DISABLE_EN, &pctl->dfistcfg0);
588*53c45f0cShuang lin 	writel(DFI_DRAM_CLK_SR_EN | DFI_DRAM_CLK_DPD_EN, &pctl->dfistcfg1);
589*53c45f0cShuang lin 	writel(DFI_PARITY_INTR_EN | DFI_PARITY_EN, &pctl->dfistcfg2);
590*53c45f0cShuang lin 	writel(7 << TLP_RESP_TIME_SHIFT | LP_SR_EN | LP_PD_EN,
591*53c45f0cShuang lin 	       &pctl->dfilpcfg0);
592*53c45f0cShuang lin 
593*53c45f0cShuang lin 	writel(1, &pctl->dfitphyupdtype0);
594*53c45f0cShuang lin 	writel(0x0d, &pctl->dfitphyrdlat);
595*53c45f0cShuang lin 
596*53c45f0cShuang lin 	/* cs0 and cs1 write odt enable */
597*53c45f0cShuang lin 	writel((RANK0_ODT_WRITE_SEL | RANK1_ODT_WRITE_SEL),
598*53c45f0cShuang lin 	       &pctl->dfiodtcfg);
599*53c45f0cShuang lin 
600*53c45f0cShuang lin 	/* odt write length */
601*53c45f0cShuang lin 	writel(7 << ODT_LEN_BL8_W_SHIFT, &pctl->dfiodtcfg1);
602*53c45f0cShuang lin 
603*53c45f0cShuang lin 	/* phyupd and ctrlupd disabled */
604*53c45f0cShuang lin 	writel(0, &pctl->dfiupdcfg);
605*53c45f0cShuang lin 
606*53c45f0cShuang lin 	if ((ddr_timing.noc_timing.burstlen << 1) == 4)
607*53c45f0cShuang lin 		burst_len = MEM_BL4;
608*53c45f0cShuang lin 	else
609*53c45f0cShuang lin 		burst_len = MEM_BL8;
610*53c45f0cShuang lin 
611*53c45f0cShuang lin 	copy_to_reg(&pctl->togcnt1u, &ddr_timing.pctl_timing.togcnt1u,
612*53c45f0cShuang lin 		    sizeof(struct rk3036_pctl_timing));
613*53c45f0cShuang lin 	reg = readl(&pctl->tcl);
614*53c45f0cShuang lin 	writel(reg - 3, &pctl->dfitrddataen);
615*53c45f0cShuang lin 	reg = readl(&pctl->tcwl);
616*53c45f0cShuang lin 	writel(reg - 1, &pctl->dfitphywrlat);
617*53c45f0cShuang lin 
618*53c45f0cShuang lin 	writel(burst_len | (1 & TFAW_CFG_MASK) << TFAW_CFG_SHIFT |
619*53c45f0cShuang lin 			PD_EXIT_SLOW_MODE | PD_ACTIVE_POWER_DOWN |
620*53c45f0cShuang lin 			(0 & PD_IDLE_MASK) << PD_IDLE_SHIFT,
621*53c45f0cShuang lin 			&pctl->mcfg);
622*53c45f0cShuang lin 
623*53c45f0cShuang lin 	writel(RK_SETBITS(MSCH4_MAINDDR3), &priv->grf->soc_con2);
624*53c45f0cShuang lin 	setbits_le32(&pctl->scfg, HW_LOW_POWER_EN);
625*53c45f0cShuang lin }
626*53c45f0cShuang lin 
627*53c45f0cShuang lin static void phy_cfg(struct rk3036_sdram_priv *priv)
628*53c45f0cShuang lin {
629*53c45f0cShuang lin 	struct rk3036_ddr_phy *ddr_phy = priv->phy;
630*53c45f0cShuang lin 	struct rk3036_service_sys *axi_bus = priv->axi_bus;
631*53c45f0cShuang lin 
632*53c45f0cShuang lin 	writel(ddr_timing.noc_timing.noc_timing, &axi_bus->ddrtiming);
633*53c45f0cShuang lin 	writel(0x3f, &axi_bus->readlatency);
634*53c45f0cShuang lin 
635*53c45f0cShuang lin 	writel(MEMORY_SELECT_DDR3 | DQS_SQU_CAL_NORMAL_MODE,
636*53c45f0cShuang lin 	       &ddr_phy->ddrphy_reg2);
637*53c45f0cShuang lin 
638*53c45f0cShuang lin 	clrsetbits_le32(&ddr_phy->ddrphy_reg3, 1, ddr_timing.phy_timing.bl);
639*53c45f0cShuang lin 	writel(ddr_timing.phy_timing.cl_al, &ddr_phy->ddrphy_reg4a);
640*53c45f0cShuang lin 	writel(PHY_DRV_ODT_SET(PHY_RON_44OHM), &ddr_phy->ddrphy_reg16);
641*53c45f0cShuang lin 	writel(PHY_DRV_ODT_SET(PHY_RON_44OHM), &ddr_phy->ddrphy_reg22);
642*53c45f0cShuang lin 	writel(PHY_DRV_ODT_SET(PHY_RON_44OHM), &ddr_phy->ddrphy_reg25);
643*53c45f0cShuang lin 	writel(PHY_DRV_ODT_SET(PHY_RON_44OHM), &ddr_phy->ddrphy_reg26);
644*53c45f0cShuang lin 	writel(PHY_DRV_ODT_SET(PHY_RTT_216OHM), &ddr_phy->ddrphy_reg27);
645*53c45f0cShuang lin 	writel(PHY_DRV_ODT_SET(PHY_RTT_216OHM), &ddr_phy->ddrphy_reg28);
646*53c45f0cShuang lin }
647*53c45f0cShuang lin 
648*53c45f0cShuang lin void dram_cfg_rbc(struct rk3036_sdram_priv *priv)
649*53c45f0cShuang lin {
650*53c45f0cShuang lin 	char noc_config;
651*53c45f0cShuang lin 	int i = 0;
652*53c45f0cShuang lin 	struct rk3036_ddr_config config = priv->ddr_config;
653*53c45f0cShuang lin 	struct rk3036_service_sys *axi_bus = priv->axi_bus;
654*53c45f0cShuang lin 
655*53c45f0cShuang lin 	move_to_config_state(priv);
656*53c45f0cShuang lin 
657*53c45f0cShuang lin 	/* 2bit in BIT1, 2 */
658*53c45f0cShuang lin 	if (config.rank == 2) {
659*53c45f0cShuang lin 		noc_config = (config.cs0_row - 13) << 4 | config.bank << 1 |
660*53c45f0cShuang lin 			      1 << 3 | (config.col - 10);
661*53c45f0cShuang lin 		if (noc_config == ddr_cfg_2_rbc[9]) {
662*53c45f0cShuang lin 			i = 9;
663*53c45f0cShuang lin 			goto finish;
664*53c45f0cShuang lin 		} else if (noc_config == ddr_cfg_2_rbc[10]) {
665*53c45f0cShuang lin 			i = 10;
666*53c45f0cShuang lin 			goto finish;
667*53c45f0cShuang lin 		}
668*53c45f0cShuang lin 	}
669*53c45f0cShuang lin 
670*53c45f0cShuang lin 	noc_config = (config.cs0_row - 13) << 4 | config.bank << 1 |
671*53c45f0cShuang lin 			(config.col - 10);
672*53c45f0cShuang lin 
673*53c45f0cShuang lin 	for (i = 0; i < sizeof(ddr_cfg_2_rbc); i++) {
674*53c45f0cShuang lin 		if (noc_config == ddr_cfg_2_rbc[i])
675*53c45f0cShuang lin 			goto finish;
676*53c45f0cShuang lin 	}
677*53c45f0cShuang lin 
678*53c45f0cShuang lin 	/* bank: 1 bit in BIT6,7, 1bit in BIT1, 2 */
679*53c45f0cShuang lin 	noc_config = 1 << 6 | (config.cs0_row - 13) << 4 |
680*53c45f0cShuang lin 			2 << 1 | (config.col - 10);
681*53c45f0cShuang lin 	if (noc_config == ddr_cfg_2_rbc[11]) {
682*53c45f0cShuang lin 		i = 11;
683*53c45f0cShuang lin 		goto finish;
684*53c45f0cShuang lin 	}
685*53c45f0cShuang lin 
686*53c45f0cShuang lin 	/* bank: 2bit in BIT6,7 */
687*53c45f0cShuang lin 	noc_config = (config.bank << 6) | (config.cs0_row - 13) << 4 |
688*53c45f0cShuang lin 			(config.col - 10);
689*53c45f0cShuang lin 
690*53c45f0cShuang lin 	if (noc_config == ddr_cfg_2_rbc[0])
691*53c45f0cShuang lin 		i = 0;
692*53c45f0cShuang lin 	else if (noc_config == ddr_cfg_2_rbc[12])
693*53c45f0cShuang lin 		i = 12;
694*53c45f0cShuang lin 	else if (noc_config == ddr_cfg_2_rbc[13])
695*53c45f0cShuang lin 		i = 13;
696*53c45f0cShuang lin finish:
697*53c45f0cShuang lin 	writel(i, &axi_bus->ddrconf);
698*53c45f0cShuang lin 	move_to_access_state(priv);
699*53c45f0cShuang lin }
700*53c45f0cShuang lin 
701*53c45f0cShuang lin static void sdram_all_config(struct rk3036_sdram_priv *priv)
702*53c45f0cShuang lin {
703*53c45f0cShuang lin 	u32 os_reg = 0;
704*53c45f0cShuang lin 	struct rk3036_ddr_config config = priv->ddr_config;
705*53c45f0cShuang lin 
706*53c45f0cShuang lin 	os_reg = config.ddr_type << DDR_TYPE_SHIFT |
707*53c45f0cShuang lin 			0 << DDR_CHN_CNT_SHIFT |
708*53c45f0cShuang lin 			(config.rank - 1) << DDR_RANK_CNT_SHIFT |
709*53c45f0cShuang lin 			(config.col - 1) << DDR_COL_SHIFT |
710*53c45f0cShuang lin 			(config.bank == 3 ? 0 : 1) << DDR_BANK_SHIFT |
711*53c45f0cShuang lin 			(config.cs0_row - 13) << DDR_CS0_ROW_SHIFT |
712*53c45f0cShuang lin 			(config.cs1_row - 13) << DDR_CS1_ROW_SHIFT |
713*53c45f0cShuang lin 			1 << DDR_BW_SHIFT | config.bw << DDR_DIE_BW_SHIFT;
714*53c45f0cShuang lin 	writel(os_reg, &priv->grf->os_reg[1]);
715*53c45f0cShuang lin }
716*53c45f0cShuang lin 
717*53c45f0cShuang lin size_t sdram_size(void)
718*53c45f0cShuang lin {
719*53c45f0cShuang lin 	u32 size, os_reg, cs0_row, cs1_row, col, bank, rank;
720*53c45f0cShuang lin 	struct rk3036_grf *grf = (void *)GRF_BASE;
721*53c45f0cShuang lin 
722*53c45f0cShuang lin 	os_reg = readl(&grf->os_reg[1]);
723*53c45f0cShuang lin 
724*53c45f0cShuang lin 	cs0_row = 13 + ((os_reg >> DDR_CS0_ROW_SHIFT) & DDR_CS0_ROW_MASK);
725*53c45f0cShuang lin 	cs1_row = 13 + ((os_reg >> DDR_CS1_ROW_SHIFT) & DDR_CS1_ROW_MASK);
726*53c45f0cShuang lin 	col = 9 + ((os_reg >> DDR_COL_SHIFT) & DDR_COL_MASK);
727*53c45f0cShuang lin 	bank = 3 - ((os_reg >> DDR_BANK_SHIFT) & DDR_BANK_MASK);
728*53c45f0cShuang lin 	rank = 1 + ((os_reg >> DDR_RANK_CNT_SHIFT) & DDR_RANK_CNT_MASK);
729*53c45f0cShuang lin 
730*53c45f0cShuang lin 	/* row + col + bank + bw(rk3036 only support 16bit, so fix in 1) */
731*53c45f0cShuang lin 	size = 1 << (cs0_row + col + bank + 1);
732*53c45f0cShuang lin 
733*53c45f0cShuang lin 	if (rank > 1)
734*53c45f0cShuang lin 		size += size >> (cs0_row - cs1_row);
735*53c45f0cShuang lin 
736*53c45f0cShuang lin 	return size;
737*53c45f0cShuang lin }
738*53c45f0cShuang lin 
739*53c45f0cShuang lin void sdram_init(void)
740*53c45f0cShuang lin {
741*53c45f0cShuang lin 	struct rk3036_sdram_priv sdram_priv;
742*53c45f0cShuang lin 
743*53c45f0cShuang lin 	sdram_priv.cru = (void *)CRU_BASE;
744*53c45f0cShuang lin 	sdram_priv.grf = (void *)GRF_BASE;
745*53c45f0cShuang lin 	sdram_priv.phy = (void *)DDR_PHY_BASE;
746*53c45f0cShuang lin 	sdram_priv.pctl = (void *)DDR_PCTL_BASE;
747*53c45f0cShuang lin 	sdram_priv.axi_bus = (void *)CPU_AXI_BUS_BASE;
748*53c45f0cShuang lin 
749*53c45f0cShuang lin 	get_ddr_config(&sdram_priv.ddr_config);
750*53c45f0cShuang lin 	sdram_all_config(&sdram_priv);
751*53c45f0cShuang lin 	rkdclk_init(&sdram_priv);
752*53c45f0cShuang lin 	phy_pctrl_reset(&sdram_priv);
753*53c45f0cShuang lin 	phy_dll_bypass_set(&sdram_priv, ddr_timing.freq);
754*53c45f0cShuang lin 	pctl_cfg(&sdram_priv);
755*53c45f0cShuang lin 	phy_cfg(&sdram_priv);
756*53c45f0cShuang lin 	writel(POWER_UP_START, &sdram_priv.pctl->powctl);
757*53c45f0cShuang lin 	while (!(readl(&sdram_priv.pctl->powstat) & POWER_UP_DONE))
758*53c45f0cShuang lin 		;
759*53c45f0cShuang lin 	memory_init(&sdram_priv);
760*53c45f0cShuang lin 	move_to_config_state(&sdram_priv);
761*53c45f0cShuang lin 	data_training(&sdram_priv);
762*53c45f0cShuang lin 	move_to_access_state(&sdram_priv);
763*53c45f0cShuang lin 	dram_cfg_rbc(&sdram_priv);
764*53c45f0cShuang lin }
765