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