xref: /openbmc/u-boot/arch/arm/mach-at91/mpddrc.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
262011840SMasahiro Yamada /*
362011840SMasahiro Yamada  * Copyright (C) 2013 Atmel Corporation
462011840SMasahiro Yamada  *		      Bo Shen <voice.shen@atmel.com>
562011840SMasahiro Yamada  *
6c2ad76c4SWenyou Yang  * Copyright (C) 2015 Atmel Corporation
7c2ad76c4SWenyou Yang  *		      Wenyou Yang <wenyou.yang@atmel.com>
862011840SMasahiro Yamada  */
962011840SMasahiro Yamada 
1062011840SMasahiro Yamada #include <common.h>
1162011840SMasahiro Yamada #include <asm/io.h>
1262011840SMasahiro Yamada #include <asm/arch/atmel_mpddrc.h>
1362011840SMasahiro Yamada 
144245701eSWenyou Yang #define SAMA5D3_MPDDRC_VERSION		0x140
154245701eSWenyou Yang 
atmel_mpddr_op(const struct atmel_mpddr * mpddr,int mode,u32 ram_address)160c01c3e8SErik van Luijk static inline void atmel_mpddr_op(const struct atmel_mpddr *mpddr,
170c01c3e8SErik van Luijk 	      int mode,
180c01c3e8SErik van Luijk 	      u32 ram_address)
1962011840SMasahiro Yamada {
2062011840SMasahiro Yamada 	writel(mode, &mpddr->mr);
2162011840SMasahiro Yamada 	writel(0, ram_address);
2262011840SMasahiro Yamada }
2362011840SMasahiro Yamada 
ddr2_decodtype_is_seq(const unsigned int base,u32 cr)244245701eSWenyou Yang static int ddr2_decodtype_is_seq(const unsigned int base, u32 cr)
2562011840SMasahiro Yamada {
264245701eSWenyou Yang 	struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base;
274245701eSWenyou Yang 	u16 version = readl(&mpddr->version) & 0xffff;
284245701eSWenyou Yang 
294245701eSWenyou Yang 	if ((version >= SAMA5D3_MPDDRC_VERSION) &&
304245701eSWenyou Yang 	    (cr & ATMEL_MPDDRC_CR_DECOD_INTERLEAVED))
3162011840SMasahiro Yamada 		return 0;
324245701eSWenyou Yang 
3362011840SMasahiro Yamada 	return 1;
3462011840SMasahiro Yamada }
3562011840SMasahiro Yamada 
360c01c3e8SErik van Luijk 
ddr2_init(const unsigned int base,const unsigned int ram_address,const struct atmel_mpddrc_config * mpddr_value)370c01c3e8SErik van Luijk int ddr2_init(const unsigned int base,
380c01c3e8SErik van Luijk 	      const unsigned int ram_address,
397e8702a0SWenyou Yang 	      const struct atmel_mpddrc_config *mpddr_value)
4062011840SMasahiro Yamada {
410c01c3e8SErik van Luijk 	const struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base;
420c01c3e8SErik van Luijk 
4362011840SMasahiro Yamada 	u32 ba_off, cr;
4462011840SMasahiro Yamada 
4562011840SMasahiro Yamada 	/* Compute bank offset according to NC in configuration register */
4662011840SMasahiro Yamada 	ba_off = (mpddr_value->cr & ATMEL_MPDDRC_CR_NC_MASK) + 9;
474245701eSWenyou Yang 	if (ddr2_decodtype_is_seq(base, mpddr_value->cr))
4862011840SMasahiro Yamada 		ba_off += ((mpddr_value->cr & ATMEL_MPDDRC_CR_NR_MASK) >> 2) + 11;
4962011840SMasahiro Yamada 
5062011840SMasahiro Yamada 	ba_off += (mpddr_value->md & ATMEL_MPDDRC_MD_DBW_MASK) ? 1 : 2;
5162011840SMasahiro Yamada 
5262011840SMasahiro Yamada 	/* Program the memory device type into the memory device register */
5362011840SMasahiro Yamada 	writel(mpddr_value->md, &mpddr->md);
5462011840SMasahiro Yamada 
5562011840SMasahiro Yamada 	/* Program the configuration register */
5662011840SMasahiro Yamada 	writel(mpddr_value->cr, &mpddr->cr);
5762011840SMasahiro Yamada 
5862011840SMasahiro Yamada 	/* Program the timing register */
5962011840SMasahiro Yamada 	writel(mpddr_value->tpr0, &mpddr->tpr0);
6062011840SMasahiro Yamada 	writel(mpddr_value->tpr1, &mpddr->tpr1);
6162011840SMasahiro Yamada 	writel(mpddr_value->tpr2, &mpddr->tpr2);
6262011840SMasahiro Yamada 
6362011840SMasahiro Yamada 	/* Issue a NOP command */
640c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
6562011840SMasahiro Yamada 
6662011840SMasahiro Yamada 	/* A 200 us is provided to precede any signal toggle */
6762011840SMasahiro Yamada 	udelay(200);
6862011840SMasahiro Yamada 
6962011840SMasahiro Yamada 	/* Issue a NOP command */
700c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
7162011840SMasahiro Yamada 
7262011840SMasahiro Yamada 	/* Issue an all banks precharge command */
730c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_PRCGALL_CMD, ram_address);
7462011840SMasahiro Yamada 
7562011840SMasahiro Yamada 	/* Issue an extended mode register set(EMRS2) to choose operation */
760c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
7762011840SMasahiro Yamada 		       ram_address + (0x2 << ba_off));
7862011840SMasahiro Yamada 
7962011840SMasahiro Yamada 	/* Issue an extended mode register set(EMRS3) to set EMSR to 0 */
800c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
8162011840SMasahiro Yamada 		       ram_address + (0x3 << ba_off));
8262011840SMasahiro Yamada 
8362011840SMasahiro Yamada 	/*
8462011840SMasahiro Yamada 	 * Issue an extended mode register set(EMRS1) to enable DLL and
8562011840SMasahiro Yamada 	 * program D.I.C (output driver impedance control)
8662011840SMasahiro Yamada 	 */
870c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
8862011840SMasahiro Yamada 		       ram_address + (0x1 << ba_off));
8962011840SMasahiro Yamada 
9062011840SMasahiro Yamada 	/* Enable DLL reset */
9162011840SMasahiro Yamada 	cr = readl(&mpddr->cr);
9262011840SMasahiro Yamada 	writel(cr | ATMEL_MPDDRC_CR_DLL_RESET_ENABLED, &mpddr->cr);
9362011840SMasahiro Yamada 
9462011840SMasahiro Yamada 	/* A mode register set(MRS) cycle is issued to reset DLL */
950c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
9662011840SMasahiro Yamada 
9762011840SMasahiro Yamada 	/* Issue an all banks precharge command */
980c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_PRCGALL_CMD, ram_address);
9962011840SMasahiro Yamada 
10062011840SMasahiro Yamada 	/* Two auto-refresh (CBR) cycles are provided */
1010c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_RFSH_CMD, ram_address);
1020c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_RFSH_CMD, ram_address);
10362011840SMasahiro Yamada 
10462011840SMasahiro Yamada 	/* Disable DLL reset */
10562011840SMasahiro Yamada 	cr = readl(&mpddr->cr);
10662011840SMasahiro Yamada 	writel(cr & (~ATMEL_MPDDRC_CR_DLL_RESET_ENABLED), &mpddr->cr);
10762011840SMasahiro Yamada 
10862011840SMasahiro Yamada 	/* A mode register set (MRS) cycle is issued to disable DLL reset */
1090c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
11062011840SMasahiro Yamada 
11162011840SMasahiro Yamada 	/* Set OCD calibration in default state */
11262011840SMasahiro Yamada 	cr = readl(&mpddr->cr);
11362011840SMasahiro Yamada 	writel(cr | ATMEL_MPDDRC_CR_OCD_DEFAULT, &mpddr->cr);
11462011840SMasahiro Yamada 
11562011840SMasahiro Yamada 	/*
11662011840SMasahiro Yamada 	 * An extended mode register set (EMRS1) cycle is issued
11762011840SMasahiro Yamada 	 * to OCD default value
11862011840SMasahiro Yamada 	 */
1190c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
12062011840SMasahiro Yamada 		       ram_address + (0x1 << ba_off));
12162011840SMasahiro Yamada 
12262011840SMasahiro Yamada 	 /* OCD calibration mode exit */
12362011840SMasahiro Yamada 	cr = readl(&mpddr->cr);
12462011840SMasahiro Yamada 	writel(cr & (~ATMEL_MPDDRC_CR_OCD_DEFAULT), &mpddr->cr);
12562011840SMasahiro Yamada 
12662011840SMasahiro Yamada 	/*
12762011840SMasahiro Yamada 	 * An extended mode register set (EMRS1) cycle is issued
12862011840SMasahiro Yamada 	 * to enable OCD exit
12962011840SMasahiro Yamada 	 */
1300c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
13162011840SMasahiro Yamada 		       ram_address + (0x1 << ba_off));
13262011840SMasahiro Yamada 
13362011840SMasahiro Yamada 	/* A nornal mode command is provided */
1340c01c3e8SErik van Luijk 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NORMAL_CMD, ram_address);
13562011840SMasahiro Yamada 
13662011840SMasahiro Yamada 	/* Perform a write access to any DDR2-SDRAM address */
13762011840SMasahiro Yamada 	writel(0, ram_address);
13862011840SMasahiro Yamada 
13962011840SMasahiro Yamada 	/* Write the refresh rate */
14062011840SMasahiro Yamada 	writel(mpddr_value->rtr, &mpddr->rtr);
14162011840SMasahiro Yamada 
14262011840SMasahiro Yamada 	return 0;
14362011840SMasahiro Yamada }
144c2ad76c4SWenyou Yang 
ddr3_init(const unsigned int base,const unsigned int ram_address,const struct atmel_mpddrc_config * mpddr_value)145c2ad76c4SWenyou Yang int ddr3_init(const unsigned int base,
146c2ad76c4SWenyou Yang 	      const unsigned int ram_address,
147c2ad76c4SWenyou Yang 	      const struct atmel_mpddrc_config *mpddr_value)
148c2ad76c4SWenyou Yang {
149c2ad76c4SWenyou Yang 	struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base;
150c2ad76c4SWenyou Yang 	u32 ba_off;
151c2ad76c4SWenyou Yang 
152c2ad76c4SWenyou Yang 	/* Compute bank offset according to NC in configuration register */
153c2ad76c4SWenyou Yang 	ba_off = (mpddr_value->cr & ATMEL_MPDDRC_CR_NC_MASK) + 9;
1544245701eSWenyou Yang 	if (ddr2_decodtype_is_seq(base, mpddr_value->cr))
155c2ad76c4SWenyou Yang 		ba_off += ((mpddr_value->cr &
156c2ad76c4SWenyou Yang 			   ATMEL_MPDDRC_CR_NR_MASK) >> 2) + 11;
157c2ad76c4SWenyou Yang 
158c2ad76c4SWenyou Yang 	ba_off += (mpddr_value->md & ATMEL_MPDDRC_MD_DBW_MASK) ? 1 : 2;
159c2ad76c4SWenyou Yang 
160c2ad76c4SWenyou Yang 	/* Program the memory device type */
161c2ad76c4SWenyou Yang 	writel(mpddr_value->md, &mpddr->md);
162c2ad76c4SWenyou Yang 
163c2ad76c4SWenyou Yang 	/*
164c2ad76c4SWenyou Yang 	 * Program features of the DDR3-SDRAM device and timing parameters
165c2ad76c4SWenyou Yang 	 */
166c2ad76c4SWenyou Yang 	writel(mpddr_value->cr, &mpddr->cr);
167c2ad76c4SWenyou Yang 
168c2ad76c4SWenyou Yang 	writel(mpddr_value->tpr0, &mpddr->tpr0);
169c2ad76c4SWenyou Yang 	writel(mpddr_value->tpr1, &mpddr->tpr1);
170c2ad76c4SWenyou Yang 	writel(mpddr_value->tpr2, &mpddr->tpr2);
171c2ad76c4SWenyou Yang 
172c2ad76c4SWenyou Yang 	/* A NOP command is issued to the DDR3-SRAM */
173c2ad76c4SWenyou Yang 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
174c2ad76c4SWenyou Yang 
175c2ad76c4SWenyou Yang 	/* A pause of at least 500us must be observed before a single toggle. */
176c2ad76c4SWenyou Yang 	udelay(500);
177c2ad76c4SWenyou Yang 
178c2ad76c4SWenyou Yang 	/* A NOP command is issued to the DDR3-SDRAM */
179c2ad76c4SWenyou Yang 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
180c2ad76c4SWenyou Yang 
181c2ad76c4SWenyou Yang 	/*
182c2ad76c4SWenyou Yang 	 * An Extended Mode Register Set (EMRS2) cycle is issued to choose
183c2ad76c4SWenyou Yang 	 * between commercial or high temperature operations.
184c2ad76c4SWenyou Yang 	 */
185c2ad76c4SWenyou Yang 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
186c2ad76c4SWenyou Yang 		       ram_address + (0x2 << ba_off));
187c2ad76c4SWenyou Yang 	/*
188c2ad76c4SWenyou Yang 	 * Step 7: An Extended Mode Register Set (EMRS3) cycle is issued to set
189c2ad76c4SWenyou Yang 	 * the Extended Mode Register to 0.
190c2ad76c4SWenyou Yang 	 */
191c2ad76c4SWenyou Yang 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
192c2ad76c4SWenyou Yang 		       ram_address + (0x3 << ba_off));
193c2ad76c4SWenyou Yang 	/*
194c2ad76c4SWenyou Yang 	 * An Extended Mode Register Set (EMRS1) cycle is issued to disable and
195c2ad76c4SWenyou Yang 	 * to program O.D.S. (Output Driver Strength).
196c2ad76c4SWenyou Yang 	 */
197c2ad76c4SWenyou Yang 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
198c2ad76c4SWenyou Yang 		       ram_address + (0x1 << ba_off));
199c2ad76c4SWenyou Yang 
200c2ad76c4SWenyou Yang 	/*
201c2ad76c4SWenyou Yang 	 * Write a one to the DLL bit (enable DLL reset) in the MPDDRC
202c2ad76c4SWenyou Yang 	 * Configuration Register.
203c2ad76c4SWenyou Yang 	 */
204c2ad76c4SWenyou Yang 
205c2ad76c4SWenyou Yang 	/* A Mode Register Set (MRS) cycle is issued to reset DLL. */
206c2ad76c4SWenyou Yang 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
207c2ad76c4SWenyou Yang 
208c2ad76c4SWenyou Yang 	udelay(50);
209c2ad76c4SWenyou Yang 
210c2ad76c4SWenyou Yang 	/*
211c2ad76c4SWenyou Yang 	 * A Calibration command (MRS) is issued to calibrate RTT and RON
212c2ad76c4SWenyou Yang 	 * values for the Process Voltage Temperature (PVT).
213c2ad76c4SWenyou Yang 	 */
214c2ad76c4SWenyou Yang 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_DEEP_CMD, ram_address);
215c2ad76c4SWenyou Yang 
216c2ad76c4SWenyou Yang 	/* A Normal Mode command is provided. */
217c2ad76c4SWenyou Yang 	atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NORMAL_CMD, ram_address);
218c2ad76c4SWenyou Yang 
219c2ad76c4SWenyou Yang 	/* Perform a write access to any DDR3-SDRAM address. */
220c2ad76c4SWenyou Yang 	writel(0, ram_address);
221c2ad76c4SWenyou Yang 
222c2ad76c4SWenyou Yang 	/*
223c2ad76c4SWenyou Yang 	 * Write the refresh rate into the COUNT field in the MPDDRC
224c2ad76c4SWenyou Yang 	 * Refresh Timer Register (MPDDRC_RTR):
225c2ad76c4SWenyou Yang 	 */
226c2ad76c4SWenyou Yang 	writel(mpddr_value->rtr, &mpddr->rtr);
227c2ad76c4SWenyou Yang 
228c2ad76c4SWenyou Yang 	return 0;
229c2ad76c4SWenyou Yang }
230