summaryrefslogtreecommitdiffstats
path: root/bsps/shared/dev/nand/xnandpsu_bbm.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/shared/dev/nand/xnandpsu_bbm.c')
-rw-r--r--bsps/shared/dev/nand/xnandpsu_bbm.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/bsps/shared/dev/nand/xnandpsu_bbm.c b/bsps/shared/dev/nand/xnandpsu_bbm.c
index dd59148536..40cf798965 100644
--- a/bsps/shared/dev/nand/xnandpsu_bbm.c
+++ b/bsps/shared/dev/nand/xnandpsu_bbm.c
@@ -62,7 +62,9 @@ static s32 XNandPsu_WriteBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc,
static s32 XNandPsu_MarkBbt(XNandPsu* InstancePtr, XNandPsu_BbtDesc *Desc,
u32 Target);
+#ifndef __rtems__
static s32 XNandPsu_UpdateBbt(XNandPsu *InstancePtr, u32 Target);
+#endif
/************************** Variable Definitions *****************************/
@@ -321,13 +323,23 @@ Out:
******************************************************************************/
static void XNandPsu_ConvertBbt(XNandPsu *InstancePtr, u8 *Buf, u32 Target)
{
+#ifndef __rtems__
u32 BlockOffset;
u8 BlockShift;
u32 Data;
u8 BlockType;
u32 BlockIndex;
+#endif
u32 BbtLen = InstancePtr->Geometry.NumTargetBlocks >>
XNANDPSU_BBT_BLOCK_SHIFT;
+#ifdef __rtems__
+ u32 BbtOffset = Target * InstancePtr->Geometry.NumTargetBlocks / XNANDPSU_BBT_ENTRY_NUM_BLOCKS;
+
+ for(u32 BbtIndex = 0; BbtIndex < BbtLen; BbtIndex++) {
+ /* Invert the byte to convert from in-flash BBT to in-memory BBT */
+ InstancePtr->Bbt[BbtIndex + BbtOffset] = ~Buf[BbtIndex];
+ }
+#else
u32 StartBlock = Target * InstancePtr->Geometry.NumTargetBlocks;
for(BlockOffset = StartBlock; BlockOffset < (StartBlock + BbtLen);
@@ -370,6 +382,7 @@ static void XNandPsu_ConvertBbt(XNandPsu *InstancePtr, u8 *Buf, u32 Target)
}
}
}
+#endif
}
/*****************************************************************************/
@@ -400,7 +413,11 @@ static s32 XNandPsu_ReadBbt(XNandPsu *InstancePtr, u32 Target)
XNandPsu_BbtDesc *Desc = &InstancePtr->BbtDesc;
XNandPsu_BbtDesc *MirrorDesc = &InstancePtr->BbtMirrorDesc;
+#ifdef __rtems__
+ BufLen = InstancePtr->Geometry.NumTargetBlocks >>
+#else
BufLen = InstancePtr->Geometry.NumBlocks >>
+#endif
XNANDPSU_BBT_BLOCK_SHIFT;
/* Search the Bad Block Table(BBT) in flash */
Status1 = XNandPsu_SearchBbt(InstancePtr, Desc, Target);
@@ -548,6 +565,9 @@ static s32 XNandPsu_SearchBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc,
VerOffset = Desc->VerOffset;
MaxBlocks = Desc->MaxBlocks;
SigLength = Desc->SigLength;
+#ifdef __rtems__
+ Desc->Valid = 0;
+#endif
/* Read the last 4 blocks for Bad Block Table(BBT) signature */
for(Block = 0U; Block < MaxBlocks; Block++) {
@@ -612,6 +632,7 @@ static s32 XNandPsu_WriteBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc,
u8 SpareBuf[XNANDPSU_MAX_SPARE_SIZE] __attribute__ ((aligned(64))) = {0U};
#endif
+#ifndef __rtems__
u8 Mask[4] = {0x00U, 0x01U, 0x02U, 0x03U};
u8 Data;
u32 BlockOffset;
@@ -621,11 +642,21 @@ static s32 XNandPsu_WriteBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc,
u32 Index;
u8 BlockType;
u32 BbtLen = InstancePtr->Geometry.NumBlocks >>
+#else
+ s32 Status;
+ u32 Index;
+ u32 BbtLen = InstancePtr->Geometry.NumTargetBlocks >>
+#endif
XNANDPSU_BBT_BLOCK_SHIFT;
/* Find a valid block to write the Bad Block Table(BBT) */
if ((!Desc->Valid) != 0U) {
for(Index = 0U; Index < Desc->MaxBlocks; Index++) {
Block = (EndBlock - Index);
+#ifdef __rtems__
+ if (XNandPsu_IsBlockBad(InstancePtr, Block) != XST_FAILURE) {
+ continue;
+ }
+#else
BlockOffset = Block >> XNANDPSU_BBT_BLOCK_SHIFT;
BlockShift = XNandPsu_BbtBlockShift(Block);
BlockType = (InstancePtr->Bbt[BlockOffset] >>
@@ -639,6 +670,7 @@ static s32 XNandPsu_WriteBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc,
/* Good Block */
break;
}
+#endif
Desc->PageOffset[Target] = Block *
InstancePtr->Geometry.PagesPerBlock;
if (Desc->PageOffset[Target] !=
@@ -666,6 +698,14 @@ static s32 XNandPsu_WriteBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc,
/* Convert the memory based BBT to flash based table */
(void)memset(Buf, 0xff, BbtLen);
+#ifdef __rtems__
+ u32 BbtTargetOffset = BbtLen * Target;
+ /* Loop through the BBT entries */
+ for(u32 BbtIndex = 0U; BbtIndex < BbtLen; BbtIndex++) {
+ /* Invert byte to convert from in-memory BBT to in-flash BBT */
+ Buf[BbtIndex] = ~InstancePtr->Bbt[BbtIndex + BbtTargetOffset];
+ }
+#else
/* Loop through the number of blocks */
for(BlockOffset = 0U; BlockOffset < BbtLen; BlockOffset++) {
Data = InstancePtr->Bbt[BlockOffset];
@@ -679,8 +719,14 @@ static s32 XNandPsu_WriteBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc,
Data >>= XNANDPSU_BBT_BLOCK_SHIFT;
}
}
+#endif
/* Write the Bad Block Table(BBT) to flash */
+#ifdef __rtems__
+ Status = XNandPsu_EraseBlock(InstancePtr, Target,
+ Block % InstancePtr->Geometry.NumTargetBlocks);
+#else
Status = XNandPsu_EraseBlock(InstancePtr, 0U, Block);
+#endif
if (Status != XST_SUCCESS) {
goto Out;
}
@@ -726,7 +772,11 @@ Out:
* - XST_FAILURE if fail.
*
******************************************************************************/
+#ifdef __rtems__
+s32 XNandPsu_UpdateBbt(XNandPsu *InstancePtr, u32 Target)
+#else
static s32 XNandPsu_UpdateBbt(XNandPsu *InstancePtr, u32 Target)
+#endif
{
s32 Status;
u8 Version;
@@ -786,7 +836,11 @@ static s32 XNandPsu_MarkBbt(XNandPsu* InstancePtr, XNandPsu_BbtDesc *Desc,
/* Mark the last four blocks as Reserved */
BlockIndex = ((Target + (u32)1) * InstancePtr->Geometry.NumTargetBlocks) -
+#ifdef __rtems__
+ Desc->MaxBlocks;
+#else
Desc->MaxBlocks - (u32)1;
+#endif
for(Index = 0U; Index < Desc->MaxBlocks; Index++) {
@@ -871,11 +925,22 @@ s32 XNandPsu_IsBlockBad(XNandPsu *InstancePtr, u32 Block)
*
******************************************************************************/
s32 XNandPsu_MarkBlockBad(XNandPsu *InstancePtr, u32 Block)
+#ifdef __rtems__
+{
+ return XNandPsu_MarkBlock(InstancePtr, Block, XNANDPSU_BLOCK_BAD );
+}
+
+s32 XNandPsu_MarkBlock(XNandPsu *InstancePtr, u32 Block, u8 BlockMark)
+#endif
{
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY)
Xil_AssertNonvoid(Block < InstancePtr->Geometry.NumBlocks);
+#ifdef __rtems__
+ BlockMark &= XNANDPSU_BLOCK_TYPE_MASK;
+#endif
+
u8 Data;
u8 BlockShift;
u32 BlockOffset;
@@ -893,7 +958,11 @@ s32 XNandPsu_MarkBlockBad(XNandPsu *InstancePtr, u32 Block)
/* Mark the block as bad in the RAM based Bad Block Table */
OldVal = Data;
Data &= ~(XNANDPSU_BLOCK_TYPE_MASK << BlockShift);
+#ifdef __rtems__
+ Data |= (BlockMark << BlockShift);
+#else
Data |= (XNANDPSU_BLOCK_BAD << BlockShift);
+#endif
NewVal = Data;
InstancePtr->Bbt[BlockOffset] = Data;
@@ -909,4 +978,24 @@ s32 XNandPsu_MarkBlockBad(XNandPsu *InstancePtr, u32 Block)
Out:
return Status;
}
+
+#ifdef __rtems__
+bool XNandPsu_StageBlockMark(XNandPsu *InstancePtr, u32 Block, u8 BlockMark)
+{
+ u8 BlockShift;
+ u32 BlockOffset;
+ u8 OldVal;
+
+ BlockMark &= XNANDPSU_BLOCK_TYPE_MASK;
+
+ BlockOffset = Block >> XNANDPSU_BBT_BLOCK_SHIFT;
+ BlockShift = XNandPsu_BbtBlockShift(Block);
+ OldVal = InstancePtr->Bbt[BlockOffset] >> BlockShift;
+ OldVal &= XNANDPSU_BLOCK_TYPE_MASK;
+ InstancePtr->Bbt[BlockOffset] &= ~(XNANDPSU_BLOCK_TYPE_MASK << BlockShift);
+ InstancePtr->Bbt[BlockOffset] |= (BlockMark << BlockShift);
+ return BlockMark != OldVal;
+}
+#endif
+
/** @} */