3 * EMK Elektronik GmbH <www.emk-elektronik.de>
4 * Reinhard Meyer <r.meyer@emk-elektronik.de>
6 * copied from the BMW Port - seems that its similiar enough
7 * to be easily adaped ;) --- Well, it turned out to become a
8 * merger between parts of the EMKstax Flash routines and the
9 * BMW funtion frames...
12 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
14 * See file CREDITS for list of people who contributed to this
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License as
19 * published by the Free Software Foundation; either version 2 of
20 * the License, or (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
36 #define FLASH_WORD_SIZE unsigned short
37 #define FLASH_WORD_WIDTH (sizeof (FLASH_WORD_SIZE))
39 flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
41 /*-----------------------------------------------------------------------
44 static int write_word (flash_info_t *info, ulong dest, ulong data);
47 /*****************************************************************************
48 * software product ID entry/exit
49 *****************************************************************************/
50 static void FlashProductIdMode (
51 volatile FLASH_WORD_SIZE *b,
56 b[0x5555] = on_off ? 0x90 : 0xf0;
59 /*****************************************************************************
61 *****************************************************************************/
62 static void FlashSectorErase (
63 volatile FLASH_WORD_SIZE *b,
64 volatile FLASH_WORD_SIZE *a)
74 /*****************************************************************************
76 *****************************************************************************/
77 static void FlashProgWord (
78 volatile FLASH_WORD_SIZE *b,
79 volatile FLASH_WORD_SIZE *a,
88 /*****************************************************************************
89 * reset bank, back to read mode
90 *****************************************************************************/
91 static void FlashReset (volatile FLASH_WORD_SIZE *b)
96 /*****************************************************************************
98 * this code is a stripped version of the FlashGetType() function in EMKstax
99 *****************************************************************************/
100 unsigned long flash_init (void)
102 volatile FLASH_WORD_SIZE * const flash = (volatile FLASH_WORD_SIZE *) CFG_FLASH_BASE;
103 FLASH_WORD_SIZE manu, dev;
104 flash_info_t * const pflinfo = &flash_info[0];
108 FlashProductIdMode (flash, 1);
111 FlashProductIdMode (flash, 0);
114 pflinfo->sector_count = 0;
115 pflinfo->flash_id = 0xffffffff;
116 pflinfo->portwidth = FLASH_CFI_16BIT;
117 pflinfo->chipwidth = FLASH_CFI_BY16;
122 pflinfo->flash_id = FLASH_MAN_AMD;
126 pflinfo->size = 0x00200000;
127 pflinfo->sector_count = 35;
128 pflinfo->flash_id |= FLASH_AM160B;
129 pflinfo->start[0] = CFG_FLASH_BASE;
130 pflinfo->start[1] = CFG_FLASH_BASE + 0x4000;
131 pflinfo->start[2] = CFG_FLASH_BASE + 0x6000;
132 pflinfo->start[3] = CFG_FLASH_BASE + 0x8000;
133 for (j = 4; j < 35; j++)
135 pflinfo->start[j] = CFG_FLASH_BASE + 0x00010000 * (j-3);
140 pflinfo->size = 0x00400000;
141 pflinfo->sector_count = 71;
142 pflinfo->flash_id |= FLASH_AM320B;
143 pflinfo->start[0] = CFG_FLASH_BASE;
144 pflinfo->start[1] = CFG_FLASH_BASE + 0x4000;
145 pflinfo->start[2] = CFG_FLASH_BASE + 0x6000;
146 pflinfo->start[3] = CFG_FLASH_BASE + 0x8000;
147 for (j = 0; j < 8; j++)
149 pflinfo->start[j] = CFG_FLASH_BASE + 0x00002000 * (j);
151 for (j = 8; j < 71; j++)
153 pflinfo->start[j] = CFG_FLASH_BASE + 0x00010000 * (j-7);
158 printf ("unknown AMD dev=%x ", dev);
159 pflinfo->flash_id |= FLASH_UNKNOWN;
164 printf ("unknown manu=%x ", manu);
166 return pflinfo->size;
169 /*****************************************************************************
170 * print info about a FLASH
171 *****************************************************************************/
172 void flash_print_info (flash_info_t *info)
174 static const char unk[] = "Unknown";
176 const char *mfct=unk,
179 if(info->flash_id != FLASH_UNKNOWN)
181 switch (info->flash_id & FLASH_VENDMASK)
188 switch (info->flash_id & FLASH_TYPEMASK)
191 type = "AM29LV160B (16 Mbit, bottom boot sect)";
194 type = "AM29LV320B (32 Mbit, bottom boot sect)";
200 "\n Brand: %s Type: %s\n"
201 " Size: %lu KB in %d Sectors\n",
208 printf (" Sector Start Addresses:");
210 for (i = 0; i < info->sector_count; i++)
214 unsigned long *flash = (unsigned long *) info->start[i];
217 * Check if whole sector is erased
220 (i != (info->sector_count - 1)) ?
221 (info->start[i + 1] - info->start[i]) >> 2 :
222 (info->start[0] + info->size - info->start[i]) >> 2;
225 flash = (unsigned long *) info->start[i], erased = 1;
226 (flash != (unsigned long *) info->start[i] + size) && erased;
229 erased = *flash == ~0x0UL;
233 (i % 5) ? "" : "\n ",
236 info->protect[i] ? "RO" : " "
244 /*****************************************************************************
245 * erase one or more sectors
246 *****************************************************************************/
247 int flash_erase (flash_info_t *info, int s_first, int s_last)
249 volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
258 if ((s_first < 0) || (s_first > s_last))
260 if (info->flash_id == FLASH_UNKNOWN)
262 printf ("- missing\n");
266 printf ("- no sectors to erase\n");
271 if ((info->flash_id == FLASH_UNKNOWN) ||
272 (info->flash_id > (FLASH_MAN_STM | FLASH_AMD_COMP)))
274 printf ("Can't erase unknown flash type - aborted\n");
279 for (sect=s_first; sect<=s_last; ++sect)
281 if (info->protect[sect])
289 printf ("- Warning: %d protected sectors will not be erased!\n",
299 /* Disable interrupts which might cause a timeout here */
300 flag = disable_interrupts();
302 /* Start erase on unprotected sectors */
303 for (sect = s_first; sect<=s_last; sect++)
305 if (info->protect[sect] == 0)
306 { /* not protected */
307 FlashSectorErase ((FLASH_WORD_SIZE *)info->start[0], (FLASH_WORD_SIZE *)info->start[sect]);
312 /* re-enable interrupts if necessary */
316 /* wait at least 80us - let's wait 1 ms */
320 * We wait for the last triggered sector
325 start = get_timer (0);
327 addr = (FLASH_WORD_SIZE *)info->start[l_sect];
328 while ((addr[0] & 0x0080) != 0x0080)
330 if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT)
332 printf ("Timeout\n");
335 /* show that we're waiting */
336 if ((now - last) > 1000)
344 /* reset to read mode */
345 FlashReset ((FLASH_WORD_SIZE *)info->start[0]);
351 /*****************************************************************************
352 * Copy memory to flash, returns:
355 * 2 - Flash not erased
356 *****************************************************************************/
357 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
366 wp = (addr & ~(FLASH_WORD_WIDTH-1)); /* get lower word aligned address */
369 * handle unaligned start bytes, if there are...
371 if ((l = addr - wp) != 0)
375 /* get the current before the new data into our data word */
376 for (i=0, cp=wp; i<l; ++i, ++cp)
378 data = (data << 8) | (*(uchar *)cp);
381 /* now merge the to be programmed values */
382 for (; i<4 && cnt>0; ++i, ++cp, --cnt)
384 data = (data << 8) | *src++;
387 /* get the current after the new data into our data word */
388 for (; cnt==0 && i<FLASH_WORD_WIDTH; ++i, ++cp)
390 data = (data << 8) | (*(uchar *)cp);
393 /* now write the combined word */
394 if ((rc = write_word (info, wp, data)) != 0)
398 wp += FLASH_WORD_WIDTH;
402 * handle word aligned part
404 while (cnt >= FLASH_WORD_WIDTH)
407 for (i=0; i<FLASH_WORD_WIDTH; ++i)
409 data = (data << 8) | *src++;
411 if ((rc = write_word (info, wp, data)) != 0)
415 wp += FLASH_WORD_WIDTH;
416 cnt -= FLASH_WORD_WIDTH;
425 * handle unaligned tail bytes, if there are...
429 /* now merge the to be programmed values */
430 for (i=0, cp=wp; i<FLASH_WORD_WIDTH && cnt>0; ++i, ++cp)
432 data = (data << 8) | *src++;
436 /* get the current after the new data into our data word */
437 for (; i<FLASH_WORD_WIDTH; ++i, ++cp)
439 data = (data << 8) | (*(uchar *)cp);
442 /* now write the combined word */
443 return (write_word (info, wp, data));
446 /*****************************************************************************
447 * Write a word to Flash, returns:
450 * 2 - Flash not erased
451 *****************************************************************************/
452 static int write_word (flash_info_t *info, ulong dest, ulong data)
454 volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)info->start[0];
455 volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *)dest;
456 FLASH_WORD_SIZE data2 = data;
460 /* Check if Flash is (sufficiently) erased */
461 if ((*dest2 & data2) != data2)
466 /* Disable interrupts which might cause a timeout here */
467 flag = disable_interrupts ();
469 FlashProgWord (addr2, dest2, data2);
471 /* re-enable interrupts if necessary */
473 enable_interrupts ();
475 /* data polling for D7 */
476 start = get_timer (0);
477 while ((*dest2 & 0x0080) != (data2 & 0x0080))
479 if (get_timer (start) > CFG_FLASH_WRITE_TOUT)
488 /*-----------------------------------------------------------------------