📄 flash.c
字号:
/* * (C) Copyright 2002 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> * Marius Groeger <mgroeger@sysgo.de> * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include "armboot.h"#if defined (AM29LV160D) || defined (HY29LV320B)#define FLASH_BANK_SIZE 0x200000#define MAIN_SECT_SIZE 0x10000#define PARAM_SECT_SIZE 0x2000#define INIT_SECT_SIZE 0x4000 /* for AMD29LV160DB */#define MIDDLE_SECT_SIZE 0x8000 /* for AMD29LV160DB */#endif#ifdef K8B1616UBA#define FLASH_BANK_SIZE 0x200000#define MAIN_SECT_SIZE 0x10000#define PARAM_SECT_SIZE 0x2000#endif#if defined(AM29LV320D) || defined(AT49BV321)#define FLASH_BANK_SIZE 0x400000#define MAIN_SECT_SIZE 0x10000#define PARAM_SECT_SIZE 0x2000#endif#ifdef SST39VF160#define FLASH_BANK_SIZE 0x200000#define MAIN_SECT_SIZE 0x10000#define PARAM_SECT_SIZE 0x1000#endifflash_info_t flash_info[CFG_MAX_FLASH_BANKS];/*----------------------------------------------------------------------- */ulong flash_init(bd_t *bd){ int i, j; ulong size = 0; for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {#if defined (AM29LV160D) || defined (HY29LV320B) ulong flashbase = 0;#if defined(MBM29LV160BE) flash_info[i].flash_id = (FUJ_MANUFACT & FLASH_VENDMASK) |(FUJ_ID_MBM29LV160BE & FLASH_TYPEMASK);#elif defined(M29W160DB) flash_info[i].flash_id = (ST_MANUFACT & FLASH_VENDMASK) |(ST_ID_M29W160DB & FLASH_TYPEMASK);#elif defined(HY29LV320B) flash_info[i].flash_id = (HYNIX_MANUFACT & FLASH_VENDMASK) |(HYNIX_ID_HY29LV320B & FLASH_TYPEMASK);#else flash_info[i].flash_id = (AMD_MANUFACT & FLASH_VENDMASK) |(AMD_ID_LV160D & FLASH_TYPEMASK);#endif flash_info[i].size = FLASH_BANK_SIZE; flash_info[i].sector_count = CFG_MAX_FLASH_SECT; memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); flashbase = PHYS_FLASH_1; for (j = 0; j < flash_info[i].sector_count; j++) { if(j <= 1) flash_info[i].start[j] = flashbase + j * INIT_SECT_SIZE; else if ((2 <= j)&&(j <= 3)) flash_info[i].start[j] = flashbase + (j+1) * PARAM_SECT_SIZE; else flash_info[i].start[j] = flashbase + (j-3)*MAIN_SECT_SIZE; } size += flash_info[i].size;#else ulong flashbase = 0;#if defined(K8B1616UBA) flash_info[i].flash_id = (SAMSUNG_MANUFACT & FLASH_VENDMASK) |(SAMSUNG_ID_K8B1616UBA & FLASH_TYPEMASK);#elif defined(AM29LV320D) flash_info[i].flash_id = (AMD_MANUFACT & FLASH_VENDMASK) |(AMD_ID_LV320DB & FLASH_TYPEMASK);#elif defined(AT49BV321) flash_info[i].flash_id = (ATMEL_MANUFACT & FLASH_VENDMASK) |(ATMEL_ID_AT49BV321 & FLASH_TYPEMASK);#elif defined(SST39VF160) flash_info[i].flash_id = (SST_MANUFACT & FLASH_VENDMASK) |(SST_ID_xF160A & FLASH_TYPEMASK);#endif flash_info[i].size = FLASH_BANK_SIZE; flash_info[i].sector_count = CFG_MAX_FLASH_SECT; memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); flashbase = PHYS_FLASH_1; for (j = 0; j < flash_info[i].sector_count; j++) {#ifdef SST39VF160 if (j <= 15)#else if (j <= 7)#endif { flash_info[i].start[j] = flashbase + j * PARAM_SECT_SIZE; } else {#ifdef SST39VF160 flash_info[i].start[j] = flashbase + (j - 15)*MAIN_SECT_SIZE;#else flash_info[i].start[j] = flashbase + (j - 7)*MAIN_SECT_SIZE;#endif } } size += flash_info[i].size;#endif } /* Protect monitor and environment sectors */ flash_protect(FLAG_PROTECT_SET, CFG_FLASH_BASE, CFG_FLASH_BASE +_armboot_end - _armboot_start, &flash_info[0]); flash_protect(FLAG_PROTECT_SET, CFG_ENV_ADDR, CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]); return size;}/*----------------------------------------------------------------------- */void flash_print_info (flash_info_t *info){ int i; switch (info->flash_id & FLASH_VENDMASK) { case (SAMSUNG_MANUFACT & FLASH_VENDMASK): printf("SAMSUNG : "); break; case (AMD_MANUFACT & FLASH_VENDMASK): printf("AMD : "); break; case (ATMEL_MANUFACT & FLASH_VENDMASK): printf("ATMEL : "); break; case (FUJ_MANUFACT & FLASH_VENDMASK): printf("FUJITSU : "); break; case (SST_MANUFACT & FLASH_VENDMASK): printf("SST : "); break; case (HYNIX_MANUFACT & FLASH_VENDMASK): printf("HYNIX : "); break; default: printf("Unknown Vendor "); break; } switch (info->flash_id & FLASH_TYPEMASK) { case (SAMSUNG_ID_K8B1616UBA & FLASH_TYPEMASK): printf("K8B1616UBA\n"); break; case (AMD_ID_LV320DB & FLASH_TYPEMASK): printf("AM29LV320D\n"); break; case (ATMEL_ID_AT49BV321 & FLASH_TYPEMASK): printf("AT49BV321\n"); break;#if defined(MBM29LV160BE) case (FUJ_ID_MBM29LV160BE & FLASH_TYPEMASK): printf("MBM29LV160BE\n"); break;#elif defined(M29W160DB) case (ST_ID_M29W160DB & FLASH_TYPEMASK): printf("M29W160DB\n"); break;#else case (AMD_ID_LV160D & FLASH_TYPEMASK): printf("AM29LV160D\n"); break;#endif case (SST_ID_xF160A & FLASH_TYPEMASK): printf("SST39VF160\n"); break; case (HYNIX_ID_HY29LV320B & FLASH_TYPEMASK): printf("HY29LV320B\n"); break; default: printf("Unknown Chip Type\n"); goto Done; break; } printf(" Size: %ld MB in %d Sectors\n",info->size >> 20, info->sector_count); printf(" Sector Start Addresses:"); for (i = 0; i < info->sector_count; i++) { if ((i % 5) == 0) { printf ("\n "); } printf (" %08lX%s", info->start[i], info->protect[i] ? " (RO)" : " "); } printf ("\n"); Done:}void Delay1Sec(unsigned int nSec){ unsigned int i; while(nSec--) { printf("\n"); i=200000; while(i--) ; } }void Delay1(unsigned int nSec){ unsigned int i; while(nSec--) { i=20; while(i--) ; } }void FlashDelay(unsigned int nusecs){ unsigned long j, k, i=0x1234; while(nusecs--) { for (j=0; j<30; j++) k = j * i; }}/*----------------------------------------------------------------------- */int flash_erase (flash_info_t *info, int s_first, int s_last){ int flag, prot, sect; int rc = ERR_OK; if (info->flash_id == FLASH_UNKNOWN) return ERR_UNKNOWN_FLASH_TYPE; if ((s_first < 0) || (s_first > s_last)) return ERR_INVAL; //if ((info->flash_id & FLASH_VENDMASK) !=(SAMSUNG_MANUFACT & FLASH_VENDMASK)) // return ERR_UNKNOWN_FLASH_VENDOR; prot = 0; for (sect=s_first; sect<=s_last; ++sect) { if (info->protect[sect]) prot++; } if (prot) { return ERR_PROTECTED; } /* * Disable interrupts which might cause a timeout * here. Remember that our exception vectors are * at address 0 in the flash, and we don't want a * (ticker) exception to happen while the flash * chip is in programming mode. */ flag = disable_interrupts(); /* Start erase on unprotected sectors */ for (sect = s_first; sect<=s_last && !ctrlc(); sect++) { unsigned short *Flash; unsigned long temp; unsigned long temp_E; unsigned long SectorAddr; Flash = (unsigned short *)(CFG_FLASH_BASE); printf("Erasing sector %2d ... ", sect); /* arm simple, non interrupt dependent timer */ /*reset_timer_masked();*/ Delay1(5); SectorAddr = flash_info[0].start[sect]; /* total address */ #ifdef SST39VF160 if(sect < 16) { *(Flash+0x5555) = 0xAA; Delay1(1); *(Flash+0x2AAA) = 0x55; Delay1(1); *(Flash+0x5555) = 0x80; Delay1(1); *(Flash+0x5555) = 0xAA; Delay1(1); *(Flash+0x2AAA) = 0x55; Delay1(1); *((volatile unsigned short *)(SectorAddr)) = 0x30; } else { *(Flash+0x5555) = 0xAA; Delay1(1); *(Flash+0x2AAA) = 0x55; Delay1(1); *(Flash+0x5555) = 0x80; Delay1(1); *(Flash+0x5555) = 0xAA; Delay1(1); *(Flash+0x2AAA) = 0x55; Delay1(1); *((volatile unsigned short *)(SectorAddr)) = 0x50; }#else *(Flash+0x555) = 0xAA; Delay1(1); *(Flash+0x2AA) = 0x55; Delay1(1); *(Flash+0x555) = 0x80; Delay1(1); *(Flash+0x555) = 0xAA; Delay1(1); *(Flash+0x2AA) = 0x55; Delay1(1); *((volatile unsigned short *)(SectorAddr)) = 0x30;#endif temp_E = SectorAddr; Delay1Sec(1); temp = (*((volatile unsigned short *)(temp_E)) & 0x00FF); while( temp != 0x00FF ) { temp = (*((volatile unsigned short *)(temp_E)) & 0x00FF); } *((volatile unsigned short *)(CFG_FLASH_BASE)) = 0xF0; } if (ctrlc()) printf("User Interrupt!\n"); #if 0outahere: /* allow flash to settle - wait 10 ms */ udelay_masked(10000); if (flag) enable_interrupts(); #endif return rc;}/*----------------------------------------------------------------------- * Copy memory to flash */static int write_word (flash_info_t *info, ulong dest, ushort data){ /*vulong *addr = (vulong *)dest;*/ unsigned short *addr; u16 barf; int rc = ERR_OK; int flag; unsigned short *Flash; addr = (unsigned short *)(dest) ; flag = disable_interrupts(); Flash = (unsigned short *)CFG_FLASH_BASE;#ifdef SST39VF160 *(Flash+0x5555) = 0xAA; Delay1(1); *(Flash+0x2AAA) = 0x55; Delay1(1); *(Flash+0x5555) = 0xA0; Delay1(1);#else *(Flash+0x555) = 0xAA; Delay1(1); *(Flash+0x2AA) = 0x55; Delay1(1); *(Flash+0x555) = 0xA0; Delay1(1);#endif *addr = (unsigned short)data; FlashDelay(10); *((unsigned short *)(CFG_FLASH_BASE)) = 0xF0; /* arm simple, non interrupt dependent timer */ reset_timer_masked(); /* wait while polling the status register */ #if 0 if (get_timer_masked() > CFG_FLASH_WRITE_TOUT) { rc = ERR_TIMOUT; Log(DEBUG,"ZZZ"); return rc; } #endif if(FlashCompareData((unsigned int)dest, dest, 1)) { barf = *addr; printf("\nFlash write error %lx at address %lx\n",(u32)barf, dest); rc = ERR_PROG_ERROR; return rc; } return rc; }/*----------------------------------------------------------------------- * Copy memory to flash. */int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt){ ulong cp, wp; int l; int i, rc; ushort data=0; wp = (addr & ~3); /* get lower word aligned address */ /* * handle unaligned start bytes */ if ((l = addr - wp) != 0) { data = 0; for (i=0, cp=wp; i<l; ++i, ++cp) data = (data >> 8) | (*(uchar *)cp << 24); for (; i<4 && cnt>0; ++i) { data = (data >> 8) | (*src++ << 24); --cnt; ++cp; } for (; cnt==0 && i<4; ++i, ++cp) data = (data >> 8) | (*(uchar *)cp << 24); if ((rc = write_word(info, wp, data)) != 0) return (rc); wp += 4; } /* * handle word aligned part */ while (cnt >= 2) { data = *((unsigned short *)src); if ((rc = write_word(info, addr, data)) != 0) return (rc); src += 2; addr += 2; cnt -= 2; } if (cnt == 0) return ERR_OK; /* * handle unaligned tail bytes */ data = 0; for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { data = (data >> 8) | (*src++ << 24); --cnt; } for (; i<4; ++i, ++cp) data = (data >> 8) | (*(uchar *)cp << 24); return write_word(info, wp, data);}//--------------------------------------------------------------------------//// FlashCompareData: compare Flash to DRAM //// ////--------------------------------------------------------------------------//int FlashCompareData( unsigned int BaseAddr, unsigned int SrcAddr, unsigned int SrcSize ){ unsigned short *src, *tgt; unsigned int i; unsigned int size; src = (unsigned short *)SrcAddr; tgt = (unsigned short *)BaseAddr; size = SrcSize/sizeof(unsigned short); for ( i=0; i<size; i++, src++, tgt++ ) { if ( *tgt != *src ) { printf("\n>> Data Compare Error!\n"); return(ERR_PROG_ERROR); } } return(ERR_OK);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -