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 18 #define STACKSIZE (512 << 10) /* 512 KiB */ 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 - \ 24 STACKSIZE) >> 17) - 2) 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 ); 250