2 * EMIF: DDR3 test commands
4 * Copyright (C) 2012-2017 Texas Instruments Incorporated, <www.ti.com>
6 * SPDX-License-Identifier: GPL-2.0+
9 #include <asm/arch/hardware.h>
10 #include <asm/cache.h>
15 DECLARE_GLOBAL_DATA_PTR
;
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) /* 512 KiB */
22 #define DDR_REMAP_ADDR 0x80000000
23 #define ECC_START_ADDR1 ((DDR_MIN_ADDR - DDR_REMAP_ADDR) >> 17)
25 #define ECC_END_ADDR1 (((gd->start_addr_sp - DDR_REMAP_ADDR - \
26 STACKSIZE) >> 17) - 2)
29 #define DDR_TEST_BURST_SIZE 1024
31 static int ddr_memory_test(u32 start_address
, u32 end_address
, int quick
)
33 u32 index_start
, value
, index
;
35 index_start
= start_address
;
39 for (index
= index_start
;
40 index
< index_start
+ DDR_TEST_BURST_SIZE
;
42 __raw_writel(index
, index
);
44 /* Read and check the pattern */
45 for (index
= index_start
;
46 index
< index_start
+ DDR_TEST_BURST_SIZE
;
48 value
= __raw_readl(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
));
57 index_start
+= DDR_TEST_BURST_SIZE
;
58 if (index_start
>= end_address
)
64 /* Write a pattern for complementary values */
65 for (index
= index_start
;
66 index
< index_start
+ DDR_TEST_BURST_SIZE
;
68 __raw_writel((u32
)~index
, index
);
70 /* Read and check the pattern */
71 for (index
= index_start
;
72 index
< index_start
+ DDR_TEST_BURST_SIZE
;
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
));
83 index_start
+= DDR_TEST_BURST_SIZE
;
84 if (index_start
>= end_address
)
88 for (index
= index_start
;
89 index
< index_start
+ DDR_TEST_BURST_SIZE
;
91 __raw_writew((u16
)index
, index
);
93 /* Read and check the pattern */
94 for (index
= index_start
;
95 index
< index_start
+ DDR_TEST_BURST_SIZE
;
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
));
106 index_start
+= DDR_TEST_BURST_SIZE
;
107 if (index_start
>= end_address
)
110 /* Write a pattern */
111 for (index
= index_start
;
112 index
< index_start
+ DDR_TEST_BURST_SIZE
;
114 __raw_writeb((u8
)index
, index
);
116 /* Read and check the pattern */
117 for (index
= index_start
;
118 index
< index_start
+ DDR_TEST_BURST_SIZE
;
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
));
129 index_start
+= DDR_TEST_BURST_SIZE
;
130 if (index_start
>= end_address
)
134 puts("ddr memory test PASSED!\n");
138 static int ddr_memory_compare(u32 address1
, u32 address2
, u32 size
)
140 u32 index
, value
, index2
, value2
;
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
);
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
);
156 puts("ddr memory compare PASSED!\n");
160 static void ddr_check_ecc_status(void)
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
);
168 env
= env_get("ecc_test");
170 ecc_test
= simple_strtol(env
, NULL
, 0);
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");
176 if (int_status
& EMIF_INT_TWOBIT_ECC_ERR_SYS_MASK
)
178 panic("\tECC test: DDR ECC 2-bit error interrupted");
180 if (int_status
& EMIF_INT_ONEBIT_ECC_ERR_SYS_MASK
)
181 puts("\tECC test: DDR ECC 1-bit error interrupted\n");
184 printf("\tECC test: 1-bit ECC err count: 0x%x\n", err_1b
);
187 static int ddr_memory_ecc_err(u32 addr
, u32 ecc_err
)
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
;
193 debug("Disabling D-Cache before ECC test\n");
195 invalidate_dcache_all();
197 puts("Testing DDR ECC:\n");
198 puts("\tECC test: Disabling DDR ECC ...\n");
199 writel(0, &emif
->emif_ecc_ctrl_reg
);
202 val2
= val1
^ ecc_err
;
206 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",
207 addr
, val1
, val2
, ecc_err
, val3
);
209 puts("\tECC test: Enabling DDR ECC ...\n");
210 #ifdef CONFIG_ARCH_KEYSTONE
211 ecc_ctrl
= ECC_START_ADDR1
| (ECC_END_ADDR1
<< 16);
212 writel(ecc_ctrl
, EMIF1_BASE
+ KS2_DDR3_ECC_ADDR_RANGE1_OFFSET
);
213 ddr3_enable_ecc(EMIF1_BASE
, 1);
215 writel(ecc_ctrl
, &emif
->emif_ecc_ctrl_reg
);
219 printf("\tECC test: addr 0x%x, read data 0x%x\n", addr
, val1
);
221 ddr_check_ecc_status();
223 debug("Enabling D-cache back after ECC test\n");
229 static int is_addr_valid(u32 addr
)
231 struct emif_reg_struct
*emif
= (struct emif_reg_struct
*)EMIF1_BASE
;
232 u32 start_addr
, end_addr
, range
, ecc_ctrl
;
234 #ifdef CONFIG_ARCH_KEYSTONE
235 ecc_ctrl
= EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK
;
236 range
= ECC_START_ADDR1
| (ECC_END_ADDR1
<< 16);
238 ecc_ctrl
= readl(&emif
->emif_ecc_ctrl_reg
);
239 range
= readl(&emif
->emif_ecc_address_range_1
);
242 /* Check in ecc address range 1 */
243 if (ecc_ctrl
& EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK
) {
244 start_addr
= ((range
& EMIF_ECC_REG_ECC_START_ADDR_MASK
) << 16)
245 + CONFIG_SYS_SDRAM_BASE
;
246 end_addr
= start_addr
+ (range
& EMIF_ECC_REG_ECC_END_ADDR_MASK
)
248 if ((addr
>= start_addr
) && (addr
<= end_addr
))
249 /* addr within ecc address range 1 */
253 /* Check in ecc address range 2 */
254 if (ecc_ctrl
& EMIF_ECC_REG_ECC_ADDR_RGN_2_EN_MASK
) {
255 range
= readl(&emif
->emif_ecc_address_range_2
);
256 start_addr
= ((range
& EMIF_ECC_REG_ECC_START_ADDR_MASK
) << 16)
257 + CONFIG_SYS_SDRAM_BASE
;
258 end_addr
= start_addr
+ (range
& EMIF_ECC_REG_ECC_END_ADDR_MASK
)
260 if ((addr
>= start_addr
) && (addr
<= end_addr
))
261 /* addr within ecc address range 2 */
268 static int is_ecc_enabled(void)
270 struct emif_reg_struct
*emif
= (struct emif_reg_struct
*)EMIF1_BASE
;
271 u32 ecc_ctrl
= readl(&emif
->emif_ecc_ctrl_reg
);
273 return (ecc_ctrl
& EMIF_ECC_CTRL_REG_ECC_EN_MASK
) &&
274 (ecc_ctrl
& EMIF_ECC_REG_RMW_EN_MASK
);
277 static int do_ddr_test(cmd_tbl_t
*cmdtp
,
278 int flag
, int argc
, char * const argv
[])
280 u32 start_addr
, end_addr
, size
, ecc_err
;
282 if ((argc
== 4) && (strncmp(argv
[1], "ecc_err", 8) == 0)) {
283 if (!is_ecc_enabled()) {
284 puts("ECC not enabled. Please Enable ECC any try again\n");
285 return CMD_RET_FAILURE
;
288 start_addr
= simple_strtoul(argv
[2], NULL
, 16);
289 ecc_err
= simple_strtoul(argv
[3], NULL
, 16);
291 if (!is_addr_valid(start_addr
)) {
292 puts("Invalid address. Please enter ECC supported address!\n");
293 return CMD_RET_FAILURE
;
296 ddr_memory_ecc_err(start_addr
, ecc_err
);
300 if (!(((argc
== 4) && (strncmp(argv
[1], "test", 5) == 0)) ||
301 ((argc
== 5) && (strncmp(argv
[1], "compare", 8) == 0))))
302 return cmd_usage(cmdtp
);
304 start_addr
= simple_strtoul(argv
[2], NULL
, 16);
305 end_addr
= simple_strtoul(argv
[3], NULL
, 16);
307 if ((start_addr
< CONFIG_SYS_SDRAM_BASE
) ||
308 (start_addr
> (CONFIG_SYS_SDRAM_BASE
+
309 get_effective_memsize() - 1)) ||
310 (end_addr
< CONFIG_SYS_SDRAM_BASE
) ||
311 (end_addr
> (CONFIG_SYS_SDRAM_BASE
+
312 get_effective_memsize() - 1)) || (start_addr
>= end_addr
)) {
313 puts("Invalid start or end address!\n");
314 return cmd_usage(cmdtp
);
317 puts("Please wait ...\n");
319 size
= simple_strtoul(argv
[4], NULL
, 16);
320 ddr_memory_compare(start_addr
, end_addr
, size
);
322 ddr_memory_test(start_addr
, end_addr
, 0);
328 U_BOOT_CMD(ddr
, 5, 1, do_ddr_test
,
330 "test <start_addr in hex> <end_addr in hex> - test DDR from start\n"
331 " address to end address\n"
332 "ddr compare <start_addr in hex> <end_addr in hex> <size in hex> -\n"
333 " compare DDR data of (size) bytes from start address to end\n"
335 "ddr ecc_err <addr in hex> <bit_err in hex> - generate bit errors\n"
336 " in DDR data at <addr>, the command will read a 32-bit data\n"
337 " from <addr>, and write (data ^ bit_err) back to <addr>\n"