xref: /openbmc/u-boot/cmd/aspeed/dramtest.c (revision fd0bc623)
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 /* ------------------------------------------------------------------------- */
30 int MMCTestBurst(unsigned int datagen)
31 {
32 	unsigned int data;
33 	unsigned int timeout = 0;
34 
35 	writel(0x00000000, 0x1E6E0070);
36 	writel((0x000000C1 | (datagen << 3)), 0x1E6E0070);
37 
38 	do {
39 		data = readl(0x1E6E0070) & 0x3000;
40 
41 		if( data & 0x2000 )
42 			return(0);
43 
44 		if( ++timeout > TIMEOUT_DRAM ) {
45 			printf("Timeout!!\n");
46 			writel(0x00000000, 0x1E6E0070);
47 			return(0);
48 		}
49 	} while (!data);
50 
51 	writel(0x00000000, 0x1E6E0070);
52 
53 	return(1);
54 }
55 
56 /* ------------------------------------------------------------------------- */
57 int MMCTestSingle(unsigned int datagen)
58 {
59 	unsigned int data;
60 	unsigned int timeout = 0;
61 
62 	writel(0x00000000, 0x1E6E0070);
63 	writel((0x00000085 | (datagen << 3)), 0x1E6E0070);
64 
65 	do {
66 		data = readl(0x1E6E0070) & 0x3000;
67 
68 		if( data & 0x2000 )
69 			return(0);
70 
71 		if( ++timeout > TIMEOUT_DRAM ){
72 			printf("Timeout!!\n");
73 			writel(0x00000000, 0x1E6E0070);
74 
75 			return(0);
76 		}
77 	} while ( !data );
78 
79 	writel(0x00000000, 0x1E6E0070);
80 
81 	return(1);
82 }
83 
84 /* ------------------------------------------------------------------------- */
85 int MMCTest(void)
86 {
87 	unsigned int pattern;
88 
89 	pattern = rand();
90 	writel(pattern, 0x1E6E007C);
91 	printf("Pattern = %08X : ",pattern);
92 
93 	if(!MMCTestBurst(0))    return(0);
94 	if(!MMCTestBurst(1))    return(0);
95 	if(!MMCTestBurst(2))    return(0);
96 	if(!MMCTestBurst(3))    return(0);
97 	if(!MMCTestBurst(4))    return(0);
98 	if(!MMCTestBurst(5))    return(0);
99 	if(!MMCTestBurst(6))    return(0);
100 	if(!MMCTestBurst(7))    return(0);
101 	if(!MMCTestSingle(0))   return(0);
102 	if(!MMCTestSingle(1))   return(0);
103 	if(!MMCTestSingle(2))   return(0);
104 	if(!MMCTestSingle(3))   return(0);
105 	if(!MMCTestSingle(4))   return(0);
106 	if(!MMCTestSingle(5))   return(0);
107 	if(!MMCTestSingle(6))   return(0);
108 	if(!MMCTestSingle(7))   return(0);
109 
110 	return(1);
111 }
112 
113 /* ------------------------------------------------------------------------- */
114 static void print_usage(void)
115 {
116 	printf("\nASPEED DRAM BIST\n\n");
117 	printf("Usage: dramtest <count> <block> <length>\n\n");
118 	printf("count:  how many iterations to run (mandatory, in decimal)\n");
119 	printf("        0: infinite loop.\n");
120 	printf("block:  index of the address block to test "
121 			"(optional, in decimal, default: 0)\n");
122 	printf("        0: [8000_0000, 8400_0000)\n");
123 	printf("        1: [8400_0000, 8800_0000)\n");
124 	printf("        2: [8800_0000, 8C00_0000)\n");
125 	printf("        n: [8000_0000 + n*64MB, 8000_0000 + (n+1)*64MB)\n");
126 	printf("           where n = [0, 31]\n");
127 	printf("length: size to test (optional, in hex, default: 0x10000)\n");
128 	printf("        0x0: test the whole memory block 64MB\n");
129 	printf("        0x1: test the first 16 Bytes of the memory block\n");
130 	printf("        0x2: test the first 2*16 Bytes of the memory block\n");
131 	printf("        n  : test the first n*16 Bytes of the memory block\n");
132 	printf("             where n = [0x00_0001, 0x3F_FFFF]\n");
133 	printf("\n\n");
134 }
135 
136 static int
137 do_ast_dramtest(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
138 {
139 	u32 PassCnt = 0;
140 	unsigned long Testcounter = 0;
141 	unsigned long block = 0;
142 	unsigned long length = 0x10000;
143 	int ret;
144 
145 	if (argc < 2) {
146 		ret = 0;
147 		goto cmd_err;
148 	}
149 
150 	ret = CMD_RET_USAGE;
151 	switch (argc) {
152 	case 4:
153 		if (strict_strtoul(argv[3], 16, &length) < 0)
154 			goto cmd_err;
155 	case 3:
156 		if (strict_strtoul(argv[2], 10, &block) < 0)
157 			goto cmd_err;
158 	case 2:
159 		if (strict_strtoul(argv[1], 10, &Testcounter) < 0)
160 			goto cmd_err;
161 		break;
162 	}
163 
164 	printf("Test range: 0x%08lx - 0x%08lx\n", DRAM_BASE + (block << 26),
165 	       DRAM_BASE + (block << 26) + (length << 4));
166 
167 	ret = 1;
168 	writel(0xFC600309, 0x1E6E0000);
169 	while ((Testcounter > PassCnt) || (Testcounter == 0)) {
170 		clrsetbits_le32(0x1E6E0074, GENMASK(30, 4),
171 				(block << 26) | (length << 4));
172 		if (!MMCTest()) {
173 			printf("FAIL %d/%ld (fail DQ 0x%08x)\n", PassCnt,
174 			       Testcounter, readl(0x1E6E0078));
175 			ret = 0;
176 			break;
177 		} else {
178 			PassCnt++;
179 			printf("Pass %d/%ld\n", PassCnt, Testcounter);
180 		}
181 	}
182 
183 	return (ret);
184 
185 cmd_err:
186 	print_usage();
187 	return (ret);
188 }
189 
190 U_BOOT_CMD(
191 	dramtest,   5, 0,  do_ast_dramtest,
192 	"ASPEED DRAM BIST",
193 	""
194 );
195