1 /*
2 * This program is distributed in the hope that it will be useful,
3 * but WITHOUT ANY WARRANTY; without even the implied warranty of
4 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5 * GNU General Public License for more details.
6 *
7 * You should have received a copy of the GNU General Public License
8 * along with this program; if not, write to the Free Software
9 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
10 */
11
12 #include <common.h>
13 #include <console.h>
14 #include <bootretry.h>
15 #include <cli.h>
16 #include <command.h>
17 #include <console.h>
18
19 #include <inttypes.h>
20 #include <mapmem.h>
21 #include <asm/io.h>
22 #include <linux/compiler.h>
23
24 DECLARE_GLOBAL_DATA_PTR;
25
26 #define DRAM_BASE 0x80000000
27 #define TIMEOUT_DRAM 5000000
28
29 #ifdef CONFIG_ASPEED_AST2600
30 #define BLK_SIZE_MB 64
31 #define N_BLK 32
32 #define MCR74_BLK_OFFSET 26
33 #define MCR74_LEN_OFFSET 4
34 #define MCR74_BLK_LEN_MASK GENMASK(30, 4)
35 #else
36 #define BLK_SIZE_MB 16
37 #define N_BLK 64
38 #define MCR74_BLK_OFFSET 24
39 #define MCR74_LEN_OFFSET 4
40 #define MCR74_BLK_LEN_MASK GENMASK(29, 4)
41 #endif
42 #define BLK_SIZE (BLK_SIZE_MB * 1024 * 1024)
43 #define N_16B_IN_BLK (BLK_SIZE / 16)
44
MMCTestBurst(u32 datagen)45 static int MMCTestBurst(u32 datagen)
46 {
47 u32 data;
48 int timeout = 0;
49
50 writel(0x00000000, 0x1e6e0070);
51 writel((0x000000c1 | (datagen << 3)), 0x1e6e0070);
52
53 do {
54 data = readl(0x1e6e0070) & 0x3000;
55
56 if (data & 0x2000)
57 return 0;
58
59 if (++timeout > TIMEOUT_DRAM) {
60 printf("Timeout!!\n");
61 writel(0x00000000, 0x1e6e0070);
62 return 0;
63 }
64 } while (!data);
65
66 writel(0x00000000, 0x1e6e0070);
67
68 return 1;
69 }
70
MMCTestSingle(u32 datagen)71 static int MMCTestSingle(u32 datagen)
72 {
73 u32 data;
74 int timeout = 0;
75
76 writel(0x00000000, 0x1e6e0070);
77 writel((0x00000085 | (datagen << 3)), 0x1e6e0070);
78
79 do {
80 data = readl(0x1e6e0070) & 0x3000;
81
82 if (data & 0x2000)
83 return 0;
84
85 if (++timeout > TIMEOUT_DRAM) {
86 printf("Timeout!!\n");
87 writel(0x00000000, 0x1e6e0070);
88
89 return 0;
90 }
91 } while (!data);
92
93 writel(0x00000000, 0x1e6e0070);
94
95 return 1;
96 }
97
MMCTest(void)98 static int MMCTest(void)
99 {
100 unsigned int pattern;
101
102 pattern = rand();
103 writel(pattern, 0x1e6e007c);
104 printf("Pattern = %08X : ", pattern);
105
106 if(!MMCTestBurst(0)) return(0);
107 if(!MMCTestBurst(1)) return(0);
108 if(!MMCTestBurst(2)) return(0);
109 if(!MMCTestBurst(3)) return(0);
110 if(!MMCTestBurst(4)) return(0);
111 if(!MMCTestBurst(5)) return(0);
112 if(!MMCTestBurst(6)) return(0);
113 if(!MMCTestBurst(7)) return(0);
114 if(!MMCTestSingle(0)) return(0);
115 if(!MMCTestSingle(1)) return(0);
116 if(!MMCTestSingle(2)) return(0);
117 if(!MMCTestSingle(3)) return(0);
118 if(!MMCTestSingle(4)) return(0);
119 if(!MMCTestSingle(5)) return(0);
120 if(!MMCTestSingle(6)) return(0);
121 if(!MMCTestSingle(7)) return(0);
122
123 return 1;
124 }
125
print_usage(void)126 static void print_usage(void)
127 {
128 printf("\nASPEED DRAM BIST\n\n");
129 printf("Usage: dramtest <count> <block> <length>\n\n");
130 printf("count: how many iterations to run (mandatory, in decimal)\n");
131 printf(" 0: infinite loop.\n");
132 printf("block: index of the address block to test "
133 "(optional, in decimal, default: 0)\n");
134 printf(" 0: [%08x, %08x)\n", DRAM_BASE + BLK_SIZE * 0, DRAM_BASE + BLK_SIZE * 1);
135 printf(" 1: [%08x, %08x)\n", DRAM_BASE + BLK_SIZE * 1, DRAM_BASE + BLK_SIZE * 2);
136 printf(" 2: [%08x, %08x)\n", DRAM_BASE + BLK_SIZE * 2, DRAM_BASE + BLK_SIZE * 3);
137 printf(" n: [80000000 + n*%dMB, 80000000 + (n+1)*%dMB)\n", BLK_SIZE_MB, BLK_SIZE_MB);
138 printf(" where n = [0, %d]\n", N_BLK - 1);
139 printf("length: size to test (optional, in hex, default: 0x10000)\n");
140 printf(" 0x0: test the whole memory block %dMB\n", BLK_SIZE_MB);
141 printf(" 0x1: test the first 16 Bytes of the memory block\n");
142 printf(" 0x2: test the first 2*16 Bytes of the memory block\n");
143 printf(" n : test the first n*16 Bytes of the memory block\n");
144 printf(" where n = [0x00000001, 0x%08x]\n", N_16B_IN_BLK);
145 printf("\n\n");
146 }
147
do_ast_dramtest(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])148 static int do_ast_dramtest(cmd_tbl_t *cmdtp, int flag, int argc,
149 char *const argv[])
150 {
151 u32 PassCnt = 0;
152 unsigned long Testcounter = 0;
153 unsigned long block = 0;
154 unsigned long length = 0x10000;
155 int ret;
156
157 if (argc < 2) {
158 ret = 0;
159 goto cmd_err;
160 }
161
162 ret = CMD_RET_USAGE;
163 switch (argc) {
164 case 4:
165 if (strict_strtoul(argv[3], 16, &length) < 0)
166 goto cmd_err;
167 case 3:
168 if (strict_strtoul(argv[2], 10, &block) < 0)
169 goto cmd_err;
170 case 2:
171 if (strict_strtoul(argv[1], 10, &Testcounter) < 0)
172 goto cmd_err;
173 break;
174 }
175
176 if (length == 0)
177 length = N_16B_IN_BLK;
178
179 printf("Test range: 0x%08lx - 0x%08lx\n", DRAM_BASE + (block << MCR74_BLK_OFFSET),
180 DRAM_BASE | (block << MCR74_BLK_OFFSET) | ((length - 1) << MCR74_LEN_OFFSET) | 0xf);
181
182 ret = 1;
183 writel(0xfc600309, 0x1e6e0000);
184 while ((Testcounter > PassCnt) || (Testcounter == 0)) {
185 clrsetbits_le32(0x1e6e0074, MCR74_BLK_LEN_MASK,
186 (block << MCR74_BLK_OFFSET) | ((length - 1) << MCR74_LEN_OFFSET));
187
188 if (!MMCTest()) {
189 printf("FAIL %d/%ld (fail DQ 0x%08x)\n", PassCnt, Testcounter,
190 readl(0x1e6e0078));
191 ret = 0;
192 break;
193 } else {
194 PassCnt++;
195 printf("Pass %d/%ld\n", PassCnt, Testcounter);
196 }
197
198 if (ctrlc())
199 break;
200 }
201
202 return ret;
203
204 cmd_err:
205 print_usage();
206 return ret;
207 }
208
209 U_BOOT_CMD(
210 dramtest, 5, 0, do_ast_dramtest,
211 "ASPEED DRAM BIST",
212 ""
213 );
214