?? intel28f128_16x2.c
字號:
/* intel28f128_16x2.c:
* Support for INTEL 28f128.
* A 16-bit device in a 2-device-wide bank.
*/
#include "config.h"
#if INCLUDE_FLASH
#include "stddefs.h"
#include "genlib.h"
#include "cpu.h"
#include "flash.h"
#include "intel28f128_16x2.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 0x00100010
extern struct flashinfo Fdev;
extern int FlashProtectWindow;
/* Manufacturer and device ids... */
#define INTEL28F128J 0x00890018
#define ftype volatile unsigned long
#define FWrite(to,frm) (*(ftype *)(to) = *(ftype *)(frm))
#define Write_to(add, val) (*(ftype *)(add) = (val))
#define Write_01_to(add) (*(ftype *)(add) = 0x00010001)
#define Write_20_to(add) (*(ftype *)(add) = 0x00200020)
#define Write_40_to(add) (*(ftype *)(add) = 0x00400040)
#define Write_60_to(add) (*(ftype *)(add) = 0x00600060)
#define Write_70_to(add) (*(ftype *)(add) = 0x00700070)
#define Write_d0_to(add) (*(ftype *)(add) = 0x00d000d0)
#define Write_50_to_base() (*(ftype *)(fdev->base) = 0x00500050)
#define Write_60_to_base() (*(ftype *)(fdev->base) = 0x00600060)
#define Write_70_to_base() (*(ftype *)(fdev->base) = 0x00700070)
#define Write_90_to_base() (*(ftype *)(fdev->base) = 0x00900090)
#define Write_d0_to_base() (*(ftype *)(fdev->base) = 0x00d000d0)
#define Write_ff_to_base() (*(ftype *)(fdev->base) = 0x00FF00FF)
#define Read_from(add) (*(ftype *)(add))
#define Read_0000_from_base() (*(ftype *)(fdev->base+(0x00000000<<2)))
#define Read_0001_from_base() (*(ftype *)(fdev->base+(0x00000001<<2)))
#define Read_5555_from_base() (*(ftype *)(fdev->base+(0x5555<<1)))
#define Is_ff(add) (*(ftype *)(add) == 0xFFFFFFFF)
#define Is_not_ff(add) (*(ftype *)(add) != 0xFFFFFFFF)
#define Is_Equal(p1,p2) (*(ftype *)(p1) == *(ftype *)(p2))
#define Is_Not_Equal(p1,p2) (*(ftype *)(p1) != *(ftype *)(p2))
#define Not32BitAligned(ptr) ((long)ptr & 3)
/* Intel28f128_16x2_erase():
* Based on the 'snum' value, erase the appropriate sector(s).
* Return 0 if success, else -1.
*/
int
Intel28f128_16x2_erase(struct flashinfo *fdev,int snum)
{
int ret, sector;
volatile int i;
ret = 0;
/* Erase the request sector(s): */
for (sector=0; sector < fdev->sectorcnt; sector++) {
if ((!FlashProtectWindow) && (fdev->sectors[sector].protected)) {
continue;
}
if ((snum == ALL_SECTORS) || (snum == sector)) {
register ulong *lp, *lp1;
int noterased;
/* See if the sector is already erased: */
noterased = 0;
lp = (ulong *)fdev->sectors[sector].begin;
lp1 = (ulong *)((char *)lp + fdev->sectors[sector].size - 1);
while(lp <= lp1) {
if (*lp++ != 0xffffffff) {
noterased = 1;
break;
}
}
if (noterased) {
/* 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 */
for (i=0; i<SR_WAIT; i++);
continue;
}
if (rsr & ESS) { /* Should not be suspended */
ret = -1;
}
if (rsr & ES) { /* Should not have error */
ret = -1;
}
break;
}
Write_50_to_base(); /* Clear status register */
Write_ff_to_base(); /* Go to read-array mode */
}
if (ret == -1)
break;
}
}
for (i=0; i<SR_WAIT; i++);
return(ret);
}
/* EndIntel28f128_16x2_erase():
* Function place holder to determine the end of the above function.
*/
void
EndIntel28f128_16x2_erase(void)
{}
/* Intel28f128_16x2_write():
* Copy specified number of bytes from source to destination. The destination
* address is assumed to be flash space.
*/
int
Intel28f128_16x2_write(struct flashinfo *fdev,uchar *dest,uchar *src,
long bytecnt)
{
ftype stat;
volatile long cnt, buf4[1];
volatile int i, tot, ret, delta;
volatile uchar *bp4;
#ifdef FLASH_TRACE
printf("fwrite(dest=0x%lx,src=0x%lx,size=%d)\n",
(ulong)dest,(ulong)src,bytecnt);
#endif
/* If the destination address is not properly aligned, then build a
* fake source buffer using bytes below dest. Then call this function
* recursively to do that operation.
*/
if (Not32BitAligned(dest)) {
uchar *tmpdest;
delta = (long)dest & 3;
tmpdest = dest - delta;
bp4 = (uchar *)buf4;
for(i=0;delta>0;i++,delta--) {
*bp4++ = *(dest-delta);
}
for(;i<4;i++) {
if (bytecnt > 0) {
*bp4++ = *src++;
bytecnt--;
}
else {
*bp4++ = *dest;
}
dest++;
}
#ifdef FLASH_TRACE
printf("pre-align: 0x%lx = %08lx\n",(ulong)tmpdest,buf4[0]);
#endif
if (Intel28f128_16x2_write(fdev,tmpdest,(uchar *)buf4,4) == -1)
return(-1);
}
#ifdef FLASH_TRACE
printf("bc=%d\n",bytecnt);
#endif
ret = 0;
cnt = bytecnt & ~3;
for (tot=0;tot<cnt;tot+=4) {
bp4 = (uchar *)buf4;
*bp4++ = *src++; /* Just in case src is not aligned... */
*bp4++ = *src++;
*bp4++ = *src++;
*bp4++ = *src++;
#ifdef FLASH_TRACE
printf("fwrite1: 0x%lx = %08lx\n",(ulong)dest,buf4[0]);
#endif
Write_40_to(dest); /* flash program setup */
FWrite(dest, buf4); /* write value */
do {
Write_70_to_base();
stat = Read_0000_from_base();
} while ( ! (stat & WSMS_H && stat & WSMS_L) );
Write_50_to_base(); /* Clear status register */
Write_ff_to_base(); /* Go to read-array mode */
if ( Is_Not_Equal(dest, buf4)) {
ret = -1;
break;
}
dest += 4;
}
onemore:
for (;tot<cnt;tot+=4) {
bp4 = (uchar *)buf4;
*bp4++ = *src++; /* Just in case src is not aligned... */
*bp4++ = *src++;
*bp4++ = *src++;
*bp4++ = *src++;
#ifdef FLASH_TRACE
printf("fwrite2: 0x%lx = %08lx\n",(ulong)dest,buf4[0]);
#endif
Write_40_to(dest); /* flash program setup */
FWrite(dest, buf4); /* write value */
do {
Write_70_to_base();
stat = Read_0000_from_base();
} while ( ! (stat & WSMS_H && stat & WSMS_L) );
Write_50_to_base(); /* Clear status register */
Write_ff_to_base(); /* Go to read-array mode */
if (Is_Not_Equal(dest,buf4)) {
ret = -1;
break;
}
dest += 4;
}
/* If cnt != bytecnt then bytecnt is not mod4, so one more write must be
* be done. To do this, we must combine the source data with data that
* is already in the flash above the intended final address...
*/
if (cnt != bytecnt) {
bp4 = (uchar *)buf4;
for(delta=0;cnt != bytecnt;delta++,cnt++)
*bp4++ = *src++;
for(;delta != 4;delta++)
*bp4++ = *(dest+delta);
src = (uchar *)buf4;
tot = cnt-1;
goto onemore;
}
return(ret);
}
/* EndIntel28f128_16x2_write():
* Function place holder to determine the end of the above function.
*/
void
EndIntel28f128_16x2_write(void)
{}
/* Intel28f128_16x2_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 the above erase & write 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. It is only needed in systems that are
* executing the monitor out of the same device that is being updated.
*/
int
Intel28f128_16x2_ewrite(struct flashinfo *fdev,uchar *destA,uchar *srcA,
long bytecnt)
{
int sector, efail, i;
void (*reset)();
uchar *src1;
ftype val;
uchar *src, *dest;
ulong rsr;
ewrite_again:
efail = 0;
src = srcA;
dest = destA;
Write_50_to_base(); /* clear status register */
Write_ff_to_base(); /* set device in read-array mode */
/* For each sector, if it overlaps any of the destination space */
/* then erase that sector. */
for (sector = 0; sector < fdev->sectorcnt; sector++) {
if ((((uchar *)dest) > (fdev->sectors[sector].end)) ||
(((uchar *)dest+bytecnt-1) < (fdev->sectors[sector].begin))) {
continue;
}
/* Issue the ERASE 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 */
for (i=0; i<SR_WAIT; i++);
continue;
}
if (rsr & (ESS|ES)) /* Failure if suspension or error. */
efail = 1;
break;
}
Write_50_to_base(); /* Clear status register */
Write_ff_to_base(); /* Go to read-array mode */
if (efail) /* If erase failed, return -1 */
return(-1);
}
src1 = (uchar *)&val;
for(i = 0; i < bytecnt; i += DEV_WIDTH) {
/* Just in case src is not aligned... */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -