1 /* 2 * EMIF: DDR3 test commands 3 * 4 * Copyright (C) 2012-2017 Texas Instruments Incorporated, <www.ti.com> 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <asm/arch/hardware.h> 10 #include <asm/cache.h> 11 #include <asm/emif.h> 12 #include <common.h> 13 #include <command.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 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 */ 21 22 #define DDR_REMAP_ADDR 0x80000000 23 #define ECC_START_ADDR1 ((DDR_MIN_ADDR - DDR_REMAP_ADDR) >> 17) 24 25 #define ECC_END_ADDR1 (((gd->start_addr_sp - DDR_REMAP_ADDR - \ 26 STACKSIZE) >> 17) - 2) 27 #endif 28 29 #define DDR_TEST_BURST_SIZE 1024 30 31 static int ddr_memory_test(u32 start_address, u32 end_address, int quick) 32 { 33 u32 index_start, value, index; 34 35 index_start = start_address; 36 37 while (1) { 38 /* Write a pattern */ 39 for (index = index_start; 40 index < index_start + DDR_TEST_BURST_SIZE; 41 index += 4) 42 __raw_writel(index, index); 43 44 /* Read and check the pattern */ 45 for (index = index_start; 46 index < index_start + DDR_TEST_BURST_SIZE; 47 index += 4) { 48 value = __raw_readl(index); 49 if (value != 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)); 52 53 return -1; 54 } 55 } 56 57 index_start += DDR_TEST_BURST_SIZE; 58 if (index_start >= end_address) 59 break; 60 61 if (quick) 62 continue; 63 64 /* Write a pattern for complementary values */ 65 for (index = index_start; 66 index < index_start + DDR_TEST_BURST_SIZE; 67 index += 4) 68 __raw_writel((u32)~index, index); 69 70 /* Read and check the pattern */ 71 for (index = index_start; 72 index < index_start + DDR_TEST_BURST_SIZE; 73 index += 4) { 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)); 78 79 return -1; 80 } 81 } 82 83 index_start += DDR_TEST_BURST_SIZE; 84 if (index_start >= end_address) 85 break; 86 87 /* Write a pattern */ 88 for (index = index_start; 89 index < index_start + DDR_TEST_BURST_SIZE; 90 index += 2) 91 __raw_writew((u16)index, index); 92 93 /* Read and check the pattern */ 94 for (index = index_start; 95 index < index_start + DDR_TEST_BURST_SIZE; 96 index += 2) { 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)); 101 102 return -1; 103 } 104 } 105 106 index_start += DDR_TEST_BURST_SIZE; 107 if (index_start >= end_address) 108 break; 109 110 /* Write a pattern */ 111 for (index = index_start; 112 index < index_start + DDR_TEST_BURST_SIZE; 113 index += 1) 114 __raw_writeb((u8)index, index); 115 116 /* Read and check the pattern */ 117 for (index = index_start; 118 index < index_start + DDR_TEST_BURST_SIZE; 119 index += 1) { 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)); 124 125 return -1; 126 } 127 } 128 129 index_start += DDR_TEST_BURST_SIZE; 130 if (index_start >= end_address) 131 break; 132 } 133 134 puts("ddr memory test PASSED!\n"); 135 return 0; 136 } 137 138 static int ddr_memory_compare(u32 address1, u32 address2, u32 size) 139 { 140 u32 index, value, index2, value2; 141 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); 147 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); 151 152 return -1; 153 } 154 } 155 156 puts("ddr memory compare PASSED!\n"); 157 return 0; 158 } 159 160 static void ddr_check_ecc_status(void) 161 { 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); 165 int ecc_test = 0; 166 char *env; 167 168 env = env_get("ecc_test"); 169 if (env) 170 ecc_test = simple_strtol(env, NULL, 0); 171 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"); 175 176 if (int_status & EMIF_INT_TWOBIT_ECC_ERR_SYS_MASK) 177 if (!ecc_test) 178 panic("\tECC test: DDR ECC 2-bit error interrupted"); 179 180 if (int_status & EMIF_INT_ONEBIT_ECC_ERR_SYS_MASK) 181 puts("\tECC test: DDR ECC 1-bit error interrupted\n"); 182 183 if (err_1b) 184 printf("\tECC test: 1-bit ECC err count: 0x%x\n", err_1b); 185 } 186 187 static int ddr_memory_ecc_err(u32 addr, u32 ecc_err) 188 { 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; 192 193 debug("Disabling D-Cache before ECC test\n"); 194 dcache_disable(); 195 invalidate_dcache_all(); 196 197 puts("Testing DDR ECC:\n"); 198 puts("\tECC test: Disabling DDR ECC ...\n"); 199 writel(0, &emif->emif_ecc_ctrl_reg); 200 201 val1 = readl(addr); 202 val2 = val1 ^ ecc_err; 203 writel(val2, addr); 204 205 val3 = readl(addr); 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); 208 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); 214 #else 215 writel(ecc_ctrl, &emif->emif_ecc_ctrl_reg); 216 #endif 217 218 val1 = readl(addr); 219 printf("\tECC test: addr 0x%x, read data 0x%x\n", addr, val1); 220 221 ddr_check_ecc_status(); 222 223 debug("Enabling D-cache back after ECC test\n"); 224 enable_caches(); 225 226 return 0; 227 } 228 229 static int is_addr_valid(u32 addr) 230 { 231 struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE; 232 u32 start_addr, end_addr, range, ecc_ctrl; 233 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); 237 #else 238 ecc_ctrl = readl(&emif->emif_ecc_ctrl_reg); 239 range = readl(&emif->emif_ecc_address_range_1); 240 #endif 241 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) 247 + 0xFFFF; 248 if ((addr >= start_addr) && (addr <= end_addr)) 249 /* addr within ecc address range 1 */ 250 return 1; 251 } 252 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) 259 + 0xFFFF; 260 if ((addr >= start_addr) && (addr <= end_addr)) 261 /* addr within ecc address range 2 */ 262 return 1; 263 } 264 265 return 0; 266 } 267 268 static int is_ecc_enabled(void) 269 { 270 struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE; 271 u32 ecc_ctrl = readl(&emif->emif_ecc_ctrl_reg); 272 273 return (ecc_ctrl & EMIF_ECC_CTRL_REG_ECC_EN_MASK) && 274 (ecc_ctrl & EMIF_ECC_REG_RMW_EN_MASK); 275 } 276 277 static int do_ddr_test(cmd_tbl_t *cmdtp, 278 int flag, int argc, char * const argv[]) 279 { 280 u32 start_addr, end_addr, size, ecc_err; 281 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; 286 } 287 288 start_addr = simple_strtoul(argv[2], NULL, 16); 289 ecc_err = simple_strtoul(argv[3], NULL, 16); 290 291 if (!is_addr_valid(start_addr)) { 292 puts("Invalid address. Please enter ECC supported address!\n"); 293 return CMD_RET_FAILURE; 294 } 295 296 ddr_memory_ecc_err(start_addr, ecc_err); 297 return 0; 298 } 299 300 if (!(((argc == 4) && (strncmp(argv[1], "test", 5) == 0)) || 301 ((argc == 5) && (strncmp(argv[1], "compare", 8) == 0)))) 302 return cmd_usage(cmdtp); 303 304 start_addr = simple_strtoul(argv[2], NULL, 16); 305 end_addr = simple_strtoul(argv[3], NULL, 16); 306 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); 315 } 316 317 puts("Please wait ...\n"); 318 if (argc == 5) { 319 size = simple_strtoul(argv[4], NULL, 16); 320 ddr_memory_compare(start_addr, end_addr, size); 321 } else { 322 ddr_memory_test(start_addr, end_addr, 0); 323 } 324 325 return 0; 326 } 327 328 U_BOOT_CMD(ddr, 5, 1, do_ddr_test, 329 "DDR3 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" 334 " address\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" 338 ); 339