]> git.sur5r.net Git - u-boot/blob - cmd/ti/ddr3.c
sunxi: Enable eMMC on Libre Computer Board ALL-H3-CC boards
[u-boot] / 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 <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 );