blob: 1e1ff1d5fc08081358c153d5b79071995186ee49 [file] [log] [blame]
Bo Shen9d9289c2013-11-15 11:12:37 +08001/*
2 * Copyright (C) 2013 Atmel Corporation
3 * Bo Shen <voice.shen@atmel.com>
4 *
Wenyou Yangc2ad76c2016-02-01 18:12:16 +08005 * Copyright (C) 2015 Atmel Corporation
6 * Wenyou Yang <wenyou.yang@atmel.com>
7 *
Bo Shen9d9289c2013-11-15 11:12:37 +08008 * SPDX-License-Identifier: GPL-2.0+
9 */
10
11#include <common.h>
12#include <asm/io.h>
13#include <asm/arch/atmel_mpddrc.h>
14
Erik van Luijk0c01c3e2015-08-13 15:43:18 +020015static inline void atmel_mpddr_op(const struct atmel_mpddr *mpddr,
16 int mode,
17 u32 ram_address)
Bo Shen9d9289c2013-11-15 11:12:37 +080018{
Bo Shen9d9289c2013-11-15 11:12:37 +080019 writel(mode, &mpddr->mr);
20 writel(0, ram_address);
21}
22
Heiko Schocher7dd58912014-10-31 08:30:58 +010023static int ddr2_decodtype_is_seq(u32 cr)
24{
Bo Shend85e8912015-03-27 14:23:35 +080025#if defined(CONFIG_SAMA5D3) || defined(CONFIG_SAMA5D4) || \
Bo Shenff255e82015-03-27 14:23:36 +080026 defined(CONFIG_AT91SAM9X5) || defined(CONFIG_AT91SAM9N12)
Heiko Schocher7dd58912014-10-31 08:30:58 +010027 if (cr & ATMEL_MPDDRC_CR_DECOD_INTERLEAVED)
28 return 0;
29#endif
30 return 1;
31}
32
Erik van Luijk0c01c3e2015-08-13 15:43:18 +020033
34int ddr2_init(const unsigned int base,
35 const unsigned int ram_address,
Wenyou Yang7e8702a2016-02-01 18:12:15 +080036 const struct atmel_mpddrc_config *mpddr_value)
Bo Shen9d9289c2013-11-15 11:12:37 +080037{
Erik van Luijk0c01c3e2015-08-13 15:43:18 +020038 const struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base;
39
Bo Shen9d9289c2013-11-15 11:12:37 +080040 u32 ba_off, cr;
41
42 /* Compute bank offset according to NC in configuration register */
43 ba_off = (mpddr_value->cr & ATMEL_MPDDRC_CR_NC_MASK) + 9;
Heiko Schocher7dd58912014-10-31 08:30:58 +010044 if (ddr2_decodtype_is_seq(mpddr_value->cr))
Heiko Schocher341f5482014-10-31 08:30:57 +010045 ba_off += ((mpddr_value->cr & ATMEL_MPDDRC_CR_NR_MASK) >> 2) + 11;
Bo Shen9d9289c2013-11-15 11:12:37 +080046
47 ba_off += (mpddr_value->md & ATMEL_MPDDRC_MD_DBW_MASK) ? 1 : 2;
48
49 /* Program the memory device type into the memory device register */
50 writel(mpddr_value->md, &mpddr->md);
51
52 /* Program the configuration register */
53 writel(mpddr_value->cr, &mpddr->cr);
54
55 /* Program the timing register */
56 writel(mpddr_value->tpr0, &mpddr->tpr0);
57 writel(mpddr_value->tpr1, &mpddr->tpr1);
58 writel(mpddr_value->tpr2, &mpddr->tpr2);
59
60 /* Issue a NOP command */
Erik van Luijk0c01c3e2015-08-13 15:43:18 +020061 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
Bo Shen9d9289c2013-11-15 11:12:37 +080062
63 /* A 200 us is provided to precede any signal toggle */
64 udelay(200);
65
66 /* Issue a NOP command */
Erik van Luijk0c01c3e2015-08-13 15:43:18 +020067 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
Bo Shen9d9289c2013-11-15 11:12:37 +080068
69 /* Issue an all banks precharge command */
Erik van Luijk0c01c3e2015-08-13 15:43:18 +020070 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_PRCGALL_CMD, ram_address);
Bo Shen9d9289c2013-11-15 11:12:37 +080071
72 /* Issue an extended mode register set(EMRS2) to choose operation */
Erik van Luijk0c01c3e2015-08-13 15:43:18 +020073 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
Bo Shen9d9289c2013-11-15 11:12:37 +080074 ram_address + (0x2 << ba_off));
75
76 /* Issue an extended mode register set(EMRS3) to set EMSR to 0 */
Erik van Luijk0c01c3e2015-08-13 15:43:18 +020077 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
Bo Shen9d9289c2013-11-15 11:12:37 +080078 ram_address + (0x3 << ba_off));
79
80 /*
81 * Issue an extended mode register set(EMRS1) to enable DLL and
82 * program D.I.C (output driver impedance control)
83 */
Erik van Luijk0c01c3e2015-08-13 15:43:18 +020084 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
Bo Shen9d9289c2013-11-15 11:12:37 +080085 ram_address + (0x1 << ba_off));
86
87 /* Enable DLL reset */
88 cr = readl(&mpddr->cr);
89 writel(cr | ATMEL_MPDDRC_CR_DLL_RESET_ENABLED, &mpddr->cr);
90
91 /* A mode register set(MRS) cycle is issued to reset DLL */
Erik van Luijk0c01c3e2015-08-13 15:43:18 +020092 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
Bo Shen9d9289c2013-11-15 11:12:37 +080093
94 /* Issue an all banks precharge command */
Erik van Luijk0c01c3e2015-08-13 15:43:18 +020095 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_PRCGALL_CMD, ram_address);
Bo Shen9d9289c2013-11-15 11:12:37 +080096
97 /* Two auto-refresh (CBR) cycles are provided */
Erik van Luijk0c01c3e2015-08-13 15:43:18 +020098 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_RFSH_CMD, ram_address);
99 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_RFSH_CMD, ram_address);
Bo Shen9d9289c2013-11-15 11:12:37 +0800100
101 /* Disable DLL reset */
102 cr = readl(&mpddr->cr);
103 writel(cr & (~ATMEL_MPDDRC_CR_DLL_RESET_ENABLED), &mpddr->cr);
104
105 /* A mode register set (MRS) cycle is issued to disable DLL reset */
Erik van Luijk0c01c3e2015-08-13 15:43:18 +0200106 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
Bo Shen9d9289c2013-11-15 11:12:37 +0800107
108 /* Set OCD calibration in default state */
109 cr = readl(&mpddr->cr);
110 writel(cr | ATMEL_MPDDRC_CR_OCD_DEFAULT, &mpddr->cr);
111
112 /*
113 * An extended mode register set (EMRS1) cycle is issued
114 * to OCD default value
115 */
Erik van Luijk0c01c3e2015-08-13 15:43:18 +0200116 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
Bo Shen9d9289c2013-11-15 11:12:37 +0800117 ram_address + (0x1 << ba_off));
118
119 /* OCD calibration mode exit */
120 cr = readl(&mpddr->cr);
121 writel(cr & (~ATMEL_MPDDRC_CR_OCD_DEFAULT), &mpddr->cr);
122
123 /*
124 * An extended mode register set (EMRS1) cycle is issued
125 * to enable OCD exit
126 */
Erik van Luijk0c01c3e2015-08-13 15:43:18 +0200127 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
Bo Shen9d9289c2013-11-15 11:12:37 +0800128 ram_address + (0x1 << ba_off));
129
130 /* A nornal mode command is provided */
Erik van Luijk0c01c3e2015-08-13 15:43:18 +0200131 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NORMAL_CMD, ram_address);
Bo Shen9d9289c2013-11-15 11:12:37 +0800132
133 /* Perform a write access to any DDR2-SDRAM address */
134 writel(0, ram_address);
135
136 /* Write the refresh rate */
137 writel(mpddr_value->rtr, &mpddr->rtr);
138
139 return 0;
140}
Wenyou Yangc2ad76c2016-02-01 18:12:16 +0800141
142int ddr3_init(const unsigned int base,
143 const unsigned int ram_address,
144 const struct atmel_mpddrc_config *mpddr_value)
145{
146 struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base;
147 u32 ba_off;
148
149 /* Compute bank offset according to NC in configuration register */
150 ba_off = (mpddr_value->cr & ATMEL_MPDDRC_CR_NC_MASK) + 9;
151 if (ddr2_decodtype_is_seq(mpddr_value->cr))
152 ba_off += ((mpddr_value->cr &
153 ATMEL_MPDDRC_CR_NR_MASK) >> 2) + 11;
154
155 ba_off += (mpddr_value->md & ATMEL_MPDDRC_MD_DBW_MASK) ? 1 : 2;
156
157 /* Program the memory device type */
158 writel(mpddr_value->md, &mpddr->md);
159
160 /*
161 * Program features of the DDR3-SDRAM device and timing parameters
162 */
163 writel(mpddr_value->cr, &mpddr->cr);
164
165 writel(mpddr_value->tpr0, &mpddr->tpr0);
166 writel(mpddr_value->tpr1, &mpddr->tpr1);
167 writel(mpddr_value->tpr2, &mpddr->tpr2);
168
169 /* A NOP command is issued to the DDR3-SRAM */
170 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
171
172 /* A pause of at least 500us must be observed before a single toggle. */
173 udelay(500);
174
175 /* A NOP command is issued to the DDR3-SDRAM */
176 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address);
177
178 /*
179 * An Extended Mode Register Set (EMRS2) cycle is issued to choose
180 * between commercial or high temperature operations.
181 */
182 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
183 ram_address + (0x2 << ba_off));
184 /*
185 * Step 7: An Extended Mode Register Set (EMRS3) cycle is issued to set
186 * the Extended Mode Register to 0.
187 */
188 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
189 ram_address + (0x3 << ba_off));
190 /*
191 * An Extended Mode Register Set (EMRS1) cycle is issued to disable and
192 * to program O.D.S. (Output Driver Strength).
193 */
194 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD,
195 ram_address + (0x1 << ba_off));
196
197 /*
198 * Write a one to the DLL bit (enable DLL reset) in the MPDDRC
199 * Configuration Register.
200 */
201
202 /* A Mode Register Set (MRS) cycle is issued to reset DLL. */
203 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address);
204
205 udelay(50);
206
207 /*
208 * A Calibration command (MRS) is issued to calibrate RTT and RON
209 * values for the Process Voltage Temperature (PVT).
210 */
211 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_DEEP_CMD, ram_address);
212
213 /* A Normal Mode command is provided. */
214 atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NORMAL_CMD, ram_address);
215
216 /* Perform a write access to any DDR3-SDRAM address. */
217 writel(0, ram_address);
218
219 /*
220 * Write the refresh rate into the COUNT field in the MPDDRC
221 * Refresh Timer Register (MPDDRC_RTR):
222 */
223 writel(mpddr_value->rtr, &mpddr->rtr);
224
225 return 0;
226}