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,
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
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
62 flash_get(volatile FLASH_WORD_SIZE *addr, flash_info_t *info)
64 volatile FLASH_WORD_SIZE *p;
65 FLASH_WORD_SIZE value;
68 addr[0] = FLASH_CMD_READ_ID;
71 value = addr[0 << FLASH_CMD_ADDR_SHIFT];
73 case (INTEL_MANUFACT & FLASH_ID_MASK):
74 info->flash_id = FLASH_MAN_INTEL;
77 info->flash_id = FLASH_UNKNOWN;
78 info->sector_count = 0;
80 *addr = FLASH_CMD_RESET;
86 value = addr[1 << FLASH_CMD_ADDR_SHIFT];
88 case (INTEL_ID_28F320J3A & FLASH_ID_MASK):
89 info->flash_id += FLASH_28F320J3A;
90 info->sector_count = 32;
91 info->size = 0x00400000;
93 case (INTEL_ID_28F640J3A & FLASH_ID_MASK):
94 info->flash_id += FLASH_28F640J3A;
95 info->sector_count = 64;
96 info->size = 0x00800000;
98 case (INTEL_ID_28F128J3A & FLASH_ID_MASK):
99 info->flash_id += FLASH_28F128J3A;
100 info->sector_count = 128;
101 info->size = 0x01000000;
104 info->flash_id = FLASH_UNKNOWN;
105 info->sector_count = 0;
107 *addr = FLASH_CMD_RESET;
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;
123 *addr = FLASH_CMD_RESET;
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);
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,
148 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
149 flash_protect(FLAG_PROTECT_SET,
151 CFG_MONITOR_FLASH+CFG_MONITOR_LEN-1,
154 #ifdef CFG_ENV_IS_IN_FLASH
155 flash_protect(FLAG_PROTECT_SET,
157 CFG_ENV_ADDR+CFG_ENV_SECT_SIZE-1,
164 flash_print_info(flash_info_t *info)
168 if (info->flash_id == FLASH_UNKNOWN) {
169 printf ("missing or unknown FLASH type\n");
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");
181 case FLASH_28F640J3A: printf ("28F640JA3 (64 Mbit)\n");
183 case FLASH_28F128J3A: printf ("28F128JA3 (128 Mbit)\n");
185 default: printf ("Unknown Chip Type");
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) {
198 info->protect[i] ? " (RO)" : " "
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");
216 printf ("- no sectors to erase\n");
221 if (info->flash_id == FLASH_UNKNOWN) {
222 printf ("Cannot erase unknown flash - aborted\n");
227 for (sect=s_first; sect<=s_last; ++sect) {
228 if (info->protect[sect]) {
234 printf ("- Warning: %d protected sectors will not be erased!\n", prot);
239 start = get_timer (0);
242 for (sect = s_first; sect<=s_last; sect++) {
243 if (info->protect[sect]) {
247 addr = (volatile FLASH_WORD_SIZE *)(info->start[sect]);
248 /* Disable interrupts which might cause a timeout here */
249 flag = disable_interrupts();
252 printf("Erase sector %d at start addr 0x%08X", sect, (unsigned int)info->start[sect]);
255 *addr = FLASH_CMD_CLEAR_STATUS;
256 *addr = FLASH_CMD_BLOCK_ERASE;
257 *addr = FLASH_CMD_ERASE_CONFIRM;
259 /* re-enable interrupts if necessary */
264 /* wait at least 80us - let's wait 1 ms */
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;
275 /* show that we're waiting */
276 if ((now - last) > 1000) { /* every second */
281 *addr = FLASH_CMD_RESET;
288 write_buff2( volatile FLASH_WORD_SIZE *dst,
289 volatile FLASH_WORD_SIZE *src,
293 FLASH_WORD_SIZE status;
296 start = get_timer (0);
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) {
305 /* re-enable interrupts if necessary */
310 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
314 dst[0] = (FLASH_WORD_SIZE)(cnt - 1);
315 for (i=0; i<cnt; i++) {
318 dst[0] = FLASH_CMD_PROG_RESUME;
328 poll_status( volatile FLASH_WORD_SIZE *addr )
332 start = get_timer (0);
333 /* wait for error or finish */
335 if (*addr == FLASH_STATUS_DONE) {
336 if (*addr == FLASH_STATUS_DONE) {
340 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
341 *addr = FLASH_CMD_RESET;
345 *addr = FLASH_CMD_RESET;
350 * write_buff return values:
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;
363 if (info->flash_id == FLASH_UNKNOWN) {
367 addr = (volatile FLASH_WORD_SIZE *)(info->start[0]);
368 dst = (volatile FLASH_WORD_SIZE *) udst;
370 #ifdef CFG_FLASH_16BIT
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]) {
383 if (write_buff2( dst,src,bcnt ) != 0) {
384 addr[0] = FLASH_CMD_READ_STATUS;
386 if (poll_status( dst ) != 0) {
395 /* Check if Flash is (sufficiently) erased */
396 if ((*dst & *src) != *src) {
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;
405 /* re-enable interrupts if necessary */
410 if (poll_status( dst ) != 0) {
420 flash_real_protect(flash_info_t *info, long sector, int prot)
422 volatile FLASH_WORD_SIZE *addr;
425 addr = (volatile FLASH_WORD_SIZE *)(info->start[sector]);
426 *addr = FLASH_CMD_CLEAR_STATUS;
427 *addr = FLASH_CMD_PROTECT;
430 *addr = FLASH_CMD_PROTECT_SET;
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;
445 /* Set software protect flag */
446 info->protect[sector] = prot;
447 *addr = FLASH_CMD_RESET;
451 /*-----------------------------------------------------------------------
452 * Support for flash file system (JFFS2)
454 * We use custom partition info function because we have to fit the
455 * file system image between first sector (containing hard reset
456 * configuration word) and the sector containing U-Boot image. Standard
457 * partition info function does not allow for last sector specification
458 * and assumes that the file system occupies flash bank up to and
459 * including bank's last sector.
461 #if (CONFIG_COMMANDS & CFG_CMD_JFFS2) && defined(CFG_JFFS_CUSTOM_PART)
464 #ifndef CFG_JFFS2_FIRST_SECTOR
465 #define CFG_JFFS2_FIRST_SECTOR 0
467 #ifndef CFG_JFFS2_FIRST_BANK
468 #define CFG_JFFS2_FIRST_BANK 0
470 #ifndef CFG_JFFS2_NUM_BANKS
471 #define CFG_JFFS2_NUM_BANKS 1
473 #define CFG_JFFS2_LAST_BANK (CFG_JFFS2_FIRST_BANK + CFG_JFFS2_NUM_BANKS - 1)
475 #include <jffs2/jffs2.h>
477 static struct part_info partition;
479 struct part_info *jffs2_part_info(int part_num)
484 if (partition.usr_priv == 0) {
486 (unsigned char *) flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR];
487 for (i = CFG_JFFS2_FIRST_BANK; i <= CFG_JFFS2_LAST_BANK; i++)
488 partition.size += flash_info[i].size;
490 flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR] -
491 flash_info[CFG_JFFS2_FIRST_BANK].start[0];
492 #ifdef CFG_JFFS2_LAST_SECTOR
493 i = flash_info[CFG_JFFS2_LAST_BANK].sector_count - 1;
495 flash_info[CFG_JFFS2_LAST_BANK].start[i] -
496 flash_info[CFG_JFFS2_LAST_BANK].start[CFG_JFFS2_LAST_SECTOR];
499 partition.usr_priv = (void *)1;