209 lines
5.1 KiB
C
209 lines
5.1 KiB
C
/* amd29LV800TMem.c - AMD 29LV800T Flash Memory library */
|
|
|
|
/* Copyright 1984-2004 Wind River Systems, Inc. */
|
|
/*
|
|
modification history
|
|
--------------------
|
|
01d,13may04,rec move from wrPpmc74xx bsp to drivers
|
|
01c,22jun01,g_h move sysNvRamGet & sysNvRamSet to sysNvRam.c and make
|
|
amd29LV800TWrite() , amd29LV800TEraseBlock() & amd29LV800TEraseSector()
|
|
global.
|
|
01b,23may01,pch Fix initializations of rmasks[] and lmasks[]
|
|
01a,22apr01,g_h written
|
|
*/
|
|
|
|
/*
|
|
DESCRIPTION
|
|
This library contains routines to manipulate AMD 29LV800T Flash memory.
|
|
Read and write routines are included.
|
|
|
|
The macros NV_RAM_ADRS and NV_RAM_SIZE must be defined to indicate the
|
|
address and size of the Flash memory.
|
|
|
|
This module use the visionWare flash algorithm.
|
|
|
|
The AMD 29LV800 access is BITS:16 BUS:64 BOOT:TOP ACCESS:DOUBLE.
|
|
|
|
INCLUDES: amd29LV800TMem.h
|
|
*/
|
|
|
|
/* includes */
|
|
#include "drv/mem/amd29LV800TMem.h"
|
|
#include "memLib.h"
|
|
#include "stdlib.h"
|
|
|
|
/* locals */
|
|
LOCAL void iOSync(void){ }
|
|
|
|
LOCAL const tFLASH unlock1 = {{ 0xAA00AA, 0xAA00AA }};
|
|
LOCAL const tFLASH unlock2 = {{ 0x550055, 0x550055 }};
|
|
LOCAL const tFLASH erase1 = {{ 0x800080, 0x800080 }};
|
|
LOCAL const tFLASH erase2 = {{ 0x300030, 0x300030 }};
|
|
LOCAL const tFLASH program = {{ 0xA000A0, 0xA000A0 }};
|
|
LOCAL const tFLASH readArray = {{ 0xF000F0, 0xF000F0 }};
|
|
LOCAL const tFLASH erased = {{ (UINT32)-1, (UINT32)-1 }};
|
|
|
|
LOCAL const tFLASH rmasks[] = {
|
|
{{0xffffffff, 0xffffffff}},
|
|
{{0xffffffff, 0xffffff00}},
|
|
{{0xffffffff, 0xffff0000}},
|
|
{{0xffffffff, 0xff000000}},
|
|
{{0xffffffff, 0x00000000}},
|
|
{{0xffffff00, 0x00000000}},
|
|
{{0xffff0000, 0x00000000}},
|
|
{{0xff000000, 0x00000000}},
|
|
};
|
|
LOCAL const tFLASH lmasks[] = {
|
|
{{0xffffffff, 0xffffffff}},
|
|
{{0x00ffffff, 0xffffffff}},
|
|
{{0x0000ffff, 0xffffffff}},
|
|
{{0x000000ff, 0xffffffff}},
|
|
{{0x00000000, 0xffffffff}},
|
|
{{0x00000000, 0x00ffffff}},
|
|
{{0x00000000, 0x0000ffff}},
|
|
{{0x00000000, 0x000000ff}},
|
|
};
|
|
|
|
LOCAL tBLOCK blocks[] = {
|
|
{ 15, 256 },
|
|
{ 1, 128 },
|
|
{ 2, 32 },
|
|
{ 1, 64 }
|
|
};
|
|
|
|
/***************************************************************************
|
|
*
|
|
* amd29LV800TWrite - write data to the AMD 29LV800T
|
|
*
|
|
* This routine write given data to the AMD 29LV800T FLASH device.
|
|
*
|
|
* RETURNS: Number of byte writen
|
|
*
|
|
* SEE ALSO: amd29LV800TEraseBlock(), amd29LV800TEraseSector()
|
|
*/
|
|
|
|
UINT32 amd29LV800TWrite
|
|
(
|
|
volatile UINT8 * pDest,
|
|
UINT8 * pSource,
|
|
UINT32 length
|
|
)
|
|
{
|
|
unsigned int originalLength = length;
|
|
UINT64 mask;
|
|
tFLASH data;
|
|
unsigned short n;
|
|
|
|
volatile UINT8 *pChip = (volatile UINT8 *)((unsigned int)pDest & ~(0x400000 - 1));
|
|
|
|
while (length)
|
|
{
|
|
n = ((unsigned int)pDest & (8 - 1));
|
|
mask = lmasks[n].Integer;
|
|
|
|
if ((n + length) < 8)
|
|
mask &= rmasks[n + length].Integer;
|
|
|
|
data.Integer = readUnaligned(pSource) & mask;
|
|
data.Integer |= *(UINT64 *)pDest & (~mask);
|
|
pSource += 8;
|
|
|
|
*(volatile DOUBLE *)(pChip + 0x2AAA8) = unlock1.Float;
|
|
iOSync();
|
|
*(volatile DOUBLE *)(pChip + 0x15550) = unlock2.Float;
|
|
iOSync();
|
|
*(volatile DOUBLE *)(pChip + 0x2AAA8) = program.Float;
|
|
iOSync();
|
|
*(volatile DOUBLE *)pDest = data.Float;
|
|
|
|
while (*(volatile UINT64 *)pDest != data.Integer);
|
|
|
|
pDest += 8;
|
|
length -= min(8 - n, length);
|
|
}
|
|
|
|
*(volatile DOUBLE *)(pDest - 8) = readArray.Float;
|
|
return originalLength - length;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* amd29LV800TEraseBlock - erase block in the AMD 29LV800T
|
|
*
|
|
* This routine erase a block in the AMD 29LV800T FLASH device.
|
|
*
|
|
* RETURNS: OK
|
|
*
|
|
* SEE ALSO: amd29LV800TWrite(), amd29LV800TEraseSector()
|
|
*/
|
|
|
|
UINT32 amd29LV800TEraseBlock
|
|
(
|
|
volatile UINT8 *pChip,
|
|
volatile UINT8 *pSector
|
|
)
|
|
{
|
|
*(volatile DOUBLE *)(pChip + 0x2AAA8) = unlock1.Float;
|
|
iOSync();
|
|
*(volatile DOUBLE *)(pChip + 0x15550) = unlock2.Float;
|
|
iOSync();
|
|
*(volatile DOUBLE *)(pChip + 0x2AAA8) = erase1.Float;
|
|
iOSync();
|
|
*(volatile DOUBLE *)(pChip + 0x2AAA8) = unlock1.Float;
|
|
iOSync();
|
|
*(volatile DOUBLE *)(pChip + 0x15550) = unlock2.Float;
|
|
iOSync();
|
|
*(volatile DOUBLE *)pSector = erase2.Float;
|
|
iOSync();
|
|
|
|
while (*(volatile UINT64 *)pSector != erased.Integer);
|
|
|
|
*(volatile DOUBLE *)pSector = readArray.Float;
|
|
|
|
return (OK);
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* amd29LV800TEraseSector - erase sector in the AMD 29LV800T
|
|
*
|
|
* This routine erase sector in the AMD 29LV800T FLASH device.
|
|
*
|
|
* RETURNS: OK
|
|
*
|
|
* SEE ALSO: amd29LV800TWrite(), amd29LV800TEraseBlock()
|
|
*/
|
|
|
|
UINT32 amd29LV800TEraseSector
|
|
(
|
|
volatile UINT8 *pSector
|
|
)
|
|
{
|
|
int i, j;
|
|
volatile UINT8 *pChip = (volatile UINT8 *)((unsigned int)pSector & ~(0x400000 - 1));
|
|
UINT32 n = pSector - pChip;
|
|
|
|
for (i = 0; i < BLOCKS; ++i)
|
|
{
|
|
if (n >= (blocks[i].Number * blocks[i].Size * 1024))
|
|
n -= (blocks[i].Number * blocks[i].Size * 1024);
|
|
else
|
|
break;
|
|
}
|
|
|
|
j = blocks[i].Number;
|
|
n = 0x40000;
|
|
while (n)
|
|
{
|
|
amd29LV800TEraseBlock (pChip, pSector);
|
|
pSector += blocks[i].Size * 1024;
|
|
n -= blocks[i].Size * 1024;
|
|
if (!--j)
|
|
{
|
|
j = blocks[++i].Number;
|
|
}
|
|
}
|
|
|
|
return (OK);
|
|
}
|