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
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099 #include "xnandpsu.h"
0100 #include "xnandpsu_bbm.h"
0101 #ifndef __rtems__
0102 #include "sleep.h"
0103 #include "xil_mem.h"
0104 #endif
0105
0106
0107 static const XNandPsu_EccMatrix EccMatrix[] = {
0108
0109 {XNANDPSU_PAGE_SIZE_512, 9U, 1U, XNANDPSU_HAMMING, 0x20DU, 0x3U},
0110 {XNANDPSU_PAGE_SIZE_512, 9U, 4U, XNANDPSU_BCH, 0x209U, 0x7U},
0111 {XNANDPSU_PAGE_SIZE_512, 9U, 8U, XNANDPSU_BCH, 0x203U, 0xDU},
0112
0113 {XNANDPSU_PAGE_SIZE_2K, 9U, 1U, XNANDPSU_HAMMING, 0x834U, 0xCU},
0114 {XNANDPSU_PAGE_SIZE_2K, 9U, 4U, XNANDPSU_BCH, 0x826U, 0x1AU},
0115 {XNANDPSU_PAGE_SIZE_2K, 9U, 8U, XNANDPSU_BCH, 0x80cU, 0x34U},
0116 {XNANDPSU_PAGE_SIZE_2K, 9U, 12U, XNANDPSU_BCH, 0x822U, 0x4EU},
0117 {XNANDPSU_PAGE_SIZE_2K, 10U, 24U, XNANDPSU_BCH, 0x81cU, 0x54U},
0118
0119 {XNANDPSU_PAGE_SIZE_4K, 9U, 1U, XNANDPSU_HAMMING, 0x1068U, 0x18U},
0120 {XNANDPSU_PAGE_SIZE_4K, 9U, 4U, XNANDPSU_BCH, 0x104cU, 0x34U},
0121 {XNANDPSU_PAGE_SIZE_4K, 9U, 8U, XNANDPSU_BCH, 0x1018U, 0x68U},
0122 {XNANDPSU_PAGE_SIZE_4K, 9U, 12U, XNANDPSU_BCH, 0x1044U, 0x9CU},
0123 {XNANDPSU_PAGE_SIZE_4K, 10U, 24U, XNANDPSU_BCH, 0x1038U, 0xA8U},
0124
0125 {XNANDPSU_PAGE_SIZE_8K, 9U, 1U, XNANDPSU_HAMMING, 0x20d0U, 0x30U},
0126 {XNANDPSU_PAGE_SIZE_8K, 9U, 4U, XNANDPSU_BCH, 0x2098U, 0x68U},
0127 {XNANDPSU_PAGE_SIZE_8K, 9U, 8U, XNANDPSU_BCH, 0x2030U, 0xD0U},
0128 {XNANDPSU_PAGE_SIZE_8K, 9U, 12U, XNANDPSU_BCH, 0x2088U, 0x138U},
0129 {XNANDPSU_PAGE_SIZE_8K, 10U, 24U, XNANDPSU_BCH, 0x2070U, 0x150U},
0130
0131 {XNANDPSU_PAGE_SIZE_16K, 9U, 1U, XNANDPSU_HAMMING, 0x4460U, 0x60U},
0132 {XNANDPSU_PAGE_SIZE_16K, 9U, 4U, XNANDPSU_BCH, 0x43f0U, 0xD0U},
0133 {XNANDPSU_PAGE_SIZE_16K, 9U, 8U, XNANDPSU_BCH, 0x4320U, 0x1A0U},
0134 {XNANDPSU_PAGE_SIZE_16K, 9U, 12U, XNANDPSU_BCH, 0x4250U, 0x270U},
0135 {XNANDPSU_PAGE_SIZE_16K, 10U, 24U, XNANDPSU_BCH, 0x4220U, 0x2A0U}
0136 };
0137
0138
0139
0140
0141
0142
0143 static s32 XNandPsu_FlashInit(XNandPsu *InstancePtr);
0144
0145 static s32 XNandPsu_InitGeometry(XNandPsu *InstancePtr, OnfiParamPage *Param);
0146
0147 static void XNandPsu_InitFeatures(XNandPsu *InstancePtr, OnfiParamPage *Param);
0148
0149 static void XNandPsu_InitDataInterface(XNandPsu *InstancePtr, OnfiParamPage *Param);
0150
0151 static void XNandPsu_InitTimingMode(XNandPsu *InstancePtr, OnfiParamPage *Param);
0152
0153 static s32 XNandPsu_PollRegTimeout(XNandPsu *InstancePtr, u32 RegOffset,
0154 u32 Mask, u32 Timeout);
0155
0156 static void XNandPsu_SetPktSzCnt(XNandPsu *InstancePtr, u32 PktSize,
0157 u32 PktCount);
0158
0159 static void XNandPsu_SetPageColAddr(XNandPsu *InstancePtr, u32 Page, u16 Col);
0160
0161 static void XNandPsu_SetPageSize(XNandPsu *InstancePtr);
0162
0163 static void XNandPsu_SelectChip(XNandPsu *InstancePtr, u32 Target);
0164
0165 static s32 XNandPsu_OnfiReset(XNandPsu *InstancePtr, u32 Target);
0166
0167 static s32 XNandPsu_OnfiReadStatus(XNandPsu *InstancePtr, u32 Target,
0168 u16 *OnfiStatus);
0169
0170 static s32 XNandPsu_OnfiReadId(XNandPsu *InstancePtr, u32 Target, u8 IdAddr,
0171 u32 IdLen, u8 *Buf);
0172
0173 static s32 XNandPsu_OnfiReadParamPage(XNandPsu *InstancePtr, u32 Target,
0174 u8 *Buf);
0175
0176 static s32 XNandPsu_ProgramPage(XNandPsu *InstancePtr, u32 Target, u32 Page,
0177 u32 Col, u8 *Buf);
0178
0179 static s32 XNandPsu_ReadPage(XNandPsu *InstancePtr, u32 Target, u32 Page,
0180 u32 Col, u8 *Buf);
0181
0182 static s32 XNandPsu_CheckOnDie(XNandPsu *InstancePtr);
0183
0184 static void XNandPsu_SetEccAddrSize(XNandPsu *InstancePtr);
0185
0186 static s32 XNandPsu_ChangeReadColumn(XNandPsu *InstancePtr, u32 Target,
0187 u32 Col, u32 PktSize, u32 PktCount,
0188 u8 *Buf);
0189
0190 static s32 XNandPsu_ChangeWriteColumn(XNandPsu *InstancePtr, u32 Target,
0191 u32 Col, u32 PktSize, u32 PktCount,
0192 u8 *Buf);
0193
0194 static s32 XNandPsu_InitExtEcc(XNandPsu *InstancePtr, OnfiExtPrmPage *ExtPrm);
0195
0196 static s32 XNandPsu_Data_ReadWrite(XNandPsu *InstancePtr, u8* Buf, u32 PktCount,
0197 u32 PktSize, u32 Operation, u8 DmaMode);
0198
0199 static s32 XNandPsu_WaitFor_Transfer_Complete(XNandPsu *InstancePtr);
0200
0201 static s32 XNandPsu_Device_Ready(XNandPsu *InstancePtr, u32 Target);
0202
0203 static void XNandPsu_Fifo_Read(XNandPsu *InstancePtr, u8* Buf, u32 Size);
0204
0205 static void XNandPsu_Fifo_Write(XNandPsu *InstancePtr, u8* Buf, u32 Size);
0206
0207 static void XNandPsu_Update_DmaAddr(XNandPsu *InstancePtr, u8* Buf);
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227 s32 XNandPsu_CfgInitialize(XNandPsu *InstancePtr, XNandPsu_Config *ConfigPtr,
0228 u32 EffectiveAddr)
0229 {
0230
0231 Xil_AssertNonvoid(InstancePtr != NULL);
0232 Xil_AssertNonvoid(ConfigPtr != NULL);
0233
0234 s32 Status = XST_FAILURE;
0235
0236
0237 InstancePtr->Config.DeviceId = ConfigPtr->DeviceId;
0238 InstancePtr->Config.BaseAddress = EffectiveAddr;
0239 InstancePtr->Config.IsCacheCoherent = ConfigPtr->IsCacheCoherent;
0240 #if defined (XCLOCKING)
0241 InstancePtr->Config.RefClk = ConfigPtr->RefClk;
0242 #endif
0243
0244 InstancePtr->Mode = XNANDPSU_POLLING;
0245
0246 InstancePtr->DmaMode = XNANDPSU_MDMA;
0247 InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
0248
0249 #ifdef __rtems__
0250
0251 InstancePtr->PartialDataPageIndex = XNANDPSU_PAGE_CACHE_UNAVAILABLE;
0252 #endif
0253
0254
0255 Status = XNandPsu_FlashInit(InstancePtr);
0256 if (Status != XST_SUCCESS) {
0257 #ifdef XNANDPSU_DEBUG
0258 xil_printf("%s: Flash init failed\r\n",__func__);
0259 #endif
0260 goto Out;
0261 }
0262
0263 if (InstancePtr->Features.EzNand != 0U) {
0264 InstancePtr->EccMode = XNANDPSU_EZNAND;
0265 } else if (InstancePtr->Features.OnDie != 0U) {
0266 InstancePtr->EccMode = XNANDPSU_ONDIE;
0267 } else {
0268 InstancePtr->EccMode = XNANDPSU_HWECC;
0269 }
0270
0271
0272 InstancePtr->Ecc_Stat_PerPage_flips = 0U;
0273 InstancePtr->Ecc_Stats_total_flips = 0U;
0274
0275
0276
0277
0278
0279
0280 XNandPsu_InitBbtDesc(InstancePtr);
0281 Status = XNandPsu_ScanBbt(InstancePtr);
0282 if (Status != XST_SUCCESS) {
0283 #ifdef XNANDPSU_DEBUG
0284 xil_printf("%s: BBT scan failed\r\n",__func__);
0285 #endif
0286 goto Out;
0287 }
0288
0289 #ifdef __rtems__
0290
0291 InstancePtr->PartialDataPageIndex = XNANDPSU_PAGE_CACHE_NONE;
0292 #endif
0293 Out:
0294 return Status;
0295 }
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311 static s32 XNandPsu_FlashInit(XNandPsu *InstancePtr)
0312 {
0313 u32 Target;
0314 u8 Id[ONFI_SIG_LEN] = {0U};
0315 OnfiParamPage Param[ONFI_MND_PRM_PGS] = {0U};
0316 s32 Status = XST_FAILURE;
0317 u32 Index;
0318 u32 Crc;
0319 u32 PrmPgOff;
0320 u32 PrmPgLen;
0321 #ifdef __ICCARM__
0322 #pragma pack(push, 1)
0323 OnfiExtPrmPage ExtParam = {0U};
0324 #pragma pack(pop)
0325 #else
0326 OnfiExtPrmPage ExtParam __attribute__ ((aligned(64))) = {0U};
0327 #endif
0328
0329
0330 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
0331 XNANDPSU_DATA_INTF_OFFSET, 0U);
0332
0333
0334 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
0335 XNANDPSU_DMA_BUF_BND_OFFSET, 0U);
0336
0337 for (Target = 0U; Target < XNANDPSU_MAX_TARGETS; Target++) {
0338
0339 Status = XNandPsu_OnfiReset(InstancePtr, Target);
0340 if (Status != XST_SUCCESS) {
0341 goto Out;
0342 }
0343
0344 Status = XNandPsu_OnfiReadId(InstancePtr, Target,
0345 ONFI_READ_ID_ADDR,
0346 ONFI_SIG_LEN,
0347 (u8 *)&Id[0]);
0348 if (Status != XST_SUCCESS) {
0349 goto Out;
0350 }
0351
0352 if (!IS_ONFI(Id)) {
0353 if (Target == 0U) {
0354 #ifdef XNANDPSU_DEBUG
0355 xil_printf("%s: ONFI ID doesn't match\r\n",
0356 __func__);
0357 #endif
0358 Status = XST_FAILURE;
0359 goto Out;
0360 }
0361 }
0362
0363
0364 Status = XNandPsu_OnfiReadParamPage(InstancePtr,
0365 Target, (u8 *)&Param[0]);
0366 if (Status != XST_SUCCESS) {
0367 goto Out;
0368 }
0369 for(Index = 0U; Index < ONFI_MND_PRM_PGS; Index++){
0370
0371 Crc = XNandPsu_OnfiParamPageCrc((u8*)&Param[Index], 0U,
0372 ONFI_CRC_LEN);
0373 if (Crc != Param[Index].Crc) {
0374 #ifdef XNANDPSU_DEBUG
0375 xil_printf("%s: ONFI parameter page (%d) crc check failed\r\n",
0376 __func__, Index);
0377 #endif
0378 continue;
0379 } else {
0380 break;
0381 }
0382 }
0383 if (Index >= ONFI_MND_PRM_PGS) {
0384 Status = XST_FAILURE;
0385 goto Out;
0386 }
0387
0388 if (Target == 0U) {
0389 Status = XNandPsu_InitGeometry(InstancePtr, &Param[Index]);
0390 if (Status != XST_SUCCESS) {
0391 goto Out;
0392 }
0393 XNandPsu_InitDataInterface(InstancePtr, &Param[Index]);
0394 XNandPsu_InitTimingMode(InstancePtr, &Param[Index]);
0395 XNandPsu_InitFeatures(InstancePtr, &Param[Index]);
0396 if ((!InstancePtr->Features.EzNand) != 0U) {
0397 Status =XNandPsu_CheckOnDie(InstancePtr);
0398 if (Status != XST_SUCCESS) {
0399 InstancePtr->Features.OnDie = 0U;
0400 }
0401 }
0402 if ((InstancePtr->Geometry.NumBitsECC == 0xFFU) &&
0403 (InstancePtr->Features.ExtPrmPage != 0U)) {
0404
0405 PrmPgLen = (u32)Param[Index].ExtParamPageLen * 16U;
0406 PrmPgOff = (u32)((u32)Param[Index].NumOfParamPages *
0407 ONFI_PRM_PG_LEN) + (Index * (u32)PrmPgLen);
0408
0409 Status = XNandPsu_ChangeReadColumn(
0410 InstancePtr, Target,
0411 PrmPgOff, PrmPgLen, 1U,
0412 (u8 *)(void *)&ExtParam);
0413 if (Status != XST_SUCCESS) {
0414 goto Out;
0415 }
0416
0417 Crc = XNandPsu_OnfiParamPageCrc(
0418 (u8 *)&ExtParam,
0419 2U, PrmPgLen);
0420 if (Crc != ExtParam.Crc) {
0421 #ifdef XNANDPSU_DEBUG
0422 xil_printf("%s: ONFI extended parameter page (%d) crc check failed\r\n",
0423 __func__, Index);
0424 #endif
0425 Status = XST_FAILURE;
0426 goto Out;
0427 }
0428
0429 Status = XNandPsu_InitExtEcc(
0430 InstancePtr,
0431 &ExtParam);
0432 if (Status != XST_SUCCESS) {
0433 #ifdef XNANDPSU_DEBUG
0434 xil_printf("%s: Init extended ecc failed\r\n",__func__);
0435 #endif
0436 goto Out;
0437 }
0438 }
0439
0440 XNandPsu_SetEccAddrSize(InstancePtr);
0441 }
0442 InstancePtr->Geometry.NumTargets++;
0443 }
0444
0445 InstancePtr->Geometry.NumPages = InstancePtr->Geometry.NumTargets *
0446 InstancePtr->Geometry.NumTargetPages;
0447 InstancePtr->Geometry.NumBlocks = InstancePtr->Geometry.NumTargets *
0448 InstancePtr->Geometry.NumTargetBlocks;
0449 InstancePtr->Geometry.DeviceSize =
0450 (u64)InstancePtr->Geometry.NumTargets *
0451 InstancePtr->Geometry.TargetSize;
0452
0453 Status = XST_SUCCESS;
0454 Out:
0455 return Status;
0456 }
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473 static s32 XNandPsu_InitGeometry(XNandPsu *InstancePtr, OnfiParamPage *Param)
0474 {
0475 s32 Status = XST_FAILURE;
0476
0477 if (Param->BytesPerPage > XNANDPSU_MAX_PAGE_SIZE) {
0478 #ifdef XNANDPSU_DEBUG
0479 xil_printf("%s: Invalid Bytes Per Page %d\r\n",
0480 __func__, Param->BytesPerPage);
0481 #endif
0482 goto Out;
0483 }
0484 InstancePtr->Geometry.BytesPerPage = Param->BytesPerPage;
0485
0486
0487 if (Param->SpareBytesPerPage > XNANDPSU_MAX_SPARE_SIZE) {
0488 #ifdef XNANDPSU_DEBUG
0489 xil_printf("%s: Invalid Spare Bytes Per Page %d\r\n",
0490 __func__, Param->SpareBytesPerPage);
0491 #endif
0492 goto Out;
0493 }
0494 InstancePtr->Geometry.SpareBytesPerPage = Param->SpareBytesPerPage;
0495
0496 if (Param->PagesPerBlock > XNANDPSU_MAX_PAGES_PER_BLOCK) {
0497 #ifdef XNANDPSU_DEBUG
0498 xil_printf("%s: Invalid Page Count Per Block %d\r\n",
0499 __func__, Param->PagesPerBlock);
0500 #endif
0501 goto Out;
0502 }
0503 InstancePtr->Geometry.PagesPerBlock = Param->PagesPerBlock;
0504
0505
0506 if (Param->BlocksPerLun > XNANDPSU_MAX_BLOCKS) {
0507 #ifdef XNANDPSU_DEBUG
0508 xil_printf("%s: Invalid block count per LUN %d\r\n",
0509 __func__, Param->BlocksPerLun);
0510 #endif
0511 goto Out;
0512 }
0513 InstancePtr->Geometry.BlocksPerLun = Param->BlocksPerLun;
0514
0515 if (Param->NumLuns > XNANDPSU_MAX_LUNS) {
0516 #ifdef XNANDPSU_DEBUG
0517 xil_printf("%s: Invalid LUN count %d\r\n",
0518 __func__, Param->NumLuns);
0519 #endif
0520 goto Out;
0521 }
0522 InstancePtr->Geometry.NumLuns = Param->NumLuns;
0523
0524 InstancePtr->Geometry.RowAddrCycles = Param->AddrCycles & 0xFU;
0525 InstancePtr->Geometry.ColAddrCycles = (Param->AddrCycles >> 4U) & 0xFU;
0526 InstancePtr->Geometry.NumBitsPerCell = Param->BitsPerCell;
0527 InstancePtr->Geometry.NumBitsECC = Param->EccBits;
0528 InstancePtr->Geometry.BlockSize = (Param->PagesPerBlock *
0529 Param->BytesPerPage);
0530 InstancePtr->Geometry.NumTargetBlocks = (Param->BlocksPerLun *
0531 (u32)Param->NumLuns);
0532 InstancePtr->Geometry.NumTargetPages = (Param->BlocksPerLun *
0533 (u32)Param->NumLuns *
0534 Param->PagesPerBlock);
0535 InstancePtr->Geometry.TargetSize = ((u64)Param->BlocksPerLun *
0536 (u64)Param->NumLuns *
0537 (u64)Param->PagesPerBlock *
0538 (u64)Param->BytesPerPage);
0539 InstancePtr->Geometry.EccCodeWordSize = 9U;
0540 if (InstancePtr->Geometry.NumTargetBlocks > XNANDPSU_MAX_BLOCKS)
0541 xil_printf("!!! Device contains more blocks than the max defined blocks in driver\r\n");
0542
0543 #ifdef XNANDPSU_DEBUG
0544 xil_printf("Manufacturer: %s\r\n", Param->DeviceManufacturer);
0545 xil_printf("Device Model: %s\r\n", Param->DeviceModel);
0546 xil_printf("Jedec ID: 0x%x\r\n", Param->JedecManufacturerId);
0547 xil_printf("Bytes Per Page: 0x%x\r\n", Param->BytesPerPage);
0548 xil_printf("Spare Bytes Per Page: 0x%x\r\n", Param->SpareBytesPerPage);
0549 xil_printf("Pages Per Block: 0x%x\r\n", Param->PagesPerBlock);
0550 xil_printf("Blocks Per LUN: 0x%x\r\n", Param->BlocksPerLun);
0551 xil_printf("Number of LUNs: 0x%x\r\n", Param->NumLuns);
0552 xil_printf("Number of bits per cell: 0x%x\r\n", Param->BitsPerCell);
0553 xil_printf("Number of ECC bits: 0x%x\r\n", Param->EccBits);
0554 xil_printf("Block Size: 0x%x\r\n", InstancePtr->Geometry.BlockSize);
0555
0556 xil_printf("Number of Target Blocks: 0x%x\r\n",
0557 InstancePtr->Geometry.NumTargetBlocks);
0558 xil_printf("Number of Target Pages: 0x%x\r\n",
0559 InstancePtr->Geometry.NumTargetPages);
0560
0561 #endif
0562 Status = XST_SUCCESS;
0563 Out:
0564 return Status;
0565 }
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581 static void XNandPsu_InitFeatures(XNandPsu *InstancePtr, OnfiParamPage *Param)
0582 {
0583 InstancePtr->Features.NvDdr = ((Param->Features & (1U << 5)) != 0U) ?
0584 1U : 0U;
0585 InstancePtr->Features.EzNand = ((Param->Features & (1U << 9)) != 0U) ?
0586 1U : 0U;
0587 InstancePtr->Features.ExtPrmPage = ((Param->Features & (1U << 7)) != 0U) ?
0588 1U : 0U;
0589 }
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605 static void XNandPsu_InitDataInterface(XNandPsu *InstancePtr, OnfiParamPage *Param)
0606 {
0607 if (Param->NVDDRTimingMode)
0608 InstancePtr->DataInterface = XNANDPSU_NVDDR;
0609 else if (Param->SDRTimingMode)
0610 InstancePtr->DataInterface = XNANDPSU_SDR;
0611 }
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627 static void XNandPsu_InitTimingMode(XNandPsu *InstancePtr, OnfiParamPage *Param)
0628 {
0629 s8 Mode;
0630 u8 TimingMode = (u8)(Param->SDRTimingMode);
0631
0632 if (InstancePtr->DataInterface == XNANDPSU_NVDDR)
0633 TimingMode = Param->NVDDRTimingMode;
0634
0635 for(Mode = XNANDPSU_MAX_TIMING_MODE; Mode >= 0; Mode--) {
0636 if (TimingMode & (0x01 << Mode)) {
0637 InstancePtr->TimingMode = Mode;
0638 break;
0639 } else {
0640 continue;
0641 }
0642 }
0643 }
0644
0645
0646
0647
0648
0649
0650
0651
0652
0653
0654
0655
0656
0657
0658
0659 static s32 XNandPsu_CheckOnDie(XNandPsu *InstancePtr)
0660 {
0661 s32 Status = XST_FAILURE;
0662 u8 JedecId[2] = {0U};
0663 u8 EccSetFeature[4] = {0x08U, 0x00U, 0x00U, 0x00U};
0664 u8 EccGetFeature[4] ={0U};
0665
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678
0679
0680 Status = XNandPsu_OnfiReadId(InstancePtr, 0U, 0x00U, 2U, &JedecId[0]);
0681 if (Status != XST_SUCCESS) {
0682 goto Out;
0683 }
0684
0685 if ((JedecId[0] == 0x2CU) &&
0686
0687 ((JedecId[1] == 0xF1U) ||
0688 (JedecId[1] == 0xA1U) ||
0689 (JedecId[1] == 0xB1U) ||
0690
0691 (JedecId[1] == 0xAAU) ||
0692 (JedecId[1] == 0xBAU) ||
0693 (JedecId[1] == 0xDAU) ||
0694 (JedecId[1] == 0xCAU) ||
0695
0696 (JedecId[1] == 0xACU) ||
0697 (JedecId[1] == 0xBCU) ||
0698 (JedecId[1] == 0xDCU) ||
0699 (JedecId[1] == 0xCCU) ||
0700
0701 (JedecId[1] == 0xA3U) ||
0702 (JedecId[1] == 0xB3U) ||
0703 (JedecId[1] == 0xD3U) ||
0704 (JedecId[1] == 0xC3U))) {
0705 #ifdef XNANDPSU_DEBUG
0706 xil_printf("%s: Ondie flash detected, jedec id 0x%x 0x%x\r\n",
0707 __func__, JedecId[0], JedecId[1]);
0708 #endif
0709
0710 Status = XNandPsu_SetFeature(InstancePtr, 0U, 0x90U,
0711 &EccSetFeature[0]);
0712 if (Status != XST_SUCCESS) {
0713 #ifdef XNANDPSU_DEBUG
0714 xil_printf("%s: Ondie set_feature failed\r\n",
0715 __func__);
0716 #endif
0717 goto Out;
0718 }
0719
0720 Status = XNandPsu_GetFeature(InstancePtr, 0U, 0x90U,
0721 &EccGetFeature[0]);
0722 if (Status != XST_SUCCESS) {
0723 #ifdef XNANDPSU_DEBUG
0724 xil_printf("%s: Ondie get_feature failed\r\n",
0725 __func__);
0726 #endif
0727 goto Out;
0728 }
0729 if ((EccGetFeature[0] & 0x08U) != 0U) {
0730 InstancePtr->Features.OnDie = 1U;
0731 Status = XST_SUCCESS;
0732 }
0733 } else {
0734
0735 Status = XST_FAILURE;
0736 }
0737 Out:
0738 return Status;
0739 }
0740
0741
0742
0743
0744
0745
0746
0747
0748
0749
0750
0751
0752
0753
0754 void XNandPsu_EnableDmaMode(XNandPsu *InstancePtr)
0755 {
0756
0757 Xil_AssertVoid(InstancePtr != NULL);
0758 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0759
0760 InstancePtr->DmaMode = XNANDPSU_MDMA;
0761 }
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774
0775
0776 void XNandPsu_DisableDmaMode(XNandPsu *InstancePtr)
0777 {
0778
0779 Xil_AssertVoid(InstancePtr != NULL);
0780 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0781
0782 InstancePtr->DmaMode = XNANDPSU_PIO;
0783 }
0784
0785
0786
0787
0788
0789
0790
0791
0792
0793
0794
0795
0796
0797
0798 void XNandPsu_EnableEccMode(XNandPsu *InstancePtr)
0799 {
0800
0801 Xil_AssertVoid(InstancePtr != NULL);
0802 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0803
0804 InstancePtr->EccMode = XNANDPSU_HWECC;
0805 }
0806
0807
0808
0809
0810
0811
0812
0813
0814
0815
0816
0817
0818
0819
0820 void XNandPsu_DisableEccMode(XNandPsu *InstancePtr)
0821 {
0822
0823 Xil_AssertVoid(InstancePtr != NULL);
0824 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0825
0826 InstancePtr->EccMode = XNANDPSU_NONE;
0827 }
0828
0829 #ifdef __rtems__
0830 #include <rtems/rtems/clock.h>
0831 static void udelay( void )
0832 {
0833 uint64_t time = rtems_clock_get_uptime_nanoseconds() + 1000;
0834 while (1) {
0835 uint64_t newtime = rtems_clock_get_uptime_nanoseconds();
0836 if (newtime > time) {
0837 break;
0838 }
0839 }
0840 }
0841 #define usleep(x) udelay()
0842 #endif
0843
0844
0845
0846
0847
0848
0849
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859
0860
0861 static s32 XNandPsu_PollRegTimeout(XNandPsu *InstancePtr, u32 RegOffset,
0862 u32 Mask, u32 Timeout)
0863 {
0864 s32 Status = XST_FAILURE;
0865 volatile u32 RegVal;
0866 u32 TimeoutVar = Timeout;
0867
0868 while (TimeoutVar > 0U) {
0869 RegVal = XNandPsu_ReadReg(InstancePtr->Config.BaseAddress,
0870 RegOffset) & Mask;
0871 if (RegVal != 0U) {
0872 break;
0873 }
0874 TimeoutVar--;
0875 usleep(1);
0876 }
0877
0878 if (TimeoutVar <= 0U) {
0879 Status = XST_FAILURE;
0880 } else {
0881 Status = XST_SUCCESS;
0882 }
0883
0884 return Status;
0885 }
0886
0887
0888
0889
0890
0891
0892
0893
0894
0895
0896
0897
0898
0899
0900
0901
0902 static void XNandPsu_SetPktSzCnt(XNandPsu *InstancePtr, u32 PktSize,
0903 u32 PktCount)
0904 {
0905
0906 XNandPsu_ReadModifyWrite(InstancePtr, XNANDPSU_PKT_OFFSET,
0907 ((u32)XNANDPSU_PKT_PKT_SIZE_MASK |
0908 (u32)XNANDPSU_PKT_PKT_CNT_MASK),
0909 ((PktSize & XNANDPSU_PKT_PKT_SIZE_MASK) |
0910 ((PktCount << XNANDPSU_PKT_PKT_CNT_SHIFT) &
0911 XNANDPSU_PKT_PKT_CNT_MASK)));
0912 }
0913
0914
0915
0916
0917
0918
0919
0920
0921
0922
0923
0924
0925
0926
0927
0928
0929 static void XNandPsu_SetPageColAddr(XNandPsu *InstancePtr, u32 Page, u16 Col)
0930 {
0931
0932 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
0933 XNANDPSU_MEM_ADDR1_OFFSET,
0934 (((u32)Col & XNANDPSU_MEM_ADDR1_COL_ADDR_MASK) |
0935 ((Page << (u32)XNANDPSU_MEM_ADDR1_PG_ADDR_SHIFT) &
0936 XNANDPSU_MEM_ADDR1_PG_ADDR_MASK)));
0937
0938 XNandPsu_ReadModifyWrite(InstancePtr, XNANDPSU_MEM_ADDR2_OFFSET,
0939 XNANDPSU_MEM_ADDR2_MEM_ADDR_MASK,
0940 ((Page >> XNANDPSU_MEM_ADDR1_PG_ADDR_SHIFT) &
0941 XNANDPSU_MEM_ADDR2_MEM_ADDR_MASK));
0942 }
0943
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954
0955
0956
0957 static void XNandPsu_SetPageSize(XNandPsu *InstancePtr)
0958 {
0959 u32 PageSizeMask = 0;
0960 u32 PageSize = InstancePtr->Geometry.BytesPerPage;
0961
0962
0963 switch(PageSize) {
0964 case XNANDPSU_PAGE_SIZE_512:
0965 PageSizeMask = (0U << XNANDPSU_CMD_PG_SIZE_SHIFT);
0966 break;
0967 case XNANDPSU_PAGE_SIZE_2K:
0968 PageSizeMask = (1U << XNANDPSU_CMD_PG_SIZE_SHIFT);
0969 break;
0970 case XNANDPSU_PAGE_SIZE_4K:
0971 PageSizeMask = (2U << XNANDPSU_CMD_PG_SIZE_SHIFT);
0972 break;
0973 case XNANDPSU_PAGE_SIZE_8K:
0974 PageSizeMask = (3U << XNANDPSU_CMD_PG_SIZE_SHIFT);
0975 break;
0976 case XNANDPSU_PAGE_SIZE_16K:
0977 PageSizeMask = (4U << XNANDPSU_CMD_PG_SIZE_SHIFT);
0978 break;
0979 case XNANDPSU_PAGE_SIZE_1K_16BIT:
0980 PageSizeMask = (5U << XNANDPSU_CMD_PG_SIZE_SHIFT);
0981 break;
0982 default:
0983
0984 break;
0985 }
0986
0987 XNandPsu_ReadModifyWrite(InstancePtr, XNANDPSU_CMD_OFFSET,
0988 XNANDPSU_CMD_PG_SIZE_MASK, PageSizeMask);
0989 }
0990
0991
0992
0993
0994
0995
0996
0997
0998
0999
1000
1001
1002
1003
1004 static void XNandPsu_SetEccAddrSize(XNandPsu *InstancePtr)
1005 {
1006 u32 PageSize = InstancePtr->Geometry.BytesPerPage;
1007 u32 CodeWordSize = InstancePtr->Geometry.EccCodeWordSize;
1008 u32 NumEccBits = InstancePtr->Geometry.NumBitsECC;
1009 u32 Index;
1010 u32 Found = 0U;
1011 u8 BchModeVal;
1012
1013 for (Index = 0U; Index < (sizeof(EccMatrix)/sizeof(XNandPsu_EccMatrix));
1014 Index++) {
1015 if ((EccMatrix[Index].PageSize == PageSize) &&
1016 (EccMatrix[Index].CodeWordSize >= CodeWordSize)) {
1017 if (EccMatrix[Index].NumEccBits >= NumEccBits) {
1018 Found = Index;
1019 break;
1020 }
1021 else {
1022 Found = Index;
1023 }
1024 }
1025 }
1026
1027 if (Found != 0U) {
1028 if(InstancePtr->Geometry.SpareBytesPerPage < 64U) {
1029 InstancePtr->EccCfg.EccAddr = (u16)PageSize;
1030 }
1031 else {
1032 InstancePtr->EccCfg.EccAddr = ((u16)PageSize +
1033 (InstancePtr->Geometry.SpareBytesPerPage
1034 - EccMatrix[Found].EccSize));
1035 }
1036 InstancePtr->EccCfg.EccSize = EccMatrix[Found].EccSize;
1037 InstancePtr->EccCfg.NumEccBits = EccMatrix[Found].NumEccBits;
1038 InstancePtr->EccCfg.CodeWordSize =
1039 EccMatrix[Found].CodeWordSize;
1040 #ifdef XNANDPSU_DEBUG
1041 xil_printf("ECC: addr 0x%x size 0x%x numbits %d "
1042 "codesz %d\r\n",
1043 InstancePtr->EccCfg.EccAddr,
1044 InstancePtr->EccCfg.EccSize,
1045 InstancePtr->EccCfg.NumEccBits,
1046 InstancePtr->EccCfg.CodeWordSize);
1047 #endif
1048 if (EccMatrix[Found].IsBCH == XNANDPSU_HAMMING) {
1049 InstancePtr->EccCfg.IsBCH = 0U;
1050 } else {
1051 InstancePtr->EccCfg.IsBCH = 1U;
1052 }
1053
1054 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
1055 (u32)XNANDPSU_ECC_OFFSET,
1056 ((u32)InstancePtr->EccCfg.EccAddr |
1057 ((u32)InstancePtr->EccCfg.EccSize << (u32)16) |
1058 ((u32)InstancePtr->EccCfg.IsBCH << (u32)27)));
1059
1060 if (EccMatrix[Found].IsBCH == XNANDPSU_BCH) {
1061
1062 switch(InstancePtr->EccCfg.NumEccBits) {
1063 case 16U:
1064 BchModeVal = 0x0U;
1065 break;
1066 case 12U:
1067 BchModeVal = 0x1U;
1068 break;
1069 case 8U:
1070 BchModeVal = 0x2U;
1071 break;
1072 case 4U:
1073 BchModeVal = 0x3U;
1074 break;
1075 case 24U:
1076 BchModeVal = 0x4U;
1077 break;
1078 default:
1079 BchModeVal = 0x0U;
1080 break;
1081 }
1082 XNandPsu_ReadModifyWrite(InstancePtr,
1083 XNANDPSU_MEM_ADDR2_OFFSET,
1084 XNANDPSU_MEM_ADDR2_NFC_BCH_MODE_MASK,
1085 ((u32)BchModeVal <<
1086 (u32)XNANDPSU_MEM_ADDR2_NFC_BCH_MODE_SHIFT));
1087 }
1088 }
1089 }
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104 static void XNandPsu_SetEccSpareCmd(XNandPsu *InstancePtr, u16 SpareCmd,
1105 u8 AddrCycles)
1106 {
1107 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
1108 (u32)XNANDPSU_ECC_SPR_CMD_OFFSET,
1109 (u32)SpareCmd | ((u32)AddrCycles << 28U));
1110 }
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126 static void XNandPsu_SelectChip(XNandPsu *InstancePtr, u32 Target)
1127 {
1128 #if defined (XCLOCKING)
1129 Xil_ClockEnable(InstancePtr->Config.RefClk);
1130 #endif
1131
1132 XNandPsu_ReadModifyWrite(InstancePtr, XNANDPSU_MEM_ADDR2_OFFSET,
1133 XNANDPSU_MEM_ADDR2_CHIP_SEL_MASK,
1134 ((Target << XNANDPSU_MEM_ADDR2_CHIP_SEL_SHIFT) &
1135 XNANDPSU_MEM_ADDR2_CHIP_SEL_MASK));
1136 }
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153 static s32 XNandPsu_OnfiReset(XNandPsu *InstancePtr, u32 Target)
1154 {
1155 s32 Status = XST_FAILURE;
1156
1157
1158 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1159 XNANDPSU_INTR_STS_EN_OFFSET,
1160 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
1161
1162 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RST, ONFI_CMD_INVALID, 0U,
1163 0U, 0U);
1164
1165 XNandPsu_SelectChip(InstancePtr, Target);
1166
1167 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1168 XNANDPSU_PROG_OFFSET, XNANDPSU_PROG_RST_MASK);
1169
1170
1171 Status = XNandPsu_WaitFor_Transfer_Complete(InstancePtr);
1172
1173 return Status;
1174 }
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192 static s32 XNandPsu_OnfiReadStatus(XNandPsu *InstancePtr, u32 Target,
1193 u16 *OnfiStatus)
1194 {
1195 s32 Status = XST_FAILURE;
1196
1197
1198 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1199 XNANDPSU_INTR_STS_EN_OFFSET,
1200 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
1201
1202 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RD_STS, ONFI_CMD_INVALID,
1203 0U, 0U, 0U);
1204
1205 XNandPsu_SelectChip(InstancePtr, Target);
1206
1207 if(InstancePtr->DataInterface == XNANDPSU_SDR)
1208 XNandPsu_SetPktSzCnt(InstancePtr, 1U, 1U);
1209 else
1210 XNandPsu_SetPktSzCnt(InstancePtr, 2U, 1U);
1211
1212
1213 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1214 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_STS_MASK);
1215
1216 Status = XNandPsu_WaitFor_Transfer_Complete(InstancePtr);
1217
1218 *OnfiStatus = (u16) XNandPsu_ReadReg(InstancePtr->Config.BaseAddress,
1219 XNANDPSU_FLASH_STS_OFFSET);
1220
1221 return Status;
1222 }
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240 static s32 XNandPsu_OnfiReadId(XNandPsu *InstancePtr, u32 Target, u8 IdAddr,
1241 u32 IdLen, u8 *Buf)
1242 {
1243 s32 Status = XST_FAILURE;
1244 u32 Index;
1245 u32 Rem;
1246 u32 RegVal;
1247 u32 RemIdx;
1248
1249 u32 *BufPtr = (u32 *)(void *)Buf;
1250
1251
1252
1253
1254
1255 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1256 XNANDPSU_INTR_STS_EN_OFFSET,
1257 XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK);
1258
1259 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RD_ID, ONFI_CMD_INVALID, 0U,
1260 0U, ONFI_READ_ID_ADDR_CYCLES);
1261
1262
1263 XNandPsu_SetPageColAddr(InstancePtr, 0U, IdAddr);
1264
1265 XNandPsu_SelectChip(InstancePtr, Target);
1266
1267 XNandPsu_SetPktSzCnt(InstancePtr, IdLen, 1U);
1268
1269 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1270 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_ID_MASK);
1271
1272
1273 Status = XNandPsu_PollRegTimeout(
1274 InstancePtr,
1275 XNANDPSU_INTR_STS_OFFSET,
1276 XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK,
1277 XNANDPSU_INTR_POLL_TIMEOUT);
1278 if (Status != XST_SUCCESS) {
1279 #ifdef XNANDPSU_DEBUG
1280 xil_printf("%s: Poll for buf read ready timeout\r\n",
1281 __func__);
1282 #endif
1283 goto Out;
1284 }
1285
1286
1287
1288
1289
1290 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1291 XNANDPSU_INTR_STS_EN_OFFSET,
1292 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
1293
1294
1295
1296
1297
1298 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1299 XNANDPSU_INTR_STS_OFFSET,
1300 XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK);
1301
1302 for (Index = 0U; Index < (IdLen/4); Index++) {
1303 *(BufPtr+Index) = XNandPsu_ReadReg(
1304 InstancePtr->Config.BaseAddress,
1305 XNANDPSU_BUF_DATA_PORT_OFFSET);
1306 }
1307 Rem = IdLen % 4;
1308 if (Rem != 0U) {
1309 RegVal = XNandPsu_ReadReg(
1310 InstancePtr->Config.BaseAddress,
1311 XNANDPSU_BUF_DATA_PORT_OFFSET);
1312 for (RemIdx = 0U; RemIdx < Rem; RemIdx++) {
1313 *(Buf + (Index * 4U) + RemIdx) = (u8) (RegVal >>
1314 (RemIdx * 8U)) & 0xFFU;
1315 }
1316 }
1317
1318 Status = XNandPsu_WaitFor_Transfer_Complete(InstancePtr);
1319
1320 Out:
1321 return Status;
1322 }
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341 static s32 XNandPsu_OnfiReadParamPage(XNandPsu *InstancePtr, u32 Target,
1342 u8 *Buf)
1343 {
1344 s32 Status = XST_FAILURE;
1345
1346
1347
1348
1349
1350 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1351 XNANDPSU_INTR_STS_EN_OFFSET,
1352 XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK);
1353
1354 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RD_PRM_PG, ONFI_CMD_INVALID,
1355 0U, 0U, ONFI_PRM_PG_ADDR_CYCLES);
1356
1357 XNandPsu_SetPageColAddr(InstancePtr, 0U, 0U);
1358
1359 XNandPsu_SelectChip(InstancePtr, Target);
1360
1361 XNandPsu_SetPktSzCnt(InstancePtr, ONFI_MND_PRM_PGS*ONFI_PRM_PG_LEN, 1U);
1362
1363 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1364 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_PRM_PG_MASK);
1365
1366 Status = XNandPsu_Data_ReadWrite(InstancePtr, Buf, 1U, ONFI_MND_PRM_PGS*ONFI_PRM_PG_LEN, 0, 0);
1367
1368 return Status;
1369 }
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387 static s32 XNandPsu_CalculateLength(XNandPsu *InstancePtr, u64 Offset,
1388 u64 Length)
1389 {
1390 s32 Status;
1391 u32 BlockSize;
1392 u32 BlockLen;
1393 u32 Block;
1394 u64 TempLen = 0;
1395 u64 OffsetVar = Offset;
1396
1397 BlockSize = InstancePtr->Geometry.BlockSize;
1398
1399 while (TempLen < Length) {
1400 Block = (u32)(OffsetVar/BlockSize);
1401 BlockLen = BlockSize - (u32)(OffsetVar % BlockSize);
1402 if (OffsetVar >= InstancePtr->Geometry.DeviceSize) {
1403 Status = XST_FAILURE;
1404 goto Out;
1405 }
1406
1407 Status = XNandPsu_IsBlockBad(InstancePtr, Block);
1408 if (Status != XST_SUCCESS) {
1409
1410 TempLen += BlockLen;
1411 }
1412 OffsetVar += BlockLen;
1413 }
1414
1415 Status = XST_SUCCESS;
1416 Out:
1417 return Status;
1418 }
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437 s32 XNandPsu_Write(XNandPsu *InstancePtr, u64 Offset, u64 Length, u8 *SrcBuf)
1438 {
1439
1440 Xil_AssertNonvoid(InstancePtr != NULL);
1441 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
1442 Xil_AssertNonvoid(SrcBuf != NULL);
1443 Xil_AssertNonvoid(Length != 0U);
1444 Xil_AssertNonvoid((Offset + Length) <=
1445 InstancePtr->Geometry.DeviceSize);
1446
1447 s32 Status = XST_FAILURE;
1448 u32 Page;
1449 u32 Col;
1450 u32 Target;
1451 u32 Block;
1452 u32 PartialBytes = 0;
1453 u32 NumBytes;
1454 u32 RemLen;
1455 u8 *BufPtr;
1456 u8 *SrcBufPtr = (u8 *)SrcBuf;
1457 u64 OffsetVar = Offset;
1458 u64 LengthVar = Length;
1459
1460
1461
1462
1463
1464 Status = XNandPsu_CalculateLength(InstancePtr, OffsetVar, LengthVar);
1465 if (Status != XST_SUCCESS) {
1466 goto Out;
1467 }
1468
1469 #ifdef __rtems__
1470 if (InstancePtr->PartialDataPageIndex != XNANDPSU_PAGE_CACHE_UNAVAILABLE) {
1471
1472 InstancePtr->PartialDataPageIndex = XNANDPSU_PAGE_CACHE_NONE;
1473 }
1474 #endif
1475 while (LengthVar > 0U) {
1476 Block = (u32) (OffsetVar/InstancePtr->Geometry.BlockSize);
1477
1478
1479
1480
1481
1482 if (XNandPsu_IsBlockBad(InstancePtr, Block) == XST_SUCCESS) {
1483 OffsetVar += (u64)InstancePtr->Geometry.BlockSize;
1484 continue;
1485 }
1486
1487 Page = (u32) (OffsetVar/InstancePtr->Geometry.BytesPerPage);
1488 Col = (u32) (OffsetVar &
1489 (InstancePtr->Geometry.BytesPerPage - 1U));
1490 PartialBytes = 0U;
1491
1492
1493
1494
1495 if ((Col > 0U) ||
1496 (LengthVar < InstancePtr->Geometry.BytesPerPage)) {
1497 RemLen = InstancePtr->Geometry.BytesPerPage - Col;
1498 PartialBytes = (RemLen < (u32)LengthVar) ?
1499 RemLen : (u32)LengthVar;
1500 }
1501
1502 Target = (u32) (OffsetVar/InstancePtr->Geometry.TargetSize);
1503 #ifdef __rtems__
1504 {
1505 #else
1506 if (Page > InstancePtr->Geometry.NumTargetPages) {
1507 #endif
1508 Page %= InstancePtr->Geometry.NumTargetPages;
1509 }
1510
1511
1512 if (PartialBytes > 0U) {
1513 BufPtr = &InstancePtr->PartialDataBuf[0];
1514 (void)memset(BufPtr, 0xFF,
1515 InstancePtr->Geometry.BytesPerPage);
1516 (void)Xil_MemCpy(BufPtr + Col, SrcBufPtr, PartialBytes);
1517
1518 NumBytes = PartialBytes;
1519 } else {
1520 BufPtr = (u8 *)SrcBufPtr;
1521 NumBytes = (InstancePtr->Geometry.BytesPerPage <
1522 (u32)LengthVar) ?
1523 InstancePtr->Geometry.BytesPerPage :
1524 (u32)LengthVar;
1525 }
1526
1527 Status = XNandPsu_ProgramPage(InstancePtr, Target, Page, 0U,
1528 BufPtr);
1529 if (Status != XST_SUCCESS)
1530 goto Out;
1531
1532 Status = XNandPsu_Device_Ready(InstancePtr, Target);
1533 if (Status != XST_SUCCESS)
1534 goto Out;
1535
1536 SrcBufPtr += NumBytes;
1537 OffsetVar += NumBytes;
1538 LengthVar -= NumBytes;
1539 }
1540
1541 Out:
1542 return Status;
1543 }
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562 s32 XNandPsu_Read(XNandPsu *InstancePtr, u64 Offset, u64 Length, u8 *DestBuf)
1563 {
1564
1565 Xil_AssertNonvoid(InstancePtr != NULL);
1566 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
1567 Xil_AssertNonvoid(DestBuf != NULL);
1568 Xil_AssertNonvoid(Length != 0U);
1569 Xil_AssertNonvoid((Offset + Length) <=
1570 InstancePtr->Geometry.DeviceSize);
1571
1572 s32 Status = XST_FAILURE;
1573 u32 Page;
1574 u32 Col;
1575 u32 Target;
1576 u32 Block;
1577 u32 PartialBytes = 0U;
1578 u32 RemLen;
1579 u32 NumBytes;
1580 u8 *BufPtr;
1581 u8 *DestBufPtr = (u8 *)DestBuf;
1582 u64 OffsetVar = Offset;
1583 u64 LengthVar = Length;
1584
1585
1586
1587
1588
1589 Status = XNandPsu_CalculateLength(InstancePtr, OffsetVar, LengthVar);
1590 if (Status != XST_SUCCESS) {
1591 goto Out;
1592 }
1593
1594 while (LengthVar > 0U) {
1595 Block = (u32)(OffsetVar/InstancePtr->Geometry.BlockSize);
1596
1597
1598
1599
1600
1601 if (XNandPsu_IsBlockBad(InstancePtr, Block) == XST_SUCCESS) {
1602 OffsetVar += (u64)InstancePtr->Geometry.BlockSize;
1603 continue;
1604 }
1605
1606 Page = (u32) (OffsetVar/InstancePtr->Geometry.BytesPerPage);
1607 Col = (u32) (OffsetVar &
1608 (InstancePtr->Geometry.BytesPerPage - 1U));
1609 PartialBytes = 0U;
1610
1611
1612
1613
1614 if ((Col > 0U) ||
1615 (LengthVar < InstancePtr->Geometry.BytesPerPage)) {
1616 RemLen = InstancePtr->Geometry.BytesPerPage - Col;
1617 PartialBytes = ((u32)RemLen < (u32)LengthVar) ?
1618 (u32)RemLen : (u32)LengthVar;
1619 }
1620
1621 Target = (u32) (OffsetVar/InstancePtr->Geometry.TargetSize);
1622 #ifdef __rtems__
1623 {
1624 #else
1625 if (Page > InstancePtr->Geometry.NumTargetPages) {
1626 #endif
1627 Page %= InstancePtr->Geometry.NumTargetPages;
1628 }
1629
1630 if (PartialBytes > 0U) {
1631 BufPtr = &InstancePtr->PartialDataBuf[0];
1632 NumBytes = PartialBytes;
1633 } else {
1634 BufPtr = DestBufPtr;
1635 NumBytes = (InstancePtr->Geometry.BytesPerPage <
1636 (u32)LengthVar) ?
1637 InstancePtr->Geometry.BytesPerPage :
1638 (u32)LengthVar;
1639 }
1640 #ifdef __rtems__
1641 if (Page == InstancePtr->PartialDataPageIndex) {
1642
1643
1644
1645
1646
1647 if (PartialBytes == 0U) {
1648 (void)Xil_MemCpy(DestBufPtr,
1649 &InstancePtr->PartialDataBuf[0],
1650 NumBytes);
1651 }
1652 } else {
1653 #endif
1654
1655 Status = XNandPsu_ReadPage(InstancePtr, Target, Page, 0U,
1656 BufPtr);
1657 #ifdef __rtems__
1658 if (PartialBytes > 0U &&
1659 InstancePtr->PartialDataPageIndex != XNANDPSU_PAGE_CACHE_UNAVAILABLE) {
1660
1661
1662
1663
1664 InstancePtr->PartialDataPageIndex = Page;
1665 }
1666 }
1667 #endif
1668 if (Status != XST_SUCCESS) {
1669 goto Out;
1670 }
1671 if (PartialBytes > 0U) {
1672 (void)Xil_MemCpy(DestBufPtr, BufPtr + Col, NumBytes);
1673 #ifdef __rtems__
1674
1675 if (InstancePtr->Config.IsCacheCoherent == 0) {
1676 Xil_DCacheFlushRange((INTPTR)(void *)DestBufPtr, NumBytes);
1677 }
1678 #endif
1679 }
1680 DestBufPtr += NumBytes;
1681 OffsetVar += NumBytes;
1682 LengthVar -= NumBytes;
1683 }
1684
1685 Status = XST_SUCCESS;
1686 Out:
1687 return Status;
1688 }
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708 s32 XNandPsu_Erase(XNandPsu *InstancePtr, u64 Offset, u64 Length)
1709 {
1710
1711 Xil_AssertNonvoid(InstancePtr != NULL);
1712 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
1713 Xil_AssertNonvoid(Length != 0U);
1714 Xil_AssertNonvoid((Offset + Length) <=
1715 InstancePtr->Geometry.DeviceSize);
1716
1717 s32 Status = XST_FAILURE;
1718 u32 Target = 0;
1719 u32 StartBlock;
1720 u32 NumBlocks = 0;
1721 u32 Block;
1722 u32 AlignOff;
1723 u32 EraseLen;
1724 u32 BlockRemLen;
1725 u64 OffsetVar = Offset;
1726 u64 LengthVar = Length;
1727
1728
1729
1730
1731
1732 Status = XNandPsu_CalculateLength(InstancePtr, OffsetVar, LengthVar);
1733 if (Status != XST_SUCCESS) {
1734 goto Out;
1735 }
1736
1737 StartBlock = (u32) (OffsetVar/InstancePtr->Geometry.BlockSize);
1738
1739 while (LengthVar > 0U) {
1740 Block = (u32) (OffsetVar/InstancePtr->Geometry.BlockSize);
1741 if (XNandPsu_IsBlockBad(InstancePtr, Block) ==
1742 XST_SUCCESS) {
1743 OffsetVar += (u64)InstancePtr->Geometry.BlockSize;
1744 NumBlocks++;
1745 continue;
1746 }
1747
1748 AlignOff = (u32)OffsetVar &
1749 (InstancePtr->Geometry.BlockSize - (u32)1);
1750 if (AlignOff > 0U) {
1751 BlockRemLen = InstancePtr->Geometry.BlockSize -
1752 AlignOff;
1753 EraseLen = (BlockRemLen < (u32)LengthVar) ?
1754 BlockRemLen :(u32)LengthVar;
1755 } else {
1756 EraseLen = (InstancePtr->Geometry.BlockSize <
1757 (u32)LengthVar) ?
1758 InstancePtr->Geometry.BlockSize:
1759 (u32)LengthVar;
1760 }
1761 NumBlocks++;
1762 OffsetVar += EraseLen;
1763 LengthVar -= EraseLen;
1764 }
1765
1766 for (Block = StartBlock; Block < (StartBlock + NumBlocks); Block++) {
1767 Target = Block/InstancePtr->Geometry.NumTargetBlocks;
1768 #ifdef __rtems__
1769 u32 ModBlock = Block % InstancePtr->Geometry.NumTargetBlocks;
1770 #else
1771 Block %= InstancePtr->Geometry.NumTargetBlocks;
1772 #endif
1773
1774 if (XNandPsu_IsBlockBad(InstancePtr, Block) ==
1775 XST_SUCCESS)
1776 continue;
1777
1778 #ifdef __rtems__
1779 Status = XNandPsu_EraseBlock(InstancePtr, Target, ModBlock);
1780 #else
1781 Status = XNandPsu_EraseBlock(InstancePtr, Target, Block);
1782 #endif
1783 if (Status != XST_SUCCESS)
1784 goto Out;
1785
1786 Status = XNandPsu_Device_Ready(InstancePtr, Target);
1787 if (Status != XST_SUCCESS)
1788 goto Out;
1789
1790 }
1791 Out:
1792 return Status;
1793 }
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813 static s32 XNandPsu_ProgramPage(XNandPsu *InstancePtr, u32 Target, u32 Page,
1814 u32 Col, u8 *Buf)
1815 {
1816 u32 PktSize;
1817 u32 PktCount;
1818 s32 Status = XST_FAILURE;
1819 u32 IsrValue;
1820 u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles +
1821 InstancePtr->Geometry.ColAddrCycles;
1822
1823 if (InstancePtr->EccCfg.CodeWordSize > 9U) {
1824 PktSize = 1024U;
1825 } else {
1826 PktSize = 512U;
1827 }
1828 PktCount = InstancePtr->Geometry.BytesPerPage/PktSize;
1829
1830 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_PG_PROG1, ONFI_CMD_PG_PROG2,
1831 1U, 1U, (u8)AddrCycles);
1832
1833 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
1834 IsrValue = XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK |
1835 XNANDPSU_INTR_STS_EN_DMA_INT_STS_EN_MASK;
1836 if (InstancePtr->Config.IsCacheCoherent == 0) {
1837 Xil_DCacheFlushRange((INTPTR)(void *)Buf, (PktSize * PktCount));
1838 }
1839 XNandPsu_Update_DmaAddr(InstancePtr, Buf);
1840 } else {
1841 IsrValue = XNANDPSU_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK;
1842 }
1843
1844 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1845 XNANDPSU_INTR_STS_EN_OFFSET, IsrValue);
1846
1847 XNandPsu_SetPageSize(InstancePtr);
1848
1849 XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
1850
1851 XNandPsu_SetPageColAddr(InstancePtr, Page, (u16)Col);
1852
1853 XNandPsu_SelectChip(InstancePtr, Target);
1854
1855 if (InstancePtr->EccMode == XNANDPSU_HWECC) {
1856 XNandPsu_SetEccSpareCmd(InstancePtr, ONFI_CMD_CHNG_WR_COL,
1857 InstancePtr->Geometry.ColAddrCycles);
1858 }
1859
1860 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1861 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_PG_PROG_MASK);
1862
1863
1864 Status = XNandPsu_Data_ReadWrite(InstancePtr, Buf, PktCount, PktSize, 1, 1);
1865
1866 return Status;
1867 }
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885 s32 XNandPsu_WriteSpareBytes(XNandPsu *InstancePtr, u32 Page, u8 *Buf)
1886 {
1887
1888 Xil_AssertNonvoid(InstancePtr != NULL);
1889 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
1890 Xil_AssertNonvoid(Page < InstancePtr->Geometry.NumPages);
1891 Xil_AssertNonvoid(Buf != NULL);
1892
1893 u32 PktCount = 1U;
1894 u16 PreEccSpareCol = 0U;
1895 u16 PreEccSpareWrCnt = 0U;
1896 u16 PostEccSpareCol = 0U;
1897 u16 PostEccSpareWrCnt = 0U;
1898 u32 PostWrite = 0U;
1899 OnfiCmdFormat Cmd;
1900 s32 Status = XST_FAILURE;
1901 u32 RegVal;
1902 u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles +
1903 InstancePtr->Geometry.ColAddrCycles;
1904 u32 Col = InstancePtr->Geometry.BytesPerPage;
1905 u32 Target = Page/InstancePtr->Geometry.NumTargetPages;
1906 u32 PktSize = InstancePtr->Geometry.SpareBytesPerPage;
1907 u32 *BufPtr = (u32 *)(void *)Buf;
1908 u32 PageVar = Page;
1909
1910 PageVar %= InstancePtr->Geometry.NumTargetPages;
1911
1912 if (InstancePtr->EccMode == XNANDPSU_HWECC) {
1913
1914 PreEccSpareCol = 0x0U;
1915 PreEccSpareWrCnt = InstancePtr->EccCfg.EccAddr -
1916 (u16)InstancePtr->Geometry.BytesPerPage;
1917
1918 PostEccSpareCol = PreEccSpareWrCnt +
1919 InstancePtr->EccCfg.EccSize;
1920 PostEccSpareWrCnt = InstancePtr->Geometry.SpareBytesPerPage -
1921 PostEccSpareCol;
1922
1923 PreEccSpareWrCnt = (PreEccSpareWrCnt/4U) * 4U;
1924 PostEccSpareWrCnt = (PostEccSpareWrCnt/4U) * 4U;
1925
1926 if (PreEccSpareWrCnt > 0U) {
1927 PktSize = PreEccSpareWrCnt;
1928 PktCount = 1U;
1929 Col = InstancePtr->Geometry.BytesPerPage +
1930 PreEccSpareCol;
1931 BufPtr = (u32 *)(void *)Buf;
1932 if (PostEccSpareWrCnt > 0U) {
1933 PostWrite = 1U;
1934 }
1935 } else if (PostEccSpareWrCnt > 0U) {
1936 PktSize = PostEccSpareWrCnt;
1937 PktCount = 1U;
1938 Col = InstancePtr->Geometry.BytesPerPage +
1939 PostEccSpareCol;
1940 BufPtr = (u32 *)(Buf + Col);
1941 } else {
1942
1943 Status = XST_FAILURE;
1944 goto Out;
1945 }
1946 }
1947
1948 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
1949 RegVal = XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK;
1950 if (InstancePtr->Config.IsCacheCoherent == 0) {
1951 Xil_DCacheFlushRange((INTPTR)(void *)BufPtr, (PktSize * PktCount));
1952 }
1953 XNandPsu_Update_DmaAddr(InstancePtr, (u8 *)BufPtr);
1954 } else {
1955 RegVal = XNANDPSU_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK;
1956 }
1957
1958 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1959 XNANDPSU_INTR_STS_EN_OFFSET, RegVal);
1960
1961 if (PostWrite > 0U) {
1962 Cmd.Command1 = 0x80U;
1963 Cmd.Command2 = 0x00U;
1964 XNandPsu_Prepare_Cmd(InstancePtr, Cmd.Command1, Cmd.Command2,
1965 0U , 1U, (u8)AddrCycles);
1966
1967 } else {
1968 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_PG_PROG1,
1969 ONFI_CMD_PG_PROG2, 0U , 1U, (u8)AddrCycles);
1970 }
1971
1972 XNandPsu_SetPageSize(InstancePtr);
1973
1974 XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
1975
1976 XNandPsu_SetPageColAddr(InstancePtr, PageVar, (u16)Col);
1977
1978 XNandPsu_SelectChip(InstancePtr, Target);
1979
1980 if (PostWrite > 0U) {
1981 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1982 XNANDPSU_PROG_OFFSET,((u32)XNANDPSU_PROG_PG_PROG_MASK |
1983 (u32)XNANDPSU_PROG_CHNG_ROW_ADDR_MASK));
1984 } else {
1985 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1986 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_PG_PROG_MASK);
1987 }
1988
1989 Status = XNandPsu_Data_ReadWrite(InstancePtr, (u8 *)BufPtr, PktCount,
1990 PktSize, 1, 1);
1991
1992 if (InstancePtr->EccMode == XNANDPSU_HWECC) {
1993 if (PostWrite > 0U) {
1994 BufPtr = (u32 *)(Buf + PostEccSpareCol);
1995 Status = XNandPsu_ChangeWriteColumn(InstancePtr,
1996 Target,
1997 PostEccSpareCol, PostEccSpareWrCnt, 1U,
1998 (u8 *)(void *)BufPtr);
1999 if (Status != XST_SUCCESS) {
2000 goto Out;
2001 }
2002 }
2003 }
2004 Out:
2005 return Status;
2006 }
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026 static s32 XNandPsu_ReadPage(XNandPsu *InstancePtr, u32 Target, u32 Page,
2027 u32 Col, u8 *Buf)
2028 {
2029 u32 PktSize;
2030 u32 PktCount;
2031 s32 Status = XST_FAILURE;
2032 u32 RegVal;
2033 u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles +
2034 InstancePtr->Geometry.ColAddrCycles;
2035
2036 if (InstancePtr->EccCfg.CodeWordSize > 9U) {
2037 PktSize = 1024U;
2038 } else {
2039 PktSize = 512U;
2040 }
2041 PktCount = InstancePtr->Geometry.BytesPerPage/PktSize;
2042
2043 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RD1, ONFI_CMD_RD2,
2044 1U, 1U, (u8)AddrCycles);
2045
2046 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
2047 RegVal = XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK |
2048 XNANDPSU_INTR_STS_EN_DMA_INT_STS_EN_MASK;
2049 if (InstancePtr->Config.IsCacheCoherent == 0) {
2050 Xil_DCacheInvalidateRange((INTPTR)(void *)Buf, (PktSize * PktCount));
2051 }
2052 XNandPsu_Update_DmaAddr(InstancePtr, Buf);
2053 } else {
2054 RegVal = XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK;
2055 }
2056
2057 if (InstancePtr->EccMode == XNANDPSU_HWECC)
2058 RegVal |= XNANDPSU_INTR_STS_EN_MUL_BIT_ERR_STS_EN_MASK |
2059 XNANDPSU_INTR_STS_EN_ERR_INTR_STS_EN_MASK;
2060
2061 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2062 XNANDPSU_INTR_STS_EN_OFFSET, RegVal);
2063
2064 XNandPsu_SetPageSize(InstancePtr);
2065
2066 XNandPsu_SetPageColAddr(InstancePtr, Page, (u16)Col);
2067
2068 XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
2069
2070 XNandPsu_SelectChip(InstancePtr, Target);
2071
2072 if (InstancePtr->EccMode == XNANDPSU_HWECC) {
2073 XNandPsu_SetEccSpareCmd(InstancePtr,
2074 (ONFI_CMD_CHNG_RD_COL1 |
2075 (ONFI_CMD_CHNG_RD_COL2 << (u8)8U)),
2076 InstancePtr->Geometry.ColAddrCycles);
2077 }
2078
2079
2080 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2081 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_MASK);
2082
2083 Status = XNandPsu_Data_ReadWrite(InstancePtr, Buf, PktCount, PktSize, 0, 1);
2084
2085 #ifdef __rtems__
2086 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
2087 if (InstancePtr->Config.IsCacheCoherent == 0) {
2088 Xil_DCacheInvalidateRange((INTPTR)(void *)Buf, (PktSize * PktCount));
2089 }
2090 }
2091 #endif
2092
2093
2094 if (InstancePtr->EccMode == XNANDPSU_HWECC) {
2095
2096 if (((u32)XNandPsu_ReadReg(InstancePtr->Config.BaseAddress,
2097 XNANDPSU_INTR_STS_OFFSET) &
2098 (u32)XNANDPSU_INTR_STS_MUL_BIT_ERR_STS_EN_MASK) != 0U) {
2099
2100 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2101 XNANDPSU_INTR_STS_OFFSET,
2102 XNANDPSU_INTR_STS_MUL_BIT_ERR_STS_EN_MASK);
2103
2104 #ifdef XNANDPSU_DEBUG
2105 xil_printf("%s: ECC Hamming multi bit error\r\n",
2106 __func__);
2107 #endif
2108 InstancePtr->Ecc_Stat_PerPage_flips =
2109 ((XNandPsu_ReadReg(
2110 InstancePtr->Config.BaseAddress,
2111 XNANDPSU_ECC_ERR_CNT_OFFSET) &
2112 0x1FF00U) >> 8U);
2113 InstancePtr->Ecc_Stats_total_flips +=
2114 InstancePtr->Ecc_Stat_PerPage_flips;
2115 Status = XST_FAILURE;
2116 }
2117
2118 if (((u32)XNandPsu_ReadReg(InstancePtr->Config.BaseAddress,
2119 XNANDPSU_INTR_STS_OFFSET) &
2120 (u32)XNANDPSU_INTR_STS_ERR_INTR_STS_EN_MASK) != 0U) {
2121
2122 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2123 XNANDPSU_INTR_STS_OFFSET,
2124 XNANDPSU_INTR_STS_ERR_INTR_STS_EN_MASK);
2125
2126 if (InstancePtr->EccCfg.IsBCH == 1U) {
2127 InstancePtr->Ecc_Stat_PerPage_flips =
2128 ((XNandPsu_ReadReg(
2129 InstancePtr->Config.BaseAddress,
2130 XNANDPSU_ECC_ERR_CNT_OFFSET)&
2131 0x1FF00U) >> 8U);
2132 InstancePtr->Ecc_Stats_total_flips +=
2133 InstancePtr->Ecc_Stat_PerPage_flips;
2134 Status = XST_SUCCESS;
2135 }
2136 }
2137 }
2138
2139 return Status;
2140 }
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158 s32 XNandPsu_ReadSpareBytes(XNandPsu *InstancePtr, u32 Page, u8 *Buf)
2159 {
2160
2161 Xil_AssertNonvoid(InstancePtr != NULL);
2162 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
2163 Xil_AssertNonvoid(Page < InstancePtr->Geometry.NumPages);
2164 Xil_AssertNonvoid(Buf != NULL);
2165
2166 u32 PktCount = 1U;
2167 s32 Status = XST_FAILURE;
2168 u32 RegVal;
2169 u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles +
2170 InstancePtr->Geometry.ColAddrCycles;
2171 u32 Col = InstancePtr->Geometry.BytesPerPage;
2172 u32 Target = Page/InstancePtr->Geometry.NumTargetPages;
2173 u32 PktSize = InstancePtr->Geometry.SpareBytesPerPage;
2174 u32 PageVar = Page;
2175
2176 PageVar %= InstancePtr->Geometry.NumTargetPages;
2177
2178 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
2179 RegVal = XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK;
2180 if (InstancePtr->Config.IsCacheCoherent == 0) {
2181 Xil_DCacheInvalidateRange((INTPTR)(void *)Buf, (PktSize * PktCount));
2182 }
2183 XNandPsu_Update_DmaAddr(InstancePtr, Buf);
2184 } else {
2185 RegVal = XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK;
2186 }
2187 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2188 XNANDPSU_INTR_STS_EN_OFFSET, RegVal);
2189
2190 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RD1, ONFI_CMD_RD2, 0U,
2191 1U, (u8)AddrCycles);
2192
2193 XNandPsu_SetPageSize(InstancePtr);
2194
2195 XNandPsu_SetPageColAddr(InstancePtr, PageVar, (u16)Col);
2196
2197 XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
2198
2199 XNandPsu_SelectChip(InstancePtr, Target);
2200
2201 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2202 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_MASK);
2203
2204 Status = XNandPsu_Data_ReadWrite(InstancePtr, Buf, PktCount, PktSize, 0, 1);
2205
2206 #ifdef __rtems__
2207 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
2208 if (InstancePtr->Config.IsCacheCoherent == 0) {
2209 Xil_DCacheInvalidateRange((INTPTR)(void *)Buf, (PktSize * PktCount));
2210 }
2211 }
2212 #endif
2213
2214 return Status;
2215 }
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233 s32 XNandPsu_EraseBlock(XNandPsu *InstancePtr, u32 Target, u32 Block)
2234 {
2235
2236 Xil_AssertNonvoid(InstancePtr != NULL);
2237 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
2238 Xil_AssertNonvoid(Target < XNANDPSU_MAX_TARGETS);
2239 #ifdef __rtems__
2240 Xil_AssertNonvoid(Block < InstancePtr->Geometry.NumTargetBlocks);
2241 #else
2242 Xil_AssertNonvoid(Block < InstancePtr->Geometry.NumBlocks);
2243 #endif
2244
2245 s32 Status = XST_FAILURE;
2246 u32 Page;
2247 u32 ErasePage;
2248 u32 EraseCol;
2249 u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles;
2250
2251 Page = Block * InstancePtr->Geometry.PagesPerBlock;
2252 ErasePage = (Page >> 16U) & 0xFFFFU;
2253 EraseCol = Page & 0xFFFFU;
2254
2255
2256
2257
2258
2259 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2260 XNANDPSU_INTR_STS_EN_OFFSET,
2261 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
2262
2263
2264 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_BLK_ERASE1,
2265 ONFI_CMD_BLK_ERASE2, 0U , 0U, (u8)AddrCycles);
2266
2267 XNandPsu_SetPageColAddr(InstancePtr, ErasePage, (u16)EraseCol);
2268
2269 XNandPsu_SelectChip(InstancePtr, Target);
2270
2271 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2272 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_BLK_ERASE_MASK);
2273
2274 Status = XNandPsu_WaitFor_Transfer_Complete(InstancePtr);
2275 return Status;
2276 }
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295 s32 XNandPsu_GetFeature(XNandPsu *InstancePtr, u32 Target, u8 Feature,
2296 u8 *Buf)
2297 {
2298
2299 Xil_AssertNonvoid(InstancePtr != NULL);
2300 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY)
2301 Xil_AssertNonvoid(Buf != NULL);
2302 Xil_AssertNonvoid(Target < XNANDPSU_MAX_TARGETS);
2303
2304 s32 Status;
2305 u32 PktSize = 4;
2306 u32 PktCount = 1;
2307
2308 if (InstancePtr->DataInterface == XNANDPSU_NVDDR) {
2309 PktSize = 8U;
2310 }
2311
2312
2313
2314
2315
2316 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2317 XNANDPSU_INTR_STS_EN_OFFSET,
2318 XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK);
2319
2320 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_GET_FEATURES,
2321 ONFI_CMD_INVALID, 0U, 0U, 1U);
2322
2323 XNandPsu_SetPageColAddr(InstancePtr, 0x0U, Feature);
2324
2325 XNandPsu_SelectChip(InstancePtr, Target);
2326
2327 XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
2328
2329 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2330 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_GET_FEATURES_MASK);
2331
2332 Status = XNandPsu_Data_ReadWrite(InstancePtr, Buf, PktCount, PktSize, 0, 0);
2333
2334 return Status;
2335 }
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354 s32 XNandPsu_SetFeature(XNandPsu *InstancePtr, u32 Target, u8 Feature,
2355 u8 *Buf)
2356 {
2357
2358 Xil_AssertNonvoid(InstancePtr != NULL);
2359 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY)
2360 Xil_AssertNonvoid(Buf != NULL);
2361 Xil_AssertNonvoid(Target < XNANDPSU_MAX_TARGETS);
2362
2363 s32 Status;
2364 u32 PktSize = 4U;
2365 u32 PktCount = 1U;
2366
2367 if (InstancePtr->DataInterface == XNANDPSU_NVDDR) {
2368 PktSize = 8U;
2369 }
2370
2371 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2372 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
2373
2374
2375
2376
2377
2378 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2379 XNANDPSU_INTR_STS_EN_OFFSET,
2380 XNANDPSU_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK);
2381
2382
2383 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_SET_FEATURES,
2384 ONFI_CMD_INVALID, 0U , 0U, 1U);
2385
2386 XNandPsu_SetPageColAddr(InstancePtr, 0x0U, Feature);
2387
2388 XNandPsu_SelectChip(InstancePtr, Target);
2389
2390 XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
2391
2392 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2393 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_SET_FEATURES_MASK);
2394
2395 Status = XNandPsu_Data_ReadWrite(InstancePtr, Buf, PktCount, PktSize, 1, 0);
2396 return Status;
2397 }
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413 static void XNandPsu_ChangeClockFreq(XNandPsu *InstancePtr, u32 ClockFreq)
2414 {
2415 (void) InstancePtr;
2416 (void) ClockFreq;
2417
2418
2419 }
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436 s32 XNandPsu_ChangeTimingMode(XNandPsu *InstancePtr,
2437 XNandPsu_DataInterface NewIntf,
2438 XNandPsu_TimingMode NewMode)
2439 {
2440
2441 Xil_AssertNonvoid(InstancePtr != NULL);
2442 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
2443
2444 s32 Status = XST_SUCCESS;
2445 u32 Target;
2446 u32 RegVal;
2447 u8 Buf[4] = {0U};
2448 u32 *Feature = (u32 *)(void *)&Buf[0];
2449 u32 SetFeature = 0U;
2450 u32 NewModeVar = (u32)NewMode;
2451
2452
2453 if(((NewIntf != XNANDPSU_SDR) && (NewIntf != XNANDPSU_NVDDR)) ||
2454 (NewModeVar > 5U)){
2455 Status = XST_FAILURE;
2456 goto Out;
2457 }
2458
2459 if(NewIntf == XNANDPSU_NVDDR){
2460 NewModeVar = NewModeVar | (u32)0x10;
2461 }
2462
2463 XNandPsu_DataInterface CurIntf = InstancePtr->DataInterface;
2464 XNandPsu_TimingMode CurMode = InstancePtr->TimingMode;
2465
2466
2467 if ((CurIntf == NewIntf) && (CurMode == NewModeVar)) {
2468 Status = XST_SUCCESS;
2469 goto Out;
2470 }
2471
2472 if ((CurIntf == XNANDPSU_NVDDR) && (NewIntf == XNANDPSU_SDR)) {
2473
2474 NewModeVar = XNANDPSU_SDR0;
2475
2476
2477 XNandPsu_ChangeClockFreq(InstancePtr, XNANDPSU_SDR_CLK);
2478
2479
2480 RegVal = ((NewModeVar % 6U) << ((NewIntf == XNANDPSU_NVDDR) ? 3U : 0U)) |
2481 ((u32)NewIntf << XNANDPSU_DATA_INTF_DATA_INTF_SHIFT);
2482 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
2483 XNANDPSU_DATA_INTF_OFFSET, RegVal);
2484
2485 for (Target = 0U; Target < InstancePtr->Geometry.NumTargets;
2486 Target++) {
2487 Status = XNandPsu_OnfiReset(InstancePtr, Target);
2488 if (Status != XST_SUCCESS) {
2489 goto Out;
2490 }
2491 }
2492
2493
2494 for (Target = 0U; Target < InstancePtr->Geometry.NumTargets;
2495 Target++) {
2496 Status = XNandPsu_SetFeature(InstancePtr, Target, 0x01U,
2497 (u8 *)(void *)&NewModeVar);
2498 if (Status != XST_SUCCESS) {
2499 goto Out;
2500 }
2501 }
2502
2503 InstancePtr->DataInterface = NewIntf;
2504 InstancePtr->TimingMode = NewModeVar;
2505
2506 for (Target = 0U; Target < InstancePtr->Geometry.NumTargets;
2507 Target++) {
2508 Status = XNandPsu_GetFeature(InstancePtr, Target, 0x01U,
2509 &Buf[0]);
2510 if (Status != XST_SUCCESS) {
2511 goto Out;
2512 }
2513
2514 if (*Feature != NewModeVar) {
2515 Status = XST_FAILURE;
2516 goto Out;
2517 }
2518 }
2519
2520 goto Out;
2521 }
2522
2523 SetFeature = NewModeVar;
2524 if((CurIntf == XNANDPSU_NVDDR) && (NewIntf == XNANDPSU_NVDDR)){
2525 SetFeature |= SetFeature << 8U;
2526 }
2527
2528 for (Target = 0U; Target < InstancePtr->Geometry.NumTargets;
2529 Target++) {
2530 Status = XNandPsu_SetFeature(InstancePtr, Target, 0x01U,
2531 (u8 *)(void *)&SetFeature);
2532 if (Status != XST_SUCCESS) {
2533 goto Out;
2534 }
2535 }
2536
2537 InstancePtr->DataInterface = NewIntf;
2538 InstancePtr->TimingMode = NewModeVar;
2539
2540 RegVal = ((NewMode % 6U) << ((NewIntf == XNANDPSU_NVDDR) ? 3U : 0U)) |
2541 ((u32)NewIntf << XNANDPSU_DATA_INTF_DATA_INTF_SHIFT);
2542 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
2543 XNANDPSU_DATA_INTF_OFFSET, RegVal);
2544
2545
2546 for (Target = 0U; Target < InstancePtr->Geometry.NumTargets;
2547 Target++) {
2548 Status = XNandPsu_GetFeature(InstancePtr, Target, 0x01U,
2549 &Buf[0]);
2550 if (Status != XST_SUCCESS) {
2551 goto Out;
2552 }
2553
2554
2555 if (*Feature != NewModeVar) {
2556 Status = XST_FAILURE;
2557 goto Out;
2558 }
2559 }
2560
2561 Out:
2562 return Status;
2563 }
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585 static s32 XNandPsu_ChangeReadColumn(XNandPsu *InstancePtr, u32 Target,
2586 u32 Col, u32 PktSize, u32 PktCount,
2587 u8 *Buf)
2588 {
2589 s32 Status = XST_FAILURE;
2590 u32 RegVal;
2591 u32 AddrCycles = InstancePtr->Geometry.ColAddrCycles;
2592
2593 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
2594 RegVal = XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK |
2595 XNANDPSU_INTR_STS_EN_DMA_INT_STS_EN_MASK;
2596 Xil_DCacheInvalidateRange((INTPTR)(void *)Buf, (PktSize * PktCount));
2597 XNandPsu_Update_DmaAddr(InstancePtr, Buf);
2598 } else {
2599 RegVal = XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK;
2600 }
2601
2602 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2603 XNANDPSU_INTR_STS_EN_OFFSET, RegVal);
2604
2605 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_CHNG_RD_COL1,
2606 ONFI_CMD_CHNG_RD_COL2, 0U , 1U, (u8)AddrCycles);
2607
2608 XNandPsu_SetPageSize(InstancePtr);
2609
2610 XNandPsu_SetPageColAddr(InstancePtr, 0U, (u16)Col);
2611
2612 XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
2613
2614 XNandPsu_SelectChip(InstancePtr, Target);
2615
2616 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2617 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_MASK);
2618
2619 Status = XNandPsu_Data_ReadWrite(InstancePtr, Buf, PktCount, PktSize, 0, 1);
2620
2621 return Status;
2622 }
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644 static s32 XNandPsu_ChangeWriteColumn(XNandPsu *InstancePtr, u32 Target,
2645 u32 Col, u32 PktSize, u32 PktCount,
2646 u8 *Buf)
2647 {
2648 s32 Status = XST_FAILURE;
2649 OnfiCmdFormat OnfiCommand;
2650 u32 RegVal;
2651 u32 AddrCycles = InstancePtr->Geometry.ColAddrCycles;
2652
2653 if (PktCount == 0U) {
2654 return XST_SUCCESS;
2655 }
2656
2657 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
2658 RegVal = XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK |
2659 XNANDPSU_INTR_STS_EN_DMA_INT_STS_EN_MASK;
2660 #ifdef __rtems__
2661 if (InstancePtr->Config.IsCacheCoherent == 0) {
2662 Xil_DCacheFlushRange((INTPTR)(void *)Buf, (PktSize * PktCount));
2663 }
2664 #endif
2665 XNandPsu_Update_DmaAddr(InstancePtr, Buf);
2666 } else {
2667 RegVal = XNANDPSU_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK;
2668 }
2669
2670 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2671 XNANDPSU_INTR_STS_EN_OFFSET, RegVal);
2672
2673 OnfiCommand.Command1 = 0x85U;
2674 OnfiCommand.Command2 = 0x10U;
2675 XNandPsu_Prepare_Cmd(InstancePtr, OnfiCommand.Command1,
2676 OnfiCommand.Command2, 0U , 0U, (u8)AddrCycles);
2677
2678
2679 XNandPsu_SetPageSize(InstancePtr);
2680
2681 XNandPsu_SetPageColAddr(InstancePtr, 0U, (u16)Col);
2682
2683 XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
2684
2685 XNandPsu_SelectChip(InstancePtr, Target);
2686
2687 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2688 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_CHNG_ROW_ADDR_END_MASK);
2689
2690 Status = XNandPsu_Data_ReadWrite(InstancePtr, Buf, PktCount, PktSize, 1, 0);
2691 return Status;
2692 }
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709 static s32 XNandPsu_InitExtEcc(XNandPsu *InstancePtr, OnfiExtPrmPage *ExtPrm)
2710 {
2711 s32 Status = XST_FAILURE;
2712 u32 Offset = 0U;
2713 u32 Found = 0U;
2714 OnfiExtEccBlock *EccBlock;
2715
2716 if (ExtPrm->Section0Type != 0x2U) {
2717 Offset += (u32)ExtPrm->Section0Len;
2718 if (ExtPrm->Section1Type != 0x2U) {
2719 #ifdef XNANDPSU_DEBUG
2720 xil_printf("%s: Extended ECC section not found\r\n",__func__);
2721 #endif
2722 Status = XST_FAILURE;
2723 } else {
2724 Found = 1U;
2725 }
2726 } else {
2727 Found = 1U;
2728 }
2729
2730 if (Found != 0U) {
2731 EccBlock = (OnfiExtEccBlock *)&ExtPrm->SectionData[Offset];
2732 Xil_AssertNonvoid(EccBlock != NULL);
2733 if (EccBlock->CodeWordSize == 0U) {
2734 Status = XST_FAILURE;
2735 } else {
2736 InstancePtr->Geometry.NumBitsECC =
2737 EccBlock->NumEccBits;
2738 InstancePtr->Geometry.EccCodeWordSize =
2739 (u32)EccBlock->CodeWordSize;
2740 Status = XST_SUCCESS;
2741 }
2742 }
2743 return Status;
2744 }
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764 void XNandPsu_Prepare_Cmd(XNandPsu *InstancePtr, u8 Cmd1, u8 Cmd2, u8 EccState,
2765 u8 DmaMode, u8 AddrCycles)
2766 {
2767 Xil_AssertVoid(InstancePtr != NULL);
2768
2769 u32 RegValue = 0U;
2770
2771 RegValue = (u32)Cmd1 | (((u32)Cmd2 << (u32)XNANDPSU_CMD_CMD2_SHIFT) &
2772 (u32)XNANDPSU_CMD_CMD2_MASK);
2773
2774 if ((EccState != 0U) && (InstancePtr->EccMode == XNANDPSU_HWECC)) {
2775 RegValue |= 1U << XNANDPSU_CMD_ECC_ON_SHIFT;
2776 }
2777
2778 if ((DmaMode != 0U) && (InstancePtr->DmaMode == XNANDPSU_MDMA)) {
2779 RegValue |= XNANDPSU_MDMA << XNANDPSU_CMD_DMA_EN_SHIFT;
2780 }
2781
2782 if (AddrCycles != 0U) {
2783 RegValue |= (u32)AddrCycles <<
2784 (u32)XNANDPSU_CMD_ADDR_CYCLES_SHIFT;
2785 }
2786
2787 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2788 XNANDPSU_CMD_OFFSET, RegValue);
2789 }
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810 static s32 XNandPsu_Data_ReadWrite(XNandPsu *InstancePtr, u8* Buf, u32 PktCount,
2811 u32 PktSize, u32 Operation, u8 DmaMode)
2812 {
2813 u32 BufRwCnt = 0U;
2814 s32 Status = XST_FAILURE;
2815 u32 Event = XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK;
2816
2817 if ((DmaMode != 0U) && (InstancePtr->DmaMode == XNANDPSU_MDMA))
2818 goto DmaDone;
2819
2820 if (Operation)
2821 Event = XNANDPSU_INTR_STS_BUFF_WR_RDY_STS_EN_MASK;
2822
2823 while (BufRwCnt < PktCount) {
2824
2825 Status = XNandPsu_PollRegTimeout(InstancePtr,
2826 XNANDPSU_INTR_STS_OFFSET, Event,
2827 XNANDPSU_INTR_POLL_TIMEOUT);
2828 if (Status != XST_SUCCESS) {
2829 xil_printf("%s: Poll for buf write ready timeout\r\n",
2830 __func__);
2831 goto Out;
2832 }
2833
2834
2835 BufRwCnt++;
2836
2837 if (BufRwCnt == PktCount)
2838 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2839 XNANDPSU_INTR_STS_EN_OFFSET,
2840 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
2841
2842 else
2843 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2844 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
2845
2846
2847
2848
2849 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2850 XNANDPSU_INTR_STS_OFFSET, Event);
2851
2852 if (Operation)
2853 XNandPsu_Fifo_Write(InstancePtr, Buf, PktSize);
2854 else
2855 XNandPsu_Fifo_Read(InstancePtr, Buf, PktSize);
2856
2857 Buf += PktSize;
2858
2859 if (BufRwCnt < PktCount)
2860 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2861 XNANDPSU_INTR_STS_EN_OFFSET, Event);
2862 else
2863 break;
2864 }
2865
2866 DmaDone:
2867 Status = XNandPsu_WaitFor_Transfer_Complete(InstancePtr);
2868 Out:
2869 return Status;
2870 }
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887 static void XNandPsu_Fifo_Write(XNandPsu *InstancePtr, u8* Buffer, u32 Size)
2888 {
2889 u32 *BufPtr = (u32 *)(void *)Buffer;
2890 u32 Index;
2891
2892 for (Index = 0U; Index < Size/4U; Index++)
2893 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
2894 XNANDPSU_BUF_DATA_PORT_OFFSET,
2895 BufPtr[Index]);
2896 }
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913 static void XNandPsu_Fifo_Read(XNandPsu *InstancePtr, u8* Buf, u32 Size)
2914 {
2915 u32 *BufPtr = (u32 *)(void *)Buf;
2916 u32 Index;
2917
2918 for (Index = 0U; Index < Size/4U; Index++)
2919 BufPtr[Index] = XNandPsu_ReadReg(InstancePtr->Config.BaseAddress,
2920 XNANDPSU_BUF_DATA_PORT_OFFSET);
2921 }
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937 static void XNandPsu_Update_DmaAddr(XNandPsu *InstancePtr, u8* Buf)
2938 {
2939 #if defined(__aarch64__) || defined(__arch64__)
2940 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
2941 XNANDPSU_DMA_SYS_ADDR1_OFFSET,
2942 (u32) (((INTPTR)Buf >> 32U) & 0xFFFFFFFFU));
2943 #endif
2944 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
2945 XNANDPSU_DMA_SYS_ADDR0_OFFSET,
2946 (u32) ((INTPTR)(void *)Buf & 0xFFFFFFFFU));
2947
2948 }
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965 static s32 XNandPsu_Device_Ready(XNandPsu *InstancePtr, u32 Target)
2966 {
2967 s32 Status = XST_SUCCESS;
2968 u16 OnfiStatus = 0U;
2969
2970 do {
2971 Status = XNandPsu_OnfiReadStatus(InstancePtr, Target,
2972 &OnfiStatus);
2973 if (Status != XST_SUCCESS)
2974 goto Out;
2975 if ((OnfiStatus & (1U << 6U)) != 0U) {
2976 if ((OnfiStatus & (1U << 0U)) != 0U) {
2977 Status = XST_FAILURE;
2978 goto Out;
2979 }
2980 }
2981 } while (((OnfiStatus >> 6U) & 0x1U) == 0U);
2982
2983 Out:
2984 return Status;
2985 }
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002 static s32 XNandPsu_WaitFor_Transfer_Complete(XNandPsu *InstancePtr)
3003 {
3004 s32 Status = XST_FAILURE;
3005
3006
3007 Status = XNandPsu_PollRegTimeout(
3008 InstancePtr,
3009 XNANDPSU_INTR_STS_OFFSET,
3010 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK,
3011 XNANDPSU_INTR_POLL_TIMEOUT);
3012 if (Status != XST_SUCCESS) {
3013 xil_printf("%s: Poll for xfer complete timeout\r\n", __func__);
3014 goto Out;
3015 }
3016
3017 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3018 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
3019
3020 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3021 XNANDPSU_INTR_STS_OFFSET,
3022 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK);
3023 #if defined (XCLOCKING)
3024 Xil_ClockDisable(InstancePtr->Config.RefClk);
3025 #endif
3026 Out:
3027 return Status;
3028 }
3029