File indexing completed on 2025-05-11 08:24:04
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #include <string.h> /**< For Xil_MemCpy and memset */
0038 #ifndef __rtems__
0039 #include "xil_types.h"
0040 #endif
0041 #include "xnandpsu.h"
0042 #include "xnandpsu_bbm.h"
0043 #ifndef __rtems__
0044 #include "xil_mem.h"
0045 #endif
0046
0047
0048
0049
0050
0051
0052
0053
0054 static s32 XNandPsu_ReadBbt(XNandPsu *InstancePtr, u32 Target);
0055
0056 static s32 XNandPsu_SearchBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc,
0057 u32 Target);
0058
0059 static void XNandPsu_CreateBbt(XNandPsu *InstancePtr, u32 Target);
0060
0061 static void XNandPsu_ConvertBbt(XNandPsu *InstancePtr, u8 *Buf, u32 Target);
0062
0063 static s32 XNandPsu_WriteBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc,
0064 XNandPsu_BbtDesc *MirrorDesc, u32 Target);
0065
0066 static s32 XNandPsu_MarkBbt(XNandPsu* InstancePtr, XNandPsu_BbtDesc *Desc,
0067 u32 Target);
0068
0069 #ifndef __rtems__
0070 static s32 XNandPsu_UpdateBbt(XNandPsu *InstancePtr, u32 Target);
0071 #endif
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086 void XNandPsu_InitBbtDesc(XNandPsu *InstancePtr)
0087 {
0088 u32 Index;
0089
0090
0091 for (Index = 0U; Index < XNANDPSU_MAX_TARGETS; Index++) {
0092 InstancePtr->BbtDesc.PageOffset[Index] =
0093 XNANDPSU_BBT_DESC_PAGE_OFFSET;
0094 }
0095 if (InstancePtr->EccMode == XNANDPSU_ONDIE) {
0096 InstancePtr->BbtDesc.SigOffset = XNANDPSU_ONDIE_SIG_OFFSET;
0097 InstancePtr->BbtDesc.VerOffset = XNANDPSU_ONDIE_VER_OFFSET;
0098 } else {
0099 InstancePtr->BbtDesc.SigOffset = XNANDPSU_BBT_DESC_SIG_OFFSET;
0100 InstancePtr->BbtDesc.VerOffset = XNANDPSU_BBT_DESC_VER_OFFSET;
0101 }
0102 InstancePtr->BbtDesc.SigLength = XNANDPSU_BBT_DESC_SIG_LEN;
0103 InstancePtr->BbtDesc.MaxBlocks = XNANDPSU_BBT_DESC_MAX_BLOCKS;
0104 (void)strcpy(&InstancePtr->BbtDesc.Signature[0], "Bbt0");
0105 for (Index = 0U; Index < XNANDPSU_MAX_TARGETS; Index++) {
0106 InstancePtr->BbtDesc.Version[Index] = 0U;
0107 }
0108 InstancePtr->BbtDesc.Valid = 0U;
0109
0110
0111 if (InstancePtr->Geometry.NumTargetBlocks <= InstancePtr->
0112 BbtDesc.MaxBlocks){
0113 InstancePtr->BbtDesc.MaxBlocks = 4U;
0114 }
0115
0116
0117 for (Index = 0U; Index < XNANDPSU_MAX_TARGETS; Index++) {
0118 InstancePtr->BbtMirrorDesc.PageOffset[Index] =
0119 XNANDPSU_BBT_DESC_PAGE_OFFSET;
0120 }
0121 if (InstancePtr->EccMode == XNANDPSU_ONDIE) {
0122 InstancePtr->BbtMirrorDesc.SigOffset =
0123 XNANDPSU_ONDIE_SIG_OFFSET;
0124 InstancePtr->BbtMirrorDesc.VerOffset =
0125 XNANDPSU_ONDIE_VER_OFFSET;
0126 } else {
0127 InstancePtr->BbtMirrorDesc.SigOffset =
0128 XNANDPSU_BBT_DESC_SIG_OFFSET;
0129 InstancePtr->BbtMirrorDesc.VerOffset =
0130 XNANDPSU_BBT_DESC_VER_OFFSET;
0131 }
0132 InstancePtr->BbtMirrorDesc.SigLength = XNANDPSU_BBT_DESC_SIG_LEN;
0133 InstancePtr->BbtMirrorDesc.MaxBlocks = XNANDPSU_BBT_DESC_MAX_BLOCKS;
0134 (void)strcpy(&InstancePtr->BbtMirrorDesc.Signature[0], "1tbB");
0135 for (Index = 0U; Index < XNANDPSU_MAX_TARGETS; Index++) {
0136 InstancePtr->BbtMirrorDesc.Version[Index] = 0U;
0137 }
0138 InstancePtr->BbtMirrorDesc.Valid = 0U;
0139
0140
0141 if (InstancePtr->Geometry.NumTargetBlocks <= InstancePtr->
0142 BbtMirrorDesc.MaxBlocks){
0143 InstancePtr->BbtMirrorDesc.MaxBlocks = 4U;
0144 }
0145
0146
0147 if (InstancePtr->Geometry.BytesPerPage > 512U) {
0148
0149 InstancePtr->BbPattern.Options = XNANDPSU_BBT_SCAN_2ND_PAGE;
0150 InstancePtr->BbPattern.Offset =
0151 XNANDPSU_BB_PTRN_OFF_LARGE_PAGE;
0152 InstancePtr->BbPattern.Length =
0153 XNANDPSU_BB_PTRN_LEN_LARGE_PAGE;
0154 } else {
0155 InstancePtr->BbPattern.Options = XNANDPSU_BBT_SCAN_2ND_PAGE;
0156 InstancePtr->BbPattern.Offset =
0157 XNANDPSU_BB_PTRN_OFF_SML_PAGE;
0158 InstancePtr->BbPattern.Length =
0159 XNANDPSU_BB_PTRN_LEN_SML_PAGE;
0160 }
0161 for(Index = 0U; Index < XNANDPSU_BB_PTRN_LEN_LARGE_PAGE; Index++) {
0162 InstancePtr->BbPattern.Pattern[Index] = XNANDPSU_BB_PATTERN;
0163 }
0164 }
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177 static void XNandPsu_CreateBbt(XNandPsu *InstancePtr, u32 Target)
0178 {
0179 u32 BlockIndex;
0180 u32 PageIndex;
0181 u32 Length;
0182 u32 BlockOffset;
0183 u8 BlockShift;
0184 u32 NumPages;
0185 u32 Page;
0186 #ifdef __ICCARM__
0187 #pragma pack(push, 1)
0188 u8 Buf[XNANDPSU_MAX_SPARE_SIZE] = {0U};
0189 #pragma pack(pop)
0190 #else
0191 u8 Buf[XNANDPSU_MAX_SPARE_SIZE] __attribute__ ((aligned(64))) = {0U};
0192 #endif
0193 u32 StartBlock = Target * InstancePtr->Geometry.NumTargetBlocks;
0194 u32 NumBlocks = InstancePtr->Geometry.NumTargetBlocks;
0195 s32 Status;
0196
0197
0198 if ((InstancePtr->BbPattern.Options & XNANDPSU_BBT_SCAN_2ND_PAGE) != 0U)
0199 {
0200 NumPages = 2U;
0201 } else {
0202 NumPages = 1U;
0203 }
0204
0205 for(BlockIndex = StartBlock; BlockIndex < (StartBlock + NumBlocks);
0206 BlockIndex++) {
0207
0208 BlockOffset = BlockIndex >> XNANDPSU_BBT_BLOCK_SHIFT;
0209
0210 BlockShift = XNandPsu_BbtBlockShift(BlockIndex);
0211 Page = BlockIndex * InstancePtr->Geometry.PagesPerBlock;
0212
0213 for(PageIndex = 0U; PageIndex < NumPages; PageIndex++) {
0214 Status = XNandPsu_ReadSpareBytes(InstancePtr,
0215 (Page + PageIndex), &Buf[0]);
0216
0217 if (Status != XST_SUCCESS) {
0218
0219 InstancePtr->Bbt[BlockOffset] |=
0220 (u8)(XNANDPSU_BLOCK_FACTORY_BAD <<
0221 BlockShift);
0222 break;
0223 }
0224
0225
0226
0227
0228 for(Length = 0U; Length <
0229 InstancePtr->BbPattern.Length; Length++) {
0230 if (Buf[InstancePtr->BbPattern.Offset + Length]
0231 !=
0232 InstancePtr->BbPattern.Pattern[Length])
0233 {
0234
0235 InstancePtr->Bbt[BlockOffset] |=
0236 (u8)
0237 (XNANDPSU_BLOCK_FACTORY_BAD <<
0238 BlockShift);
0239 break;
0240 }
0241 }
0242 }
0243 }
0244 }
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259 s32 XNandPsu_ScanBbt(XNandPsu *InstancePtr)
0260 {
0261 Xil_AssertNonvoid(InstancePtr != NULL);
0262 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY)
0263
0264 s32 Status;
0265 u32 Index;
0266 u32 BbtLen;
0267
0268
0269 BbtLen = InstancePtr->Geometry.NumBlocks >>
0270 XNANDPSU_BBT_BLOCK_SHIFT;
0271 (void)memset(&InstancePtr->Bbt[0], 0, BbtLen);
0272
0273 for (Index = 0U; Index < InstancePtr->Geometry.NumTargets; Index++) {
0274
0275 if (XNandPsu_ReadBbt(InstancePtr, Index) != XST_SUCCESS) {
0276
0277 XNandPsu_CreateBbt(InstancePtr, Index);
0278
0279 Status = XNandPsu_WriteBbt(InstancePtr,
0280 &InstancePtr->BbtDesc,
0281 &InstancePtr->BbtMirrorDesc, Index);
0282 if (Status != XST_SUCCESS) {
0283 goto Out;
0284 }
0285
0286 Status = XNandPsu_WriteBbt(InstancePtr,
0287 &InstancePtr->BbtMirrorDesc,
0288 &InstancePtr->BbtDesc, Index);
0289 if (Status != XST_SUCCESS) {
0290 goto Out;
0291 }
0292
0293
0294
0295
0296 Status = XNandPsu_MarkBbt(InstancePtr,
0297 &InstancePtr->BbtDesc,
0298 Index);
0299 if (Status != XST_SUCCESS) {
0300 goto Out;
0301 }
0302 Status = XNandPsu_MarkBbt(InstancePtr,
0303 &InstancePtr->BbtMirrorDesc,
0304 Index);
0305 if (Status != XST_SUCCESS) {
0306 goto Out;
0307 }
0308 }
0309 }
0310
0311 Status = XST_SUCCESS;
0312 Out:
0313 return Status;
0314 }
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328 static void XNandPsu_ConvertBbt(XNandPsu *InstancePtr, u8 *Buf, u32 Target)
0329 {
0330 #ifndef __rtems__
0331 u32 BlockOffset;
0332 u8 BlockShift;
0333 u32 Data;
0334 u8 BlockType;
0335 u32 BlockIndex;
0336 #endif
0337 u32 BbtLen = InstancePtr->Geometry.NumTargetBlocks >>
0338 XNANDPSU_BBT_BLOCK_SHIFT;
0339 #ifdef __rtems__
0340 u32 BbtOffset = Target * InstancePtr->Geometry.NumTargetBlocks / XNANDPSU_BBT_ENTRY_NUM_BLOCKS;
0341
0342 for(u32 BbtIndex = 0; BbtIndex < BbtLen; BbtIndex++) {
0343
0344 InstancePtr->Bbt[BbtIndex + BbtOffset] = ~Buf[BbtIndex];
0345 }
0346 #else
0347 u32 StartBlock = Target * InstancePtr->Geometry.NumTargetBlocks;
0348
0349 for(BlockOffset = StartBlock; BlockOffset < (StartBlock + BbtLen);
0350 BlockOffset++) {
0351 Data = *(Buf + BlockOffset);
0352
0353 InstancePtr->Bbt[BlockOffset] = 0x0U;
0354
0355 for(BlockIndex = 0U; BlockIndex < XNANDPSU_BBT_ENTRY_NUM_BLOCKS;
0356 BlockIndex++) {
0357 BlockShift = XNandPsu_BbtBlockShift(BlockIndex);
0358 BlockType = (u8) ((Data >> BlockShift) &
0359 XNANDPSU_BLOCK_TYPE_MASK);
0360 switch(BlockType) {
0361 case XNANDPSU_FLASH_BLOCK_FAC_BAD:
0362
0363 InstancePtr->Bbt[BlockOffset] |=
0364 (u8)
0365 (XNANDPSU_BLOCK_FACTORY_BAD <<
0366 BlockShift);
0367 break;
0368 case XNANDPSU_FLASH_BLOCK_RESERVED:
0369
0370 InstancePtr->Bbt[BlockOffset] |=
0371 (u8)
0372 (XNANDPSU_BLOCK_RESERVED <<
0373 BlockShift);
0374 break;
0375 case XNANDPSU_FLASH_BLOCK_BAD:
0376
0377 InstancePtr->Bbt[BlockOffset] |=
0378 (u8)(XNANDPSU_BLOCK_BAD <<
0379 BlockShift);
0380 break;
0381 default:
0382
0383
0384
0385 break;
0386 }
0387 }
0388 }
0389 #endif
0390 }
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403 static s32 XNandPsu_ReadBbt(XNandPsu *InstancePtr, u32 Target)
0404 {
0405 u64 Offset;
0406 #ifdef __ICCARM__
0407 #pragma pack(push, 1)
0408 u8 Buf[XNANDPSU_BBT_BUF_LENGTH]= {0U};
0409 #pragma pack(pop)
0410 #else
0411 u8 Buf[XNANDPSU_BBT_BUF_LENGTH] __attribute__ ((aligned(64))) = {0U};
0412 #endif
0413 s32 Status1;
0414 s32 Status2;
0415 s32 Status;
0416 u32 BufLen;
0417
0418 XNandPsu_BbtDesc *Desc = &InstancePtr->BbtDesc;
0419 XNandPsu_BbtDesc *MirrorDesc = &InstancePtr->BbtMirrorDesc;
0420 #ifdef __rtems__
0421 BufLen = InstancePtr->Geometry.NumTargetBlocks >>
0422 #else
0423 BufLen = InstancePtr->Geometry.NumBlocks >>
0424 #endif
0425 XNANDPSU_BBT_BLOCK_SHIFT;
0426
0427 Status1 = XNandPsu_SearchBbt(InstancePtr, Desc, Target);
0428 Status2 = XNandPsu_SearchBbt(InstancePtr, MirrorDesc, Target);
0429 if ((Status1 != XST_SUCCESS) && (Status2 != XST_SUCCESS)) {
0430 #ifdef XNANDPSU_DEBUG
0431 xil_printf("%s: Bad block table not found\r\n",__func__);
0432 #endif
0433 Status = XST_FAILURE;
0434 goto Out;
0435 }
0436 #ifdef XNANDPSU_DEBUG
0437 xil_printf("%s: Bad block table found\r\n",__func__);
0438 #endif
0439
0440 if ((Desc->Valid != 0U) && (MirrorDesc->Valid != 0U)) {
0441
0442 if (Desc->Version[Target] > MirrorDesc->Version[Target]) {
0443 Offset = (u64)Desc->PageOffset[Target] *
0444 (u64)InstancePtr->Geometry.BytesPerPage;
0445 Status = XNandPsu_Read(InstancePtr, Offset, BufLen,
0446 &Buf[0]);
0447 if (Status != XST_SUCCESS) {
0448 goto Out;
0449 }
0450
0451 XNandPsu_ConvertBbt(InstancePtr, &Buf[0], Target);
0452 MirrorDesc->Version[Target] = Desc->Version[Target];
0453
0454
0455 Status = XNandPsu_WriteBbt(InstancePtr, MirrorDesc,
0456 Desc, Target);
0457 if (Status != XST_SUCCESS) {
0458 goto Out;
0459 }
0460 } else if (Desc->Version[Target] <
0461 MirrorDesc->Version[Target]) {
0462 Offset = (u64)MirrorDesc->PageOffset[Target] *
0463 (u64)InstancePtr->Geometry.BytesPerPage;
0464 Status = XNandPsu_Read(InstancePtr, Offset, BufLen,
0465 &Buf[0]);
0466 if (Status != XST_SUCCESS) {
0467 goto Out;
0468 }
0469
0470 XNandPsu_ConvertBbt(InstancePtr, &Buf[0], Target);
0471 Desc->Version[Target] = MirrorDesc->Version[Target];
0472
0473
0474 Status = XNandPsu_WriteBbt(InstancePtr, Desc,
0475 MirrorDesc, Target);
0476 if (Status != XST_SUCCESS) {
0477 goto Out;
0478 }
0479 } else {
0480
0481 Offset = (u64)Desc->PageOffset[Target] *
0482 (u64)InstancePtr->Geometry.BytesPerPage;
0483 Status = XNandPsu_Read(InstancePtr, Offset, BufLen,
0484 &Buf[0]);
0485 if (Status != XST_SUCCESS) {
0486 goto Out;
0487 }
0488
0489 XNandPsu_ConvertBbt(InstancePtr, &Buf[0], Target);
0490 }
0491 } else if (Desc->Valid != 0U) {
0492
0493 Offset = (u64)Desc->PageOffset[Target] *
0494 (u64)InstancePtr->Geometry.BytesPerPage;
0495 Status = XNandPsu_Read(InstancePtr, Offset, BufLen, &Buf[0]);
0496 if (Status != XST_SUCCESS) {
0497 goto Out;
0498 }
0499
0500 XNandPsu_ConvertBbt(InstancePtr, &Buf[0], Target);
0501 MirrorDesc->Version[Target] = Desc->Version[Target];
0502
0503
0504 Status = XNandPsu_WriteBbt(InstancePtr, MirrorDesc, Desc,
0505 Target);
0506 if (Status != XST_SUCCESS) {
0507 goto Out;
0508 }
0509 } else {
0510
0511 Offset = (u64)MirrorDesc->PageOffset[Target] *
0512 (u64)InstancePtr->Geometry.BytesPerPage;
0513 Status = XNandPsu_Read(InstancePtr, Offset, BufLen, &Buf[0]);
0514 if (Status != XST_SUCCESS) {
0515 goto Out;
0516 }
0517
0518 XNandPsu_ConvertBbt(InstancePtr, &Buf[0], Target);
0519 Desc->Version[Target] = MirrorDesc->Version[Target];
0520
0521
0522 Status = XNandPsu_WriteBbt(InstancePtr, Desc, MirrorDesc,
0523 Target);
0524 if (Status != XST_SUCCESS) {
0525 goto Out;
0526 }
0527 }
0528
0529 Status = XST_SUCCESS;
0530 Out:
0531 return Status;
0532 }
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546 static s32 XNandPsu_SearchBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc,
0547 u32 Target)
0548 {
0549 u32 StartBlock;
0550 u32 SigOffset;
0551 u32 VerOffset;
0552 u32 MaxBlocks;
0553 u32 PageOff;
0554 u32 SigLength;
0555 #ifdef __ICCARM__
0556 #pragma pack(push, 1)
0557 u8 Buf[XNANDPSU_MAX_SPARE_SIZE] = {0U};
0558 #pragma pack(pop)
0559 #else
0560 u8 Buf[XNANDPSU_MAX_SPARE_SIZE] __attribute__ ((aligned(64))) = {0U};
0561 #endif
0562 u32 Block;
0563 u32 Offset;
0564 s32 Status;
0565
0566 StartBlock = ((Target + (u32)1) *
0567 InstancePtr->Geometry.NumTargetBlocks) - (u32)1;
0568 SigOffset = Desc->SigOffset;
0569 VerOffset = Desc->VerOffset;
0570 MaxBlocks = Desc->MaxBlocks;
0571 SigLength = Desc->SigLength;
0572 #ifdef __rtems__
0573 Desc->Valid = 0;
0574 #endif
0575
0576
0577 for(Block = 0U; Block < MaxBlocks; Block++) {
0578 PageOff = (StartBlock - Block) *
0579 InstancePtr->Geometry.PagesPerBlock;
0580
0581 Status = XNandPsu_ReadSpareBytes(InstancePtr, PageOff, &Buf[0]);
0582 if (Status != XST_SUCCESS) {
0583 continue;
0584 }
0585
0586 for(Offset = 0U; Offset < SigLength; Offset++) {
0587 if (Buf[Offset + SigOffset] !=
0588 (u8)(Desc->Signature[Offset]))
0589 {
0590 break;
0591 }
0592 }
0593 if (Offset >= SigLength) {
0594
0595 Desc->PageOffset[Target] = PageOff;
0596 Desc->Version[Target] = Buf[VerOffset];
0597 Desc->Valid = 1U;
0598
0599 Status = XST_SUCCESS;
0600 goto Out;
0601 }
0602 }
0603
0604 Status = XST_FAILURE;
0605 Out:
0606 return Status;
0607 }
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622 static s32 XNandPsu_WriteBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc,
0623 XNandPsu_BbtDesc *MirrorDesc, u32 Target)
0624 {
0625 u64 Offset;
0626 u32 Block = {0U};
0627 u32 EndBlock = ((Target + (u32)1) *
0628 InstancePtr->Geometry.NumTargetBlocks) - (u32)1;
0629 #ifdef __ICCARM__
0630 #pragma pack(push, 1)
0631 u8 Buf[XNANDPSU_BBT_BUF_LENGTH]= {0U};
0632 u8 SpareBuf[XNANDPSU_MAX_SPARE_SIZE]= {0U};
0633 #pragma pack(pop)
0634 #else
0635 u8 Buf[XNANDPSU_BBT_BUF_LENGTH] __attribute__ ((aligned(64))) = {0U};
0636 u8 SpareBuf[XNANDPSU_MAX_SPARE_SIZE] __attribute__ ((aligned(64))) = {0U};
0637 #endif
0638
0639 #ifndef __rtems__
0640 u8 Mask[4] = {0x00U, 0x01U, 0x02U, 0x03U};
0641 u8 Data;
0642 u32 BlockOffset;
0643 u8 BlockShift;
0644 s32 Status;
0645 u32 BlockIndex;
0646 u32 Index;
0647 u8 BlockType;
0648 u32 BbtLen = InstancePtr->Geometry.NumBlocks >>
0649 #else
0650 s32 Status;
0651 u32 Index;
0652 u32 BbtLen = InstancePtr->Geometry.NumTargetBlocks >>
0653 #endif
0654 XNANDPSU_BBT_BLOCK_SHIFT;
0655
0656 if ((!Desc->Valid) != 0U) {
0657 for(Index = 0U; Index < Desc->MaxBlocks; Index++) {
0658 Block = (EndBlock - Index);
0659 #ifdef __rtems__
0660 if (XNandPsu_IsBlockBad(InstancePtr, Block) != XST_FAILURE) {
0661 continue;
0662 }
0663 #else
0664 BlockOffset = Block >> XNANDPSU_BBT_BLOCK_SHIFT;
0665 BlockShift = XNandPsu_BbtBlockShift(Block);
0666 BlockType = (InstancePtr->Bbt[BlockOffset] >>
0667 BlockShift) & XNANDPSU_BLOCK_TYPE_MASK;
0668 switch(BlockType)
0669 {
0670 case XNANDPSU_BLOCK_BAD:
0671 case XNANDPSU_BLOCK_FACTORY_BAD:
0672 continue;
0673 default:
0674
0675 break;
0676 }
0677 #endif
0678 Desc->PageOffset[Target] = Block *
0679 InstancePtr->Geometry.PagesPerBlock;
0680 if (Desc->PageOffset[Target] !=
0681 MirrorDesc->PageOffset[Target]) {
0682
0683 Desc->Valid = 1U;
0684 break;
0685 }
0686 }
0687
0688
0689
0690 if (Index >= Desc->MaxBlocks) {
0691 #ifdef XNANDPSU_DEBUG
0692 xil_printf("%s: Blocks unavailable for writing BBT\r\n",
0693 __func__);
0694 #endif
0695 Status = XST_FAILURE;
0696 goto Out;
0697 }
0698 } else {
0699 Block = Desc->PageOffset[Target] /
0700 InstancePtr->Geometry.PagesPerBlock;
0701 }
0702
0703 (void)memset(Buf, 0xff, BbtLen);
0704
0705 #ifdef __rtems__
0706 u32 BbtTargetOffset = BbtLen * Target;
0707
0708 for(u32 BbtIndex = 0U; BbtIndex < BbtLen; BbtIndex++) {
0709
0710 Buf[BbtIndex] = ~InstancePtr->Bbt[BbtIndex + BbtTargetOffset];
0711 }
0712 #else
0713
0714 for(BlockOffset = 0U; BlockOffset < BbtLen; BlockOffset++) {
0715 Data = InstancePtr->Bbt[BlockOffset];
0716
0717 for(BlockIndex = 0U; BlockIndex < XNANDPSU_BBT_ENTRY_NUM_BLOCKS;
0718 BlockIndex++) {
0719 BlockShift = XNandPsu_BbtBlockShift(BlockIndex);
0720 Buf[BlockOffset] &= ~(Mask[Data &
0721 XNANDPSU_BLOCK_TYPE_MASK] <<
0722 BlockShift);
0723 Data >>= XNANDPSU_BBT_BLOCK_SHIFT;
0724 }
0725 }
0726 #endif
0727
0728 #ifdef __rtems__
0729 Status = XNandPsu_EraseBlock(InstancePtr, Target,
0730 Block % InstancePtr->Geometry.NumTargetBlocks);
0731 #else
0732 Status = XNandPsu_EraseBlock(InstancePtr, 0U, Block);
0733 #endif
0734 if (Status != XST_SUCCESS) {
0735 goto Out;
0736 }
0737
0738
0739 Offset = (u64)Desc->PageOffset[Target] *
0740 (u64)InstancePtr->Geometry.BytesPerPage;
0741 Status = XNandPsu_Write(InstancePtr, Offset, BbtLen, &Buf[0]);
0742 if (Status != XST_SUCCESS) {
0743 goto Out;
0744 }
0745
0746 (void)memset(SpareBuf, 0xff, InstancePtr->Geometry.SpareBytesPerPage);
0747 Status = XNandPsu_ReadSpareBytes(InstancePtr, Desc->PageOffset[Target],
0748 &SpareBuf[0]);
0749 if (Status != XST_SUCCESS) {
0750 goto Out;
0751 }
0752
0753 (void)Xil_MemCpy(SpareBuf + Desc->SigOffset, &Desc->Signature[0],
0754 Desc->SigLength);
0755 (void)memcpy(SpareBuf + Desc->VerOffset, &Desc->Version[Target], 1U);
0756
0757 Status = XNandPsu_WriteSpareBytes(InstancePtr,
0758 Desc->PageOffset[Target], &SpareBuf[0]);
0759 if (Status != XST_SUCCESS) {
0760 goto Out;
0761 }
0762
0763 Status = XST_SUCCESS;
0764 Out:
0765 return Status;
0766 }
0767
0768
0769
0770
0771
0772
0773
0774
0775
0776
0777
0778
0779 #ifdef __rtems__
0780 s32 XNandPsu_UpdateBbt(XNandPsu *InstancePtr, u32 Target)
0781 #else
0782 static s32 XNandPsu_UpdateBbt(XNandPsu *InstancePtr, u32 Target)
0783 #endif
0784 {
0785 s32 Status;
0786 u8 Version;
0787
0788
0789 Version = InstancePtr->BbtDesc.Version[Target];
0790 InstancePtr->BbtDesc.Version[Target] = (u8)(((u16)Version +
0791 (u16)1) % (u16)256U);
0792
0793 Version = InstancePtr->BbtMirrorDesc.Version[Target];
0794 InstancePtr->BbtMirrorDesc.Version[Target] = (u8)(((u16)Version +
0795 (u16)1) % (u16)256);
0796
0797 Status = XNandPsu_WriteBbt(InstancePtr, &InstancePtr->BbtDesc,
0798 &InstancePtr->BbtMirrorDesc,
0799 Target);
0800 if (Status != XST_SUCCESS) {
0801 goto Out;
0802 }
0803
0804
0805 Status = XNandPsu_WriteBbt(InstancePtr, &InstancePtr->BbtMirrorDesc,
0806 &InstancePtr->BbtDesc,
0807 Target);
0808 if (Status != XST_SUCCESS) {
0809 goto Out;
0810 }
0811
0812 Status = XST_SUCCESS;
0813 Out:
0814 return Status;
0815 }
0816
0817
0818
0819
0820
0821
0822
0823
0824
0825
0826
0827
0828
0829 static s32 XNandPsu_MarkBbt(XNandPsu* InstancePtr, XNandPsu_BbtDesc *Desc,
0830 u32 Target)
0831 {
0832 u32 BlockIndex;
0833 u32 BlockOffset;
0834 u8 BlockShift;
0835 u8 OldVal;
0836 u8 NewVal;
0837 s32 Status;
0838 u32 UpdateBbt = 0U;
0839 u32 Index;
0840
0841
0842 BlockIndex = ((Target + (u32)1) * InstancePtr->Geometry.NumTargetBlocks) -
0843 #ifdef __rtems__
0844 Desc->MaxBlocks;
0845 #else
0846 Desc->MaxBlocks - (u32)1;
0847 #endif
0848
0849 for(Index = 0U; Index < Desc->MaxBlocks; Index++) {
0850
0851 BlockOffset = BlockIndex >> XNANDPSU_BBT_BLOCK_SHIFT;
0852 BlockShift = XNandPsu_BbtBlockShift(BlockIndex);
0853 OldVal = InstancePtr->Bbt[BlockOffset];
0854 NewVal = (u8) (OldVal | (XNANDPSU_BLOCK_RESERVED <<
0855 BlockShift));
0856 InstancePtr->Bbt[BlockOffset] = NewVal;
0857
0858 if (OldVal != NewVal) {
0859 UpdateBbt = 1U;
0860 }
0861 BlockIndex++;
0862 }
0863
0864
0865 if (UpdateBbt != 0U) {
0866 Status = XNandPsu_UpdateBbt(InstancePtr, Target);
0867 if (Status != XST_SUCCESS) {
0868 goto Out;
0869 }
0870 }
0871
0872 Status = XST_SUCCESS;
0873 Out:
0874 return Status;
0875 }
0876
0877
0878
0879
0880
0881
0882
0883
0884
0885
0886
0887
0888
0889
0890
0891 s32 XNandPsu_IsBlockBad(XNandPsu *InstancePtr, u32 Block)
0892 {
0893 Xil_AssertNonvoid(InstancePtr != NULL);
0894 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY)
0895 Xil_AssertNonvoid(Block < InstancePtr->Geometry.NumBlocks);
0896
0897 u8 Data;
0898 u8 BlockShift;
0899 u8 BlockType;
0900 u32 BlockOffset;
0901 s32 Status;
0902
0903 BlockOffset = Block >> XNANDPSU_BBT_BLOCK_SHIFT;
0904 BlockShift = XNandPsu_BbtBlockShift(Block);
0905 Data = InstancePtr->Bbt[BlockOffset];
0906 BlockType = (Data >> BlockShift) & XNANDPSU_BLOCK_TYPE_MASK;
0907
0908 if ((BlockType != XNANDPSU_BLOCK_GOOD) &&
0909 (BlockType != XNANDPSU_BLOCK_RESERVED)) {
0910 Status = XST_SUCCESS;
0911 }
0912 else {
0913 Status = XST_FAILURE;
0914 }
0915 return Status;
0916 }
0917
0918
0919
0920
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930
0931 s32 XNandPsu_MarkBlockBad(XNandPsu *InstancePtr, u32 Block)
0932 #ifdef __rtems__
0933 {
0934 return XNandPsu_MarkBlock(InstancePtr, Block, XNANDPSU_BLOCK_BAD );
0935 }
0936
0937 s32 XNandPsu_MarkBlock(XNandPsu *InstancePtr, u32 Block, u8 BlockMark)
0938 #endif
0939 {
0940 Xil_AssertNonvoid(InstancePtr != NULL);
0941 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY)
0942 Xil_AssertNonvoid(Block < InstancePtr->Geometry.NumBlocks);
0943
0944 #ifdef __rtems__
0945 BlockMark &= XNANDPSU_BLOCK_TYPE_MASK;
0946 #endif
0947
0948 u8 Data;
0949 u8 BlockShift;
0950 u32 BlockOffset;
0951 u8 OldVal;
0952 u8 NewVal;
0953 s32 Status;
0954 u32 Target;
0955
0956 Target = Block / InstancePtr->Geometry.NumTargetBlocks;
0957
0958 BlockOffset = Block >> XNANDPSU_BBT_BLOCK_SHIFT;
0959 BlockShift = XNandPsu_BbtBlockShift(Block);
0960 Data = InstancePtr->Bbt[BlockOffset];
0961
0962
0963 OldVal = Data;
0964 Data &= ~(XNANDPSU_BLOCK_TYPE_MASK << BlockShift);
0965 #ifdef __rtems__
0966 Data |= (BlockMark << BlockShift);
0967 #else
0968 Data |= (XNANDPSU_BLOCK_BAD << BlockShift);
0969 #endif
0970 NewVal = Data;
0971 InstancePtr->Bbt[BlockOffset] = Data;
0972
0973
0974 if (OldVal != NewVal) {
0975 Status = XNandPsu_UpdateBbt(InstancePtr, Target);
0976 if (Status != XST_SUCCESS) {
0977 goto Out;
0978 }
0979 }
0980
0981 Status = XST_SUCCESS;
0982 Out:
0983 return Status;
0984 }
0985
0986 #ifdef __rtems__
0987 bool XNandPsu_StageBlockMark(XNandPsu *InstancePtr, u32 Block, u8 BlockMark)
0988 {
0989 u8 BlockShift;
0990 u32 BlockOffset;
0991 u8 OldVal;
0992
0993 BlockMark &= XNANDPSU_BLOCK_TYPE_MASK;
0994
0995 BlockOffset = Block >> XNANDPSU_BBT_BLOCK_SHIFT;
0996 BlockShift = XNandPsu_BbtBlockShift(Block);
0997 OldVal = InstancePtr->Bbt[BlockOffset] >> BlockShift;
0998 OldVal &= XNANDPSU_BLOCK_TYPE_MASK;
0999 InstancePtr->Bbt[BlockOffset] &= ~(XNANDPSU_BLOCK_TYPE_MASK << BlockShift);
1000 InstancePtr->Bbt[BlockOffset] |= (BlockMark << BlockShift);
1001 return BlockMark != OldVal;
1002 }
1003 #endif
1004
1005