1 // SPDX-License-Identifier: GPL-2.0+
3 * EMIF: DDR3 test commands
5 * Copyright (C) 2012-2017 Texas Instruments Incorporated, <www.ti.com>
10 #include <asm/arch/hardware.h>
11 #include <asm/cache.h>
16 DECLARE_GLOBAL_DATA_PTR;
18 #ifdef CONFIG_ARCH_KEYSTONE
19 #include <asm/arch/ddr3.h>
20 #define DDR_MIN_ADDR CONFIG_SYS_SDRAM_BASE
21 #define STACKSIZE (512 << 10) /* 512 KiB */
23 #define DDR_REMAP_ADDR 0x80000000
24 #define ECC_START_ADDR1 ((DDR_MIN_ADDR - DDR_REMAP_ADDR) >> 17)
26 #define ECC_END_ADDR1 (((gd->start_addr_sp - DDR_REMAP_ADDR - \
27 STACKSIZE) >> 17) - 2)
30 #define DDR_TEST_BURST_SIZE 1024
32 static int ddr_memory_test(u32 start_address, u32 end_address, int quick)
34 u32 index_start, value, index;
36 index_start = start_address;
40 for (index = index_start;
41 index < index_start + DDR_TEST_BURST_SIZE;
43 __raw_writel(index, index);
45 /* Read and check the pattern */
46 for (index = index_start;
47 index < index_start + DDR_TEST_BURST_SIZE;
49 value = __raw_readl(index);
51 printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
52 index, value, __raw_readl(index));
58 index_start += DDR_TEST_BURST_SIZE;
59 if (index_start >= end_address)
65 /* Write a pattern for complementary values */
66 for (index = index_start;
67 index < index_start + DDR_TEST_BURST_SIZE;
69 __raw_writel((u32)~index, index);
71 /* Read and check the pattern */
72 for (index = index_start;
73 index < index_start + DDR_TEST_BURST_SIZE;
75 value = __raw_readl(index);
76 if (value != ~index) {
77 printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
78 index, value, __raw_readl(index));
84 index_start += DDR_TEST_BURST_SIZE;
85 if (index_start >= end_address)
89 for (index = index_start;
90 index < index_start + DDR_TEST_BURST_SIZE;
92 __raw_writew((u16)index, index);
94 /* Read and check the pattern */
95 for (index = index_start;
96 index < index_start + DDR_TEST_BURST_SIZE;
98 value = __raw_readw(index);
99 if (value != (u16)index) {
100 printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
101 index, value, __raw_readw(index));
107 index_start += DDR_TEST_BURST_SIZE;
108 if (index_start >= end_address)
111 /* Write a pattern */
112 for (index = index_start;
113 index < index_start + DDR_TEST_BURST_SIZE;
115 __raw_writeb((u8)index, index);
117 /* Read and check the pattern */
118 for (index = index_start;
119 index < index_start + DDR_TEST_BURST_SIZE;
121 value = __raw_readb(index);
122 if (value != (u8)index) {
123 printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
124 index, value, __raw_readb(index));
130 index_start += DDR_TEST_BURST_SIZE;
131 if (index_start >= end_address)
135 puts("ddr memory test PASSED!\n");
139 static int ddr_memory_compare(u32 address1, u32 address2, u32 size)
141 u32 index, value, index2, value2;
143 for (index = address1, index2 = address2;
144 index < address1 + size;
145 index += 4, index2 += 4) {
146 value = __raw_readl(index);
147 value2 = __raw_readl(index2);
149 if (value != value2) {
150 printf("ddr_memory_test: Compare failed at address = 0x%x value = 0x%x, address2 = 0x%x value2 = 0x%x\n",
151 index, value, index2, value2);
157 puts("ddr memory compare PASSED!\n");
161 static void ddr_check_ecc_status(void)
163 struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
164 u32 err_1b = readl(&emif->emif_1b_ecc_err_cnt);
165 u32 int_status = readl(&emif->emif_irqstatus_raw_sys);
169 env = env_get("ecc_test");
171 ecc_test = simple_strtol(env, NULL, 0);
173 puts("ECC test Status:\n");
174 if (int_status & EMIF_INT_WR_ECC_ERR_SYS_MASK)
175 puts("\tECC test: DDR ECC write error interrupted\n");
177 if (int_status & EMIF_INT_TWOBIT_ECC_ERR_SYS_MASK)
179 panic("\tECC test: DDR ECC 2-bit error interrupted");
181 if (int_status & EMIF_INT_ONEBIT_ECC_ERR_SYS_MASK)
182 puts("\tECC test: DDR ECC 1-bit error interrupted\n");
185 printf("\tECC test: 1-bit ECC err count: 0x%x\n", err_1b);
188 static int ddr_memory_ecc_err(u32 addr, u32 ecc_err)
190 struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
191 u32 ecc_ctrl = readl(&emif->emif_ecc_ctrl_reg);
192 u32 val1, val2, val3;
194 debug("Disabling D-Cache before ECC test\n");
196 invalidate_dcache_all();
198 puts("Testing DDR ECC:\n");
199 puts("\tECC test: Disabling DDR ECC ...\n");
200 writel(0, &emif->emif_ecc_ctrl_reg);
203 val2 = val1 ^ ecc_err;
207 #ifdef CONFIG_ARCH_KEYSTONE
208 ecc_ctrl = ECC_START_ADDR1 | (ECC_END_ADDR1 << 16);
209 writel(ecc_ctrl, EMIF1_BASE + KS2_DDR3_ECC_ADDR_RANGE1_OFFSET);
210 ddr3_enable_ecc(EMIF1_BASE, 1);
212 writel(ecc_ctrl, &emif->emif_ecc_ctrl_reg);
215 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",
216 addr, val1, val2, ecc_err, val3);
218 puts("\tECC test: Enabled DDR ECC ...\n");
221 printf("\tECC test: addr 0x%x, read data 0x%x\n", addr, val1);
223 ddr_check_ecc_status();
225 debug("Enabling D-cache back after ECC test\n");
231 static int is_addr_valid(u32 addr)
233 struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
234 u32 start_addr, end_addr, range, ecc_ctrl;
236 #ifdef CONFIG_ARCH_KEYSTONE
237 ecc_ctrl = EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK;
238 range = ECC_START_ADDR1 | (ECC_END_ADDR1 << 16);
240 ecc_ctrl = readl(&emif->emif_ecc_ctrl_reg);
241 range = readl(&emif->emif_ecc_address_range_1);
244 /* Check in ecc address range 1 */
245 if (ecc_ctrl & EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK) {
246 start_addr = ((range & EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16)
247 + CONFIG_SYS_SDRAM_BASE;
248 end_addr = (range & EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0xFFFF +
249 CONFIG_SYS_SDRAM_BASE;
250 if ((addr >= start_addr) && (addr <= end_addr))
251 /* addr within ecc address range 1 */
255 /* Check in ecc address range 2 */
256 if (ecc_ctrl & EMIF_ECC_REG_ECC_ADDR_RGN_2_EN_MASK) {
257 range = readl(&emif->emif_ecc_address_range_2);
258 start_addr = ((range & EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16)
259 + CONFIG_SYS_SDRAM_BASE;
260 end_addr = (range & EMIF_ECC_REG_ECC_END_ADDR_MASK) + 0xFFFF +
261 CONFIG_SYS_SDRAM_BASE;
262 if ((addr >= start_addr) && (addr <= end_addr))
263 /* addr within ecc address range 2 */
270 static int is_ecc_enabled(void)
272 struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
273 u32 ecc_ctrl = readl(&emif->emif_ecc_ctrl_reg);
275 return (ecc_ctrl & EMIF_ECC_CTRL_REG_ECC_EN_MASK) &&
276 (ecc_ctrl & EMIF_ECC_REG_RMW_EN_MASK);
279 static int do_ddr_test(cmd_tbl_t *cmdtp,
280 int flag, int argc, char * const argv[])
282 u32 start_addr, end_addr, size, ecc_err;
284 if ((argc == 4) && (strncmp(argv[1], "ecc_err", 8) == 0)) {
285 if (!is_ecc_enabled()) {
286 puts("ECC not enabled. Please Enable ECC any try again\n");
287 return CMD_RET_FAILURE;
290 start_addr = simple_strtoul(argv[2], NULL, 16);
291 ecc_err = simple_strtoul(argv[3], NULL, 16);
293 if (!is_addr_valid(start_addr)) {
294 puts("Invalid address. Please enter ECC supported address!\n");
295 return CMD_RET_FAILURE;
298 ddr_memory_ecc_err(start_addr, ecc_err);
302 if (!(((argc == 4) && (strncmp(argv[1], "test", 5) == 0)) ||
303 ((argc == 5) && (strncmp(argv[1], "compare", 8) == 0))))
304 return cmd_usage(cmdtp);
306 start_addr = simple_strtoul(argv[2], NULL, 16);
307 end_addr = simple_strtoul(argv[3], NULL, 16);
309 if ((start_addr < CONFIG_SYS_SDRAM_BASE) ||
310 (start_addr > (CONFIG_SYS_SDRAM_BASE +
311 get_effective_memsize() - 1)) ||
312 (end_addr < CONFIG_SYS_SDRAM_BASE) ||
313 (end_addr > (CONFIG_SYS_SDRAM_BASE +
314 get_effective_memsize() - 1)) || (start_addr >= end_addr)) {
315 puts("Invalid start or end address!\n");
316 return cmd_usage(cmdtp);
319 puts("Please wait ...\n");
321 size = simple_strtoul(argv[4], NULL, 16);
322 ddr_memory_compare(start_addr, end_addr, size);
324 ddr_memory_test(start_addr, end_addr, 0);
330 U_BOOT_CMD(ddr, 5, 1, do_ddr_test,
332 "test <start_addr in hex> <end_addr in hex> - test DDR from start\n"
333 " address to end address\n"
334 "ddr compare <start_addr in hex> <end_addr in hex> <size in hex> -\n"
335 " compare DDR data of (size) bytes from start address to end\n"
337 "ddr ecc_err <addr in hex> <bit_err in hex> - generate bit errors\n"
338 " in DDR data at <addr>, the command will read a 32-bit data\n"
339 " from <addr>, and write (data ^ bit_err) back to <addr>\n"