]>
Commit | Line | Data |
---|---|---|
931da93e WD |
1 | /* |
2 | * (C) Copyright 2005 | |
3 | * Wolfgang Denk, DENX Software Engineering, [email protected]. | |
4 | * | |
5 | * See file CREDITS for list of people who contributed to this | |
6 | * project. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | * | |
23 | * The test exercises SDRAM accesses in burst mode | |
24 | */ | |
25 | ||
26 | #include <common.h> | |
27 | #include <exports.h> | |
28 | ||
29 | #include <commproc.h> | |
30 | #include <asm/mmu.h> | |
31 | #include <asm/processor.h> | |
32 | ||
33 | #include <serial.h> | |
34 | #include <watchdog.h> | |
35 | ||
36 | #include "test_burst.h" | |
37 | ||
38 | /* 8 MB test region of physical RAM */ | |
39 | #define TEST_PADDR 0x00800000 | |
40 | /* The uncached virtual region */ | |
41 | #define TEST_VADDR_NC 0x00800000 | |
42 | /* The cached virtual region */ | |
43 | #define TEST_VADDR_C 0x01000000 | |
44 | /* When an error is detected, the address where the error has been found, | |
45 | and also the current and the expected data will be written to | |
46 | the following flash address | |
47 | */ | |
48 | #define TEST_FLASH_ADDR 0x40100000 | |
49 | ||
c0176630 WD |
50 | /* Define GPIO ports to signal start of burst transfers and errors */ |
51 | #ifdef CONFIG_LWMON | |
52 | /* Use PD.8 to signal start of burst transfers */ | |
6d0f6bcf | 53 | #define GPIO1_DAT (((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddat) |
c0176630 WD |
54 | #define GPIO1_BIT 0x0080 |
55 | /* Configure PD.8 as general purpose output */ | |
56 | #define GPIO1_INIT \ | |
6d0f6bcf JCPV |
57 | ((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdpar &= ~GPIO1_BIT; \ |
58 | ((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddir |= GPIO1_BIT; | |
c0176630 | 59 | /* Use PD.9 to signal error */ |
6d0f6bcf | 60 | #define GPIO2_DAT (((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddat) |
c0176630 WD |
61 | #define GPIO2_BIT 0x0040 |
62 | /* Configure PD.9 as general purpose output */ | |
63 | #define GPIO2_INIT \ | |
6d0f6bcf JCPV |
64 | ((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdpar &= ~GPIO2_BIT; \ |
65 | ((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddir |= GPIO2_BIT; | |
c0176630 WD |
66 | #endif /* CONFIG_LWMON */ |
67 | ||
68 | ||
931da93e WD |
69 | static void test_prepare (void); |
70 | static int test_burst_start (unsigned long size, unsigned long pattern); | |
71 | static void test_map_8M (unsigned long paddr, unsigned long vaddr, int cached); | |
72 | static int test_mmu_is_on(void); | |
73 | static void test_desc(unsigned long size); | |
74 | static void test_error(char * step, volatile void * addr, unsigned long val, unsigned long pattern); | |
c0176630 | 75 | static void signal_init(void); |
931da93e WD |
76 | static void signal_start(void); |
77 | static void signal_error(void); | |
78 | static void test_usage(void); | |
79 | ||
80 | static unsigned long test_pattern [] = { | |
81 | 0x00000000, | |
82 | 0xffffffff, | |
83 | 0x55555555, | |
84 | 0xaaaaaaaa, | |
85 | }; | |
86 | ||
87 | ||
88 | int test_burst (int argc, char *argv[]) | |
89 | { | |
90 | unsigned long size = CACHE_LINE_SIZE; | |
2eab48f5 WD |
91 | unsigned int pass = 0; |
92 | int res = 0; | |
93 | int i, j; | |
931da93e | 94 | |
2eab48f5 | 95 | if (argc == 3) { |
931da93e WD |
96 | char * d; |
97 | for (size = 0, d = argv[1]; *d >= '0' && *d <= '9'; d++) { | |
98 | size *= 10; | |
99 | size += *d - '0'; | |
100 | } | |
101 | if (size == 0 || *d) { | |
102 | test_usage(); | |
103 | return 1; | |
104 | } | |
2eab48f5 WD |
105 | for (d = argv[2]; *d >= '0' && *d <= '9'; d++) { |
106 | pass *= 10; | |
107 | pass += *d - '0'; | |
108 | } | |
109 | if (*d) { | |
110 | test_usage(); | |
111 | return 1; | |
112 | } | |
113 | } else if (argc > 3) { | |
931da93e WD |
114 | test_usage(); |
115 | return 1; | |
116 | } | |
117 | ||
118 | size += (CACHE_LINE_SIZE - 1); | |
119 | size &= ~(CACHE_LINE_SIZE - 1); | |
120 | ||
121 | if (!test_mmu_is_on()) { | |
122 | test_prepare(); | |
123 | } | |
124 | ||
125 | test_desc(size); | |
126 | ||
2eab48f5 WD |
127 | for (j = 0; !pass || j < pass; j++) { |
128 | for (i = 0; i < sizeof(test_pattern) / sizeof(test_pattern[0]); | |
129 | i++) { | |
130 | res = test_burst_start(size, test_pattern[i]); | |
131 | if (res != 0) { | |
132 | goto Done; | |
133 | } | |
931da93e | 134 | } |
2eab48f5 WD |
135 | |
136 | printf ("Iteration #%d passed\n", j + 1); | |
137 | ||
138 | if (tstc() && 0x03 == getc()) | |
139 | break; | |
931da93e WD |
140 | } |
141 | Done: | |
142 | return res; | |
143 | } | |
144 | ||
145 | static void test_prepare (void) | |
146 | { | |
931da93e WD |
147 | printf ("\n"); |
148 | ||
149 | caches_init(); | |
150 | disable_interrupts(); | |
151 | mmu_init(); | |
152 | ||
153 | printf ("Interrupts are disabled\n"); | |
154 | printf ("I-Cache is ON\n"); | |
155 | printf ("D-Cache is ON\n"); | |
156 | printf ("MMU is ON\n"); | |
157 | ||
158 | printf ("\n"); | |
159 | ||
160 | test_map_8M (TEST_PADDR, TEST_VADDR_NC, 0); | |
161 | test_map_8M (TEST_PADDR, TEST_VADDR_C, 1); | |
162 | ||
163 | test_map_8M (TEST_FLASH_ADDR & 0xFF800000, TEST_FLASH_ADDR & 0xFF800000, 0); | |
164 | ||
c0176630 WD |
165 | /* Configure GPIO ports */ |
166 | signal_init(); | |
931da93e WD |
167 | } |
168 | ||
169 | static int test_burst_start (unsigned long size, unsigned long pattern) | |
170 | { | |
171 | volatile unsigned long * vaddr_c = (unsigned long *)TEST_VADDR_C; | |
172 | volatile unsigned long * vaddr_nc = (unsigned long *)TEST_VADDR_NC; | |
173 | int i, n; | |
174 | int res = 1; | |
175 | ||
06c53bea | 176 | printf ("Test pattern %08lx ...", pattern); |
931da93e WD |
177 | |
178 | n = size / 4; | |
179 | ||
180 | for (i = 0; i < n; i ++) { | |
181 | vaddr_c [i] = pattern; | |
182 | } | |
183 | signal_start(); | |
184 | flush_dcache_range((unsigned long)vaddr_c, (unsigned long)(vaddr_c + n) - 1); | |
185 | ||
186 | for (i = 0; i < n; i ++) { | |
187 | register unsigned long tmp = vaddr_nc [i]; | |
188 | if (tmp != pattern) { | |
189 | test_error("2a", vaddr_nc + i, tmp, pattern); | |
190 | goto Done; | |
191 | } | |
192 | } | |
193 | ||
194 | for (i = 0; i < n; i ++) { | |
195 | register unsigned long tmp = vaddr_c [i]; | |
196 | if (tmp != pattern) { | |
197 | test_error("2b", vaddr_c + i, tmp, pattern); | |
198 | goto Done; | |
199 | } | |
200 | } | |
201 | ||
202 | for (i = 0; i < n; i ++) { | |
203 | vaddr_nc [i] = pattern; | |
204 | } | |
205 | ||
206 | for (i = 0; i < n; i ++) { | |
207 | register unsigned long tmp = vaddr_nc [i]; | |
208 | if (tmp != pattern) { | |
209 | test_error("3a", vaddr_nc + i, tmp, pattern); | |
210 | goto Done; | |
211 | } | |
212 | } | |
213 | ||
214 | signal_start(); | |
215 | for (i = 0; i < n; i ++) { | |
216 | register unsigned long tmp = vaddr_c [i]; | |
217 | if (tmp != pattern) { | |
218 | test_error("3b", vaddr_c + i, tmp, pattern); | |
219 | goto Done; | |
220 | } | |
221 | } | |
222 | ||
223 | res = 0; | |
224 | Done: | |
225 | printf(" %s\n", res == 0 ? "OK" : ""); | |
226 | ||
227 | return res; | |
228 | } | |
229 | ||
230 | static void test_map_8M (unsigned long paddr, unsigned long vaddr, int cached) | |
231 | { | |
232 | mtspr (MD_EPN, (vaddr & 0xFFFFFC00) | MI_EVALID); | |
233 | mtspr (MD_TWC, MI_PS8MEG | MI_SVALID); | |
234 | mtspr (MD_RPN, (paddr & 0xFFFFF000) | MI_BOOTINIT | (cached ? 0 : 2)); | |
235 | mtspr (MD_AP, MI_Kp); | |
236 | } | |
237 | ||
238 | static int test_mmu_is_on(void) | |
239 | { | |
240 | unsigned long msr; | |
241 | ||
242 | asm volatile("mfmsr %0" : "=r" (msr) :); | |
243 | ||
244 | return msr & MSR_DR; | |
245 | } | |
246 | ||
247 | static void test_desc(unsigned long size) | |
248 | { | |
249 | printf( | |
250 | "The following tests will be conducted:\n" | |
06c53bea | 251 | "1) Map %ld-byte region of physical RAM at 0x%08x\n" |
931da93e WD |
252 | " into two virtual regions:\n" |
253 | " one cached at 0x%08x and\n" | |
254 | " the the other uncached at 0x%08x.\n", | |
255 | size, TEST_PADDR, TEST_VADDR_NC, TEST_VADDR_C); | |
256 | ||
257 | puts( | |
258 | "2) Fill the cached region with a pattern, and flush the cache\n" | |
259 | "2a) Check the uncached region to match the pattern\n" | |
260 | "2b) Check the cached region to match the pattern\n" | |
261 | "3) Fill the uncached region with a pattern\n" | |
262 | "3a) Check the cached region to match the pattern\n" | |
263 | "3b) Check the uncached region to match the pattern\n" | |
264 | "2b) Change the patterns and go to step 2\n" | |
265 | "\n" | |
266 | ); | |
267 | } | |
268 | ||
269 | static void test_error( | |
270 | char * step, volatile void * addr, unsigned long val, unsigned long pattern) | |
271 | { | |
272 | volatile unsigned long * p = (void *)TEST_FLASH_ADDR; | |
273 | ||
274 | signal_error(); | |
275 | ||
276 | p[0] = (unsigned long)addr; | |
277 | p[1] = val; | |
278 | p[2] = pattern; | |
279 | ||
06c53bea | 280 | printf ("\nError at step %s, addr %08lx: read %08lx, pattern %08lx", |
9b55a253 | 281 | step, (unsigned long)addr, val, pattern); |
931da93e WD |
282 | } |
283 | ||
c0176630 | 284 | static void signal_init(void) |
931da93e | 285 | { |
c0176630 WD |
286 | #if defined(GPIO1_INIT) |
287 | GPIO1_INIT; | |
288 | #endif | |
289 | #if defined(GPIO2_INIT) | |
290 | GPIO2_INIT; | |
291 | #endif | |
292 | } | |
931da93e | 293 | |
c0176630 WD |
294 | static void signal_start(void) |
295 | { | |
296 | #if defined(GPIO1_INIT) | |
297 | if (GPIO1_DAT & GPIO1_BIT) { | |
298 | GPIO1_DAT &= ~GPIO1_BIT; | |
931da93e | 299 | } else { |
c0176630 | 300 | GPIO1_DAT |= GPIO1_BIT; |
931da93e | 301 | } |
c0176630 | 302 | #endif |
931da93e WD |
303 | } |
304 | ||
305 | static void signal_error(void) | |
306 | { | |
c0176630 WD |
307 | #if defined(GPIO2_INIT) |
308 | if (GPIO2_DAT & GPIO2_BIT) { | |
309 | GPIO2_DAT &= ~GPIO2_BIT; | |
931da93e | 310 | } else { |
c0176630 | 311 | GPIO2_DAT |= GPIO2_BIT; |
931da93e | 312 | } |
c0176630 | 313 | #endif |
931da93e WD |
314 | } |
315 | ||
316 | static void test_usage(void) | |
317 | { | |
2eab48f5 | 318 | printf("Usage: go 0x40004 [size] [count]\n"); |
931da93e | 319 | } |