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