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