📄 flashpic.c
字号:
/* * flashpic.c: * * by Thomas E. Arvanitis (tharvan@inaccessnetworks.com) * * This file contains the flash-support code that is relocated to * RAM prior to execution. * * TODO: Need some cleanup, and perhaps rewrite to use buffer write * to speed up operations. * * Here we only do WIDTH32 specifically. */#include "config.h"#if INCLUDE_FLASHtypedef unsigned char uchar;typedef unsigned short ushort;typedef unsigned long ulong;typedef volatile unsigned char vuchar;typedef volatile unsigned short vushort;typedef volatile unsigned long vulong;typedef volatile unsigned int vuint;typedef volatile int vint;#include "cpu.h"#include "flashdev.h"#include "flash.h"#define SR_WAIT 100000#define WR_WAIT 50#define DEV_WIDTH 4#define WSMS 0x00800080#define WSMS_L 0x00000080#define WSMS_H 0x00800000#define ESS 0x00400040#define ES 0x00200020#define PSS 0x00040004#define PS 0x00100010extern struct flashinfo Fdev;extern int FlashProtectWindow;intFlashlock32(struct flashinfo *fdev,int snum,int operation){ ulong add; int sector; add = (ulong)(fdev->base); /* Lock the requested sector(s): */ for (sector=0;sector<fdev->sectorcnt;sector++) { if ((snum == ALL_SECTORS) || (snum == sector)) { /* Issue the appropriate command sequence: */ Write_60_to_base(); switch(operation) { case FLASH_UNLOCK: Write_d0_to(add); break; case FLASH_LOCK: Write_01_to(add); break; case FLASH_LOCKDWN: return(-1); break; } } add += fdev->sectors[sector].size; } Write_ff_to_base(); /* Go to read-array mode */ return(0);}voidEndFlashlock32(){}/* Flasherase(): Based on the 'snum' value, erase the appropriate sector(s). Write the "Erase Setup" and "Erase Confirm" commands... Return 0 if success, else -1.*/intFlasherase32(struct flashinfo *fdev,int snum){ int ret, sector; volatile int i; ret = 0; FDEBUG('E'); /* Erase the request sector(s): */ for (sector=0; sector < fdev->sectorcnt; sector++) { FDEBUG('2'); if ((!FlashProtectWindow) && (fdev->sectors[sector].protected)) { FDEBUG('3'); continue; } if ((snum == ALL_SECTORS) || (snum == sector)) { register ulong *lp, *lp1; int noterased; FDEBUG('4'); /* See if the sector is already erased: */ noterased = 0; lp = (ulong *)fdev->sectors[sector].begin; lp1 = (ulong *)((char *)lp + fdev->sectors[sector].size); while(lp < lp1) { if (*lp++ != 0xffffffff) { FDEBUG('a'); noterased = 1; break; } } FDEBUG('5'); if (noterased) { FDEBUG('6'); /* Issue the setup/confirm sequence: */ Write_20_to(fdev->sectors[sector].begin);/* setup */ Write_d0_to(fdev->sectors[sector].begin);/* confirm */ /* Wait for sector erase to complete by polling RSR... */ while(1) { ulong rsr; Write_70_to_base(); rsr = Read_0000_from_base(); if (! (rsr & WSMS_H && rsr & WSMS_L)) { /* Wait till ready */ FDEBUG('a'); for (i=0; i<SR_WAIT; i++); continue; } if (rsr & ESS) { /* Should not be suspended */ FDEBUG('b'); ret = -1; } if (rsr & ES) { /* Should not have error */ FDEBUG('c'); ret = -1; } break; } FDEBUG('7'); Write_50_to_base(); /* Clear status register */ Write_ff_to_base(); /* Go to read-array mode */ } FDEBUG('8'); if (ret == -1) break; } FDEBUG('9'); } FDEBUG('\n'); FDEBUG('\r'); for (i=0; i<SR_WAIT; i++); return(ret);}/* EndFlasherase(): Function place holder to determine the "end" of the sectorerase() function.*/voidEndFlasherase32(){}/* Flashwrite(): Return 0 if successful, else -1.*/intFlashwrite32(struct flashinfo *fdev, uchar *dest, uchar *src, long bytecnt){ int rval; ulong sr, obuff, addrC, addrE, addrL; rval = 0; addrC = (ulong)dest; addrE = (ulong)dest + bytecnt; addrL = (ulong)dest & ~0x03UL; while (addrC < addrE) { obuff = *(ftype *)addrL; switch (addrC & 0x03UL) { case 0x0: obuff &= (ulong)(*src++ << 0x00) | 0xffffff00; if ( ++addrC == addrE ) break; /* fall through */ case 0x1: obuff &= (ulong)(*src++ << 0x08) | 0xffff00ff; if ( ++addrC == addrE ) break; /* fall through */ case 0x2: obuff &= (ulong)(*src++ << 0x10) | 0xff00ffff; if ( ++addrC == addrE ) break; /* fall through */ case 0x3: obuff &= (ulong)(*src++ << 0x18) | 0x00ffffff; if ( ++addrC == addrE ) break; } Write_40_to(addrL); /* flash program setup */ FWrite(addrL, &obuff); /* write value */ do { Write_70_to_base(); sr = Read_0000_from_base(); } while ( ! (sr & WSMS_H && sr & WSMS_L) ); Write_50_to_base(); /* Clear status register */ Write_ff_to_base(); /* Go to read-array mode */ if ( Is_Not_Equal(addrL, &obuff) ) { rval = -1; break; } addrL = addrC; } return rval;}/* EndFlashwrite(): Function place holder to determine the "end" of the Flashwrite() function.*/voidEndFlashwrite32(){}/* Ewrite(): Erase all sectors that are part of the address space to be written, then write the data to that address space. This is basically a concatenation of flasherase and flashwrite done in one step. This is necessary primarily for re-writing the bootcode; because after the boot code is erased, there is nowhere to return so the re-write must be done while executing out of ram also.*/intFlashewrite32(struct flashinfo *fdev,uchar *destA,uchar *srcA,int bytecnt){ int sector, i; void (*reset)(); uchar *src1; ftype val; uchar *src, *dest; ulong rsr;ewrite_again: src = srcA; dest = destA; Write_50_to_base(); /* clear status register */ Write_ff_to_base(); /* set device in read-array mode */ FDEBUG('A'); /* For each sector, if it overlaps any of the destination space */ /* then erase that sector. */ for (sector = 0; sector < fdev->sectorcnt; sector++) { FDEBUG('1'); if ((((uchar *)dest) > (fdev->sectors[sector].end)) || (((uchar *)dest+bytecnt) < (fdev->sectors[sector].begin))) { FDEBUG('2'); continue; } FDEBUG('3'); /* Issue the ERASE setup/confirm sequence: */ Write_20_to(fdev->sectors[sector].begin);/* setup */ Write_d0_to(fdev->sectors[sector].begin);/* confirm */ FDEBUG('4'); /* Wait for sector erase to complete by polling RSR... */ do { Write_70_to_base(); rsr = Read_0000_from_base(); } while (! (rsr & WSMS_H && rsr & WSMS_L)); FDEBUG('5'); Write_50_to_base(); /* Clear status register */ Write_ff_to_base(); /* Go to read-array mode */ FDEBUG(':'); } FDEBUG('\n'); FDEBUG('\r'); FDEBUG('6'); src1 = (uchar *)&val; for(i = 0; i < bytecnt; i += DEV_WIDTH) { /* Just in case src is not aligned... */ src1[0] = src[0]; src1[1] = src[1]; src1[2] = src[2]; src1[3] = src[3]; /* Flash program setup command */ Write_40_to(dest); /* Write the value */ FWrite(dest,src1); /* Wait for write to complete by polling RSR... */ do { Write_70_to_base(); rsr = Read_0000_from_base(); } while (! (rsr & WSMS_H && rsr & WSMS_L)); Write_50_to_base(); /* Clear status register */ Write_ff_to_base(); /* Go to read-array mode */ if (Is_Not_Equal(dest, src1)) { FPRINT('E'); FPRINT('1'); goto ewrite_again; } dest+=DEV_WIDTH; src+=DEV_WIDTH; } FDEBUG('7'); FDEBUG('\n'); FDEBUG('\r'); /* Now that the re-programming of flash is complete, reset: */ reset = RESETFUNC(); reset(); return(0); /* won't get here */}/* EndFlashewrite(): Function place holder to determine the "end" of the FlashEraseAndWrite() function.*/voidEndFlashewrite32(){}/* Flashtype(): Use the ReadCOnfiguration command (90H) to read manufacturer code (0000) and device id code (0001).*/intFlashtype32(struct flashinfo *fdev){ ushort man, dev; ulong id; /* Issue the read configuration command: */ Write_90_to_base(); man = (ushort)Read_0000_from_base(); /* manufacturer ID */ dev = (ushort)Read_0001_from_base(); /* device ID */ id = man; id <<= 16; id |= dev; fdev->id = id; /* Issue the read array command: */ Write_ff_to_base(); return((int)(fdev->id));}/* EndFlashtype(): Function place holder to determine the "end" of the Flashtype() function.*/voidEndFlashtype32(){}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -