]> git.ipfire.org Git - people/ms/u-boot.git/blob - board/gw8260/flash.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[people/ms/u-boot.git] / board / gw8260 / flash.c
1 /*
2 * (C) Copyright 2000
3 * Marius Groeger <mgroeger@sysgo.de>
4 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
5 *
6 * (C) Copyright 2000, 2001
7 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
8 *
9 * (C) Copyright 2001
10 * Advent Networks, Inc. <http://www.adventnetworks.com>
11 * Oliver Brown <oliverb@alumni.utexas.net>
12 *
13 * SPDX-License-Identifier: GPL-2.0+
14 */
15
16 /*********************************************************************/
17 /* DESCRIPTION:
18 * This file contains the flash routines for the GW8260 board.
19 *
20 *
21 *
22 * MODULE DEPENDENCY:
23 * None
24 *
25 *
26 * RESTRICTIONS/LIMITATIONS:
27 *
28 * Only supports the following flash devices:
29 * AMD 29F080B
30 * AMD 29F016D
31 *
32 * Copyright (c) 2001, Advent Networks, Inc.
33 *
34 */
35 /*********************************************************************/
36
37 #include <common.h>
38 #include <mpc8260.h>
39
40 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
41
42 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
43 static int write_word (flash_info_t *info, ulong dest, ulong data);
44
45 /*********************************************************************/
46 /* functions */
47 /*********************************************************************/
48
49 /*
50 * NAME: flash_init() - initializes flash banks
51 *
52 * DESCRIPTION:
53 * This function initializes the flash bank(s).
54 *
55 * RETURNS:
56 * The size in bytes of the flash
57 *
58 * RESTRICTIONS/LIMITATIONS:
59 *
60 *
61 */
62 unsigned long flash_init(void)
63 {
64 int i;
65
66 /* Init: no FLASHes known */
67 for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i)
68 flash_info[i].flash_id = FLASH_UNKNOWN;
69
70 /* for now, only support the 4 MB Flash SIMM */
71 (void)flash_get_size((vu_long *) CONFIG_SYS_FLASH0_BASE,
72 &flash_info[0]);
73 /*
74 * protect monitor and environment sectors
75 */
76 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH0_BASE
77 flash_protect(FLAG_PROTECT_SET,
78 CONFIG_SYS_MONITOR_BASE,
79 CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
80 &flash_info[0]);
81 #endif
82
83 #if defined(CONFIG_ENV_IS_IN_FLASH) && defined(CONFIG_ENV_ADDR)
84 #ifndef CONFIG_ENV_SIZE
85 #define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE
86 #endif
87 flash_protect(FLAG_PROTECT_SET,
88 CONFIG_ENV_ADDR,
89 CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
90 #endif
91
92 return CONFIG_SYS_FLASH0_SIZE * 1024 * 1024; /*size */
93 }
94
95 /*********************************************************************/
96 /* NAME: flash_print_info() - prints flash imformation */
97 /* */
98 /* DESCRIPTION: */
99 /* This function prints the flash information. */
100 /* */
101 /* INPUTS: */
102 /* flash_info_t *info - flash information structure */
103 /* */
104 /* OUTPUTS: */
105 /* Displays flash information to console */
106 /* */
107 /* RETURNS: */
108 /* None */
109 /* */
110 /* RESTRICTIONS/LIMITATIONS: */
111 /* */
112 /* */
113 /*********************************************************************/
114 void flash_print_info (flash_info_t *info)
115 {
116 int i;
117
118 if (info->flash_id == FLASH_UNKNOWN) {
119 printf ("missing or unknown FLASH type\n");
120 return;
121 }
122
123 switch ((info->flash_id >> 16) & 0xff) {
124 case 0x1:
125 printf ("AMD ");
126 break;
127 default:
128 printf ("Unknown Vendor ");
129 break;
130 }
131
132 switch (info->flash_id & FLASH_TYPEMASK) {
133 case AMD_ID_F040B:
134 printf ("AM29F040B (4 Mbit)\n");
135 break;
136 case AMD_ID_F080B:
137 printf ("AM29F080B (8 Mbit)\n");
138 break;
139 case AMD_ID_F016D:
140 printf ("AM29F016D (16 Mbit)\n");
141 break;
142 default:
143 printf ("Unknown Chip Type\n");
144 break;
145 }
146
147 printf (" Size: %ld MB in %d Sectors\n",
148 info->size >> 20, info->sector_count);
149
150 printf (" Sector Start Addresses:");
151 for (i=0; i<info->sector_count; ++i) {
152 if ((i % 5) == 0)
153 printf ("\n ");
154 printf (" %08lX%s",
155 info->start[i],
156 info->protect[i] ? " (RO)" : " "
157 );
158 }
159 printf ("\n");
160 return;
161 }
162
163 /*********************************************************************/
164 /* The following code cannot be run from FLASH! */
165 /*********************************************************************/
166
167 /*********************************************************************/
168 /* NAME: flash_get_size() - detects the flash size */
169 /* */
170 /* DESCRIPTION: */
171 /* 1) Reads vendor ID and devices ID from the flash devices. */
172 /* 2) Initializes flash info struct. */
173 /* 3) Return the flash size */
174 /* */
175 /* INPUTS: */
176 /* vu_long *addr - pointer to start of flash */
177 /* flash_info_t *info - flash information structure */
178 /* */
179 /* OUTPUTS: */
180 /* None */
181 /* */
182 /* RETURNS: */
183 /* Size of the flash in bytes, or 0 if device id is unknown. */
184 /* */
185 /* RESTRICTIONS/LIMITATIONS: */
186 /* Only supports the following devices: */
187 /* AM29F080D */
188 /* AM29F016D */
189 /* */
190 /*********************************************************************/
191 static ulong flash_get_size (vu_long *addr, flash_info_t *info)
192 {
193 short i;
194 vu_long vendor, devid;
195 ulong base = (ulong)addr;
196
197 /*printf("addr = %08lx\n", (unsigned long)addr); */
198
199 /* Reset and Write auto select command: read Manufacturer ID */
200 addr[0x0000] = 0xf0f0f0f0;
201 addr[0x0555] = 0xAAAAAAAA;
202 addr[0x02AA] = 0x55555555;
203 addr[0x0555] = 0x90909090;
204 udelay (1000);
205
206 vendor = addr[0];
207 /*printf("vendor = %08lx\n", vendor); */
208 if (vendor != 0x01010101) {
209 info->size = 0;
210 goto out;
211 }
212
213 devid = addr[1];
214 /*printf("devid = %08lx\n", devid); */
215
216 if ((devid & 0xff) == AMD_ID_F080B) {
217 info->flash_id = (vendor & 0xff) << 16 | AMD_ID_F080B;
218 /* we have 16 sectors with 64KB each x 4 */
219 info->sector_count = 16;
220 info->size = 4 * info->sector_count * 64*1024;
221 } else if ((devid & 0xff) == AMD_ID_F016D){
222 info->flash_id = (vendor & 0xff) << 16 | AMD_ID_F016D;
223 /* we have 32 sectors with 64KB each x 4 */
224 info->sector_count = 32;
225 info->size = 4 * info->sector_count * 64*1024;
226 } else {
227 info->size = 0;
228 goto out;
229 }
230 /*printf("sector count = %08x\n", info->sector_count); */
231 /* check for protected sectors */
232 for (i = 0; i < info->sector_count; i++) {
233 /* sector base address */
234 info->start[i] = base + i * (info->size / info->sector_count);
235 /* read sector protection at sector address, (A7 .. A0) = 0x02 */
236 /* D0 = 1 if protected */
237 addr = (volatile unsigned long *)(info->start[i]);
238 info->protect[i] = addr[2] & 1;
239 }
240
241 /* reset command */
242 addr = (vu_long *)info->start[0];
243
244 out:
245 addr[0] = 0xf0f0f0f0;
246
247 /*printf("size = %08x\n", info->size); */
248 return info->size;
249 }
250
251 /*********************************************************************/
252 /* NAME: flash_erase() - erases flash by sector */
253 /* */
254 /* DESCRIPTION: */
255 /* This function erases flash sectors starting for s_first to */
256 /* s_last. */
257 /* */
258 /* INPUTS: */
259 /* flash_info_t *info - flash information structure */
260 /* int s_first - first sector to erase */
261 /* int s_last - last sector to erase */
262 /* */
263 /* OUTPUTS: */
264 /* None */
265 /* */
266 /* RETURNS: */
267 /* Returns 0 for success, 1 for failure. */
268 /* */
269 /* RESTRICTIONS/LIMITATIONS: */
270 /* */
271 /*********************************************************************/
272 int flash_erase (flash_info_t *info, int s_first, int s_last)
273 {
274 vu_long *addr = (vu_long*)(info->start[0]);
275 int flag, prot, sect, l_sect;
276 ulong start, now, last;
277
278 if ((s_first < 0) || (s_first > s_last)) {
279 if (info->flash_id == FLASH_UNKNOWN) {
280 printf ("- missing\n");
281 } else {
282 printf ("- no sectors to erase\n");
283 }
284 return 1;
285 }
286
287 prot = 0;
288 for (sect = s_first; sect <= s_last; sect++) {
289 if (info->protect[sect]) {
290 prot++;
291 }
292 }
293
294 if (prot) {
295 printf ("- Warning: %d protected sectors will not be erased!\n",
296 prot);
297 } else {
298 printf ("\n");
299 }
300
301 l_sect = -1;
302
303 /* Disable interrupts which might cause a timeout here */
304 flag = disable_interrupts();
305
306 addr[0x0555] = 0xAAAAAAAA;
307 addr[0x02AA] = 0x55555555;
308 addr[0x0555] = 0x80808080;
309 addr[0x0555] = 0xAAAAAAAA;
310 addr[0x02AA] = 0x55555555;
311 udelay (100);
312
313 /* Start erase on unprotected sectors */
314 for (sect = s_first; sect <= s_last; sect++) {
315 if (info->protect[sect] == 0) { /* not protected */
316 addr = (vu_long*)(info->start[sect]);
317 addr[0] = 0x30303030;
318 l_sect = sect;
319 }
320 }
321
322 /* re-enable interrupts if necessary */
323 if (flag)
324 enable_interrupts();
325
326 /* wait at least 80us - let's wait 1 ms */
327 udelay (1000);
328
329 /*
330 * We wait for the last triggered sector
331 */
332 if (l_sect < 0)
333 goto DONE;
334
335 start = get_timer (0);
336 last = start;
337 addr = (vu_long*)(info->start[l_sect]);
338 while ((addr[0] & 0x80808080) != 0x80808080) {
339 if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
340 printf ("Timeout\n");
341 return 1;
342 }
343 /* show that we're waiting */
344 if ((now - last) > 1000) { /* every second */
345 serial_putc ('.');
346 last = now;
347 }
348 }
349
350 DONE:
351 /* reset to read mode */
352 addr = (volatile unsigned long *)info->start[0];
353 addr[0] = 0xF0F0F0F0; /* reset bank */
354
355 printf (" done\n");
356 return 0;
357 }
358
359 /*********************************************************************/
360 /* NAME: write_buff() - writes a buffer to flash */
361 /* */
362 /* DESCRIPTION: */
363 /* This function copies a buffer, *src, to flash. */
364 /* */
365 /* INPUTS: */
366 /* flash_info_t *info - flash information structure */
367 /* uchar *src - pointer to buffer to write to flash */
368 /* ulong addr - address to start write at */
369 /* ulong cnt - number of bytes to write to flash */
370 /* */
371 /* OUTPUTS: */
372 /* None */
373 /* */
374 /* RETURNS: */
375 /* 0 - OK */
376 /* 1 - write timeout */
377 /* 2 - Flash not erased */
378 /* */
379 /* RESTRICTIONS/LIMITATIONS: */
380 /* */
381 /*********************************************************************/
382 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
383 {
384 ulong cp, wp, data;
385 int i, l, rc;
386
387 wp = (addr & ~3); /* get lower word aligned address */
388
389 /*
390 * handle unaligned start bytes
391 */
392 if ((l = addr - wp) != 0) {
393 data = 0;
394 for (i = 0, cp = wp; i < l; ++i, ++cp) {
395 data = (data << 8) | (*(uchar *)cp);
396 }
397 for (; (i < 4) && (cnt > 0); ++i) {
398 data = (data << 8) | *src++;
399 --cnt;
400 ++cp;
401 }
402 for (; (cnt == 0) && (i < 4); ++i, ++cp) {
403 data = (data << 8) | (*(uchar *)cp);
404 }
405
406 if ((rc = write_word(info, wp, data)) != 0) {
407 return (rc);
408 }
409 wp += 4;
410 }
411
412 /*
413 * handle word aligned part
414 */
415 while (cnt >= 4) {
416 data = 0;
417 for (i = 0; i < 4; ++i) {
418 data = (data << 8) | *src++;
419 }
420 if ((rc = write_word(info, wp, data)) != 0) {
421 return (rc);
422 }
423 wp += 4;
424 cnt -= 4;
425 }
426
427 if (cnt == 0) {
428 return (0);
429 }
430
431 /*
432 * handle unaligned tail bytes
433 */
434 data = 0;
435 for (i = 0, cp = wp; (i < 4) && (cnt > 0); ++i, ++cp) {
436 data = (data << 8) | *src++;
437 --cnt;
438 }
439 for (; (i < 4); ++i, ++cp) {
440 data = (data << 8) | (*(uchar *)cp);
441 }
442
443 return (write_word(info, wp, data));
444 }
445
446 /*********************************************************************/
447 /* NAME: write_word() - writes a word to flash */
448 /* */
449 /* DESCRIPTION: */
450 /* This writes a single word to flash. */
451 /* */
452 /* INPUTS: */
453 /* flash_info_t *info - flash information structure */
454 /* ulong dest - address to write */
455 /* ulong data - data to write */
456 /* */
457 /* OUTPUTS: */
458 /* None */
459 /* */
460 /* RETURNS: */
461 /* 0 - OK */
462 /* 1 - write timeout */
463 /* 2 - Flash not erased */
464 /* */
465 /* RESTRICTIONS/LIMITATIONS: */
466 /* */
467 /*********************************************************************/
468 static int write_word (flash_info_t *info, ulong dest, ulong data)
469 {
470 vu_long *addr = (vu_long*)(info->start[0]);
471 ulong start;
472 int flag;
473
474 /* Check if Flash is (sufficiently) erased */
475 if ((*((vu_long *)dest) & data) != data) {
476 return (2);
477 }
478 /* Disable interrupts which might cause a timeout here */
479 flag = disable_interrupts();
480
481 addr[0x0555] = 0xAAAAAAAA;
482 addr[0x02AA] = 0x55555555;
483 addr[0x0555] = 0xA0A0A0A0;
484
485 *((vu_long *)dest) = data;
486
487 /* re-enable interrupts if necessary */
488 if (flag)
489 enable_interrupts();
490
491 /* data polling for D7 */
492 start = get_timer (0);
493 while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080)) {
494 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
495 return (1);
496 }
497 }
498 return (0);
499 }
500 /*********************************************************************/
501 /* End of flash.c */
502 /*********************************************************************/