xref: /OK3568_Linux_fs/u-boot/arch/arm/mach-at91/mpddrc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (C) 2013 Atmel Corporation
3*4882a593Smuzhiyun  *		      Bo Shen <voice.shen@atmel.com>
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2015 Atmel Corporation
6*4882a593Smuzhiyun  *		      Wenyou Yang <wenyou.yang@atmel.com>
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <common.h>
12*4882a593Smuzhiyun #include <asm/io.h>
13*4882a593Smuzhiyun #include <asm/arch/atmel_mpddrc.h>
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #define SAMA5D3_MPDDRC_VERSION		0x140
16*4882a593Smuzhiyun 
atmel_mpddr_op(const struct atmel_mpddr * mpddr,int mode,u32 ram_address)17*4882a593Smuzhiyun static inline void atmel_mpddr_op(const struct atmel_mpddr *mpddr,
18*4882a593Smuzhiyun 	      int mode,
19*4882a593Smuzhiyun 	      u32 ram_address)
20*4882a593Smuzhiyun {
21*4882a593Smuzhiyun 	writel(mode, &mpddr->mr);
22*4882a593Smuzhiyun 	writel(0, ram_address);
23*4882a593Smuzhiyun }
24*4882a593Smuzhiyun 
ddr2_decodtype_is_seq(const unsigned int base,u32 cr)25*4882a593Smuzhiyun static int ddr2_decodtype_is_seq(const unsigned int base, u32 cr)
26*4882a593Smuzhiyun {
27*4882a593Smuzhiyun 	struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base;
28*4882a593Smuzhiyun 	u16 version = readl(&mpddr->version) & 0xffff;
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 	if ((version >= SAMA5D3_MPDDRC_VERSION) &&
31*4882a593Smuzhiyun 	    (cr & ATMEL_MPDDRC_CR_DECOD_INTERLEAVED))
32*4882a593Smuzhiyun 		return 0;
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun 	return 1;
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 
ddr2_init(const unsigned int base,const unsigned int ram_address,const struct atmel_mpddrc_config * mpddr_value)38*4882a593Smuzhiyun int ddr2_init(const unsigned int base,
39*4882a593Smuzhiyun 	      const unsigned int ram_address,
40*4882a593Smuzhiyun 	      const struct atmel_mpddrc_config *mpddr_value)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun 	const struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base;
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	u32 ba_off, cr;
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	/* Compute bank offset according to NC in configuration register */
47*4882a593Smuzhiyun 	ba_off = (mpddr_value->cr & ATMEL_MPDDRC_CR_NC_MASK) + 9;
48*4882a593Smuzhiyun 	if (ddr2_decodtype_is_seq(base, mpddr_value->cr))
49*4882a593Smuzhiyun 		ba_off += ((mpddr_value->cr & ATMEL_MPDDRC_CR_NR_MASK) >> 2) + 11;
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	ba_off += (mpddr_value->md & ATMEL_MPDDRC_MD_DBW_MASK) ? 1 : 2;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	/* Program the memory device type into the memory device register */
54*4882a593Smuzhiyun 	writel(mpddr_value->md, &mpddr->md);
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	/* Program the configuration register */
57*4882a593Smuzhiyun 	writel(mpddr_value->cr, &mpddr->cr);
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	/* Program the timing register */
60*4882a593Smuzhiyun 	writel(mpddr_value->tpr0, &mpddr->tpr0);
61*4882a593Smuzhiyun 	writel(mpddr_value->tpr1, &mpddr->tpr1);
62*4882a593Smuzhiyun 	writel(mpddr_value->tpr2, &mpddr->tpr2);
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	/* Issue a NOP command */
65*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	/* A 200 us is provided to precede any signal toggle */
68*4882a593Smuzhiyun 	udelay(200);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	/* Issue a NOP command */
71*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	/* Issue an all banks precharge command */
74*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_PRCGALL_CMD, ram_address);
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	/* Issue an extended mode register set(EMRS2) to choose operation */
77*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
78*4882a593Smuzhiyun 		       ram_address + (0x2 << ba_off));
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	/* Issue an extended mode register set(EMRS3) to set EMSR to 0 */
81*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
82*4882a593Smuzhiyun 		       ram_address + (0x3 << ba_off));
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	/*
85*4882a593Smuzhiyun 	 * Issue an extended mode register set(EMRS1) to enable DLL and
86*4882a593Smuzhiyun 	 * program D.I.C (output driver impedance control)
87*4882a593Smuzhiyun 	 */
88*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
89*4882a593Smuzhiyun 		       ram_address + (0x1 << ba_off));
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	/* Enable DLL reset */
92*4882a593Smuzhiyun 	cr = readl(&mpddr->cr);
93*4882a593Smuzhiyun 	writel(cr | ATMEL_MPDDRC_CR_DLL_RESET_ENABLED, &mpddr->cr);
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	/* A mode register set(MRS) cycle is issued to reset DLL */
96*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	/* Issue an all banks precharge command */
99*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_PRCGALL_CMD, ram_address);
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	/* Two auto-refresh (CBR) cycles are provided */
102*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_RFSH_CMD, ram_address);
103*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_RFSH_CMD, ram_address);
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	/* Disable DLL reset */
106*4882a593Smuzhiyun 	cr = readl(&mpddr->cr);
107*4882a593Smuzhiyun 	writel(cr & (~ATMEL_MPDDRC_CR_DLL_RESET_ENABLED), &mpddr->cr);
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	/* A mode register set (MRS) cycle is issued to disable DLL reset */
110*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	/* Set OCD calibration in default state */
113*4882a593Smuzhiyun 	cr = readl(&mpddr->cr);
114*4882a593Smuzhiyun 	writel(cr | ATMEL_MPDDRC_CR_OCD_DEFAULT, &mpddr->cr);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	/*
117*4882a593Smuzhiyun 	 * An extended mode register set (EMRS1) cycle is issued
118*4882a593Smuzhiyun 	 * to OCD default value
119*4882a593Smuzhiyun 	 */
120*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
121*4882a593Smuzhiyun 		       ram_address + (0x1 << ba_off));
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	 /* OCD calibration mode exit */
124*4882a593Smuzhiyun 	cr = readl(&mpddr->cr);
125*4882a593Smuzhiyun 	writel(cr & (~ATMEL_MPDDRC_CR_OCD_DEFAULT), &mpddr->cr);
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	/*
128*4882a593Smuzhiyun 	 * An extended mode register set (EMRS1) cycle is issued
129*4882a593Smuzhiyun 	 * to enable OCD exit
130*4882a593Smuzhiyun 	 */
131*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
132*4882a593Smuzhiyun 		       ram_address + (0x1 << ba_off));
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	/* A nornal mode command is provided */
135*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NORMAL_CMD, ram_address);
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	/* Perform a write access to any DDR2-SDRAM address */
138*4882a593Smuzhiyun 	writel(0, ram_address);
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	/* Write the refresh rate */
141*4882a593Smuzhiyun 	writel(mpddr_value->rtr, &mpddr->rtr);
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	return 0;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun 
ddr3_init(const unsigned int base,const unsigned int ram_address,const struct atmel_mpddrc_config * mpddr_value)146*4882a593Smuzhiyun int ddr3_init(const unsigned int base,
147*4882a593Smuzhiyun 	      const unsigned int ram_address,
148*4882a593Smuzhiyun 	      const struct atmel_mpddrc_config *mpddr_value)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun 	struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base;
151*4882a593Smuzhiyun 	u32 ba_off;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	/* Compute bank offset according to NC in configuration register */
154*4882a593Smuzhiyun 	ba_off = (mpddr_value->cr & ATMEL_MPDDRC_CR_NC_MASK) + 9;
155*4882a593Smuzhiyun 	if (ddr2_decodtype_is_seq(base, mpddr_value->cr))
156*4882a593Smuzhiyun 		ba_off += ((mpddr_value->cr &
157*4882a593Smuzhiyun 			   ATMEL_MPDDRC_CR_NR_MASK) >> 2) + 11;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	ba_off += (mpddr_value->md & ATMEL_MPDDRC_MD_DBW_MASK) ? 1 : 2;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	/* Program the memory device type */
162*4882a593Smuzhiyun 	writel(mpddr_value->md, &mpddr->md);
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	/*
165*4882a593Smuzhiyun 	 * Program features of the DDR3-SDRAM device and timing parameters
166*4882a593Smuzhiyun 	 */
167*4882a593Smuzhiyun 	writel(mpddr_value->cr, &mpddr->cr);
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	writel(mpddr_value->tpr0, &mpddr->tpr0);
170*4882a593Smuzhiyun 	writel(mpddr_value->tpr1, &mpddr->tpr1);
171*4882a593Smuzhiyun 	writel(mpddr_value->tpr2, &mpddr->tpr2);
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	/* A NOP command is issued to the DDR3-SRAM */
174*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	/* A pause of at least 500us must be observed before a single toggle. */
177*4882a593Smuzhiyun 	udelay(500);
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	/* A NOP command is issued to the DDR3-SDRAM */
180*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	/*
183*4882a593Smuzhiyun 	 * An Extended Mode Register Set (EMRS2) cycle is issued to choose
184*4882a593Smuzhiyun 	 * between commercial or high temperature operations.
185*4882a593Smuzhiyun 	 */
186*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
187*4882a593Smuzhiyun 		       ram_address + (0x2 << ba_off));
188*4882a593Smuzhiyun 	/*
189*4882a593Smuzhiyun 	 * Step 7: An Extended Mode Register Set (EMRS3) cycle is issued to set
190*4882a593Smuzhiyun 	 * the Extended Mode Register to 0.
191*4882a593Smuzhiyun 	 */
192*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
193*4882a593Smuzhiyun 		       ram_address + (0x3 << ba_off));
194*4882a593Smuzhiyun 	/*
195*4882a593Smuzhiyun 	 * An Extended Mode Register Set (EMRS1) cycle is issued to disable and
196*4882a593Smuzhiyun 	 * to program O.D.S. (Output Driver Strength).
197*4882a593Smuzhiyun 	 */
198*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
199*4882a593Smuzhiyun 		       ram_address + (0x1 << ba_off));
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	/*
202*4882a593Smuzhiyun 	 * Write a one to the DLL bit (enable DLL reset) in the MPDDRC
203*4882a593Smuzhiyun 	 * Configuration Register.
204*4882a593Smuzhiyun 	 */
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	/* A Mode Register Set (MRS) cycle is issued to reset DLL. */
207*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	udelay(50);
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	/*
212*4882a593Smuzhiyun 	 * A Calibration command (MRS) is issued to calibrate RTT and RON
213*4882a593Smuzhiyun 	 * values for the Process Voltage Temperature (PVT).
214*4882a593Smuzhiyun 	 */
215*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_DEEP_CMD, ram_address);
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	/* A Normal Mode command is provided. */
218*4882a593Smuzhiyun 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NORMAL_CMD, ram_address);
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	/* Perform a write access to any DDR3-SDRAM address. */
221*4882a593Smuzhiyun 	writel(0, ram_address);
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	/*
224*4882a593Smuzhiyun 	 * Write the refresh rate into the COUNT field in the MPDDRC
225*4882a593Smuzhiyun 	 * Refresh Timer Register (MPDDRC_RTR):
226*4882a593Smuzhiyun 	 */
227*4882a593Smuzhiyun 	writel(mpddr_value->rtr, &mpddr->rtr);
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	return 0;
230*4882a593Smuzhiyun }
231