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