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