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 19 #define DDR_REMAP_ADDR 0x80000000 20 #define ECC_START_ADDR1 ((DDR_MIN_ADDR - DDR_REMAP_ADDR) >> 17) 21 22 #define ECC_END_ADDR1 (((gd->start_addr_sp - DDR_REMAP_ADDR - \ 23 CONFIG_STACKSIZE) >> 17) - 2) 24 25 #define DDR_TEST_BURST_SIZE 1024 26 27 static int ddr_memory_test(u32 start_address, u32 end_address, int quick) 28 { 29 u32 index_start, value, index; 30 31 index_start = start_address; 32 33 while (1) { 34 /* Write a pattern */ 35 for (index = index_start; 36 index < index_start + DDR_TEST_BURST_SIZE; 37 index += 4) 38 __raw_writel(index, index); 39 40 /* Read and check the pattern */ 41 for (index = index_start; 42 index < index_start + DDR_TEST_BURST_SIZE; 43 index += 4) { 44 value = __raw_readl(index); 45 if (value != index) { 46 printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n", 47 index, value, __raw_readl(index)); 48 49 return -1; 50 } 51 } 52 53 index_start += DDR_TEST_BURST_SIZE; 54 if (index_start >= end_address) 55 break; 56 57 if (quick) 58 continue; 59 60 /* Write a pattern for complementary values */ 61 for (index = index_start; 62 index < index_start + DDR_TEST_BURST_SIZE; 63 index += 4) 64 __raw_writel((u32)~index, index); 65 66 /* Read and check the pattern */ 67 for (index = index_start; 68 index < index_start + DDR_TEST_BURST_SIZE; 69 index += 4) { 70 value = __raw_readl(index); 71 if (value != ~index) { 72 printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n", 73 index, value, __raw_readl(index)); 74 75 return -1; 76 } 77 } 78 79 index_start += DDR_TEST_BURST_SIZE; 80 if (index_start >= end_address) 81 break; 82 83 /* Write a pattern */ 84 for (index = index_start; 85 index < index_start + DDR_TEST_BURST_SIZE; 86 index += 2) 87 __raw_writew((u16)index, index); 88 89 /* Read and check the pattern */ 90 for (index = index_start; 91 index < index_start + DDR_TEST_BURST_SIZE; 92 index += 2) { 93 value = __raw_readw(index); 94 if (value != (u16)index) { 95 printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n", 96 index, value, __raw_readw(index)); 97 98 return -1; 99 } 100 } 101 102 index_start += DDR_TEST_BURST_SIZE; 103 if (index_start >= end_address) 104 break; 105 106 /* Write a pattern */ 107 for (index = index_start; 108 index < index_start + DDR_TEST_BURST_SIZE; 109 index += 1) 110 __raw_writeb((u8)index, index); 111 112 /* Read and check the pattern */ 113 for (index = index_start; 114 index < index_start + DDR_TEST_BURST_SIZE; 115 index += 1) { 116 value = __raw_readb(index); 117 if (value != (u8)index) { 118 printf("ddr_memory_test: Failed at address index = 0x%x value = 0x%x *(index) = 0x%x\n", 119 index, value, __raw_readb(index)); 120 121 return -1; 122 } 123 } 124 125 index_start += DDR_TEST_BURST_SIZE; 126 if (index_start >= end_address) 127 break; 128 } 129 130 puts("ddr memory test PASSED!\n"); 131 return 0; 132 } 133 134 static int ddr_memory_compare(u32 address1, u32 address2, u32 size) 135 { 136 u32 index, value, index2, value2; 137 138 for (index = address1, index2 = address2; 139 index < address1 + size; 140 index += 4, index2 += 4) { 141 value = __raw_readl(index); 142 value2 = __raw_readl(index2); 143 144 if (value != value2) { 145 printf("ddr_memory_test: Compare failed at address = 0x%x value = 0x%x, address2 = 0x%x value2 = 0x%x\n", 146 index, value, index2, value2); 147 148 return -1; 149 } 150 } 151 152 puts("ddr memory compare PASSED!\n"); 153 return 0; 154 } 155 156 static int ddr_memory_ecc_err(u32 base, u32 address, u32 ecc_err) 157 { 158 u32 value1, value2, value3; 159 160 puts("Disabling DDR ECC ...\n"); 161 ddr3_disable_ecc(base); 162 163 value1 = __raw_readl(address); 164 value2 = value1 ^ ecc_err; 165 __raw_writel(value2, address); 166 167 value3 = __raw_readl(address); 168 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", 169 address, value1, value2, ecc_err, value3); 170 171 __raw_writel(ECC_START_ADDR1 | (ECC_END_ADDR1 << 16), 172 base + KS2_DDR3_ECC_ADDR_RANGE1_OFFSET); 173 174 puts("Enabling DDR ECC ...\n"); 175 ddr3_enable_ecc(base, 1); 176 177 value1 = __raw_readl(address); 178 printf("ECC err test, addr 0x%x, read data 0x%x\n", address, value1); 179 180 ddr3_check_ecc_int(base); 181 return 0; 182 } 183 184 static int do_ddr_test(cmd_tbl_t *cmdtp, 185 int flag, int argc, char * const argv[]) 186 { 187 u32 start_addr, end_addr, size, ecc_err; 188 189 if ((argc == 4) && (strncmp(argv[1], "ecc_err", 8) == 0)) { 190 if (!ddr3_ecc_support_rmw(KS2_DDR3A_EMIF_CTRL_BASE)) { 191 puts("ECC RMW isn't supported for this SOC\n"); 192 return 1; 193 } 194 195 start_addr = simple_strtoul(argv[2], NULL, 16); 196 ecc_err = simple_strtoul(argv[3], NULL, 16); 197 198 if ((start_addr < CONFIG_SYS_SDRAM_BASE) || 199 (start_addr > (CONFIG_SYS_SDRAM_BASE + 200 CONFIG_MAX_RAM_BANK_SIZE - 1))) { 201 puts("Invalid address!\n"); 202 return cmd_usage(cmdtp); 203 } 204 205 ddr_memory_ecc_err(KS2_DDR3A_EMIF_CTRL_BASE, 206 start_addr, ecc_err); 207 return 0; 208 } 209 210 if (!(((argc == 4) && (strncmp(argv[1], "test", 5) == 0)) || 211 ((argc == 5) && (strncmp(argv[1], "compare", 8) == 0)))) 212 return cmd_usage(cmdtp); 213 214 start_addr = simple_strtoul(argv[2], NULL, 16); 215 end_addr = simple_strtoul(argv[3], NULL, 16); 216 217 if ((start_addr < CONFIG_SYS_SDRAM_BASE) || 218 (start_addr > (CONFIG_SYS_SDRAM_BASE + 219 CONFIG_MAX_RAM_BANK_SIZE - 1)) || 220 (end_addr < CONFIG_SYS_SDRAM_BASE) || 221 (end_addr > (CONFIG_SYS_SDRAM_BASE + 222 CONFIG_MAX_RAM_BANK_SIZE - 1)) || (start_addr >= end_addr)) { 223 puts("Invalid start or end address!\n"); 224 return cmd_usage(cmdtp); 225 } 226 227 puts("Please wait ...\n"); 228 if (argc == 5) { 229 size = simple_strtoul(argv[4], NULL, 16); 230 ddr_memory_compare(start_addr, end_addr, size); 231 } else { 232 ddr_memory_test(start_addr, end_addr, 0); 233 } 234 235 return 0; 236 } 237 238 U_BOOT_CMD(ddr, 5, 1, do_ddr_test, 239 "DDR3 test", 240 "test <start_addr in hex> <end_addr in hex> - test DDR from start\n" 241 " address to end address\n" 242 "ddr compare <start_addr in hex> <end_addr in hex> <size in hex> -\n" 243 " compare DDR data of (size) bytes from start address to end\n" 244 " address\n" 245 "ddr ecc_err <addr in hex> <bit_err in hex> - generate bit errors\n" 246 " in DDR data at <addr>, the command will read a 32-bit data\n" 247 " from <addr>, and write (data ^ bit_err) back to <addr>\n" 248 ); 249