📄 intel28f256_8x1.c
字号:
/* intel28f256_8x1.c:
* Support for a single INTEL 28f256 device configured in 8-bit mode.
*/
#include "config.h"
#if INCLUDE_FLASH
#include "stddefs.h"
#include "genlib.h"
#include "cpu.h"
#include "flash.h"
#include "intel28f256_8x1.h"
#define SR_WAIT 50000
/* Strata flash buffer info:
* Each device can buffer 32 bytes.
* In this configuration we have 4 devices in parallel;
* hence, 128 byte buffering...
*/
#define BUFFER_SIZE 32
#define BUFFER_ALIGN 0x1f
#define DEV_WIDTH 1
#define WSMS 0x80
#define ESS 0x40
#define ES 0x20
#define PSS 0x04
#define PS 0x10
#define WBS 0x80
#define ftype volatile unsigned char
/* Manufacturer and device id... */
#define DEVICE_28F320J3 0x00890016 /* 32 Mbit (3 volt strata) */
#define DEVICE_28F640J3 0x00890017 /* 64 Mbit (3 volt strata) */
#define DEVICE_28F128J3 0x00890018 /* 128 Mbit (3 volt strata) */
#define DEVICE_28F256J3 0x0089001d /* 256 Mbit (3 volt strata) */
/* INTEL_STRATA-Specific Macros...
*/
#define STRATACMD_READARRAY() (*(ftype *)(fdev->base) = 0xff)
#define STRATACMD_PROTPROGRAM() (*(ftype *)(fdev->base) = 0xc0)
#define STRATACMD_READID() (*(ftype *)(fdev->base) = 0x90)
#define STRATACMD_READSTATUS() (*(ftype *)(fdev->base) = 0x70)
#define STRATACMD_LOCKBIT() (*(ftype *)(fdev->base) = 0x60)
#define STRATACMD_CLEARSTATUS() (*(ftype *)(fdev->base) = 0x50)
#define STRATACMD_PROGRAM(addr) (*(ftype *)(addr) = 0x40)
#define STRATACMD_WRITETOBUFFER(addr) (*(ftype *)(addr) = 0xe8)
#define STRATACMD_CONFIRM(addr) (*(ftype *)(addr) = 0xd0)
#define STRATACMD_BLOCKERASE(addr) (*(ftype *)(addr) = 0x20)
#define STRATACMD_SETLOCKCONFIRM(addr) (*(ftype *)(addr) = 0x01)
/* General Macros...
*/
#define FLASH_READ(addr) (*(ftype *)(addr))
#define FLASH_READBASE() (*(ftype *)(fdev->base))
#define FLASH_READ_MANUFACTURER() (*(ftype *)(fdev->base))
//#define FLASH_READ_DEVICEID() (*(ftype *)(fdev->base+8))
#define FLASH_READ_BLOCKSTATUS(sbase) (*(ftype *)(sbase+4))
#define FLASH_WRITE(to,frm) (*(ftype *)(to) = *(ftype *)(frm))
#define WAIT_FOR_DATA(add,data) \
{ \
volatile int timeout = FLASH_LOOP_TIMEOUT; \
while(*(ftype *)add != *(ftype *)data) { \
if (--timeout <= 0) { \
STRATACMD_READARRAY(); \
return(-2); \
} \
WATCHDOG_MACRO; \
} \
}
#define WAIT_FOR_FF(add) \
{ \
volatile int timeout = FLASH_LOOP_TIMEOUT; \
while(*(ftype *)add != 0xff) { \
if (--timeout <= 0) { \
STRATACMD_READARRAY(); \
return(-3); \
} \
WATCHDOG_MACRO; \
} \
}
#define WAIT_FOR_WSMS_READY() \
{ \
volatile int timeout = FLASH_LOOP_TIMEOUT; \
while((*(ftype *)(fdev->base) & WSMS) != WSMS) { \
if (--timeout <= 0) { \
STRATACMD_READARRAY(); \
return(-4); \
} \
WATCHDOG_MACRO; \
} \
}
#define ERASE_FAILURE() (*(ftype *)(fdev->base) & (ESS|ES|PS))
/* Intel28f256_8x1_erase():
* Erase the sector specified by snum.
* Return 0 if success, else negative to indicate some failure.
*/
int
Intel28f256_8x1_erase(struct flashinfo *fdev,int snum)
{
STRATACMD_CLEARSTATUS();
/* Issue the setup/confirm sequence: */
STRATACMD_BLOCKERASE(fdev->base);
STRATACMD_CONFIRM(fdev->sectors[snum].begin);
/* Wait for sector erase to complete by polling RSR... */
WAIT_FOR_WSMS_READY();
if (ERASE_FAILURE()) {
STRATACMD_READARRAY();
return(-1);
}
STRATACMD_READARRAY();
WAIT_FOR_FF(fdev->sectors[snum].begin);
return(0);
}
/* EndIntel28f256_8x1_erase():
* Function place holder to determine the end of the above function.
*/
void
EndIntel28f256_8x1_erase(void)
{}
int
Intel28f256_8x1_write(struct flashinfo *fdev,uchar *dest,uchar *src, long bytecnt)
{
volatile int tot;
ulong bcount;
int i, j, giveup, aligntot, size;
volatile uchar buf[BUFFER_SIZE], *aligndest, *block, *destend;
/* The write buffer can only be used on (32)-byte blocks; hence, the
* low 5 bits of the destination must be zero at the start of a
* buffer write. This means that we must align the destination
* address on this boundary. To do this, we decrement the destination
* address until the alignment is reached, then load that space with
* the same data that is already there.
*/
destend = dest + bytecnt;
aligntot = 0;
aligndest = dest;
while(((ulong)aligndest & BUFFER_ALIGN) != 0)
{
aligndest--;
aligntot++;
bytecnt++;
}
tot = 0;
while(tot < bytecnt)
{
size = bytecnt - tot;
if (size > BUFFER_SIZE) size = BUFFER_SIZE;
block = aligndest;
/* Copy buffer's worth of data into local buffer just in
* case the source is this flash device.
*/
for(i = 0; i < size; i++)
{
if (aligndest < dest)
buf[i] = *aligndest++;
else
buf[i] = *src++;
}
j = 0;
while (size < BUFFER_SIZE)
{
size++;
buf[i++] = destend[j++];
}
aligndest = block;
/* Issue request to write to the buffer, then poll extended
* status register to wait for availability.
*/
giveup = SR_WAIT;
do {
STRATACMD_WRITETOBUFFER(aligndest);
giveup--;
} while (((FLASH_READ(aligndest) & WBS) != WBS) && (giveup > 0));
if (giveup == 0) {
STRATACMD_READARRAY();
return(-1);
}
/* Write the byte count. Notice that the bytecount fed to the
* device is one less than the actual count.*/
bcount = size-1;
*(ftype *)block = bcount;
/* Write the buffer data...
*/
for(i = 0; i < size; i++)
{
FLASH_WRITE(aligndest,(&buf[i]));
aligndest+=1;
}
STRATACMD_CONFIRM(block);
tot += size;
giveup = SR_WAIT;
do {
STRATACMD_READSTATUS();
giveup--;
} while(((FLASH_READBASE() & WSMS) != WSMS) && (giveup > 0));
if (giveup == 0) {
STRATACMD_READARRAY();
return(-2);
}
STRATACMD_READARRAY();
}
return(0);
}
/* EndIntel28f256_8x1_write():
* Function place holder to determine the end of the above function.
*/
void
EndIntel28f256_8x1_write(void)
{}
/* Intel28f256_8x1_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
Intel28f256_8x1_ewrite(struct flashinfo *fdev,uchar *destA,uchar *srcA,
long bytecnt)
{
ulong addr;
volatile int sector, i;
void (*reset)();
volatile uchar *src, *dest;
src = srcA;
dest = destA;
STRATACMD_CLEARSTATUS();
/* 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;
}
addr = (ulong)(fdev->sectors[sector].begin);
/* Issue the ERASE setup/confirm sequence: */
STRATACMD_BLOCKERASE(addr);
STRATACMD_CONFIRM(addr);
/* Wait for sector erase to complete by polling RSR... */
WAIT_FOR_WSMS_READY();
STRATACMD_READARRAY();
WAIT_FOR_FF(addr);
}
for(i = 0; i < bytecnt; i++)
{
/* Flash program setup command */
STRATACMD_PROGRAM(dest);
/* Write the value */
FLASH_WRITE(dest,src);
WAIT_FOR_WSMS_READY();
STRATACMD_READARRAY();
WAIT_FOR_DATA(dest,src);
++dest;
++src;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -