]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
9d9289cb BS |
2 | /* |
3 | * Copyright (C) 2013 Atmel Corporation | |
4 | * Bo Shen <[email protected]> | |
5 | * | |
c2ad76c4 WY |
6 | * Copyright (C) 2015 Atmel Corporation |
7 | * Wenyou Yang <[email protected]> | |
9d9289cb BS |
8 | */ |
9 | ||
10 | #include <common.h> | |
11 | #include <asm/io.h> | |
12 | #include <asm/arch/atmel_mpddrc.h> | |
13 | ||
4245701e WY |
14 | #define SAMA5D3_MPDDRC_VERSION 0x140 |
15 | ||
0c01c3e8 EL |
16 | static inline void atmel_mpddr_op(const struct atmel_mpddr *mpddr, |
17 | int mode, | |
18 | u32 ram_address) | |
9d9289cb | 19 | { |
9d9289cb BS |
20 | writel(mode, &mpddr->mr); |
21 | writel(0, ram_address); | |
22 | } | |
23 | ||
4245701e | 24 | static int ddr2_decodtype_is_seq(const unsigned int base, u32 cr) |
7dd58910 | 25 | { |
4245701e WY |
26 | struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base; |
27 | u16 version = readl(&mpddr->version) & 0xffff; | |
28 | ||
29 | if ((version >= SAMA5D3_MPDDRC_VERSION) && | |
30 | (cr & ATMEL_MPDDRC_CR_DECOD_INTERLEAVED)) | |
7dd58910 | 31 | return 0; |
4245701e | 32 | |
7dd58910 HS |
33 | return 1; |
34 | } | |
35 | ||
0c01c3e8 EL |
36 | |
37 | int ddr2_init(const unsigned int base, | |
38 | const unsigned int ram_address, | |
7e8702a0 | 39 | const struct atmel_mpddrc_config *mpddr_value) |
9d9289cb | 40 | { |
0c01c3e8 EL |
41 | const struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base; |
42 | ||
9d9289cb BS |
43 | u32 ba_off, cr; |
44 | ||
45 | /* Compute bank offset according to NC in configuration register */ | |
46 | ba_off = (mpddr_value->cr & ATMEL_MPDDRC_CR_NC_MASK) + 9; | |
4245701e | 47 | if (ddr2_decodtype_is_seq(base, mpddr_value->cr)) |
341f548e | 48 | ba_off += ((mpddr_value->cr & ATMEL_MPDDRC_CR_NR_MASK) >> 2) + 11; |
9d9289cb BS |
49 | |
50 | ba_off += (mpddr_value->md & ATMEL_MPDDRC_MD_DBW_MASK) ? 1 : 2; | |
51 | ||
52 | /* Program the memory device type into the memory device register */ | |
53 | writel(mpddr_value->md, &mpddr->md); | |
54 | ||
55 | /* Program the configuration register */ | |
56 | writel(mpddr_value->cr, &mpddr->cr); | |
57 | ||
58 | /* Program the timing register */ | |
59 | writel(mpddr_value->tpr0, &mpddr->tpr0); | |
60 | writel(mpddr_value->tpr1, &mpddr->tpr1); | |
61 | writel(mpddr_value->tpr2, &mpddr->tpr2); | |
62 | ||
63 | /* Issue a NOP command */ | |
0c01c3e8 | 64 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address); |
9d9289cb BS |
65 | |
66 | /* A 200 us is provided to precede any signal toggle */ | |
67 | udelay(200); | |
68 | ||
69 | /* Issue a NOP command */ | |
0c01c3e8 | 70 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address); |
9d9289cb BS |
71 | |
72 | /* Issue an all banks precharge command */ | |
0c01c3e8 | 73 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_PRCGALL_CMD, ram_address); |
9d9289cb BS |
74 | |
75 | /* Issue an extended mode register set(EMRS2) to choose operation */ | |
0c01c3e8 | 76 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD, |
9d9289cb BS |
77 | ram_address + (0x2 << ba_off)); |
78 | ||
79 | /* Issue an extended mode register set(EMRS3) to set EMSR to 0 */ | |
0c01c3e8 | 80 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD, |
9d9289cb BS |
81 | ram_address + (0x3 << ba_off)); |
82 | ||
83 | /* | |
84 | * Issue an extended mode register set(EMRS1) to enable DLL and | |
85 | * program D.I.C (output driver impedance control) | |
86 | */ | |
0c01c3e8 | 87 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD, |
9d9289cb BS |
88 | ram_address + (0x1 << ba_off)); |
89 | ||
90 | /* Enable DLL reset */ | |
91 | cr = readl(&mpddr->cr); | |
92 | writel(cr | ATMEL_MPDDRC_CR_DLL_RESET_ENABLED, &mpddr->cr); | |
93 | ||
94 | /* A mode register set(MRS) cycle is issued to reset DLL */ | |
0c01c3e8 | 95 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address); |
9d9289cb BS |
96 | |
97 | /* Issue an all banks precharge command */ | |
0c01c3e8 | 98 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_PRCGALL_CMD, ram_address); |
9d9289cb BS |
99 | |
100 | /* Two auto-refresh (CBR) cycles are provided */ | |
0c01c3e8 EL |
101 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_RFSH_CMD, ram_address); |
102 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_RFSH_CMD, ram_address); | |
9d9289cb BS |
103 | |
104 | /* Disable DLL reset */ | |
105 | cr = readl(&mpddr->cr); | |
106 | writel(cr & (~ATMEL_MPDDRC_CR_DLL_RESET_ENABLED), &mpddr->cr); | |
107 | ||
108 | /* A mode register set (MRS) cycle is issued to disable DLL reset */ | |
0c01c3e8 | 109 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address); |
9d9289cb BS |
110 | |
111 | /* Set OCD calibration in default state */ | |
112 | cr = readl(&mpddr->cr); | |
113 | writel(cr | ATMEL_MPDDRC_CR_OCD_DEFAULT, &mpddr->cr); | |
114 | ||
115 | /* | |
116 | * An extended mode register set (EMRS1) cycle is issued | |
117 | * to OCD default value | |
118 | */ | |
0c01c3e8 | 119 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD, |
9d9289cb BS |
120 | ram_address + (0x1 << ba_off)); |
121 | ||
122 | /* OCD calibration mode exit */ | |
123 | cr = readl(&mpddr->cr); | |
124 | writel(cr & (~ATMEL_MPDDRC_CR_OCD_DEFAULT), &mpddr->cr); | |
125 | ||
126 | /* | |
127 | * An extended mode register set (EMRS1) cycle is issued | |
128 | * to enable OCD exit | |
129 | */ | |
0c01c3e8 | 130 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD, |
9d9289cb BS |
131 | ram_address + (0x1 << ba_off)); |
132 | ||
133 | /* A nornal mode command is provided */ | |
0c01c3e8 | 134 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NORMAL_CMD, ram_address); |
9d9289cb BS |
135 | |
136 | /* Perform a write access to any DDR2-SDRAM address */ | |
137 | writel(0, ram_address); | |
138 | ||
139 | /* Write the refresh rate */ | |
140 | writel(mpddr_value->rtr, &mpddr->rtr); | |
141 | ||
142 | return 0; | |
143 | } | |
c2ad76c4 WY |
144 | |
145 | int ddr3_init(const unsigned int base, | |
146 | const unsigned int ram_address, | |
147 | const struct atmel_mpddrc_config *mpddr_value) | |
148 | { | |
149 | struct atmel_mpddr *mpddr = (struct atmel_mpddr *)base; | |
150 | u32 ba_off; | |
151 | ||
152 | /* Compute bank offset according to NC in configuration register */ | |
153 | ba_off = (mpddr_value->cr & ATMEL_MPDDRC_CR_NC_MASK) + 9; | |
4245701e | 154 | if (ddr2_decodtype_is_seq(base, mpddr_value->cr)) |
c2ad76c4 WY |
155 | ba_off += ((mpddr_value->cr & |
156 | ATMEL_MPDDRC_CR_NR_MASK) >> 2) + 11; | |
157 | ||
158 | ba_off += (mpddr_value->md & ATMEL_MPDDRC_MD_DBW_MASK) ? 1 : 2; | |
159 | ||
160 | /* Program the memory device type */ | |
161 | writel(mpddr_value->md, &mpddr->md); | |
162 | ||
163 | /* | |
164 | * Program features of the DDR3-SDRAM device and timing parameters | |
165 | */ | |
166 | writel(mpddr_value->cr, &mpddr->cr); | |
167 | ||
168 | writel(mpddr_value->tpr0, &mpddr->tpr0); | |
169 | writel(mpddr_value->tpr1, &mpddr->tpr1); | |
170 | writel(mpddr_value->tpr2, &mpddr->tpr2); | |
171 | ||
172 | /* A NOP command is issued to the DDR3-SRAM */ | |
173 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address); | |
174 | ||
175 | /* A pause of at least 500us must be observed before a single toggle. */ | |
176 | udelay(500); | |
177 | ||
178 | /* A NOP command is issued to the DDR3-SDRAM */ | |
179 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NOP_CMD, ram_address); | |
180 | ||
181 | /* | |
182 | * An Extended Mode Register Set (EMRS2) cycle is issued to choose | |
183 | * between commercial or high temperature operations. | |
184 | */ | |
185 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD, | |
186 | ram_address + (0x2 << ba_off)); | |
187 | /* | |
188 | * Step 7: An Extended Mode Register Set (EMRS3) cycle is issued to set | |
189 | * the Extended Mode Register to 0. | |
190 | */ | |
191 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD, | |
192 | ram_address + (0x3 << ba_off)); | |
193 | /* | |
194 | * An Extended Mode Register Set (EMRS1) cycle is issued to disable and | |
195 | * to program O.D.S. (Output Driver Strength). | |
196 | */ | |
197 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_EXT_LMR_CMD, | |
198 | ram_address + (0x1 << ba_off)); | |
199 | ||
200 | /* | |
201 | * Write a one to the DLL bit (enable DLL reset) in the MPDDRC | |
202 | * Configuration Register. | |
203 | */ | |
204 | ||
205 | /* A Mode Register Set (MRS) cycle is issued to reset DLL. */ | |
206 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_LMR_CMD, ram_address); | |
207 | ||
208 | udelay(50); | |
209 | ||
210 | /* | |
211 | * A Calibration command (MRS) is issued to calibrate RTT and RON | |
212 | * values for the Process Voltage Temperature (PVT). | |
213 | */ | |
214 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_DEEP_CMD, ram_address); | |
215 | ||
216 | /* A Normal Mode command is provided. */ | |
217 | atmel_mpddr_op(mpddr, ATMEL_MPDDRC_MR_MODE_NORMAL_CMD, ram_address); | |
218 | ||
219 | /* Perform a write access to any DDR3-SDRAM address. */ | |
220 | writel(0, ram_address); | |
221 | ||
222 | /* | |
223 | * Write the refresh rate into the COUNT field in the MPDDRC | |
224 | * Refresh Timer Register (MPDDRC_RTR): | |
225 | */ | |
226 | writel(mpddr_value->rtr, &mpddr->rtr); | |
227 | ||
228 | return 0; | |
229 | } |