1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31#include <common.h>
32#include <mpc8xx.h>
33
34flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
35
36
37
38
39
40static ulong flash_get_size (vu_char *addr, flash_info_t *info);
41static int write_byte (flash_info_t *info, ulong dest, uchar data);
42
43
44
45
46unsigned long flash_init (void)
47{
48 unsigned long size;
49 int i;
50
51
52 for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
53 flash_info[i].flash_id = FLASH_UNKNOWN;
54 }
55
56
57
58
59
60
61
62 size = flash_get_size((vu_char *)CONFIG_SYS_FLASH_PRELIMBASE, &flash_info[0]);
63 if (size)
64 {
65 flash_get_size((vu_char *)(-size), &flash_info[0]);
66 }
67
68#if (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_PRELIMBASE)
69
70 flash_protect(FLAG_PROTECT_SET,
71 CONFIG_SYS_MONITOR_BASE,
72 CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
73 &flash_info[0]);
74#endif
75
76#if defined(CONFIG_ENV_IS_IN_FLASH) && defined(CONFIG_ENV_ADDR)
77# ifndef CONFIG_ENV_SIZE
78# define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE
79# endif
80 flash_protect(FLAG_PROTECT_SET,
81 CONFIG_ENV_ADDR,
82 CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
83 &flash_info[0]);
84#endif
85
86 return (size);
87}
88
89
90
91void flash_print_info (flash_info_t *info)
92{
93 int i;
94
95 if (info->flash_id == FLASH_UNKNOWN) {
96 printf ("missing or unknown FLASH type\n");
97 return;
98 }
99
100 switch (info->flash_id & FLASH_VENDMASK) {
101 case FLASH_MAN_STM:
102 printf ("ST ");
103 break;
104 default:
105 printf ("Unknown Vendor ");
106 break;
107 }
108
109 switch (info->flash_id & FLASH_TYPEMASK) {
110 case FLASH_STM320DB:
111 printf ("M29W320DB (32 Mbit)\n");
112 break;
113 case FLASH_STM800DB:
114 printf ("M29W800DB (8 Mbit, bottom boot block)\n");
115 break;
116 case FLASH_STM800DT:
117 printf ("M29W800DT (8 Mbit, top boot block)\n");
118 break;
119 default:
120 printf ("Unknown Chip Type\n");
121 break;
122 }
123
124 printf (" Size: %ld KB in %d Sectors\n",
125 info->size >> 10, info->sector_count);
126
127 printf (" Sector Start Addresses:");
128 for (i=0; i<info->sector_count; ++i) {
129 if ((i % 5) == 0)
130 printf ("\n ");
131 printf (" %08lX%s",
132 info->start[i],
133 info->protect[i] ? " (RO)" : " "
134 );
135 }
136 printf ("\n");
137 return;
138}
139
140
141
142
143
144static ulong flash_get_size (vu_char *addr, flash_info_t *info)
145{
146 short i;
147 uchar vendor, devid;
148 ulong base = (ulong)addr;
149
150
151 addr[0x0AAA] = 0xAA;
152 addr[0x0555] = 0x55;
153 addr[0x0AAA] = 0x90;
154
155 udelay(1000);
156
157 vendor = addr[0];
158 devid = addr[2];
159
160
161 if ((vendor << 16) != FLASH_MAN_STM) {
162 return 0;
163 }
164
165 if (devid == FLASH_STM320DB) {
166
167
168 info->flash_id = vendor << 16 | devid;
169 info->sector_count = 32;
170 info->size = info->sector_count * 0x10000;
171 for (i = 0; i < info->sector_count; i++) {
172 info->start[i] = base + i * 0x10000;
173 }
174 }
175 else if (devid == FLASH_STM800DB) {
176 info->flash_id = vendor << 16 | devid;
177 info->sector_count = 19;
178 info->size = 0x100000;
179 info->start[0] = 0x0000;
180 info->start[1] = 0x4000;
181 info->start[2] = 0x6000;
182 info->start[3] = 0x8000;
183 for (i = 4; i < info->sector_count; i++) {
184 info->start[i] = base + (i-3) * 0x10000;
185 }
186 }
187 else if (devid == FLASH_STM800DT) {
188 info->flash_id = vendor << 16 | devid;
189 info->sector_count = 19;
190 info->size = 0x100000;
191 for (i = 0; i < info->sector_count-4; i++) {
192 info->start[i] = base + i * 0x10000;
193 }
194 info->start[i] = base + i * 0x10000;
195 info->start[i+1] = base + i * 0x10000 + 0x8000;
196 info->start[i+2] = base + i * 0x10000 + 0xa000;
197 info->start[i+3] = base + i * 0x10000 + 0xc000;
198 }
199 else {
200 return 0;
201 }
202
203
204 for (i = 0; i < info->sector_count; i++) {
205 info->protect[i] = 0;
206 }
207
208
209 if (info->flash_id != FLASH_UNKNOWN) {
210 addr[0] = 0xF0;
211 }
212
213 return (info->size);
214}
215
216
217
218
219
220int flash_erase (flash_info_t *info, int s_first, int s_last)
221{
222 vu_char *addr = (vu_char *)(info->start[0]);
223 int flag, prot, sect, l_sect;
224 ulong start, now, last;
225
226 if ((s_first < 0) || (s_first > s_last)) {
227 if (info->flash_id == FLASH_UNKNOWN) {
228 printf ("- missing\n");
229 } else {
230 printf ("- no sectors to erase\n");
231 }
232 return 1;
233 }
234
235 prot = 0;
236 for (sect = s_first; sect <= s_last; sect++) {
237 if (info->protect[sect]) {
238 prot++;
239 }
240 }
241
242 if (prot) {
243 printf ("- Warning: %d protected sectors will not be erased!\n",
244 prot);
245 } else {
246 printf ("\n");
247 }
248
249 l_sect = -1;
250
251
252 flag = disable_interrupts();
253
254 addr[0x0AAA] = 0xAA;
255 addr[0x0555] = 0x55;
256 addr[0x0AAA] = 0x80;
257 addr[0x0AAA] = 0xAA;
258 addr[0x0555] = 0x55;
259
260
261 udelay (1000);
262
263
264 for (sect = s_first; sect<=s_last; sect++) {
265 if (info->protect[sect] == 0) {
266 addr = (vu_char *)(info->start[sect]);
267 addr[0] = 0x30;
268 l_sect = sect;
269 }
270 }
271
272
273 if (flag)
274 enable_interrupts();
275
276
277 udelay (1000);
278
279
280
281
282 if (l_sect < 0)
283 goto DONE;
284
285 start = get_timer (0);
286 last = start;
287 addr = (vu_char *)(info->start[l_sect]);
288 while ((addr[0] & 0x80) != 0x80) {
289 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
290 printf ("Timeout\n");
291 return 1;
292 }
293
294 if ((now - last) > 1000) {
295 serial_putc ('.');
296 last = now;
297 }
298 }
299
300 DONE:
301
302 addr = (volatile unsigned char *)info->start[0];
303 addr[0] = 0xF0;
304
305 printf (" done\n");
306 return 0;
307}
308
309
310
311
312
313
314
315
316int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
317{
318 int rc;
319
320 while (cnt > 0) {
321 if ((rc = write_byte(info, addr, *src)) != 0) {
322 return (rc);
323 }
324 addr++;
325 src++;
326 cnt--;
327 }
328
329 return (0);
330}
331
332
333
334
335
336
337
338static int write_byte (flash_info_t *info, ulong dest, uchar data)
339{
340 vu_char *addr = (vu_char *)(info->start[0]);
341 ulong start;
342 int flag;
343
344
345 if ((*((vu_char *)dest) & data) != data) {
346 return (2);
347 }
348
349 flag = disable_interrupts();
350
351 addr[0x0AAA] = 0xAA;
352 addr[0x0555] = 0x55;
353 addr[0x0AAA] = 0xA0;
354
355 *((vu_char *)dest) = data;
356
357
358 if (flag)
359 enable_interrupts();
360
361
362 start = get_timer (0);
363 while ((*((vu_char *)dest) & 0x80) != (data & 0x80)) {
364 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
365 return (1);
366 }
367 }
368 return (0);
369}
370
371
372
373