📄 flashprg.c
字号:
/* openbios/arch/vesta/olivia/flashprg.c, redbios, redbios_iii_1.0 6/14/99 14:33:55 *//*-----------------------------------------------------------------------------+|| This source code has been made available to you by IBM on an AS-IS| basis. Anyone receiving this source is licensed under IBM| copyrights to use it in any way he or she deems fit, including| copying it, modifying it, compiling it, and redistributing it either| with or without modifications. No license under IBM patents or| patent applications is to be implied by the copyright license.|| Any user of this software should understand that IBM cannot provide| technical support for this software and will not be responsible for| any consequences resulting from the use of this software.|| Any person who transfers this source code or any derivative work| must include the IBM copyright notice, this paragraph, and the| preceding two paragraphs in the transferred software.|| COPYRIGHT I B M CORPORATION 1995| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M+-----------------------------------------------------------------------------*//*-----------------------------------------------------------------------------+|| File Name: flash_prog.c|| Function: Programs flash memory, must run out of DRAM.|| Author: Maciej P. Tyrlik.|| Change Activity-|| Date Description of Change BY| --------- --------------------- ---| 14-Jun-94 Created MPT| 15-Jun-94 Finished MPT| 30-Sep-94 Changed to use ROM ID (removed PASS_TWO_128 & PASS_TWO_512) KDW| 05-Oct-94 Added more comments KDW| 08-Nov-94 Removed PASS_ONE MPT| 24-Apr-95 Include s1Lib.h for function prototypes JWB| 23-Jan-97 Ported to DDI board KDW| 27-Jun-97 Updated to support multiple sector erease and programming pag| 25-Feb-98 ported to redwood board pag| 04-Jun-98 fixed comments, added no_erase_mode flag. pag| 15-Jan-99 Ported to Redwood III (removed dram refresh) pag| 10-Jun-99 Replaced intemp and outtemp with macros pag| 14-Jun-99 copy code to RAM in order to simplify make file. pag| 03-Mar-00 Rewrite using Sector Map Table jfh| 03-Mar-00 Rewrite for 16 Meg Flash devices AMD 29LV160BB jfh| 25-Apr-00 Move FLASH_CODE_ADDRESS to eval.h (easier to see Mem Map) jfh| 07-Jan-02 Rewrite to enable random write accross all range YYD| by read before write| 31-Jan-02 Rewrite to support SHARP LH28F160BJE devices YYD| 24-Jun-02 Added interrupt lock and cache flush for flash_prog YYD|+-----------------------------------------------------------------------------*/#include <stddef.h>#include <ppcLib.h>#include <s1Lib.h>#include <string.h>#include <s1ldLib.h>#include <eval.h>#include "flash.h"//#define DEBUG#undef DEBUG/* function pointers for copied code that does the actual work */static unsigned long (*get_flash_type_ptr)(void);static int (*write_flash_ptr)(unsigned short *, unsigned short, unsigned short);static int (*flash_prog_ptr)(unsigned long start, int offset, char *addr, size_t len, int no_erase_mode);static int (*flash_printf)(const char *format, ...);static void (*enable_flash_write_ptr)(void);static void (*disable_flash_write_ptr)(void);/* prototypes for copied code that does the actual work */static void zenable_flash_write(void);static void zdisable_flash_write(void);static unsigned long zget_flash_type(void);static int zwrite_flash(unsigned short *, unsigned short, unsigned short);static int zflash_prog(unsigned long start, int offset, char *addr, size_t len, int no_erase_mode);void init_flash_code(void){ int len = zflash_code_size(); int i; unsigned long *sptr, *dptr;#ifdef DEBUG if(len > BIOS_FLASH_CODE_SIZE) { s1printf("Flash code size 0x%08x too large !\nSystem halt!\n", len); ppcHalt(); } s1printf("Copying Flash code to RAM... \n");#endif /* copy the flash code to RAM one word at a time to support OCM */ sptr = (unsigned long *) zenable_flash_write; dptr = (unsigned long *) BIOS_FLASH_CODE_ADDR;#ifdef DEBUG s1printf(" Source %x\n", sptr); s1printf(" Destination %x\n", dptr);#endif /* copy the code to FLASH code to the address where it will run */ for (i = 0; i < len/4; ++i) { *dptr++ = *sptr++; }#ifdef DEBUG s1printf("Copying completed\n");#endif /* update the function pointers to the newly copied locations. */ enable_flash_write_ptr = (void (*)(void))BIOS_FLASH_CODE_ADDR; disable_flash_write_ptr = (void (*)(void)) (BIOS_FLASH_CODE_ADDR + (int)zdisable_flash_write - (int)zenable_flash_write); get_flash_type_ptr = (unsigned long (*)(void)) (BIOS_FLASH_CODE_ADDR + (int)zget_flash_type - (int)zenable_flash_write); write_flash_ptr = (int (*)(unsigned short *, unsigned short, unsigned short)) (BIOS_FLASH_CODE_ADDR + (int)zwrite_flash - (int)zenable_flash_write); flash_prog_ptr = (int (*)(unsigned long, int, char *, size_t, int)) (BIOS_FLASH_CODE_ADDR + (int)zflash_prog - (int)zenable_flash_write); flash_printf = s1printf; // warning, this may not work during programming#ifdef DEBUG s1printf("Enable Flash WR %x\n", enable_flash_write_ptr); s1printf("Disable Flash WR %x\n", disable_flash_write_ptr); s1printf("Get Flash Type %x\n", get_flash_type_ptr); s1printf("Write Flash %x\n", write_flash_ptr); s1printf("Program Flash %x\n", flash_prog_ptr);#endif}unsigned long get_flash_type(){ return get_flash_type_ptr();}int flash_prog(unsigned long start, int offset, char *addr, size_t len, int no_erase_mode){ // YYD, added interrupt lock and cache invalidate int rtn; unsigned long msr; msr=ppcAndMsr(~(ppcMsrEE|ppcMsrCI)); rtn = flash_prog_ptr(start, offset, addr, len, no_erase_mode); invalidated_invlidatei((unsigned char *)(start + offset), len); (void)ppcMtmsr(msr); return rtn;}static void zenable_flash_write(void){#ifdef BIOS_OLIVIA // make sure the flash is write enabled - clear the GPIO Flash Write Disable bit *(unsigned int *)0x40060000 &= 0x7fffffff ;#endif}static void zdisable_flash_write(void){#ifdef BIOS_OLIVIA // make sure the flash is write disabled - set the GPIO Flash Write Disable bit *(unsigned int *)0x40060000 |= 0x80000000 ;#endif}/* This function will allow for determining the manufacturing information *//* associated with the ROM being used. Code sequences were taken from the *//* AMD Flash Memory Products 1992/1993 Data Book/Handbook. */// YYD, changed for SHARP LH28F160BVE devicesunsigned long zget_flash_type(){ unsigned int fl_base; unsigned short device_id; volatile unsigned short *flashp; /*--------------------------------------------------------------------------+ | Read Autoselect bytes to determnine FLASH type. +--------------------------------------------------------------------------*/ for (fl_base = FLASH_START; fl_base < (unsigned)FLASH_START + FLASH_TOTAL_SIZE; fl_base = fl_base + FLASH_DEV_SIZE) { enable_flash_write_ptr(); EIEIO(); flashp = (unsigned short *)fl_base; flashp[0] = 0x90; EIEIO(); device_id = (flashp[0]<<8) | flashp[1]; EIEIO(); /*---------------------------------------------------------------------+ | Reset the FLASH (enable read access) +----------------------------------------------------------------------*/ flashp[0] = 0xFF; EIEIO(); disable_flash_write_ptr(); #ifdef DEBUG flash_printf("device_id = %08x \n", device_id);#endif if (device_id != DEVICE_ID) { flash_printf("Device %08x is not recognized\n", device_id); return -1; // YYD } } return(device_id);}/* writes one word to the flash at specified address */int zwrite_flash(unsigned short *addr, unsigned short data, unsigned short mask){ volatile unsigned short *flashp; unsigned short temp; flashp = addr; if (mask == 0xffff) { temp = data; } else { temp = (flashp[0] & ~mask) | (data & mask); }// enable_flash_write_ptr();// EIEIO(); flashp[0] = 0x50; // clear status EIEIO(); // enable word write flashp[0] = 0x40; EIEIO(); // write the data flashp[0] = temp; EIEIO(); do { flashp[0] = 0x70; // read status EIEIO(); } while(!(flashp[0] & 0x80)); // until ready if(flashp[0] & 0x10) { // write fail return -1; } return 0;}// YYD, this one has been rewrite to enable random write by read before writeint zflash_prog(unsigned long start, int offset, char *addr, size_t len, int no_erase_mode){ int sector, ftype; unsigned long nvptr, nvend, bufptr; /* Determine the size of the flash being used. */ if ((ftype = get_flash_type_ptr()) != DEVICE_ID) // YYD {#ifdef DEBUG flash_printf("Unsupported FLASH device %08x\n", ftype);#endif return -1; } /*--------------------------------------------------------------------------+ | Write requested information. +--------------------------------------------------------------------------*/ /* Set nvstart to the address where writing will begin. */ nvptr = (start + offset) & FLASH_ADDR_MASK; nvend = nvptr + len; bufptr = 0; if(nvptr < FLASH_START || nvptr >= (unsigned)FLASH_START + FLASH_TOTAL_SIZE || nvend >= (unsigned)FLASH_START + FLASH_TOTAL_SIZE) {#ifdef DEBUG flash_printf("Flash address out of range\n");#endif return -1; }#ifdef DEBUG flash_printf("FLASH: Flashing address 0x%08x 0x%08x\n", nvptr, nvend);#endif /*--------------------------------------------------------------------------+ | Locate the first modified sector +--------------------------------------------------------------------------*/ for (sector = 0; sector < NUM_SECTORS; sector++) { if (nvptr >= flash_map[sector].start_addr && nvptr < flash_map[sector+1].start_addr) { break; } } if(sector >= NUM_SECTORS) //YYD, failed to located the sector address {#ifdef DEBUG flash_printf("FLASH: Flash address out of range\n");#endif return -1; // should not happen since we have checked the address } while(nvptr < nvend) { int sect_len, k; unsigned short *flash_buffer, *sect_addr; volatile unsigned short *flashp; sect_len = flash_map[sector+1].start_addr - flash_map[sector].start_addr; flash_buffer = (unsigned short *)BIOS_FLASH_BUFFER_ADDR; sect_addr = (unsigned short *)flash_map[sector].start_addr; if(sect_len > BIOS_FLASH_BUFFER_SIZE) {#ifdef DEBUG flash_printf("FLASH: device secter too large, please change BIOS_FLASH_BUFFER_SIZE\n");#endif return -1; } if (nvptr < flash_map[sector].start_addr || nvptr >= flash_map[sector+1].start_addr) { return -1; // some dirty mistake happened } // read the sector first for(k=0; k<sect_len/2; k++) { flash_buffer[k] = sect_addr[k]; }#ifdef DEBUG flash_printf("FLASH: copied sector %d (%d) bytes\n", sector, sect_len);#endif // copy the changed content then for(k=nvptr-(unsigned int)sect_addr; k<sect_len && nvptr<nvend; nvptr++, bufptr++, k++) { *((unsigned char *)flash_buffer + k) = addr[bufptr]; } flashp = (unsigned short *)((unsigned int)sect_addr & 0x7fffffff);#ifdef DEBUG flash_printf("Erasing sector %d (0x%08x)\n", sector, (unsigned int)flashp);#endif // enable the program enable_flash_write_ptr(); EIEIO(); flashp[0] = 0xff; // RESET EIEIO(); flashp[0] = 0x50; // clear status EIEIO(); // erase the sector now /*--------------------------------------------------------------------------+ | Start the erase sector in each sector that needs to be erased. +--------------------------------------------------------------------------*/ flashp[0] = 0x20; // enable erase EIEIO(); flashp[0] = 0xd0; // erase /*--------------------------------------------------------------------------+ | Poll for completion of the erase sector in each sector that we're erasing. +--------------------------------------------------------------------------*/ do { flashp[0] = 0x70; // read status EIEIO(); } while(!(flashp[0] & 0x80)); // until ready if(flashp[0] & 0x20) { // write fail flashp[0] = 0xFF; // reset flash EIEIO(); disable_flash_write_ptr(); EIEIO();#ifdef DEBUG flash_printf("Failed to erase flash sector 0x%08x\n", sect_addr);#endif return -1; } flashp[0] = 0xFF; // reset flash EIEIO();#ifdef DEBUG flash_printf("Erased sector %d\n", sector);#endif // at last, write the updated sector for(k=0; k<sect_len/2; k++) { if(flash_buffer[k] == 0xffff) continue; // we could save a lot of time using this if (write_flash_ptr(sect_addr+k, flash_buffer[k], 0xffff)) { flashp[0] = 0xff; // RESET EIEIO(); disable_flash_write_ptr(); EIEIO();#ifdef DEBUG flash_printf("FLASH: write 0x%08x failed\n", sect_addr+k);#endif return(-1); } } flashp[0] = 0xff; // RESET EIEIO(); disable_flash_write_ptr(); EIEIO(); #ifdef DEBUG flash_printf("Programmed sector %d\n", sector);#endif // then move to next sector sector ++; if(sector >= NUM_SECTORS && nvptr < nvend) {#ifdef DEBUG flash_printf("FLASH: sector number out of range\n");#endif return -1; // we should never be here } } return(0);}int zflash_code_size(void){ return (int) zflash_code_size - (int) zenable_flash_write;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -