]>
Commit | Line | Data |
---|---|---|
26459488 HZ |
1 | /* |
2 | * Keystone2: DDR3 test commands | |
3 | * | |
4 | * (C) Copyright 2012-2014 | |
5 | * Texas Instruments Incorporated, <www.ti.com> | |
6 | * | |
7 | * SPDX-License-Identifier: GPL-2.0+ | |
8 | */ | |
9 | ||
10 | #include <asm/arch/hardware.h> | |
11 | #include <asm/arch/ddr3.h> | |
12 | #include <common.h> | |
13 | #include <command.h> | |
14 | ||
15 | DECLARE_GLOBAL_DATA_PTR; | |
16 | ||
17 | #define DDR_MIN_ADDR CONFIG_SYS_SDRAM_BASE | |
01abae4d | 18 | #define STACKSIZE (512 << 10) /* 512 KiB */ |
26459488 HZ |
19 | |
20 | #define DDR_REMAP_ADDR 0x80000000 | |
21 | #define ECC_START_ADDR1 ((DDR_MIN_ADDR - DDR_REMAP_ADDR) >> 17) | |
22 | ||
23 | #define ECC_END_ADDR1 (((gd->start_addr_sp - DDR_REMAP_ADDR - \ | |
01abae4d | 24 | STACKSIZE) >> 17) - 2) |
26459488 HZ |
25 | |
26 | #define DDR_TEST_BURST_SIZE 1024 | |
27 | ||
28 | static int ddr_memory_test(u32 start_address, u32 end_address, int quick) | |
29 | { | |
30 | u32 index_start, value, index; | |
31 | ||
32 | index_start = start_address; | |
33 | ||
34 | while (1) { | |
35 | /* Write a pattern */ | |
36 | for (index = index_start; | |
37 | index < index_start + DDR_TEST_BURST_SIZE; | |
38 | index += 4) | |
39 | __raw_writel(index, index); | |
40 | ||
41 | /* Read and check the pattern */ | |
42 | for (index = index_start; | |
43 | index < index_start + DDR_TEST_BURST_SIZE; | |
44 | index += 4) { | |
45 | value = __raw_readl(index); | |
46 | if (value != index) { | |
47 | printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n", | |
48 | index, value, __raw_readl(index)); | |
49 | ||
50 | return -1; | |
51 | } | |
52 | } | |
53 | ||
54 | index_start += DDR_TEST_BURST_SIZE; | |
55 | if (index_start >= end_address) | |
56 | break; | |
57 | ||
58 | if (quick) | |
59 | continue; | |
60 | ||
61 | /* Write a pattern for complementary values */ | |
62 | for (index = index_start; | |
63 | index < index_start + DDR_TEST_BURST_SIZE; | |
64 | index += 4) | |
65 | __raw_writel((u32)~index, index); | |
66 | ||
67 | /* Read and check the pattern */ | |
68 | for (index = index_start; | |
69 | index < index_start + DDR_TEST_BURST_SIZE; | |
70 | index += 4) { | |
71 | value = __raw_readl(index); | |
72 | if (value != ~index) { | |
73 | printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n", | |
74 | index, value, __raw_readl(index)); | |
75 | ||
76 | return -1; | |
77 | } | |
78 | } | |
79 | ||
80 | index_start += DDR_TEST_BURST_SIZE; | |
81 | if (index_start >= end_address) | |
82 | break; | |
83 | ||
84 | /* Write a pattern */ | |
85 | for (index = index_start; | |
86 | index < index_start + DDR_TEST_BURST_SIZE; | |
87 | index += 2) | |
88 | __raw_writew((u16)index, index); | |
89 | ||
90 | /* Read and check the pattern */ | |
91 | for (index = index_start; | |
92 | index < index_start + DDR_TEST_BURST_SIZE; | |
93 | index += 2) { | |
94 | value = __raw_readw(index); | |
95 | if (value != (u16)index) { | |
96 | printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n", | |
97 | index, value, __raw_readw(index)); | |
98 | ||
99 | return -1; | |
100 | } | |
101 | } | |
102 | ||
103 | index_start += DDR_TEST_BURST_SIZE; | |
104 | if (index_start >= end_address) | |
105 | break; | |
106 | ||
107 | /* Write a pattern */ | |
108 | for (index = index_start; | |
109 | index < index_start + DDR_TEST_BURST_SIZE; | |
110 | index += 1) | |
111 | __raw_writeb((u8)index, index); | |
112 | ||
113 | /* Read and check the pattern */ | |
114 | for (index = index_start; | |
115 | index < index_start + DDR_TEST_BURST_SIZE; | |
116 | index += 1) { | |
117 | value = __raw_readb(index); | |
118 | if (value != (u8)index) { | |
119 | printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n", | |
120 | index, value, __raw_readb(index)); | |
121 | ||
122 | return -1; | |
123 | } | |
124 | } | |
125 | ||
126 | index_start += DDR_TEST_BURST_SIZE; | |
127 | if (index_start >= end_address) | |
128 | break; | |
129 | } | |
130 | ||
131 | puts("ddr memory test PASSED!\n"); | |
132 | return 0; | |
133 | } | |
134 | ||
135 | static int ddr_memory_compare(u32 address1, u32 address2, u32 size) | |
136 | { | |
137 | u32 index, value, index2, value2; | |
138 | ||
139 | for (index = address1, index2 = address2; | |
140 | index < address1 + size; | |
141 | index += 4, index2 += 4) { | |
142 | value = __raw_readl(index); | |
143 | value2 = __raw_readl(index2); | |
144 | ||
145 | if (value != value2) { | |
146 | printf("ddr_memory_test: Compare failed at address = 0x%x value = 0x%x, address2 = 0x%x value2 = 0x%x\n", | |
147 | index, value, index2, value2); | |
148 | ||
149 | return -1; | |
150 | } | |
151 | } | |
152 | ||
153 | puts("ddr memory compare PASSED!\n"); | |
154 | return 0; | |
155 | } | |
156 | ||
157 | static int ddr_memory_ecc_err(u32 base, u32 address, u32 ecc_err) | |
158 | { | |
159 | u32 value1, value2, value3; | |
160 | ||
161 | puts("Disabling DDR ECC ...\n"); | |
162 | ddr3_disable_ecc(base); | |
163 | ||
164 | value1 = __raw_readl(address); | |
165 | value2 = value1 ^ ecc_err; | |
166 | __raw_writel(value2, address); | |
167 | ||
168 | value3 = __raw_readl(address); | |
169 | printf("ECC err test, addr 0x%x, read data 0x%x, wrote data 0x%x, err pattern: 0x%x, read after write data 0x%x\n", | |
170 | address, value1, value2, ecc_err, value3); | |
171 | ||
172 | __raw_writel(ECC_START_ADDR1 | (ECC_END_ADDR1 << 16), | |
173 | base + KS2_DDR3_ECC_ADDR_RANGE1_OFFSET); | |
174 | ||
175 | puts("Enabling DDR ECC ...\n"); | |
176 | ddr3_enable_ecc(base, 1); | |
177 | ||
178 | value1 = __raw_readl(address); | |
179 | printf("ECC err test, addr 0x%x, read data 0x%x\n", address, value1); | |
180 | ||
181 | ddr3_check_ecc_int(base); | |
182 | return 0; | |
183 | } | |
184 | ||
185 | static int do_ddr_test(cmd_tbl_t *cmdtp, | |
186 | int flag, int argc, char * const argv[]) | |
187 | { | |
188 | u32 start_addr, end_addr, size, ecc_err; | |
189 | ||
190 | if ((argc == 4) && (strncmp(argv[1], "ecc_err", 8) == 0)) { | |
191 | if (!ddr3_ecc_support_rmw(KS2_DDR3A_EMIF_CTRL_BASE)) { | |
192 | puts("ECC RMW isn't supported for this SOC\n"); | |
193 | return 1; | |
194 | } | |
195 | ||
196 | start_addr = simple_strtoul(argv[2], NULL, 16); | |
197 | ecc_err = simple_strtoul(argv[3], NULL, 16); | |
198 | ||
199 | if ((start_addr < CONFIG_SYS_SDRAM_BASE) || | |
200 | (start_addr > (CONFIG_SYS_SDRAM_BASE + | |
201 | CONFIG_MAX_RAM_BANK_SIZE - 1))) { | |
202 | puts("Invalid address!\n"); | |
203 | return cmd_usage(cmdtp); | |
204 | } | |
205 | ||
206 | ddr_memory_ecc_err(KS2_DDR3A_EMIF_CTRL_BASE, | |
207 | start_addr, ecc_err); | |
208 | return 0; | |
209 | } | |
210 | ||
211 | if (!(((argc == 4) && (strncmp(argv[1], "test", 5) == 0)) || | |
212 | ((argc == 5) && (strncmp(argv[1], "compare", 8) == 0)))) | |
213 | return cmd_usage(cmdtp); | |
214 | ||
215 | start_addr = simple_strtoul(argv[2], NULL, 16); | |
216 | end_addr = simple_strtoul(argv[3], NULL, 16); | |
217 | ||
218 | if ((start_addr < CONFIG_SYS_SDRAM_BASE) || | |
219 | (start_addr > (CONFIG_SYS_SDRAM_BASE + | |
220 | CONFIG_MAX_RAM_BANK_SIZE - 1)) || | |
221 | (end_addr < CONFIG_SYS_SDRAM_BASE) || | |
222 | (end_addr > (CONFIG_SYS_SDRAM_BASE + | |
223 | CONFIG_MAX_RAM_BANK_SIZE - 1)) || (start_addr >= end_addr)) { | |
224 | puts("Invalid start or end address!\n"); | |
225 | return cmd_usage(cmdtp); | |
226 | } | |
227 | ||
228 | puts("Please wait ...\n"); | |
229 | if (argc == 5) { | |
230 | size = simple_strtoul(argv[4], NULL, 16); | |
231 | ddr_memory_compare(start_addr, end_addr, size); | |
232 | } else { | |
233 | ddr_memory_test(start_addr, end_addr, 0); | |
234 | } | |
235 | ||
236 | return 0; | |
237 | } | |
238 | ||
239 | U_BOOT_CMD(ddr, 5, 1, do_ddr_test, | |
240 | "DDR3 test", | |
241 | "test <start_addr in hex> <end_addr in hex> - test DDR from start\n" | |
242 | " address to end address\n" | |
243 | "ddr compare <start_addr in hex> <end_addr in hex> <size in hex> -\n" | |
244 | " compare DDR data of (size) bytes from start address to end\n" | |
245 | " address\n" | |
246 | "ddr ecc_err <addr in hex> <bit_err in hex> - generate bit errors\n" | |
247 | " in DDR data at <addr>, the command will read a 32-bit data\n" | |
248 | " from <addr>, and write (data ^ bit_err) back to <addr>\n" | |
249 | ); |