8 * Applied Research Laboratories, The University of Texas at Austin
10 * See file CREDITS for list of people who contributed to this
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation; either version 2 of
16 * the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
31 #include <asm/processor.h>
33 #define ROM_CS0_START 0xFF800000
34 #define ROM_CS1_START 0xFF000000
36 #if defined(CFG_ENV_IS_IN_FLASH)
38 # define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET)
41 # define CFG_ENV_SIZE CFG_ENV_SECT_SIZE
43 # ifndef CFG_ENV_SECT_SIZE
44 # define CFG_ENV_SECT_SIZE CFG_ENV_SIZE
48 #define FLASH_BANK_SIZE 0x200000
49 #define MAIN_SECT_SIZE 0x10000
50 #define SECT_SIZE_32KB 0x8000
51 #define SECT_SIZE_8KB 0x2000
53 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
55 static int write_word (flash_info_t *info, ulong dest, ulong data);
57 static __inline__ unsigned long get_msr(void)
59 __asm__ __volatile__ ("mfmsr %0" : "=r" (msr) :);
63 static __inline__ void set_msr(unsigned long msr)
65 __asm__ __volatile__ ("mtmsr %0" : : "r" (msr));
68 /*flash command address offsets*/
73 #define FLASH_WORD_SIZE unsigned char
75 /*---------------------------------------------------------------------*/
76 /*#define DEBUG_FLASH 1 */
78 /*---------------------------------------------------------------------*/
80 unsigned long flash_init(void)
84 unsigned char manuf_id, device_id;
86 for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)
88 vu_char *addr = (vu_char *)(CFG_FLASH_BASE + i * FLASH_BANK_SIZE);
90 addr[0x555] = 0xAA; /* 3 cycles to read device info. See */
91 addr[0x2AA] = 0x55; /* AM29LV116D datasheet for list of */
92 addr[0x555] = 0x90; /* available commands. */
97 #if defined DEBUG_FLASH
98 printf("manuf_id = %x, device_id = %x\n", manuf_id, device_id);
101 if ( (manuf_id == (uchar)(AMD_MANUFACT)) &&
102 ( device_id == AMD_ID_LV116DT))
104 flash_info[i].flash_id = ((FLASH_MAN_AMD & FLASH_VENDMASK) << 16) |
105 (AMD_ID_LV116DT & FLASH_TYPEMASK);
107 flash_info[i].flash_id = FLASH_UNKNOWN;
108 addr[0] = (long)0xFFFFFFFF;
112 #if defined DEBUG_FLASH
113 printf ("flash_id = 0x%08lX\n", flash_info[i].flash_id);
116 addr[0] = (long)0xFFFFFFFF;
118 flash_info[i].size = FLASH_BANK_SIZE;
119 flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
120 memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
122 for (j = 0; j < flash_info[i].sector_count; j++)
125 if (j < (CFG_MAX_FLASH_SECT - 3) )
127 flash_info[i].start[j] = CFG_FLASH_BASE + i * FLASH_BANK_SIZE +
130 else if (j == (CFG_MAX_FLASH_SECT - 3) )
132 flash_info[i].start[j] = flash_info[i].start[j-1] + SECT_SIZE_32KB;
137 flash_info[i].start[j] = flash_info[i].start[j-1] + SECT_SIZE_8KB;
141 size += flash_info[i].size;
144 /* Protect monitor and environment sectors
146 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
147 flash_protect(FLAG_PROTECT_SET, CFG_MONITOR_BASE,
148 CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1, &flash_info[0]);
151 #if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR)
152 flash_protect(FLAG_PROTECT_SET, CFG_ENV_ADDR,
153 CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
160 /*-----------------------------------------------------------------------
162 void flash_print_info(flash_info_t *info)
164 static const char unk[] = "Unknown";
165 const char *mfct = unk, *type = unk;
168 if(info->flash_id != FLASH_UNKNOWN)
170 switch(info->flash_id & FLASH_VENDMASK)
172 case FLASH_MAN_AMD: mfct = "AMD"; break;
173 case FLASH_MAN_FUJ: mfct = "FUJITSU"; break;
174 case FLASH_MAN_STM: mfct = "STM"; break;
175 case FLASH_MAN_SST: mfct = "SST"; break;
176 case FLASH_MAN_BM: mfct = "Bright Microelectonics"; break;
177 case FLASH_MAN_INTEL: mfct = "Intel"; break;
180 switch(info->flash_id & FLASH_TYPEMASK)
182 case FLASH_AM040: type = "AM29F040B (512K * 8, uniform sector size)"; break;
183 case FLASH_AM400B: type = "AM29LV400B (4 Mbit, bottom boot sect)"; break;
184 case FLASH_AM400T: type = "AM29LV400T (4 Mbit, top boot sector)"; break;
185 case FLASH_AM800B: type = "AM29LV800B (8 Mbit, bottom boot sect)"; break;
186 case FLASH_AM800T: type = "AM29LV800T (8 Mbit, top boot sector)"; break;
187 case FLASH_AM160T: type = "AM29LV160T (16 Mbit, top boot sector)"; break;
188 case FLASH_AM320B: type = "AM29LV320B (32 Mbit, bottom boot sect)"; break;
189 case FLASH_AM320T: type = "AM29LV320T (32 Mbit, top boot sector)"; break;
190 case FLASH_STM800AB: type = "M29W800AB (8 Mbit, bottom boot sect)"; break;
191 case FLASH_SST800A: type = "SST39LF/VF800 (8 Mbit, uniform sector size)"; break;
192 case FLASH_SST160A: type = "SST39LF/VF160 (16 Mbit, uniform sector size)"; break;
197 "\n Brand: %s Type: %s\n"
198 " Size: %lu KB in %d Sectors\n",
205 printf (" Sector Start Addresses:");
207 for (i = 0; i < info->sector_count; i++)
211 unsigned long * flash = (unsigned long *) info->start[i];
214 * Check if whole sector is erased
217 (i != (info->sector_count - 1)) ?
218 (info->start[i + 1] - info->start[i]) >> 2 :
219 (info->start[0] + info->size - info->start[i]) >> 2;
222 flash = (unsigned long *) info->start[i], erased = 1;
223 (flash != (unsigned long *) info->start[i] + size) && erased;
226 erased = *flash == ~0x0UL;
230 (i % 5) ? "" : "\n ",
233 info->protect[i] ? "RO" : " "
241 /*-----------------------------------------------------------------------
244 int flash_erase (flash_info_t *info, int s_first, int s_last)
246 volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
247 int flag, prot, sect, l_sect;
248 ulong start, now, last;
251 if ((s_first < 0) || (s_first > s_last)) {
252 if (info->flash_id == FLASH_UNKNOWN) {
253 printf ("- missing\n");
255 printf ("- no sectors to erase\n");
260 if ((info->flash_id == FLASH_UNKNOWN) ||
261 (info->flash_id > (FLASH_MAN_STM | FLASH_AMD_COMP))) {
262 printf ("Can't erase unknown flash type - aborted\n");
267 for (sect=s_first; sect<=s_last; ++sect) {
268 if (info->protect[sect]) {
274 printf ("- Warning: %d protected sectors will not be erased!\n",
282 /* Check the ROM CS */
283 if ((info->start[0] >= ROM_CS1_START) && (info->start[0] < ROM_CS0_START))
288 /* Disable interrupts which might cause a timeout here */
289 flag = disable_interrupts();
291 addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
292 addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
293 addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00800080;
294 addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
295 addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
297 /* Start erase on unprotected sectors */
298 for (sect = s_first; sect<=s_last; sect++)
300 if (info->protect[sect] == 0)
301 { /* not protected */
302 addr = (FLASH_WORD_SIZE *)(info->start[0] + (
303 (info->start[sect] - info->start[0]) << sh8b));
305 if (info->flash_id & FLASH_MAN_SST)
307 addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
308 addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
309 addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00800080;
310 addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
311 addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
312 addr[0] = (FLASH_WORD_SIZE)0x00500050; /* block erase */
313 udelay(30000); /* wait 30 ms */
317 addr[0] = (FLASH_WORD_SIZE)0x00300030; /* sector erase */
323 /* re-enable interrupts if necessary */
327 /* wait at least 80us - let's wait 1 ms */
331 * We wait for the last triggered sector
336 start = get_timer (0);
338 addr = (FLASH_WORD_SIZE *)(info->start[0] + (
339 (info->start[l_sect] - info->start[0]) << sh8b));
340 while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
341 if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
342 printf ("Timeout\n");
345 /* show that we're waiting */
346 if ((now - last) > 1000) { /* every second */
353 /* reset to read mode */
354 addr = (FLASH_WORD_SIZE *)info->start[0];
355 addr[0] = (FLASH_WORD_SIZE)0x00F000F0; /* reset bank */
362 /*-----------------------------------------------------------------------
363 * Copy memory to flash, returns:
366 * 2 - Flash not erased
369 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
374 wp = (addr & ~3); /* get lower word aligned address */
377 * handle unaligned start bytes
379 if ((l = addr - wp) != 0) {
381 for (i=0, cp=wp; i<l; ++i, ++cp) {
382 data = (data << 8) | (*(uchar *)cp);
384 for (; i<4 && cnt>0; ++i) {
385 data = (data << 8) | *src++;
389 for (; cnt==0 && i<4; ++i, ++cp) {
390 data = (data << 8) | (*(uchar *)cp);
393 if ((rc = write_word(info, wp, data)) != 0) {
400 * handle word aligned part
404 for (i=0; i<4; ++i) {
405 data = (data << 8) | *src++;
407 if ((rc = write_word(info, wp, data)) != 0) {
419 * handle unaligned tail bytes
422 for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
423 data = (data << 8) | *src++;
426 for (; i<4; ++i, ++cp) {
427 data = (data << 8) | (*(uchar *)cp);
430 return (write_word(info, wp, data));
434 /*-----------------------------------------------------------------------
435 * Write a word to Flash, returns:
438 * 2 - Flash not erased
440 static int write_word (flash_info_t *info, ulong dest, ulong data)
442 volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)info->start[0];
443 volatile FLASH_WORD_SIZE *dest2;
444 volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data;
450 /* Check the ROM CS */
451 if ((info->start[0] >= ROM_CS1_START) && (info->start[0] < ROM_CS0_START))
456 dest2 = (FLASH_WORD_SIZE *)(((dest - info->start[0]) << sh8b) +
459 /* Check if Flash is (sufficiently) erased */
460 if ((*dest2 & (FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) {
463 /* Disable interrupts which might cause a timeout here */
464 flag = disable_interrupts();
466 for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++)
468 addr2[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
469 addr2[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
470 addr2[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00A000A0;
472 dest2[i << sh8b] = data2[i];
474 /* re-enable interrupts if necessary */
478 /* data polling for D7 */
479 start = get_timer (0);
480 while ((dest2[i << sh8b] & (FLASH_WORD_SIZE)0x00800080) !=
481 (data2[i] & (FLASH_WORD_SIZE)0x00800080)) {
482 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
490 /*-----------------------------------------------------------------------