to make u-boot work for fat32 filesystem
[jz_uboot.git] / board / funkwerk / vovpn-gw / flash.c
blob7dd0d3f23468d8b80619d21a7bf8d6cae935961b
1 /*
2 * (C) Copyright 2004
3 * Elmeg Communications Systems GmbH, Juergen Selent (j.selent@elmeg.de)
5 * Support for the Elmeg VoVPN Gateway Module
6 * ------------------------------------------
7 * This is a signle bank flashdriver for INTEL 28F320J3, 28F640J3
8 * and 28F128J3A flashs working in 8 Bit mode.
10 * Most of this code is taken from existing u-boot source code.
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 * MA 02111-1307 USA
28 #include <common.h>
30 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
32 #define FLASH_CMD_READ_ID 0x90
33 #define FLASH_CMD_READ_STATUS 0x70
34 #define FLASH_CMD_RESET 0xff
35 #define FLASH_CMD_BLOCK_ERASE 0x20
36 #define FLASH_CMD_ERASE_CONFIRM 0xd0
37 #define FLASH_CMD_CLEAR_STATUS 0x50
38 #define FLASH_CMD_SUSPEND_ERASE 0xb0
39 #define FLASH_CMD_WRITE 0x40
40 #define FLASH_CMD_WRITE_BUFF 0xe8
41 #define FLASH_CMD_PROG_RESUME 0xd0
42 #define FLASH_CMD_PROTECT 0x60
43 #define FLASH_CMD_PROTECT_SET 0x01
44 #define FLASH_CMD_PROTECT_CLEAR 0xd0
45 #define FLASH_STATUS_DONE 0x80
47 #define FLASH_WRITE_BUFFER_SIZE 32
49 #ifdef CFG_FLASH_16BIT
50 #define FLASH_WORD_SIZE unsigned short
51 #define FLASH_ID_MASK 0xffff
52 #define FLASH_CMD_ADDR_SHIFT 0
53 #else
54 #define FLASH_WORD_SIZE unsigned char
55 #define FLASH_ID_MASK 0xff
56 /* A0 is not used in either 8x or 16x for READ ID */
57 #define FLASH_CMD_ADDR_SHIFT 1
58 #endif
61 static unsigned long
62 flash_get(volatile FLASH_WORD_SIZE *addr, flash_info_t *info)
64 volatile FLASH_WORD_SIZE *p;
65 FLASH_WORD_SIZE value;
66 int i;
68 addr[0] = FLASH_CMD_READ_ID;
70 /* manufactor */
71 value = addr[0 << FLASH_CMD_ADDR_SHIFT];
72 switch (value) {
73 case (INTEL_MANUFACT & FLASH_ID_MASK):
74 info->flash_id = FLASH_MAN_INTEL;
75 break;
76 default:
77 info->flash_id = FLASH_UNKNOWN;
78 info->sector_count = 0;
79 info->size = 0;
80 *addr = FLASH_CMD_RESET;
81 return (0);
85 /* device */
86 value = addr[1 << FLASH_CMD_ADDR_SHIFT];
87 switch (value) {
88 case (INTEL_ID_28F320J3A & FLASH_ID_MASK):
89 info->flash_id += FLASH_28F320J3A;
90 info->sector_count = 32;
91 info->size = 0x00400000;
92 break;
93 case (INTEL_ID_28F640J3A & FLASH_ID_MASK):
94 info->flash_id += FLASH_28F640J3A;
95 info->sector_count = 64;
96 info->size = 0x00800000;
97 break;
98 case (INTEL_ID_28F128J3A & FLASH_ID_MASK):
99 info->flash_id += FLASH_28F128J3A;
100 info->sector_count = 128;
101 info->size = 0x01000000;
102 break;
103 default:
104 info->flash_id = FLASH_UNKNOWN;
105 info->sector_count = 0;
106 info->size = 0;
107 *addr = FLASH_CMD_RESET;
108 return (0);
111 /* setup sectors */
112 for (i = 0; i < info->sector_count; i++) {
113 info->start[i] = (unsigned long)addr + (i * info->size/info->sector_count);
116 /* check protected sectors */
117 for (i = 0; i < info->sector_count; i++) {
118 p = (volatile FLASH_WORD_SIZE *)(info->start[i]);
119 info->protect[i] = p[2 << FLASH_CMD_ADDR_SHIFT] & 1;
122 /* reset bank */
123 *addr = FLASH_CMD_RESET;
124 return (info->size);
127 unsigned long
128 flash_init(void)
130 unsigned long size;
131 int i;
133 for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
134 flash_info[i].flash_id = FLASH_UNKNOWN;
136 size = flash_get((volatile FLASH_WORD_SIZE *)CFG_FLASH_BASE, &flash_info[0]);
137 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
138 printf ("## Unknown FLASH Size=0x%08lx\n", size);
139 return (0);
142 /* always protect 1 sector containing the HRCW */
143 flash_protect(FLAG_PROTECT_SET,
144 flash_info[0].start[0],
145 flash_info[0].start[1] - 1,
146 &flash_info[0]);
148 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
149 flash_protect(FLAG_PROTECT_SET,
150 CFG_MONITOR_FLASH,
151 CFG_MONITOR_FLASH+CFG_MONITOR_LEN-1,
152 &flash_info[0]);
153 #endif
154 #ifdef CFG_ENV_IS_IN_FLASH
155 flash_protect(FLAG_PROTECT_SET,
156 CFG_ENV_ADDR,
157 CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
158 &flash_info[0]);
159 #endif
160 return (size);
163 void
164 flash_print_info(flash_info_t *info)
166 int i;
168 if (info->flash_id == FLASH_UNKNOWN) {
169 printf ("missing or unknown FLASH type\n");
170 return;
173 switch (info->flash_id & FLASH_VENDMASK) {
174 case FLASH_MAN_INTEL: printf ("INTEL "); break;
175 default: printf ("Unknown Vendor "); break;
178 switch (info->flash_id & FLASH_TYPEMASK) {
179 case FLASH_28F320J3A: printf ("28F320JA3 (32 Mbit)\n");
180 break;
181 case FLASH_28F640J3A: printf ("28F640JA3 (64 Mbit)\n");
182 break;
183 case FLASH_28F128J3A: printf ("28F128JA3 (128 Mbit)\n");
184 break;
185 default: printf ("Unknown Chip Type");
186 break;
189 printf (" Size: %ld MB in %d Sectors\n",
190 info->size >> 20, info->sector_count);
192 printf (" Sector Start Addresses:");
193 for (i=0; i<info->sector_count; ++i) {
194 if ((i % 5) == 0)
195 printf ("\n ");
196 printf (" %08lX%s",
197 info->start[i],
198 info->protect[i] ? " (RO)" : " "
201 printf ("\n");
205 flash_erase(flash_info_t *info, int s_first, int s_last)
207 unsigned long start, now, last;
208 int flag, prot, sect;
209 volatile FLASH_WORD_SIZE *addr;
210 FLASH_WORD_SIZE status;
212 if ((s_first < 0) || (s_first > s_last)) {
213 if (info->flash_id == FLASH_UNKNOWN) {
214 printf ("- missing\n");
215 } else {
216 printf ("- no sectors to erase\n");
218 return (1);
221 if (info->flash_id == FLASH_UNKNOWN) {
222 printf ("Cannot erase unknown flash - aborted\n");
223 return (1);
226 prot = 0;
227 for (sect=s_first; sect<=s_last; ++sect) {
228 if (info->protect[sect]) {
229 prot++;
233 if (prot) {
234 printf ("- Warning: %d protected sectors will not be erased!\n", prot);
235 } else {
236 printf ("\n");
239 start = get_timer (0);
240 last = start;
242 for (sect = s_first; sect<=s_last; sect++) {
243 if (info->protect[sect]) {
244 continue;
247 addr = (volatile FLASH_WORD_SIZE *)(info->start[sect]);
248 /* Disable interrupts which might cause a timeout here */
249 flag = disable_interrupts();
251 #ifdef DEBUG
252 printf("Erase sector %d at start addr 0x%08X", sect, (unsigned int)info->start[sect]);
253 #endif
255 *addr = FLASH_CMD_CLEAR_STATUS;
256 *addr = FLASH_CMD_BLOCK_ERASE;
257 *addr = FLASH_CMD_ERASE_CONFIRM;
259 /* re-enable interrupts if necessary */
260 if (flag) {
261 enable_interrupts();
264 /* wait at least 80us - let's wait 1 ms */
265 udelay (1000);
267 while (((status = *addr) & FLASH_STATUS_DONE) != FLASH_STATUS_DONE) {
268 if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
269 printf("Flash erase timeout at address %lx\n", info->start[sect]);
270 *addr = FLASH_CMD_SUSPEND_ERASE;
271 *addr = FLASH_CMD_RESET;
272 return (1);
275 /* show that we're waiting */
276 if ((now - last) > 1000) { /* every second */
277 putc ('.');
278 last = now;
281 *addr = FLASH_CMD_RESET;
283 printf (" done\n");
284 return (0);
287 static int
288 write_buff2( volatile FLASH_WORD_SIZE *dst,
289 volatile FLASH_WORD_SIZE *src,
290 unsigned long cnt )
292 unsigned long start;
293 FLASH_WORD_SIZE status;
294 int flag, i;
296 start = get_timer (0);
297 while (1) {
298 /* Disable interrupts which might cause a timeout here */
299 flag = disable_interrupts();
300 dst[0] = FLASH_CMD_WRITE_BUFF;
301 if ((status = *dst) & FLASH_STATUS_DONE) {
302 break;
305 /* re-enable interrupts if necessary */
306 if (flag) {
307 enable_interrupts();
310 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
311 return (-1);
314 dst[0] = (FLASH_WORD_SIZE)(cnt - 1);
315 for (i=0; i<cnt; i++) {
316 dst[i] = src[i];
318 dst[0] = FLASH_CMD_PROG_RESUME;
320 if (flag) {
321 enable_interrupts();
324 return( 0 );
327 static int
328 poll_status( volatile FLASH_WORD_SIZE *addr )
330 unsigned long start;
332 start = get_timer (0);
333 /* wait for error or finish */
334 while (1) {
335 if (*addr == FLASH_STATUS_DONE) {
336 if (*addr == FLASH_STATUS_DONE) {
337 break;
340 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
341 *addr = FLASH_CMD_RESET;
342 return (-1);
345 *addr = FLASH_CMD_RESET;
346 return (0);
350 * write_buff return values:
351 * 0 - OK
352 * 1 - write timeout
353 * 2 - Flash not erased
354 * 4 - Flash not identified
357 write_buff(flash_info_t *info, uchar *src, ulong udst, ulong cnt)
359 volatile FLASH_WORD_SIZE *addr, *dst;
360 unsigned long bcnt;
361 int flag, i;
363 if (info->flash_id == FLASH_UNKNOWN) {
364 return (4);
367 addr = (volatile FLASH_WORD_SIZE *)(info->start[0]);
368 dst = (volatile FLASH_WORD_SIZE *) udst;
370 #ifdef CFG_FLASH_16BIT
371 #error NYI
372 #else
373 while (cnt > 0) {
374 /* Check if buffer write is possible */
375 if (cnt > 1 && (((unsigned long)dst & (FLASH_WRITE_BUFFER_SIZE - 1)) == 0)) {
376 bcnt = cnt > FLASH_WRITE_BUFFER_SIZE ? FLASH_WRITE_BUFFER_SIZE : cnt;
377 /* Check if Flash is (sufficiently) erased */
378 for (i=0; i<bcnt; i++) {
379 if ((dst[i] & src[i]) != src[i]) {
380 return (2);
383 if (write_buff2( dst,src,bcnt ) != 0) {
384 addr[0] = FLASH_CMD_READ_STATUS;
386 if (poll_status( dst ) != 0) {
387 return (1);
389 cnt -= bcnt;
390 dst += bcnt;
391 src += bcnt;
392 continue;
395 /* Check if Flash is (sufficiently) erased */
396 if ((*dst & *src) != *src) {
397 return (2);
400 /* Disable interrupts which might cause a timeout here */
401 flag = disable_interrupts();
402 addr[0] = FLASH_CMD_ERASE_CONFIRM;
403 addr[0] = FLASH_CMD_WRITE;
404 *dst++ = *src++;
405 /* re-enable interrupts if necessary */
406 if (flag) {
407 enable_interrupts();
410 if (poll_status( dst ) != 0) {
411 return (1);
413 cnt --;
415 #endif
416 return (0);
420 flash_real_protect(flash_info_t *info, long sector, int prot)
422 volatile FLASH_WORD_SIZE *addr;
423 unsigned long start;
425 addr = (volatile FLASH_WORD_SIZE *)(info->start[sector]);
426 *addr = FLASH_CMD_CLEAR_STATUS;
427 *addr = FLASH_CMD_PROTECT;
429 if(prot) {
430 *addr = FLASH_CMD_PROTECT_SET;
431 } else {
432 *addr = FLASH_CMD_PROTECT_CLEAR;
435 /* wait for error or finish */
436 start = get_timer (0);
437 while(!(addr[0] & FLASH_STATUS_DONE)){
438 if (get_timer(start) > CFG_FLASH_ERASE_TOUT) {
439 printf("Flash protect timeout at address %lx\n", info->start[sector]);
440 addr[0] = FLASH_CMD_RESET;
441 return (1);
445 /* Set software protect flag */
446 info->protect[sector] = prot;
447 *addr = FLASH_CMD_RESET;
448 return (0);