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