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