xref: /rk3399_rockchip-uboot/arch/arm/mach-at91/mpddrc.c (revision 161b1fe745394f34c4aa506edc964089785919f6)
162011840SMasahiro Yamada /*
262011840SMasahiro Yamada  * Copyright (C) 2013 Atmel Corporation
362011840SMasahiro Yamada  *		      Bo Shen <voice.shen@atmel.com>
462011840SMasahiro Yamada  *
5c2ad76c4SWenyou Yang  * Copyright (C) 2015 Atmel Corporation
6c2ad76c4SWenyou Yang  *		      Wenyou Yang <wenyou.yang@atmel.com>
7c2ad76c4SWenyou Yang  *
862011840SMasahiro Yamada  * SPDX-License-Identifier:	GPL-2.0+
962011840SMasahiro Yamada  */
1062011840SMasahiro Yamada 
1162011840SMasahiro Yamada #include <common.h>
1262011840SMasahiro Yamada #include <asm/io.h>
1362011840SMasahiro Yamada #include <asm/arch/atmel_mpddrc.h>
1462011840SMasahiro Yamada 
15*4245701eSWenyou Yang #define SAMA5D3_MPDDRC_VERSION		0x140
16*4245701eSWenyou Yang 
atmel_mpddr_op(const struct atmel_mpddr * mpddr,int mode,u32 ram_address)170c01c3e8SErik van Luijk static inline void atmel_mpddr_op(const struct atmel_mpddr *mpddr,
180c01c3e8SErik van Luijk 	      int mode,
190c01c3e8SErik van Luijk 	      u32 ram_address)
2062011840SMasahiro Yamada {
2162011840SMasahiro Yamada 	writel(mode, &mpddr->mr);
2262011840SMasahiro Yamada 	writel(0, ram_address);
2362011840SMasahiro Yamada }
2462011840SMasahiro Yamada 
ddr2_decodtype_is_seq(const unsigned int base,u32 cr)25*4245701eSWenyou Yang static int ddr2_decodtype_is_seq(const unsigned int base, u32 cr)
2662011840SMasahiro Yamada {
27*4245701eSWenyou Yang 	struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base;
28*4245701eSWenyou Yang 	u16 version = readl(&mpddr->version) & 0xffff;
29*4245701eSWenyou Yang 
30*4245701eSWenyou Yang 	if ((version >= SAMA5D3_MPDDRC_VERSION) &&
31*4245701eSWenyou Yang 	    (cr & ATMEL_MPDDRC_CR_DECOD_INTERLEAVED))
3262011840SMasahiro Yamada 		return 0;
33*4245701eSWenyou Yang 
3462011840SMasahiro Yamada 	return 1;
3562011840SMasahiro Yamada }
3662011840SMasahiro Yamada 
370c01c3e8SErik van Luijk 
ddr2_init(const unsigned int base,const unsigned int ram_address,const struct atmel_mpddrc_config * mpddr_value)380c01c3e8SErik van Luijk int ddr2_init(const unsigned int base,
390c01c3e8SErik van Luijk 	      const unsigned int ram_address,
407e8702a0SWenyou Yang 	      const struct atmel_mpddrc_config *mpddr_value)
4162011840SMasahiro Yamada {
420c01c3e8SErik van Luijk 	const struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base;
430c01c3e8SErik van Luijk 
4462011840SMasahiro Yamada 	u32 ba_off, cr;
4562011840SMasahiro Yamada 
4662011840SMasahiro Yamada 	/* Compute bank offset according to NC in configuration register */
4762011840SMasahiro Yamada 	ba_off = (mpddr_value->cr & ATMEL_MPDDRC_CR_NC_MASK) + 9;
48*4245701eSWenyou Yang 	if (ddr2_decodtype_is_seq(base, mpddr_value->cr))
4962011840SMasahiro Yamada 		ba_off += ((mpddr_value->cr & ATMEL_MPDDRC_CR_NR_MASK) >> 2) + 11;
5062011840SMasahiro Yamada 
5162011840SMasahiro Yamada 	ba_off += (mpddr_value->md & ATMEL_MPDDRC_MD_DBW_MASK) ? 1 : 2;
5262011840SMasahiro Yamada 
5362011840SMasahiro Yamada 	/* Program the memory device type into the memory device register */
5462011840SMasahiro Yamada 	writel(mpddr_value->md, &mpddr->md);
5562011840SMasahiro Yamada 
5662011840SMasahiro Yamada 	/* Program the configuration register */
5762011840SMasahiro Yamada 	writel(mpddr_value->cr, &mpddr->cr);
5862011840SMasahiro Yamada 
5962011840SMasahiro Yamada 	/* Program the timing register */
6062011840SMasahiro Yamada 	writel(mpddr_value->tpr0, &mpddr->tpr0);
6162011840SMasahiro Yamada 	writel(mpddr_value->tpr1, &mpddr->tpr1);
6262011840SMasahiro Yamada 	writel(mpddr_value->tpr2, &mpddr->tpr2);
6362011840SMasahiro Yamada 
6462011840SMasahiro Yamada 	/* Issue a NOP command */
650c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
6662011840SMasahiro Yamada 
6762011840SMasahiro Yamada 	/* A 200 us is provided to precede any signal toggle */
6862011840SMasahiro Yamada 	udelay(200);
6962011840SMasahiro Yamada 
7062011840SMasahiro Yamada 	/* Issue a NOP command */
710c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
7262011840SMasahiro Yamada 
7362011840SMasahiro Yamada 	/* Issue an all banks precharge command */
740c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_PRCGALL_CMD, ram_address);
7562011840SMasahiro Yamada 
7662011840SMasahiro Yamada 	/* Issue an extended mode register set(EMRS2) to choose operation */
770c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
7862011840SMasahiro Yamada 		       ram_address + (0x2 << ba_off));
7962011840SMasahiro Yamada 
8062011840SMasahiro Yamada 	/* Issue an extended mode register set(EMRS3) to set EMSR to 0 */
810c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
8262011840SMasahiro Yamada 		       ram_address + (0x3 << ba_off));
8362011840SMasahiro Yamada 
8462011840SMasahiro Yamada 	/*
8562011840SMasahiro Yamada 	 * Issue an extended mode register set(EMRS1) to enable DLL and
8662011840SMasahiro Yamada 	 * program D.I.C (output driver impedance control)
8762011840SMasahiro Yamada 	 */
880c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
8962011840SMasahiro Yamada 		       ram_address + (0x1 << ba_off));
9062011840SMasahiro Yamada 
9162011840SMasahiro Yamada 	/* Enable DLL reset */
9262011840SMasahiro Yamada 	cr = readl(&mpddr->cr);
9362011840SMasahiro Yamada 	writel(cr | ATMEL_MPDDRC_CR_DLL_RESET_ENABLED, &mpddr->cr);
9462011840SMasahiro Yamada 
9562011840SMasahiro Yamada 	/* A mode register set(MRS) cycle is issued to reset DLL */
960c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
9762011840SMasahiro Yamada 
9862011840SMasahiro Yamada 	/* Issue an all banks precharge command */
990c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_PRCGALL_CMD, ram_address);
10062011840SMasahiro Yamada 
10162011840SMasahiro Yamada 	/* Two auto-refresh (CBR) cycles are provided */
1020c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_RFSH_CMD, ram_address);
1030c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_RFSH_CMD, ram_address);
10462011840SMasahiro Yamada 
10562011840SMasahiro Yamada 	/* Disable DLL reset */
10662011840SMasahiro Yamada 	cr = readl(&mpddr->cr);
10762011840SMasahiro Yamada 	writel(cr & (~ATMEL_MPDDRC_CR_DLL_RESET_ENABLED), &mpddr->cr);
10862011840SMasahiro Yamada 
10962011840SMasahiro Yamada 	/* A mode register set (MRS) cycle is issued to disable DLL reset */
1100c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
11162011840SMasahiro Yamada 
11262011840SMasahiro Yamada 	/* Set OCD calibration in default state */
11362011840SMasahiro Yamada 	cr = readl(&mpddr->cr);
11462011840SMasahiro Yamada 	writel(cr | ATMEL_MPDDRC_CR_OCD_DEFAULT, &mpddr->cr);
11562011840SMasahiro Yamada 
11662011840SMasahiro Yamada 	/*
11762011840SMasahiro Yamada 	 * An extended mode register set (EMRS1) cycle is issued
11862011840SMasahiro Yamada 	 * to OCD default value
11962011840SMasahiro Yamada 	 */
1200c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
12162011840SMasahiro Yamada 		       ram_address + (0x1 << ba_off));
12262011840SMasahiro Yamada 
12362011840SMasahiro Yamada 	 /* OCD calibration mode exit */
12462011840SMasahiro Yamada 	cr = readl(&mpddr->cr);
12562011840SMasahiro Yamada 	writel(cr & (~ATMEL_MPDDRC_CR_OCD_DEFAULT), &mpddr->cr);
12662011840SMasahiro Yamada 
12762011840SMasahiro Yamada 	/*
12862011840SMasahiro Yamada 	 * An extended mode register set (EMRS1) cycle is issued
12962011840SMasahiro Yamada 	 * to enable OCD exit
13062011840SMasahiro Yamada 	 */
1310c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
13262011840SMasahiro Yamada 		       ram_address + (0x1 << ba_off));
13362011840SMasahiro Yamada 
13462011840SMasahiro Yamada 	/* A nornal mode command is provided */
1350c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NORMAL_CMD, ram_address);
13662011840SMasahiro Yamada 
13762011840SMasahiro Yamada 	/* Perform a write access to any DDR2-SDRAM address */
13862011840SMasahiro Yamada 	writel(0, ram_address);
13962011840SMasahiro Yamada 
14062011840SMasahiro Yamada 	/* Write the refresh rate */
14162011840SMasahiro Yamada 	writel(mpddr_value->rtr, &mpddr->rtr);
14262011840SMasahiro Yamada 
14362011840SMasahiro Yamada 	return 0;
14462011840SMasahiro Yamada }
145c2ad76c4SWenyou Yang 
ddr3_init(const unsigned int base,const unsigned int ram_address,const struct atmel_mpddrc_config * mpddr_value)146c2ad76c4SWenyou Yang int ddr3_init(const unsigned int base,
147c2ad76c4SWenyou Yang 	      const unsigned int ram_address,
148c2ad76c4SWenyou Yang 	      const struct atmel_mpddrc_config *mpddr_value)
149c2ad76c4SWenyou Yang {
150c2ad76c4SWenyou Yang 	struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base;
151c2ad76c4SWenyou Yang 	u32 ba_off;
152c2ad76c4SWenyou Yang 
153c2ad76c4SWenyou Yang 	/* Compute bank offset according to NC in configuration register */
154c2ad76c4SWenyou Yang 	ba_off = (mpddr_value->cr & ATMEL_MPDDRC_CR_NC_MASK) + 9;
155*4245701eSWenyou Yang 	if (ddr2_decodtype_is_seq(base, mpddr_value->cr))
156c2ad76c4SWenyou Yang 		ba_off += ((mpddr_value->cr &
157c2ad76c4SWenyou Yang 			   ATMEL_MPDDRC_CR_NR_MASK) >> 2) + 11;
158c2ad76c4SWenyou Yang 
159c2ad76c4SWenyou Yang 	ba_off += (mpddr_value->md & ATMEL_MPDDRC_MD_DBW_MASK) ? 1 : 2;
160c2ad76c4SWenyou Yang 
161c2ad76c4SWenyou Yang 	/* Program the memory device type */
162c2ad76c4SWenyou Yang 	writel(mpddr_value->md, &mpddr->md);
163c2ad76c4SWenyou Yang 
164c2ad76c4SWenyou Yang 	/*
165c2ad76c4SWenyou Yang 	 * Program features of the DDR3-SDRAM device and timing parameters
166c2ad76c4SWenyou Yang 	 */
167c2ad76c4SWenyou Yang 	writel(mpddr_value->cr, &mpddr->cr);
168c2ad76c4SWenyou Yang 
169c2ad76c4SWenyou Yang 	writel(mpddr_value->tpr0, &mpddr->tpr0);
170c2ad76c4SWenyou Yang 	writel(mpddr_value->tpr1, &mpddr->tpr1);
171c2ad76c4SWenyou Yang 	writel(mpddr_value->tpr2, &mpddr->tpr2);
172c2ad76c4SWenyou Yang 
173c2ad76c4SWenyou Yang 	/* A NOP command is issued to the DDR3-SRAM */
174c2ad76c4SWenyou Yang 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
175c2ad76c4SWenyou Yang 
176c2ad76c4SWenyou Yang 	/* A pause of at least 500us must be observed before a single toggle. */
177c2ad76c4SWenyou Yang 	udelay(500);
178c2ad76c4SWenyou Yang 
179c2ad76c4SWenyou Yang 	/* A NOP command is issued to the DDR3-SDRAM */
180c2ad76c4SWenyou Yang 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
181c2ad76c4SWenyou Yang 
182c2ad76c4SWenyou Yang 	/*
183c2ad76c4SWenyou Yang 	 * An Extended Mode Register Set (EMRS2) cycle is issued to choose
184c2ad76c4SWenyou Yang 	 * between commercial or high temperature operations.
185c2ad76c4SWenyou Yang 	 */
186c2ad76c4SWenyou Yang 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
187c2ad76c4SWenyou Yang 		       ram_address + (0x2 << ba_off));
188c2ad76c4SWenyou Yang 	/*
189c2ad76c4SWenyou Yang 	 * Step 7: An Extended Mode Register Set (EMRS3) cycle is issued to set
190c2ad76c4SWenyou Yang 	 * the Extended Mode Register to 0.
191c2ad76c4SWenyou Yang 	 */
192c2ad76c4SWenyou Yang 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
193c2ad76c4SWenyou Yang 		       ram_address + (0x3 << ba_off));
194c2ad76c4SWenyou Yang 	/*
195c2ad76c4SWenyou Yang 	 * An Extended Mode Register Set (EMRS1) cycle is issued to disable and
196c2ad76c4SWenyou Yang 	 * to program O.D.S. (Output Driver Strength).
197c2ad76c4SWenyou Yang 	 */
198c2ad76c4SWenyou Yang 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
199c2ad76c4SWenyou Yang 		       ram_address + (0x1 << ba_off));
200c2ad76c4SWenyou Yang 
201c2ad76c4SWenyou Yang 	/*
202c2ad76c4SWenyou Yang 	 * Write a one to the DLL bit (enable DLL reset) in the MPDDRC
203c2ad76c4SWenyou Yang 	 * Configuration Register.
204c2ad76c4SWenyou Yang 	 */
205c2ad76c4SWenyou Yang 
206c2ad76c4SWenyou Yang 	/* A Mode Register Set (MRS) cycle is issued to reset DLL. */
207c2ad76c4SWenyou Yang 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
208c2ad76c4SWenyou Yang 
209c2ad76c4SWenyou Yang 	udelay(50);
210c2ad76c4SWenyou Yang 
211c2ad76c4SWenyou Yang 	/*
212c2ad76c4SWenyou Yang 	 * A Calibration command (MRS) is issued to calibrate RTT and RON
213c2ad76c4SWenyou Yang 	 * values for the Process Voltage Temperature (PVT).
214c2ad76c4SWenyou Yang 	 */
215c2ad76c4SWenyou Yang 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_DEEP_CMD, ram_address);
216c2ad76c4SWenyou Yang 
217c2ad76c4SWenyou Yang 	/* A Normal Mode command is provided. */
218c2ad76c4SWenyou Yang 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NORMAL_CMD, ram_address);
219c2ad76c4SWenyou Yang 
220c2ad76c4SWenyou Yang 	/* Perform a write access to any DDR3-SDRAM address. */
221c2ad76c4SWenyou Yang 	writel(0, ram_address);
222c2ad76c4SWenyou Yang 
223c2ad76c4SWenyou Yang 	/*
224c2ad76c4SWenyou Yang 	 * Write the refresh rate into the COUNT field in the MPDDRC
225c2ad76c4SWenyou Yang 	 * Refresh Timer Register (MPDDRC_RTR):
226c2ad76c4SWenyou Yang 	 */
227c2ad76c4SWenyou Yang 	writel(mpddr_value->rtr, &mpddr->rtr);
228c2ad76c4SWenyou Yang 
229c2ad76c4SWenyou Yang 	return 0;
230c2ad76c4SWenyou Yang }
231