xref: /rk3399_rockchip-uboot/arch/arm/mach-keystone/cmd_ddr3.c (revision 01abae4d04868dede60947867699bf096a1831ff)
139a72345SMasahiro Yamada /*
239a72345SMasahiro Yamada  * Keystone2: DDR3 test commands
339a72345SMasahiro Yamada  *
439a72345SMasahiro Yamada  * (C) Copyright 2012-2014
539a72345SMasahiro Yamada  *     Texas Instruments Incorporated, <www.ti.com>
639a72345SMasahiro Yamada  *
739a72345SMasahiro Yamada  * SPDX-License-Identifier:     GPL-2.0+
839a72345SMasahiro Yamada  */
939a72345SMasahiro Yamada 
1039a72345SMasahiro Yamada #include <asm/arch/hardware.h>
1139a72345SMasahiro Yamada #include <asm/arch/ddr3.h>
1239a72345SMasahiro Yamada #include <common.h>
1339a72345SMasahiro Yamada #include <command.h>
1439a72345SMasahiro Yamada 
1539a72345SMasahiro Yamada DECLARE_GLOBAL_DATA_PTR;
1639a72345SMasahiro Yamada 
1739a72345SMasahiro Yamada #define DDR_MIN_ADDR		CONFIG_SYS_SDRAM_BASE
18*01abae4dSTom Rini #define STACKSIZE		(512 << 10)     /* 512 KiB */
1939a72345SMasahiro Yamada 
2039a72345SMasahiro Yamada #define DDR_REMAP_ADDR		0x80000000
2139a72345SMasahiro Yamada #define ECC_START_ADDR1		((DDR_MIN_ADDR - DDR_REMAP_ADDR) >> 17)
2239a72345SMasahiro Yamada 
2339a72345SMasahiro Yamada #define ECC_END_ADDR1		(((gd->start_addr_sp - DDR_REMAP_ADDR - \
24*01abae4dSTom Rini 				 STACKSIZE) >> 17) - 2)
2539a72345SMasahiro Yamada 
2639a72345SMasahiro Yamada #define DDR_TEST_BURST_SIZE	1024
2739a72345SMasahiro Yamada 
ddr_memory_test(u32 start_address,u32 end_address,int quick)2839a72345SMasahiro Yamada static int ddr_memory_test(u32 start_address, u32 end_address, int quick)
2939a72345SMasahiro Yamada {
3039a72345SMasahiro Yamada 	u32 index_start, value, index;
3139a72345SMasahiro Yamada 
3239a72345SMasahiro Yamada 	index_start = start_address;
3339a72345SMasahiro Yamada 
3439a72345SMasahiro Yamada 	while (1) {
3539a72345SMasahiro Yamada 		/* Write a pattern */
3639a72345SMasahiro Yamada 		for (index = index_start;
3739a72345SMasahiro Yamada 				index < index_start + DDR_TEST_BURST_SIZE;
3839a72345SMasahiro Yamada 				index += 4)
3939a72345SMasahiro Yamada 			__raw_writel(index, index);
4039a72345SMasahiro Yamada 
4139a72345SMasahiro Yamada 		/* Read and check the pattern */
4239a72345SMasahiro Yamada 		for (index = index_start;
4339a72345SMasahiro Yamada 				index < index_start + DDR_TEST_BURST_SIZE;
4439a72345SMasahiro Yamada 				index += 4) {
4539a72345SMasahiro Yamada 			value = __raw_readl(index);
4639a72345SMasahiro Yamada 			if (value != index) {
4739a72345SMasahiro Yamada 				printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
4839a72345SMasahiro Yamada 				       index, value, __raw_readl(index));
4939a72345SMasahiro Yamada 
5039a72345SMasahiro Yamada 				return -1;
5139a72345SMasahiro Yamada 			}
5239a72345SMasahiro Yamada 		}
5339a72345SMasahiro Yamada 
5439a72345SMasahiro Yamada 		index_start += DDR_TEST_BURST_SIZE;
5539a72345SMasahiro Yamada 		if (index_start >= end_address)
5639a72345SMasahiro Yamada 			break;
5739a72345SMasahiro Yamada 
5839a72345SMasahiro Yamada 		if (quick)
5939a72345SMasahiro Yamada 			continue;
6039a72345SMasahiro Yamada 
6139a72345SMasahiro Yamada 		/* Write a pattern for complementary values */
6239a72345SMasahiro Yamada 		for (index = index_start;
6339a72345SMasahiro Yamada 		     index < index_start + DDR_TEST_BURST_SIZE;
6439a72345SMasahiro Yamada 		     index += 4)
6539a72345SMasahiro Yamada 			__raw_writel((u32)~index, index);
6639a72345SMasahiro Yamada 
6739a72345SMasahiro Yamada 		/* Read and check the pattern */
6839a72345SMasahiro Yamada 		for (index = index_start;
6939a72345SMasahiro Yamada 		     index < index_start + DDR_TEST_BURST_SIZE;
7039a72345SMasahiro Yamada 		     index += 4) {
7139a72345SMasahiro Yamada 			value = __raw_readl(index);
7239a72345SMasahiro Yamada 			if (value != ~index) {
7339a72345SMasahiro Yamada 				printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
7439a72345SMasahiro Yamada 				       index, value, __raw_readl(index));
7539a72345SMasahiro Yamada 
7639a72345SMasahiro Yamada 				return -1;
7739a72345SMasahiro Yamada 			}
7839a72345SMasahiro Yamada 		}
7939a72345SMasahiro Yamada 
8039a72345SMasahiro Yamada 		index_start += DDR_TEST_BURST_SIZE;
8139a72345SMasahiro Yamada 		if (index_start >= end_address)
8239a72345SMasahiro Yamada 			break;
8339a72345SMasahiro Yamada 
8439a72345SMasahiro Yamada 		/* Write a pattern */
8539a72345SMasahiro Yamada 		for (index = index_start;
8639a72345SMasahiro Yamada 		     index < index_start + DDR_TEST_BURST_SIZE;
8739a72345SMasahiro Yamada 		     index += 2)
8839a72345SMasahiro Yamada 			__raw_writew((u16)index, index);
8939a72345SMasahiro Yamada 
9039a72345SMasahiro Yamada 		/* Read and check the pattern */
9139a72345SMasahiro Yamada 		for (index = index_start;
9239a72345SMasahiro Yamada 		     index < index_start + DDR_TEST_BURST_SIZE;
9339a72345SMasahiro Yamada 		     index += 2) {
9439a72345SMasahiro Yamada 			value = __raw_readw(index);
9539a72345SMasahiro Yamada 			if (value != (u16)index) {
9639a72345SMasahiro Yamada 				printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
9739a72345SMasahiro Yamada 				       index, value, __raw_readw(index));
9839a72345SMasahiro Yamada 
9939a72345SMasahiro Yamada 				return -1;
10039a72345SMasahiro Yamada 			}
10139a72345SMasahiro Yamada 		}
10239a72345SMasahiro Yamada 
10339a72345SMasahiro Yamada 		index_start += DDR_TEST_BURST_SIZE;
10439a72345SMasahiro Yamada 		if (index_start >= end_address)
10539a72345SMasahiro Yamada 			break;
10639a72345SMasahiro Yamada 
10739a72345SMasahiro Yamada 		/* Write a pattern */
10839a72345SMasahiro Yamada 		for (index = index_start;
10939a72345SMasahiro Yamada 		     index < index_start + DDR_TEST_BURST_SIZE;
11039a72345SMasahiro Yamada 		     index += 1)
11139a72345SMasahiro Yamada 			__raw_writeb((u8)index, index);
11239a72345SMasahiro Yamada 
11339a72345SMasahiro Yamada 		/* Read and check the pattern */
11439a72345SMasahiro Yamada 		for (index = index_start;
11539a72345SMasahiro Yamada 		     index < index_start + DDR_TEST_BURST_SIZE;
11639a72345SMasahiro Yamada 		     index += 1) {
11739a72345SMasahiro Yamada 			value = __raw_readb(index);
11839a72345SMasahiro Yamada 			if (value != (u8)index) {
11939a72345SMasahiro Yamada 				printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n",
12039a72345SMasahiro Yamada 				       index, value, __raw_readb(index));
12139a72345SMasahiro Yamada 
12239a72345SMasahiro Yamada 				return -1;
12339a72345SMasahiro Yamada 			}
12439a72345SMasahiro Yamada 		}
12539a72345SMasahiro Yamada 
12639a72345SMasahiro Yamada 		index_start += DDR_TEST_BURST_SIZE;
12739a72345SMasahiro Yamada 		if (index_start >= end_address)
12839a72345SMasahiro Yamada 			break;
12939a72345SMasahiro Yamada 	}
13039a72345SMasahiro Yamada 
13139a72345SMasahiro Yamada 	puts("ddr memory test PASSED!\n");
13239a72345SMasahiro Yamada 	return 0;
13339a72345SMasahiro Yamada }
13439a72345SMasahiro Yamada 
ddr_memory_compare(u32 address1,u32 address2,u32 size)13539a72345SMasahiro Yamada static int ddr_memory_compare(u32 address1, u32 address2, u32 size)
13639a72345SMasahiro Yamada {
13739a72345SMasahiro Yamada 	u32 index, value, index2, value2;
13839a72345SMasahiro Yamada 
13939a72345SMasahiro Yamada 	for (index = address1, index2 = address2;
14039a72345SMasahiro Yamada 	     index < address1 + size;
14139a72345SMasahiro Yamada 	     index += 4, index2 += 4) {
14239a72345SMasahiro Yamada 		value = __raw_readl(index);
14339a72345SMasahiro Yamada 		value2 = __raw_readl(index2);
14439a72345SMasahiro Yamada 
14539a72345SMasahiro Yamada 		if (value != value2) {
14639a72345SMasahiro Yamada 			printf("ddr_memory_test: Compare failed at address = 0x%x value = 0x%x, address2 = 0x%x value2 = 0x%x\n",
14739a72345SMasahiro Yamada 			       index, value, index2, value2);
14839a72345SMasahiro Yamada 
14939a72345SMasahiro Yamada 			return -1;
15039a72345SMasahiro Yamada 		}
15139a72345SMasahiro Yamada 	}
15239a72345SMasahiro Yamada 
15339a72345SMasahiro Yamada 	puts("ddr memory compare PASSED!\n");
15439a72345SMasahiro Yamada 	return 0;
15539a72345SMasahiro Yamada }
15639a72345SMasahiro Yamada 
ddr_memory_ecc_err(u32 base,u32 address,u32 ecc_err)15739a72345SMasahiro Yamada static int ddr_memory_ecc_err(u32 base, u32 address, u32 ecc_err)
15839a72345SMasahiro Yamada {
15939a72345SMasahiro Yamada 	u32 value1, value2, value3;
16039a72345SMasahiro Yamada 
16139a72345SMasahiro Yamada 	puts("Disabling DDR ECC ...\n");
16239a72345SMasahiro Yamada 	ddr3_disable_ecc(base);
16339a72345SMasahiro Yamada 
16439a72345SMasahiro Yamada 	value1 = __raw_readl(address);
16539a72345SMasahiro Yamada 	value2 = value1 ^ ecc_err;
16639a72345SMasahiro Yamada 	__raw_writel(value2, address);
16739a72345SMasahiro Yamada 
16839a72345SMasahiro Yamada 	value3 = __raw_readl(address);
16939a72345SMasahiro Yamada 	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",
17039a72345SMasahiro Yamada 	       address, value1, value2, ecc_err, value3);
17139a72345SMasahiro Yamada 
17239a72345SMasahiro Yamada 	__raw_writel(ECC_START_ADDR1 | (ECC_END_ADDR1 << 16),
17339a72345SMasahiro Yamada 		     base + KS2_DDR3_ECC_ADDR_RANGE1_OFFSET);
17439a72345SMasahiro Yamada 
17539a72345SMasahiro Yamada 	puts("Enabling DDR ECC ...\n");
17639a72345SMasahiro Yamada 	ddr3_enable_ecc(base, 1);
17739a72345SMasahiro Yamada 
17839a72345SMasahiro Yamada 	value1 = __raw_readl(address);
17939a72345SMasahiro Yamada 	printf("ECC err test, addr 0x%x, read data 0x%x\n", address, value1);
18039a72345SMasahiro Yamada 
18139a72345SMasahiro Yamada 	ddr3_check_ecc_int(base);
18239a72345SMasahiro Yamada 	return 0;
18339a72345SMasahiro Yamada }
18439a72345SMasahiro Yamada 
do_ddr_test(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])18539a72345SMasahiro Yamada static int do_ddr_test(cmd_tbl_t *cmdtp,
18639a72345SMasahiro Yamada 		       int flag, int argc, char * const argv[])
18739a72345SMasahiro Yamada {
18839a72345SMasahiro Yamada 	u32 start_addr, end_addr, size, ecc_err;
18939a72345SMasahiro Yamada 
19039a72345SMasahiro Yamada 	if ((argc == 4) && (strncmp(argv[1], "ecc_err", 8) == 0)) {
19139a72345SMasahiro Yamada 		if (!ddr3_ecc_support_rmw(KS2_DDR3A_EMIF_CTRL_BASE)) {
19239a72345SMasahiro Yamada 			puts("ECC RMW isn't supported for this SOC\n");
19339a72345SMasahiro Yamada 			return 1;
19439a72345SMasahiro Yamada 		}
19539a72345SMasahiro Yamada 
19639a72345SMasahiro Yamada 		start_addr = simple_strtoul(argv[2], NULL, 16);
19739a72345SMasahiro Yamada 		ecc_err = simple_strtoul(argv[3], NULL, 16);
19839a72345SMasahiro Yamada 
19939a72345SMasahiro Yamada 		if ((start_addr < CONFIG_SYS_SDRAM_BASE) ||
20039a72345SMasahiro Yamada 		    (start_addr > (CONFIG_SYS_SDRAM_BASE +
20139a72345SMasahiro Yamada 		     CONFIG_MAX_RAM_BANK_SIZE - 1))) {
20239a72345SMasahiro Yamada 			puts("Invalid address!\n");
20339a72345SMasahiro Yamada 			return cmd_usage(cmdtp);
20439a72345SMasahiro Yamada 		}
20539a72345SMasahiro Yamada 
20639a72345SMasahiro Yamada 		ddr_memory_ecc_err(KS2_DDR3A_EMIF_CTRL_BASE,
20739a72345SMasahiro Yamada 				   start_addr, ecc_err);
20839a72345SMasahiro Yamada 		return 0;
20939a72345SMasahiro Yamada 	}
21039a72345SMasahiro Yamada 
21139a72345SMasahiro Yamada 	if (!(((argc == 4) && (strncmp(argv[1], "test", 5) == 0)) ||
21239a72345SMasahiro Yamada 	      ((argc == 5) && (strncmp(argv[1], "compare", 8) == 0))))
21339a72345SMasahiro Yamada 		return cmd_usage(cmdtp);
21439a72345SMasahiro Yamada 
21539a72345SMasahiro Yamada 	start_addr = simple_strtoul(argv[2], NULL, 16);
21639a72345SMasahiro Yamada 	end_addr = simple_strtoul(argv[3], NULL, 16);
21739a72345SMasahiro Yamada 
21839a72345SMasahiro Yamada 	if ((start_addr < CONFIG_SYS_SDRAM_BASE) ||
21939a72345SMasahiro Yamada 	    (start_addr > (CONFIG_SYS_SDRAM_BASE +
22039a72345SMasahiro Yamada 	     CONFIG_MAX_RAM_BANK_SIZE - 1)) ||
22139a72345SMasahiro Yamada 	    (end_addr < CONFIG_SYS_SDRAM_BASE) ||
22239a72345SMasahiro Yamada 	    (end_addr > (CONFIG_SYS_SDRAM_BASE +
22339a72345SMasahiro Yamada 	     CONFIG_MAX_RAM_BANK_SIZE - 1)) || (start_addr >= end_addr)) {
22439a72345SMasahiro Yamada 		puts("Invalid start or end address!\n");
22539a72345SMasahiro Yamada 		return cmd_usage(cmdtp);
22639a72345SMasahiro Yamada 	}
22739a72345SMasahiro Yamada 
22839a72345SMasahiro Yamada 	puts("Please wait ...\n");
22939a72345SMasahiro Yamada 	if (argc == 5) {
23039a72345SMasahiro Yamada 		size = simple_strtoul(argv[4], NULL, 16);
23139a72345SMasahiro Yamada 		ddr_memory_compare(start_addr, end_addr, size);
23239a72345SMasahiro Yamada 	} else {
23339a72345SMasahiro Yamada 		ddr_memory_test(start_addr, end_addr, 0);
23439a72345SMasahiro Yamada 	}
23539a72345SMasahiro Yamada 
23639a72345SMasahiro Yamada 	return 0;
23739a72345SMasahiro Yamada }
23839a72345SMasahiro Yamada 
23939a72345SMasahiro Yamada U_BOOT_CMD(ddr,	5, 1, do_ddr_test,
24039a72345SMasahiro Yamada 	   "DDR3 test",
24139a72345SMasahiro Yamada 	   "test <start_addr in hex> <end_addr in hex> - test DDR from start\n"
24239a72345SMasahiro Yamada 	   "	address to end address\n"
24339a72345SMasahiro Yamada 	   "ddr compare <start_addr in hex> <end_addr in hex> <size in hex> -\n"
24439a72345SMasahiro Yamada 	   "	compare DDR data of (size) bytes from start address to end\n"
24539a72345SMasahiro Yamada 	   "	address\n"
24639a72345SMasahiro Yamada 	   "ddr ecc_err <addr in hex> <bit_err in hex> - generate bit errors\n"
24739a72345SMasahiro Yamada 	   "	in DDR data at <addr>, the command will read a 32-bit data\n"
24839a72345SMasahiro Yamada 	   "	from <addr>, and write (data ^ bit_err) back to <addr>\n"
24939a72345SMasahiro Yamada );
250