xref: /openbmc/u-boot/cmd/aspeed/dramtest.c (revision 67bb2848)
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 
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 
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 
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 
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 
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 
199 	return ret;
200 
201 cmd_err:
202 	print_usage();
203 	return ret;
204 }
205 
206 U_BOOT_CMD(
207 	dramtest,   5, 0,  do_ast_dramtest,
208 	"ASPEED DRAM BIST",
209 	""
210 );
211