1
2
3
4
5
6
7
8#include <cpu_func.h>
9#include <asm/arch/hardware.h>
10#include <asm/cache.h>
11#include <asm/emif.h>
12#include <common.h>
13#include <command.h>
14
15DECLARE_GLOBAL_DATA_PTR;
16
17#ifdef CONFIG_ARCH_KEYSTONE
18#include <asm/arch/ddr3.h>
19#define DDR_MIN_ADDR CONFIG_SYS_SDRAM_BASE
20#define STACKSIZE (512 << 10)
21
22#define DDR_REMAP_ADDR 0x80000000
23#define ECC_START_ADDR1 ((DDR_MIN_ADDR - DDR_REMAP_ADDR) >> 17)
24
25#define ECC_END_ADDR1 (((gd->start_addr_sp - DDR_REMAP_ADDR - \
26 STACKSIZE) >> 17) - 2)
27#endif
28
29#define DDR_TEST_BURST_SIZE 1024
30
31static int ddr_memory_test(u32 start_address, u32 end_address, int quick)
32{
33 u32 index_start, value, index;
34
35 index_start = start_address;
36
37 while (1) {
38
39 for (index = index_start;
40 index < index_start + DDR_TEST_BURST_SIZE;
41 index += 4)
42 __raw_writel(index, index);
43
44
45 for (index = index_start;
46 index < index_start + DDR_TEST_BURST_SIZE;
47 index += 4) {
48 value = __raw_readl(index);
49 if (value != index) {
50 printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
51 index, value, __raw_readl(index));
52
53 return -1;
54 }
55 }
56
57 index_start += DDR_TEST_BURST_SIZE;
58 if (index_start >= end_address)
59 break;
60
61 if (quick)
62 continue;
63
64
65 for (index = index_start;
66 index < index_start + DDR_TEST_BURST_SIZE;
67 index += 4)
68 __raw_writel((u32)~index, index);
69
70
71 for (index = index_start;
72 index < index_start + DDR_TEST_BURST_SIZE;
73 index += 4) {
74 value = __raw_readl(index);
75 if (value != ~index) {
76 printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
77 index, value, __raw_readl(index));
78
79 return -1;
80 }
81 }
82
83 index_start += DDR_TEST_BURST_SIZE;
84 if (index_start >= end_address)
85 break;
86
87
88 for (index = index_start;
89 index < index_start + DDR_TEST_BURST_SIZE;
90 index += 2)
91 __raw_writew((u16)index, index);
92
93
94 for (index = index_start;
95 index < index_start + DDR_TEST_BURST_SIZE;
96 index += 2) {
97 value = __raw_readw(index);
98 if (value != (u16)index) {
99 printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
100 index, value, __raw_readw(index));
101
102 return -1;
103 }
104 }
105
106 index_start += DDR_TEST_BURST_SIZE;
107 if (index_start >= end_address)
108 break;
109
110
111 for (index = index_start;
112 index < index_start + DDR_TEST_BURST_SIZE;
113 index += 1)
114 __raw_writeb((u8)index, index);
115
116
117 for (index = index_start;
118 index < index_start + DDR_TEST_BURST_SIZE;
119 index += 1) {
120 value = __raw_readb(index);
121 if (value != (u8)index) {
122 printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
123 index, value, __raw_readb(index));
124
125 return -1;
126 }
127 }
128
129 index_start += DDR_TEST_BURST_SIZE;
130 if (index_start >= end_address)
131 break;
132 }
133
134 puts("ddr memory test PASSED!\n");
135 return 0;
136}
137
138static int ddr_memory_compare(u32 address1, u32 address2, u32 size)
139{
140 u32 index, value, index2, value2;
141
142 for (index = address1, index2 = address2;
143 index < address1 + size;
144 index += 4, index2 += 4) {
145 value = __raw_readl(index);
146 value2 = __raw_readl(index2);
147
148 if (value != value2) {
149 printf("ddr_memory_test: Compare failed at address = 0x%x value = 0x%x, address2 = 0x%x value2 = 0x%x\n",
150 index, value, index2, value2);
151
152 return -1;
153 }
154 }
155
156 puts("ddr memory compare PASSED!\n");
157 return 0;
158}
159
160static void ddr_check_ecc_status(void)
161{
162 struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
163 u32 err_1b = readl(&emif->emif_1b_ecc_err_cnt);
164 u32 int_status = readl(&emif->emif_irqstatus_raw_sys);
165 int ecc_test = 0;
166 char *env;
167
168 env = env_get("ecc_test");
169 if (env)
170 ecc_test = simple_strtol(env, NULL, 0);
171
172 puts("ECC test Status:\n");
173 if (int_status & EMIF_INT_WR_ECC_ERR_SYS_MASK)
174 puts("\tECC test: DDR ECC write error interrupted\n");
175
176 if (int_status & EMIF_INT_TWOBIT_ECC_ERR_SYS_MASK)
177 if (!ecc_test)
178 panic("\tECC test: DDR ECC 2-bit error interrupted");
179
180 if (int_status & EMIF_INT_ONEBIT_ECC_ERR_SYS_MASK)
181 puts("\tECC test: DDR ECC 1-bit error interrupted\n");
182
183 if (err_1b)
184 printf("\tECC test: 1-bit ECC err count: 0x%x\n", err_1b);
185}
186
187static int ddr_memory_ecc_err(u32 addr, u32 ecc_err)
188{
189 struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
190 u32 ecc_ctrl = readl(&emif->emif_ecc_ctrl_reg);
191 u32 val1, val2, val3;
192
193 debug("Disabling D-Cache before ECC test\n");
194 dcache_disable();
195 invalidate_dcache_all();
196
197 puts("Testing DDR ECC:\n");
198 puts("\tECC test: Disabling DDR ECC ...\n");
199 writel(0, &emif->emif_ecc_ctrl_reg);
200
201 val1 = readl(addr);
202 val2 = val1 ^ ecc_err;
203 writel(val2, addr);
204
205 val3 = readl(addr);
206#ifdef CONFIG_ARCH_KEYSTONE
207 ecc_ctrl = ECC_START_ADDR1 | (ECC_END_ADDR1 << 16);
208 writel(ecc_ctrl, EMIF1_BASE + KS2_DDR3_ECC_ADDR_RANGE1_OFFSET);
209 ddr3_enable_ecc(EMIF1_BASE, 1);
210#else
211 writel(ecc_ctrl, &emif->emif_ecc_ctrl_reg);
212#endif
213
214 printf("\tECC test: addr 0x%x, read data 0x%x, written data 0x%x, err pattern: 0x%x, read after write data 0x%x\n",
215 addr, val1, val2, ecc_err, val3);
216
217 puts("\tECC test: Enabled DDR ECC ...\n");
218
219 val1 = readl(addr);
220 printf("\tECC test: addr 0x%x, read data 0x%x\n", addr, val1);
221
222 ddr_check_ecc_status();
223
224 debug("Enabling D-cache back after ECC test\n");
225 enable_caches();
226
227 return 0;
228}
229
230static int is_addr_valid(u32 addr)
231{
232 struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
233 u32 start_addr, end_addr, range, ecc_ctrl;
234
235#ifdef CONFIG_ARCH_KEYSTONE
236 ecc_ctrl = EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK;
237 range = ECC_START_ADDR1 | (ECC_END_ADDR1 << 16);
238#else
239 ecc_ctrl = readl(&emif->emif_ecc_ctrl_reg);
240 range = readl(&emif->emif_ecc_address_range_1);
241#endif
242
243
244 if (ecc_ctrl & EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK) {
245 start_addr = ((range & EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16)
246 + CONFIG_SYS_SDRAM_BASE;
247 end_addr = (range & EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0xFFFF +
248 CONFIG_SYS_SDRAM_BASE;
249 if ((addr >= start_addr) && (addr <= end_addr))
250
251 return 1;
252 }
253
254
255 if (ecc_ctrl & EMIF_ECC_REG_ECC_ADDR_RGN_2_EN_MASK) {
256 range = readl(&emif->emif_ecc_address_range_2);
257 start_addr = ((range & EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16)
258 + CONFIG_SYS_SDRAM_BASE;
259 end_addr = (range & EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0xFFFF +
260 CONFIG_SYS_SDRAM_BASE;
261 if ((addr >= start_addr) && (addr <= end_addr))
262
263 return 1;
264 }
265
266 return 0;
267}
268
269static int is_ecc_enabled(void)
270{
271 struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
272 u32 ecc_ctrl = readl(&emif->emif_ecc_ctrl_reg);
273
274 return (ecc_ctrl & EMIF_ECC_CTRL_REG_ECC_EN_MASK) &&
275 (ecc_ctrl & EMIF_ECC_REG_RMW_EN_MASK);
276}
277
278static int do_ddr_test(cmd_tbl_t *cmdtp,
279 int flag, int argc, char * const argv[])
280{
281 u32 start_addr, end_addr, size, ecc_err;
282
283 if ((argc == 4) && (strncmp(argv[1], "ecc_err", 8) == 0)) {
284 if (!is_ecc_enabled()) {
285 puts("ECC not enabled. Please Enable ECC any try again\n");
286 return CMD_RET_FAILURE;
287 }
288
289 start_addr = simple_strtoul(argv[2], NULL, 16);
290 ecc_err = simple_strtoul(argv[3], NULL, 16);
291
292 if (!is_addr_valid(start_addr)) {
293 puts("Invalid address. Please enter ECC supported address!\n");
294 return CMD_RET_FAILURE;
295 }
296
297 ddr_memory_ecc_err(start_addr, ecc_err);
298 return 0;
299 }
300
301 if (!(((argc == 4) && (strncmp(argv[1], "test", 5) == 0)) ||
302 ((argc == 5) && (strncmp(argv[1], "compare", 8) == 0))))
303 return cmd_usage(cmdtp);
304
305 start_addr = simple_strtoul(argv[2], NULL, 16);
306 end_addr = simple_strtoul(argv[3], NULL, 16);
307
308 if ((start_addr < CONFIG_SYS_SDRAM_BASE) ||
309 (start_addr > (CONFIG_SYS_SDRAM_BASE +
310 get_effective_memsize() - 1)) ||
311 (end_addr < CONFIG_SYS_SDRAM_BASE) ||
312 (end_addr > (CONFIG_SYS_SDRAM_BASE +
313 get_effective_memsize() - 1)) || (start_addr >= end_addr)) {
314 puts("Invalid start or end address!\n");
315 return cmd_usage(cmdtp);
316 }
317
318 puts("Please wait ...\n");
319 if (argc == 5) {
320 size = simple_strtoul(argv[4], NULL, 16);
321 ddr_memory_compare(start_addr, end_addr, size);
322 } else {
323 ddr_memory_test(start_addr, end_addr, 0);
324 }
325
326 return 0;
327}
328
329U_BOOT_CMD(ddr, 5, 1, do_ddr_test,
330 "DDR3 test",
331 "test <start_addr in hex> <end_addr in hex> - test DDR from start\n"
332 " address to end address\n"
333 "ddr compare <start_addr in hex> <end_addr in hex> <size in hex> -\n"
334 " compare DDR data of (size) bytes from start address to end\n"
335 " address\n"
336 "ddr ecc_err <addr in hex> <bit_err in hex> - generate bit errors\n"
337 " in DDR data at <addr>, the command will read a 32-bit data\n"
338 " from <addr>, and write (data ^ bit_err) back to <addr>\n"
339);
340