1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * EMIF: DDR3 test commands 4 * 5 * Copyright (C) 2012-2017 Texas Instruments Incorporated, <www.ti.com> 6 */ 7 8 #include <asm/arch/hardware.h> 9 #include <asm/cache.h> 10 #include <asm/emif.h> 11 #include <common.h> 12 #include <command.h> 13 14 DECLARE_GLOBAL_DATA_PTR; 15 16 #ifdef CONFIG_ARCH_KEYSTONE 17 #include <asm/arch/ddr3.h> 18 #define DDR_MIN_ADDR CONFIG_SYS_SDRAM_BASE 19 #define STACKSIZE (512 << 10) /* 512 KiB */ 20 21 #define DDR_REMAP_ADDR 0x80000000 22 #define ECC_START_ADDR1 ((DDR_MIN_ADDR - DDR_REMAP_ADDR) >> 17) 23 24 #define ECC_END_ADDR1 (((gd->start_addr_sp - DDR_REMAP_ADDR - \ 25 STACKSIZE) >> 17) - 2) 26 #endif 27 28 #define DDR_TEST_BURST_SIZE 1024 29 30 static int ddr_memory_test(u32 start_address, u32 end_address, int quick) 31 { 32 u32 index_start, value, index; 33 34 index_start = start_address; 35 36 while (1) { 37 /* Write a pattern */ 38 for (index = index_start; 39 index < index_start + DDR_TEST_BURST_SIZE; 40 index += 4) 41 __raw_writel(index, index); 42 43 /* Read and check the pattern */ 44 for (index = index_start; 45 index < index_start + DDR_TEST_BURST_SIZE; 46 index += 4) { 47 value = __raw_readl(index); 48 if (value != index) { 49 printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n", 50 index, value, __raw_readl(index)); 51 52 return -1; 53 } 54 } 55 56 index_start += DDR_TEST_BURST_SIZE; 57 if (index_start >= end_address) 58 break; 59 60 if (quick) 61 continue; 62 63 /* Write a pattern for complementary values */ 64 for (index = index_start; 65 index < index_start + DDR_TEST_BURST_SIZE; 66 index += 4) 67 __raw_writel((u32)~index, index); 68 69 /* Read and check the pattern */ 70 for (index = index_start; 71 index < index_start + DDR_TEST_BURST_SIZE; 72 index += 4) { 73 value = __raw_readl(index); 74 if (value != ~index) { 75 printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n", 76 index, value, __raw_readl(index)); 77 78 return -1; 79 } 80 } 81 82 index_start += DDR_TEST_BURST_SIZE; 83 if (index_start >= end_address) 84 break; 85 86 /* Write a pattern */ 87 for (index = index_start; 88 index < index_start + DDR_TEST_BURST_SIZE; 89 index += 2) 90 __raw_writew((u16)index, index); 91 92 /* Read and check the pattern */ 93 for (index = index_start; 94 index < index_start + DDR_TEST_BURST_SIZE; 95 index += 2) { 96 value = __raw_readw(index); 97 if (value != (u16)index) { 98 printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n", 99 index, value, __raw_readw(index)); 100 101 return -1; 102 } 103 } 104 105 index_start += DDR_TEST_BURST_SIZE; 106 if (index_start >= end_address) 107 break; 108 109 /* Write a pattern */ 110 for (index = index_start; 111 index < index_start + DDR_TEST_BURST_SIZE; 112 index += 1) 113 __raw_writeb((u8)index, index); 114 115 /* Read and check the pattern */ 116 for (index = index_start; 117 index < index_start + DDR_TEST_BURST_SIZE; 118 index += 1) { 119 value = __raw_readb(index); 120 if (value != (u8)index) { 121 printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n", 122 index, value, __raw_readb(index)); 123 124 return -1; 125 } 126 } 127 128 index_start += DDR_TEST_BURST_SIZE; 129 if (index_start >= end_address) 130 break; 131 } 132 133 puts("ddr memory test PASSED!\n"); 134 return 0; 135 } 136 137 static int ddr_memory_compare(u32 address1, u32 address2, u32 size) 138 { 139 u32 index, value, index2, value2; 140 141 for (index = address1, index2 = address2; 142 index < address1 + size; 143 index += 4, index2 += 4) { 144 value = __raw_readl(index); 145 value2 = __raw_readl(index2); 146 147 if (value != value2) { 148 printf("ddr_memory_test: Compare failed at address = 0x%x value = 0x%x, address2 = 0x%x value2 = 0x%x\n", 149 index, value, index2, value2); 150 151 return -1; 152 } 153 } 154 155 puts("ddr memory compare PASSED!\n"); 156 return 0; 157 } 158 159 static void ddr_check_ecc_status(void) 160 { 161 struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE; 162 u32 err_1b = readl(&emif->emif_1b_ecc_err_cnt); 163 u32 int_status = readl(&emif->emif_irqstatus_raw_sys); 164 int ecc_test = 0; 165 char *env; 166 167 env = env_get("ecc_test"); 168 if (env) 169 ecc_test = simple_strtol(env, NULL, 0); 170 171 puts("ECC test Status:\n"); 172 if (int_status & EMIF_INT_WR_ECC_ERR_SYS_MASK) 173 puts("\tECC test: DDR ECC write error interrupted\n"); 174 175 if (int_status & EMIF_INT_TWOBIT_ECC_ERR_SYS_MASK) 176 if (!ecc_test) 177 panic("\tECC test: DDR ECC 2-bit error interrupted"); 178 179 if (int_status & EMIF_INT_ONEBIT_ECC_ERR_SYS_MASK) 180 puts("\tECC test: DDR ECC 1-bit error interrupted\n"); 181 182 if (err_1b) 183 printf("\tECC test: 1-bit ECC err count: 0x%x\n", err_1b); 184 } 185 186 static int ddr_memory_ecc_err(u32 addr, u32 ecc_err) 187 { 188 struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE; 189 u32 ecc_ctrl = readl(&emif->emif_ecc_ctrl_reg); 190 u32 val1, val2, val3; 191 192 debug("Disabling D-Cache before ECC test\n"); 193 dcache_disable(); 194 invalidate_dcache_all(); 195 196 puts("Testing DDR ECC:\n"); 197 puts("\tECC test: Disabling DDR ECC ...\n"); 198 writel(0, &emif->emif_ecc_ctrl_reg); 199 200 val1 = readl(addr); 201 val2 = val1 ^ ecc_err; 202 writel(val2, addr); 203 204 val3 = readl(addr); 205 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", 206 addr, val1, val2, ecc_err, val3); 207 208 puts("\tECC test: Enabling DDR ECC ...\n"); 209 #ifdef CONFIG_ARCH_KEYSTONE 210 ecc_ctrl = ECC_START_ADDR1 | (ECC_END_ADDR1 << 16); 211 writel(ecc_ctrl, EMIF1_BASE + KS2_DDR3_ECC_ADDR_RANGE1_OFFSET); 212 ddr3_enable_ecc(EMIF1_BASE, 1); 213 #else 214 writel(ecc_ctrl, &emif->emif_ecc_ctrl_reg); 215 #endif 216 217 val1 = readl(addr); 218 printf("\tECC test: addr 0x%x, read data 0x%x\n", addr, val1); 219 220 ddr_check_ecc_status(); 221 222 debug("Enabling D-cache back after ECC test\n"); 223 enable_caches(); 224 225 return 0; 226 } 227 228 static int is_addr_valid(u32 addr) 229 { 230 struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE; 231 u32 start_addr, end_addr, range, ecc_ctrl; 232 233 #ifdef CONFIG_ARCH_KEYSTONE 234 ecc_ctrl = EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK; 235 range = ECC_START_ADDR1 | (ECC_END_ADDR1 << 16); 236 #else 237 ecc_ctrl = readl(&emif->emif_ecc_ctrl_reg); 238 range = readl(&emif->emif_ecc_address_range_1); 239 #endif 240 241 /* Check in ecc address range 1 */ 242 if (ecc_ctrl & EMIF_ECC_REG_ECC_ADDR_RGN_1_EN_MASK) { 243 start_addr = ((range & EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16) 244 + CONFIG_SYS_SDRAM_BASE; 245 end_addr = start_addr + (range & EMIF_ECC_REG_ECC_END_ADDR_MASK) 246 + 0xFFFF; 247 if ((addr >= start_addr) && (addr <= end_addr)) 248 /* addr within ecc address range 1 */ 249 return 1; 250 } 251 252 /* Check in ecc address range 2 */ 253 if (ecc_ctrl & EMIF_ECC_REG_ECC_ADDR_RGN_2_EN_MASK) { 254 range = readl(&emif->emif_ecc_address_range_2); 255 start_addr = ((range & EMIF_ECC_REG_ECC_START_ADDR_MASK) << 16) 256 + CONFIG_SYS_SDRAM_BASE; 257 end_addr = start_addr + (range & EMIF_ECC_REG_ECC_END_ADDR_MASK) 258 + 0xFFFF; 259 if ((addr >= start_addr) && (addr <= end_addr)) 260 /* addr within ecc address range 2 */ 261 return 1; 262 } 263 264 return 0; 265 } 266 267 static int is_ecc_enabled(void) 268 { 269 struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE; 270 u32 ecc_ctrl = readl(&emif->emif_ecc_ctrl_reg); 271 272 return (ecc_ctrl & EMIF_ECC_CTRL_REG_ECC_EN_MASK) && 273 (ecc_ctrl & EMIF_ECC_REG_RMW_EN_MASK); 274 } 275 276 static int do_ddr_test(cmd_tbl_t *cmdtp, 277 int flag, int argc, char * const argv[]) 278 { 279 u32 start_addr, end_addr, size, ecc_err; 280 281 if ((argc == 4) && (strncmp(argv[1], "ecc_err", 8) == 0)) { 282 if (!is_ecc_enabled()) { 283 puts("ECC not enabled. Please Enable ECC any try again\n"); 284 return CMD_RET_FAILURE; 285 } 286 287 start_addr = simple_strtoul(argv[2], NULL, 16); 288 ecc_err = simple_strtoul(argv[3], NULL, 16); 289 290 if (!is_addr_valid(start_addr)) { 291 puts("Invalid address. Please enter ECC supported address!\n"); 292 return CMD_RET_FAILURE; 293 } 294 295 ddr_memory_ecc_err(start_addr, ecc_err); 296 return 0; 297 } 298 299 if (!(((argc == 4) && (strncmp(argv[1], "test", 5) == 0)) || 300 ((argc == 5) && (strncmp(argv[1], "compare", 8) == 0)))) 301 return cmd_usage(cmdtp); 302 303 start_addr = simple_strtoul(argv[2], NULL, 16); 304 end_addr = simple_strtoul(argv[3], NULL, 16); 305 306 if ((start_addr < CONFIG_SYS_SDRAM_BASE) || 307 (start_addr > (CONFIG_SYS_SDRAM_BASE + 308 get_effective_memsize() - 1)) || 309 (end_addr < CONFIG_SYS_SDRAM_BASE) || 310 (end_addr > (CONFIG_SYS_SDRAM_BASE + 311 get_effective_memsize() - 1)) || (start_addr >= end_addr)) { 312 puts("Invalid start or end address!\n"); 313 return cmd_usage(cmdtp); 314 } 315 316 puts("Please wait ...\n"); 317 if (argc == 5) { 318 size = simple_strtoul(argv[4], NULL, 16); 319 ddr_memory_compare(start_addr, end_addr, size); 320 } else { 321 ddr_memory_test(start_addr, end_addr, 0); 322 } 323 324 return 0; 325 } 326 327 U_BOOT_CMD(ddr, 5, 1, do_ddr_test, 328 "DDR3 test", 329 "test <start_addr in hex> <end_addr in hex> - test DDR from start\n" 330 " address to end address\n" 331 "ddr compare <start_addr in hex> <end_addr in hex> <size in hex> -\n" 332 " compare DDR data of (size) bytes from start address to end\n" 333 " address\n" 334 "ddr ecc_err <addr in hex> <bit_err in hex> - generate bit errors\n" 335 " in DDR data at <addr>, the command will read a 32-bit data\n" 336 " from <addr>, and write (data ^ bit_err) back to <addr>\n" 337 ); 338