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