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