1 /******************************************************************************
3 * Copyright (C) 2015 Xilinx, Inc. All rights reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
31 ******************************************************************************/
32 /*****************************************************************************/
37 * This file contains the implementation of the interface functions for
38 * XNandPsu driver. Refer to the header file xnandpsu.h for more detailed
41 * This module supports for NAND flash memory devices that conform to the
42 * "Open NAND Flash Interface" (ONFI) 3.0 Specification. This modules
43 * implements basic flash operations like read, write and erase.
45 * @note Driver has been renamed to nandpsu after change in
49 * MODIFICATION HISTORY:
51 * Ver Who Date Changes
52 * ----- ---- ---------- -----------------------------------------------
53 * 1.0 nm 05/06/2014 First release
54 * 2.0 sb 01/12/2015 Removed Null checks for Buffer passed
55 * as parameter to Read API's
59 * - XNandPsu_SetFeature()
60 * - XNandPsu_GetFeature()
61 * and made them public.
62 * Removed Failure Return for BCF Error check in
63 * XNandPsu_ReadPage() and added BCH_Error counter
64 * in the instance pointer structure.
65 * Added XNandPsu_Prepare_Cmd API
67 * - XNandPsu_IntrStsEnable
68 * - XNandPsu_IntrStsClear
69 * - XNandPsu_IntrClear
70 * - XNandPsu_SetProgramReg
71 * with XNandPsu_WriteReg call
72 * Modified xnandpsu.c file API's with above changes.
73 * Corrected the program command for Set Feature API.
75 * - XNandPsu_OnfiReadStatus
76 * - XNandPsu_GetFeature
77 * - XNandPsu_SetFeature
78 * to add support for DDR mode.
79 * Changed Convention for SLC/MLC
83 * Removed extra DMA mode initialization from
84 * the XNandPsu_CfgInitialize API.
86 * - XNandPsu_SetEccAddrSize
87 * ECC address now is calculated based upon the
89 * Modified Block Erase API, removed clearing of
90 * packet register before erase.
91 * Clearing Data Interface Register before
92 * XNandPsu_OnfiReset call.
93 * Modified XNandPsu_ChangeTimingMode API supporting
94 * SDR and NVDDR interface for timing modes 0 to 5.
95 * Modified Bbt Signature and Version Offset value for
96 * Oob and No-Oob region.
99 ******************************************************************************/
101 /***************************** Include Files *********************************/
102 #include "xnandpsu.h"
103 #include "xnandpsu_bbm.h"
104 /************************** Constant Definitions *****************************/
106 const XNandPsu_EccMatrix EccMatrix[] = {
110 {XNANDPSU_PAGE_SIZE_512, 9U, 1U, XNANDPSU_HAMMING, 0x20DU, 0x3U},
111 {XNANDPSU_PAGE_SIZE_512, 9U, 4U, XNANDPSU_BCH, 0x209U, 0x7U},
112 {XNANDPSU_PAGE_SIZE_512, 9U, 8U, XNANDPSU_BCH, 0x203U, 0xDU},
116 {XNANDPSU_PAGE_SIZE_2K, 9U, 1U, XNANDPSU_HAMMING, 0x834U, 0xCU},
117 {XNANDPSU_PAGE_SIZE_2K, 9U, 4U, XNANDPSU_BCH, 0x826U, 0x1AU},
118 {XNANDPSU_PAGE_SIZE_2K, 9U, 8U, XNANDPSU_BCH, 0x80cU, 0x34U},
119 {XNANDPSU_PAGE_SIZE_2K, 9U, 12U, XNANDPSU_BCH, 0x822U, 0x4EU},
120 {XNANDPSU_PAGE_SIZE_2K, 10U, 24U, XNANDPSU_BCH, 0x81cU, 0x54U},
124 {XNANDPSU_PAGE_SIZE_4K, 9U, 1U, XNANDPSU_HAMMING, 0x1068U, 0x18U},
125 {XNANDPSU_PAGE_SIZE_4K, 9U, 4U, XNANDPSU_BCH, 0x104cU, 0x34U},
126 {XNANDPSU_PAGE_SIZE_4K, 9U, 8U, XNANDPSU_BCH, 0x1018U, 0x68U},
127 {XNANDPSU_PAGE_SIZE_4K, 9U, 12U, XNANDPSU_BCH, 0x1044U, 0x9CU},
128 {XNANDPSU_PAGE_SIZE_4K, 10U, 24U, XNANDPSU_BCH, 0x1038U, 0xA8U},
132 {XNANDPSU_PAGE_SIZE_8K, 9U, 1U, XNANDPSU_HAMMING, 0x20d0U, 0x30U},
133 {XNANDPSU_PAGE_SIZE_8K, 9U, 4U, XNANDPSU_BCH, 0x2098U, 0x68U},
134 {XNANDPSU_PAGE_SIZE_8K, 9U, 8U, XNANDPSU_BCH, 0x2030U, 0xD0U},
135 {XNANDPSU_PAGE_SIZE_8K, 9U, 12U, XNANDPSU_BCH, 0x2088U, 0x138U},
136 {XNANDPSU_PAGE_SIZE_8K, 10U, 24U, XNANDPSU_BCH, 0x2070U, 0x150U},
140 {XNANDPSU_PAGE_SIZE_16K, 9U, 1U, XNANDPSU_HAMMING, 0x4460U, 0x60U},
141 {XNANDPSU_PAGE_SIZE_16K, 9U, 4U, XNANDPSU_BCH, 0x43f0U, 0xD0U},
142 {XNANDPSU_PAGE_SIZE_16K, 9U, 8U, XNANDPSU_BCH, 0x4320U, 0x1A0U},
143 {XNANDPSU_PAGE_SIZE_16K, 9U, 12U, XNANDPSU_BCH, 0x4250U, 0x270U},
144 {XNANDPSU_PAGE_SIZE_16K, 10U, 24U, XNANDPSU_BCH, 0x4220U, 0x2A0U}
147 /**************************** Type Definitions *******************************/
148 static u8 isQemuPlatform = 0U;
149 /***************** Macros (Inline Functions) Definitions *********************/
151 /************************** Function Prototypes ******************************/
153 static s32 XNandPsu_FlashInit(XNandPsu *InstancePtr);
155 static void XNandPsu_InitGeometry(XNandPsu *InstancePtr, OnfiParamPage *Param);
157 static void XNandPsu_InitFeatures(XNandPsu *InstancePtr, OnfiParamPage *Param);
159 static s32 XNandPsu_PollRegTimeout(XNandPsu *InstancePtr, u32 RegOffset,
160 u32 Mask, u32 Timeout);
162 static void XNandPsu_SetPktSzCnt(XNandPsu *InstancePtr, u32 PktSize,
165 static void XNandPsu_SetPageColAddr(XNandPsu *InstancePtr, u32 Page, u16 Col);
167 static void XNandPsu_SetPageSize(XNandPsu *InstancePtr);
169 static void XNandPsu_SetBusWidth(XNandPsu *InstancePtr);
171 static void XNandPsu_SelectChip(XNandPsu *InstancePtr, u32 Target);
173 static s32 XNandPsu_OnfiReset(XNandPsu *InstancePtr, u32 Target);
175 static s32 XNandPsu_OnfiReadStatus(XNandPsu *InstancePtr, u32 Target,
178 static s32 XNandPsu_OnfiReadId(XNandPsu *InstancePtr, u32 Target, u8 IdAddr,
181 static s32 XNandPsu_OnfiReadParamPage(XNandPsu *InstancePtr, u32 Target,
184 static s32 XNandPsu_ProgramPage(XNandPsu *InstancePtr, u32 Target, u32 Page,
187 static s32 XNandPsu_ReadPage(XNandPsu *InstancePtr, u32 Target, u32 Page,
190 static s32 XNandPsu_CheckOnDie(XNandPsu *InstancePtr, OnfiParamPage *Param);
192 static void XNandPsu_SetEccAddrSize(XNandPsu *InstancePtr);
194 static s32 XNandPsu_ChangeReadColumn(XNandPsu *InstancePtr, u32 Target,
195 u32 Col, u32 PktSize, u32 PktCount,
198 static s32 XNandPsu_ChangeWriteColumn(XNandPsu *InstancePtr, u32 Target,
199 u32 Col, u32 PktSize, u32 PktCount,
202 static s32 XNandPsu_InitExtEcc(XNandPsu *InstancePtr, OnfiExtPrmPage *ExtPrm);
204 /*****************************************************************************/
207 * This function initializes a specific XNandPsu instance. This function must
208 * be called prior to using the NAND flash device to read or write any data.
210 * @param InstancePtr is a pointer to the XNandPsu instance.
211 * @param ConfigPtr points to XNandPsu device configuration structure.
212 * @param EffectiveAddr is the base address of NAND flash controller.
215 * - XST_SUCCESS if successful.
216 * - XST_FAILURE if fail.
218 * @note The user needs to first call the XNandPsu_LookupConfig() API
219 * which returns the Configuration structure pointer which is
220 * passed as a parameter to the XNandPsu_CfgInitialize() API.
222 ******************************************************************************/
223 s32 XNandPsu_CfgInitialize(XNandPsu *InstancePtr, XNandPsu_Config *ConfigPtr,
226 s32 Status = XST_FAILURE;
229 * Assert the input arguments.
231 Xil_AssertNonvoid(InstancePtr != NULL);
232 Xil_AssertNonvoid(ConfigPtr != NULL);
235 * Initialize InstancePtr Config structure
237 InstancePtr->Config.DeviceId = ConfigPtr->DeviceId;
238 InstancePtr->Config.BaseAddress = EffectiveAddr;
240 * Operate in Polling Mode
242 InstancePtr->Mode = XNANDPSU_POLLING;
244 * Enable MDMA mode by default
246 InstancePtr->DmaMode = XNANDPSU_MDMA;
247 InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
250 * Temporary hack for disabling the ecc on qemu as currently there
251 * is no support in the utility for writing images with ecc enabled.
253 #define CSU_VER_REG 0xFFCA0044U
254 #define CSU_VER_PLATFORM_MASK 0xF000U
255 #define CSU_VER_PLATFORM_QEMU_VAL 0x3000U
256 if ((*(u32 *)CSU_VER_REG & CSU_VER_PLATFORM_MASK) ==
257 CSU_VER_PLATFORM_QEMU_VAL) {
261 * Initialize the NAND flash targets
263 Status = XNandPsu_FlashInit(InstancePtr);
264 if (Status != XST_SUCCESS) {
265 #ifdef XNANDPSU_DEBUG
266 xil_printf("%s: Flash init failed\r\n",__func__);
273 if (InstancePtr->Features.EzNand != 0U) {
274 InstancePtr->EccMode = XNANDPSU_EZNAND;
275 } else if (InstancePtr->Features.OnDie != 0U) {
276 InstancePtr->EccMode = XNANDPSU_ONDIE;
278 InstancePtr->EccMode = XNANDPSU_HWECC;
281 if (isQemuPlatform != 0U) {
282 InstancePtr->EccMode = XNANDPSU_NONE;
287 * Initialize Ecc Error flip counters
289 InstancePtr->Ecc_Stat_PerPage_flips = 0U;
290 InstancePtr->Ecc_Stats_total_flips = 0U;
293 * Scan for the bad block table(bbt) stored in the flash & load it in
294 * memory(RAM). If bbt is not found, create bbt by scanning factory
295 * marked bad blocks and store it in last good blocks of flash.
297 XNandPsu_InitBbtDesc(InstancePtr);
298 Status = XNandPsu_ScanBbt(InstancePtr);
299 if (Status != XST_SUCCESS) {
300 #ifdef XNANDPSU_DEBUG
301 xil_printf("%s: BBT scan failed\r\n",__func__);
310 /*****************************************************************************/
313 * This function initializes the NAND flash and gets the geometry information.
315 * @param InstancePtr is a pointer to the XNandPsu instance.
318 * - XST_SUCCESS if successful.
319 * - XST_FAILURE if failed.
323 ******************************************************************************/
324 static s32 XNandPsu_FlashInit(XNandPsu *InstancePtr)
327 u8 Id[ONFI_SIG_LEN] = {0U};
328 OnfiParamPage Param = {0U};
329 s32 Status = XST_FAILURE;
334 OnfiExtPrmPage ExtParam __attribute__ ((aligned(64)));
337 * Assert the input arguments.
339 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
342 * Clear Data Interface Register
344 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
345 XNANDPSU_DATA_INTF_OFFSET, 0U);
347 /* Clear DMA Buffer Boundary Register */
348 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
349 XNANDPSU_DMA_BUF_BND_OFFSET, 0U);
351 for (Target = 0U; Target < XNANDPSU_MAX_TARGETS; Target++) {
355 Status = XNandPsu_OnfiReset(InstancePtr, Target);
356 if (Status != XST_SUCCESS) {
362 Status = XNandPsu_OnfiReadId(InstancePtr, Target,
366 if (Status != XST_SUCCESS) {
372 #ifdef XNANDPSU_DEBUG
373 xil_printf("%s: ONFI ID doesn't match\r\n",
376 Status = XST_FAILURE;
381 /* Read Parameter Page */
382 for(Index = 0U; Index < ONFI_MND_PRM_PGS; Index++) {
384 Status = XNandPsu_OnfiReadParamPage(InstancePtr,
385 Target, (u8 *)&Param);
387 PrmPgOff = Index * ONFI_PRM_PG_LEN;
388 PrmPgLen = ONFI_PRM_PG_LEN;
389 Status = XNandPsu_ChangeReadColumn(InstancePtr,
394 if (Status != XST_SUCCESS) {
398 Crc = XNandPsu_OnfiParamPageCrc((u8*)&Param, 0U,
400 if (Crc != Param.Crc) {
401 #ifdef XNANDPSU_DEBUG
402 xil_printf("%s: ONFI parameter page (%d) crc check failed\r\n",
410 if (Index >= ONFI_MND_PRM_PGS) {
411 Status = XST_FAILURE;
414 /* Fill Geometry for the first target */
416 XNandPsu_InitGeometry(InstancePtr, &Param);
417 XNandPsu_InitFeatures(InstancePtr, &Param);
418 if ((!InstancePtr->Features.EzNand) != 0U) {
419 Status =XNandPsu_CheckOnDie(InstancePtr,&Param);
420 if (Status != XST_SUCCESS) {
421 InstancePtr->Features.OnDie = 0U;
424 if (isQemuPlatform != 0U) {
425 InstancePtr->Geometry.NumTargets++;
428 if ((InstancePtr->Geometry.NumBitsECC == 0xFFU) &&
429 (InstancePtr->Features.ExtPrmPage != 0U)) {
430 /* ONFI 3.1 section 5.7.1.6 & 5.7.1.7 */
431 PrmPgLen = (u32)Param.ExtParamPageLen * 16U;
432 PrmPgOff = (u32)((u32)Param.NumOfParamPages *
434 (Index * (u32)PrmPgLen);
435 Status = XNandPsu_ChangeReadColumn(
440 (u8 *)(void *)&ExtParam);
441 if (Status != XST_SUCCESS) {
447 Crc = XNandPsu_OnfiParamPageCrc(
451 if (Crc != ExtParam.Crc) {
452 #ifdef XNANDPSU_DEBUG
453 xil_printf("%s: ONFI extended parameter page (%d) crc check failed\r\n",
456 Status = XST_FAILURE;
460 * Initialize Extended ECC info
462 Status = XNandPsu_InitExtEcc(
465 if (Status != XST_SUCCESS) {
466 #ifdef XNANDPSU_DEBUG
467 xil_printf("%s: Init extended ecc failed\r\n",__func__);
472 /* Configure ECC settings */
473 XNandPsu_SetEccAddrSize(InstancePtr);
475 InstancePtr->Geometry.NumTargets++;
478 * Calculate total number of blocks and total size of flash
480 InstancePtr->Geometry.NumPages = InstancePtr->Geometry.NumTargets *
481 InstancePtr->Geometry.NumTargetPages;
482 InstancePtr->Geometry.NumBlocks = InstancePtr->Geometry.NumTargets *
483 InstancePtr->Geometry.NumTargetBlocks;
484 InstancePtr->Geometry.DeviceSize =
485 (u64)InstancePtr->Geometry.NumTargets *
486 InstancePtr->Geometry.TargetSize;
488 Status = XST_SUCCESS;
493 /*****************************************************************************/
496 * This function initializes the geometry information from ONFI parameter page.
498 * @param InstancePtr is a pointer to the XNandPsu instance.
499 * @param Param is pointer to the ONFI parameter page.
506 ******************************************************************************/
507 static void XNandPsu_InitGeometry(XNandPsu *InstancePtr, OnfiParamPage *Param)
510 * Assert the input arguments.
512 Xil_AssertVoid(Param != NULL);
514 InstancePtr->Geometry.BytesPerPage = Param->BytesPerPage;
515 InstancePtr->Geometry.SpareBytesPerPage = Param->SpareBytesPerPage;
516 InstancePtr->Geometry.PagesPerBlock = Param->PagesPerBlock;
517 InstancePtr->Geometry.BlocksPerLun = Param->BlocksPerLun;
518 InstancePtr->Geometry.NumLuns = Param->NumLuns;
519 InstancePtr->Geometry.RowAddrCycles = Param->AddrCycles & 0xFU;
520 InstancePtr->Geometry.ColAddrCycles = (Param->AddrCycles >> 4U) & 0xFU;
521 InstancePtr->Geometry.NumBitsPerCell = Param->BitsPerCell;
522 InstancePtr->Geometry.NumBitsECC = Param->EccBits;
523 InstancePtr->Geometry.BlockSize = (Param->PagesPerBlock *
524 Param->BytesPerPage);
525 InstancePtr->Geometry.NumTargetBlocks = (Param->BlocksPerLun *
526 (u32)Param->NumLuns);
527 InstancePtr->Geometry.NumTargetPages = (Param->BlocksPerLun *
528 (u32)Param->NumLuns *
529 Param->PagesPerBlock);
530 InstancePtr->Geometry.TargetSize = ((u64)Param->BlocksPerLun *
531 (u64)Param->NumLuns *
532 (u64)Param->PagesPerBlock *
533 (u64)Param->BytesPerPage);
534 InstancePtr->Geometry.EccCodeWordSize = 9U; /* 2 power of 9 = 512 */
536 #ifdef XNANDPSU_DEBUG
537 xil_printf("Manufacturer: %s\r\n", Param->DeviceManufacturer);
538 xil_printf("Device Model: %s\r\n", Param->DeviceModel);
539 xil_printf("Jedec ID: 0x%x\r\n", Param->JedecManufacturerId);
540 xil_printf("Bytes Per Page: 0x%x\r\n", Param->BytesPerPage);
541 xil_printf("Spare Bytes Per Page: 0x%x\r\n", Param->SpareBytesPerPage);
542 xil_printf("Pages Per Block: 0x%x\r\n", Param->PagesPerBlock);
543 xil_printf("Blocks Per LUN: 0x%x\r\n", Param->BlocksPerLun);
544 xil_printf("Number of LUNs: 0x%x\r\n", Param->NumLuns);
545 xil_printf("Number of bits per cell: 0x%x\r\n", Param->BitsPerCell);
546 xil_printf("Number of ECC bits: 0x%x\r\n", Param->EccBits);
547 xil_printf("Block Size: 0x%x\r\n", InstancePtr->Geometry.BlockSize);
549 xil_printf("Number of Target Blocks: 0x%x\r\n",
550 InstancePtr->Geometry.NumTargetBlocks);
551 xil_printf("Number of Target Pages: 0x%x\r\n",
552 InstancePtr->Geometry.NumTargetPages);
557 /*****************************************************************************/
560 * This function initializes the feature list from ONFI parameter page.
562 * @param InstancePtr is a pointer to the XNandPsu instance.
563 * @param Param is pointer to ONFI parameter page buffer.
570 ******************************************************************************/
571 static void XNandPsu_InitFeatures(XNandPsu *InstancePtr, OnfiParamPage *Param)
574 * Assert the input arguments.
576 Xil_AssertVoid(Param != NULL);
578 InstancePtr->Features.BusWidth = ((Param->Features & (1U << 0U)) != 0U) ?
579 XNANDPSU_BUS_WIDTH_16 :
580 XNANDPSU_BUS_WIDTH_8;
581 InstancePtr->Features.NvDdr = ((Param->Features & (1U << 5)) != 0U) ?
583 InstancePtr->Features.EzNand = ((Param->Features & (1U << 9)) != 0U) ?
585 InstancePtr->Features.ExtPrmPage = ((Param->Features & (1U << 7)) != 0U) ?
589 /*****************************************************************************/
592 * This function checks if the flash supports on-die ECC.
594 * @param InstancePtr is a pointer to the XNandPsu instance.
595 * @param Param is pointer to ONFI parameter page.
602 ******************************************************************************/
603 static s32 XNandPsu_CheckOnDie(XNandPsu *InstancePtr, OnfiParamPage *Param)
605 s32 Status = XST_FAILURE;
606 u8 JedecId[2] = {0U};
607 u8 EccSetFeature[4] = {0x08U, 0x00U, 0x00U, 0x00U};
608 u8 EccGetFeature[4] ={0U};
611 * Assert the input arguments.
613 Xil_AssertNonvoid(Param != NULL);
616 * Check if this flash supports On-Die ECC.
617 * For more information, refer to Micron TN2945.
618 * Micron Flash: MT29F1G08ABADA, MT29F1G08ABBDA
620 * MT29F2G08ABBEA, MT29F2G16ABBEA,
621 * MT29F2G08ABAEA, MT29F2G16ABAEA,
622 * MT29F4G08ABBDA, MT29F4G16ABBDA,
623 * MT29F4G08ABADA, MT29F4G16ABADA,
624 * MT29F8G08ADBDA, MT29F8G16ADBDA,
625 * MT29F8G08ADADA, MT29F8G16ADADA
631 Status = XNandPsu_OnfiReadId(InstancePtr, 0U, 0x00U, 2U, &JedecId[0]);
632 if (Status != XST_SUCCESS) {
636 if ((JedecId[0] == 0x2CU) &&
640 ((JedecId[1] == 0xF1U) ||
641 (JedecId[1] == 0xA1U) ||
642 (JedecId[1] == 0xB1U) ||
646 (JedecId[1] == 0xAAU) ||
647 (JedecId[1] == 0xBAU) ||
648 (JedecId[1] == 0xDAU) ||
649 (JedecId[1] == 0xCAU) ||
653 (JedecId[1] == 0xACU) ||
654 (JedecId[1] == 0xBCU) ||
655 (JedecId[1] == 0xDCU) ||
656 (JedecId[1] == 0xCCU) ||
660 (JedecId[1] == 0xA3U) ||
661 (JedecId[1] == 0xB3U) ||
662 (JedecId[1] == 0xD3U) ||
663 (JedecId[1] == 0xC3U))) {
664 #ifdef XNANDPSU_DEBUG
665 xil_printf("%s: Ondie flash detected, jedec id 0x%x 0x%x\r\n",
666 __func__, JedecId[0], JedecId[1]);
671 Status = XNandPsu_SetFeature(InstancePtr, 0U, 0x90U,
673 if (Status != XST_SUCCESS) {
674 #ifdef XNANDPSU_DEBUG
675 xil_printf("%s: Ondie set_feature failed\r\n",
681 * Check to see if ECC feature is set
683 Status = XNandPsu_GetFeature(InstancePtr, 0U, 0x90U,
685 if (Status != XST_SUCCESS) {
686 #ifdef XNANDPSU_DEBUG
687 xil_printf("%s: Ondie get_feature failed\r\n",
692 if ((EccGetFeature[0] & 0x08U) != 0U) {
693 InstancePtr->Features.OnDie = 1U;
694 Status = XST_SUCCESS;
698 * On-Die flash not found
700 Status = XST_FAILURE;
706 /*****************************************************************************/
709 * This function enables DMA mode of controller operation.
711 * @param InstancePtr is a pointer to the XNandPsu instance.
718 ******************************************************************************/
719 void XNandPsu_EnableDmaMode(XNandPsu *InstancePtr)
722 * Assert the input arguments.
724 Xil_AssertVoid(InstancePtr != NULL);
725 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
727 InstancePtr->DmaMode = XNANDPSU_MDMA;
730 /*****************************************************************************/
733 * This function disables DMA mode of driver/controller operation.
735 * @param InstancePtr is a pointer to the XNandPsu instance.
742 ******************************************************************************/
743 void XNandPsu_DisableDmaMode(XNandPsu *InstancePtr)
746 * Assert the input arguments.
748 Xil_AssertVoid(InstancePtr != NULL);
749 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
751 InstancePtr->DmaMode = XNANDPSU_PIO;
754 /*****************************************************************************/
757 * This function enables ECC mode of driver/controller operation.
759 * @param InstancePtr is a pointer to the XNandPsu instance.
766 ******************************************************************************/
767 void XNandPsu_EnableEccMode(XNandPsu *InstancePtr)
770 * Assert the input arguments.
772 Xil_AssertVoid(InstancePtr != NULL);
773 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
775 InstancePtr->EccMode = XNANDPSU_HWECC;
778 /*****************************************************************************/
781 * This function disables ECC mode of driver/controller operation.
783 * @param InstancePtr is a pointer to the XNandPsu instance.
790 ******************************************************************************/
791 void XNandPsu_DisableEccMode(XNandPsu *InstancePtr)
794 * Assert the input arguments.
796 Xil_AssertVoid(InstancePtr != NULL);
797 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
799 InstancePtr->EccMode = XNANDPSU_NONE;
802 /*****************************************************************************/
805 * This function enables storing bbt version in oob area.
807 * @param InstancePtr is a pointer to the XNandPsu instance.
814 ******************************************************************************/
815 void XNandPsu_EnableBbtOobMode(XNandPsu *InstancePtr)
818 * Assert the input arguments.
820 Xil_AssertVoid(InstancePtr != NULL);
821 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
822 InstancePtr->BbtDesc.Option = XNANDPSU_BBT_OOB;
823 InstancePtr->BbtMirrorDesc.Option = XNANDPSU_BBT_OOB;
825 * Setting the Signature and Version Offset
827 InstancePtr->BbtDesc.SigOffset = XNANDPSU_BBT_DESC_SIG_OFFSET;
828 InstancePtr->BbtMirrorDesc.SigOffset = XNANDPSU_BBT_DESC_SIG_OFFSET;
829 InstancePtr->BbtDesc.VerOffset = XNANDPSU_BBT_DESC_VER_OFFSET;
830 InstancePtr->BbtMirrorDesc.VerOffset = XNANDPSU_BBT_DESC_VER_OFFSET;
833 /*****************************************************************************/
836 * This function enables storing bbt version in no oob area i.e. page memory.
838 * @param InstancePtr is a pointer to the XNandPsu instance.
845 ******************************************************************************/
846 void XNandPsu_DisableBbtOobMode(XNandPsu *InstancePtr)
849 * Assert the input arguments.
851 Xil_AssertVoid(InstancePtr != NULL);
852 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
853 InstancePtr->BbtDesc.Option = XNANDPSU_BBT_NO_OOB;
854 InstancePtr->BbtMirrorDesc.Option = XNANDPSU_BBT_NO_OOB;
856 * Setting the Signature and Version Offset
858 InstancePtr->BbtDesc.SigOffset = XNANDPSU_NO_OOB_BBT_DESC_SIG_OFFSET;
859 InstancePtr->BbtMirrorDesc.SigOffset =
860 XNANDPSU_NO_OOB_BBT_DESC_SIG_OFFSET;
861 InstancePtr->BbtDesc.VerOffset = XNANDPSU_NO_OOB_BBT_DESC_VER_OFFSET;
862 InstancePtr->BbtMirrorDesc.VerOffset =
863 XNANDPSU_NO_OOB_BBT_DESC_VER_OFFSET;
866 /*****************************************************************************/
869 * This function polls for a register bit set status till the timeout.
871 * @param InstancePtr is a pointer to the XNandPsu instance.
872 * @param RegOffset is the offset of register.
873 * @param Mask is the bitmask.
874 * @param Timeout is the timeout value.
877 * - XST_SUCCESS if successful.
878 * - XST_FAILURE if failed.
882 ******************************************************************************/
883 static s32 XNandPsu_PollRegTimeout(XNandPsu *InstancePtr, u32 RegOffset,
884 u32 Mask, u32 Timeout)
886 s32 Status = XST_FAILURE;
888 u32 TimeoutVar = Timeout;
890 while (TimeoutVar > 0U) {
891 RegVal = XNandPsu_ReadReg(InstancePtr->Config.BaseAddress,
893 if ((RegVal & Mask) != 0U) {
899 if (TimeoutVar <= 0U) {
900 Status = XST_FAILURE;
902 Status = XST_SUCCESS;
908 /*****************************************************************************/
911 * This function sets packet size and packet count values in packet register.
913 * @param InstancePtr is a pointer to the XNandPsu instance.
914 * @param PktSize is the packet size.
915 * @param PktCount is the packet count.
922 ******************************************************************************/
923 static void XNandPsu_SetPktSzCnt(XNandPsu *InstancePtr, u32 PktSize,
927 * Assert the input arguments.
929 Xil_AssertVoid(PktSize <= XNANDPSU_MAX_PKT_SIZE);
930 Xil_AssertVoid(PktCount <= XNANDPSU_MAX_PKT_COUNT);
933 * Update Packet Register with pkt size and count
935 XNandPsu_ReadModifyWrite(InstancePtr, XNANDPSU_PKT_OFFSET,
936 ((u32)XNANDPSU_PKT_PKT_SIZE_MASK |
937 (u32)XNANDPSU_PKT_PKT_CNT_MASK),
938 ((PktSize & XNANDPSU_PKT_PKT_SIZE_MASK) |
939 ((PktCount << XNANDPSU_PKT_PKT_CNT_SHIFT) &
940 XNANDPSU_PKT_PKT_CNT_MASK)));
943 /*****************************************************************************/
946 * This function sets Page and Column values in the Memory address registers.
948 * @param InstancePtr is a pointer to the XNandPsu instance.
949 * @param Page is the page value.
950 * @param Col is the column value.
957 ******************************************************************************/
958 static void XNandPsu_SetPageColAddr(XNandPsu *InstancePtr, u32 Page, u16 Col)
961 * Program Memory Address Register 1
963 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
964 XNANDPSU_MEM_ADDR1_OFFSET,
965 ((Col & XNANDPSU_MEM_ADDR1_COL_ADDR_MASK) |
966 ((Page << (u32)XNANDPSU_MEM_ADDR1_PG_ADDR_SHIFT) &
967 XNANDPSU_MEM_ADDR1_PG_ADDR_MASK)));
969 * Program Memory Address Register 2
971 XNandPsu_ReadModifyWrite(InstancePtr, XNANDPSU_MEM_ADDR2_OFFSET,
972 XNANDPSU_MEM_ADDR2_MEM_ADDR_MASK,
973 ((Page >> XNANDPSU_MEM_ADDR1_PG_ADDR_SHIFT) &
974 XNANDPSU_MEM_ADDR2_MEM_ADDR_MASK));
977 /*****************************************************************************/
980 * This function sets the size of page in Command Register.
982 * @param InstancePtr is a pointer to the XNandPsu instance.
989 ******************************************************************************/
990 static void XNandPsu_SetPageSize(XNandPsu *InstancePtr)
992 u32 PageSizeMask = 0;
993 u32 PageSize = InstancePtr->Geometry.BytesPerPage;
996 * Calculate page size mask
999 case XNANDPSU_PAGE_SIZE_512:
1000 PageSizeMask = (0U << XNANDPSU_CMD_PG_SIZE_SHIFT);
1002 case XNANDPSU_PAGE_SIZE_2K:
1003 PageSizeMask = (1U << XNANDPSU_CMD_PG_SIZE_SHIFT);
1005 case XNANDPSU_PAGE_SIZE_4K:
1006 PageSizeMask = (2U << XNANDPSU_CMD_PG_SIZE_SHIFT);
1008 case XNANDPSU_PAGE_SIZE_8K:
1009 PageSizeMask = (3U << XNANDPSU_CMD_PG_SIZE_SHIFT);
1011 case XNANDPSU_PAGE_SIZE_16K:
1012 PageSizeMask = (4U << XNANDPSU_CMD_PG_SIZE_SHIFT);
1014 case XNANDPSU_PAGE_SIZE_1K_16BIT:
1015 PageSizeMask = (5U << XNANDPSU_CMD_PG_SIZE_SHIFT);
1024 * Update Command Register
1026 XNandPsu_ReadModifyWrite(InstancePtr, XNANDPSU_CMD_OFFSET,
1027 XNANDPSU_CMD_PG_SIZE_MASK, PageSizeMask);
1030 /*****************************************************************************/
1033 * This function setup the Ecc Register.
1035 * @param InstancePtr is a pointer to the XNandPsu instance.
1042 ******************************************************************************/
1043 static void XNandPsu_SetEccAddrSize(XNandPsu *InstancePtr)
1045 u32 PageSize = InstancePtr->Geometry.BytesPerPage;
1046 u32 CodeWordSize = InstancePtr->Geometry.EccCodeWordSize;
1047 u32 NumEccBits = InstancePtr->Geometry.NumBitsECC;
1052 for (Index = 0U; Index < (sizeof(EccMatrix)/sizeof(XNandPsu_EccMatrix));
1054 if ((EccMatrix[Index].PageSize == PageSize) &&
1055 (EccMatrix[Index].CodeWordSize >= CodeWordSize)) {
1056 if (EccMatrix[Index].NumEccBits >= NumEccBits) {
1067 if(InstancePtr->Geometry.SpareBytesPerPage < 64U) {
1068 InstancePtr->EccCfg.EccAddr = PageSize;
1071 InstancePtr->EccCfg.EccAddr = PageSize +
1072 (InstancePtr->Geometry.SpareBytesPerPage
1073 - EccMatrix[Found].EccSize);
1075 InstancePtr->EccCfg.EccSize = EccMatrix[Found].EccSize;
1076 InstancePtr->EccCfg.NumEccBits = EccMatrix[Found].NumEccBits;
1077 InstancePtr->EccCfg.CodeWordSize =
1078 EccMatrix[Found].CodeWordSize;
1079 #ifdef XNANDPSU_DEBUG
1080 xil_printf("ECC: addr 0x%x size 0x%x numbits %d "
1082 InstancePtr->EccCfg.EccAddr,
1083 InstancePtr->EccCfg.EccSize,
1084 InstancePtr->EccCfg.NumEccBits,
1085 InstancePtr->EccCfg.CodeWordSize);
1087 if (EccMatrix[Found].IsBCH == XNANDPSU_HAMMING) {
1088 InstancePtr->EccCfg.IsBCH = 0U;
1090 InstancePtr->EccCfg.IsBCH = 1U;
1093 * Write ECC register
1095 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
1096 (u32)XNANDPSU_ECC_OFFSET,
1097 ((u32)InstancePtr->EccCfg.EccAddr |
1098 ((u32)InstancePtr->EccCfg.EccSize << (u32)16) |
1099 ((u32)InstancePtr->EccCfg.IsBCH << (u32)27)));
1101 if (EccMatrix[Found].IsBCH == XNANDPSU_BCH) {
1103 * Write memory address register 2
1105 switch(InstancePtr->EccCfg.NumEccBits) {
1124 XNandPsu_ReadModifyWrite(InstancePtr,
1125 XNANDPSU_MEM_ADDR2_OFFSET,
1126 XNANDPSU_MEM_ADDR2_NFC_BCH_MODE_MASK,
1128 (u32)XNANDPSU_MEM_ADDR2_NFC_BCH_MODE_SHIFT));
1133 /*****************************************************************************/
1136 * This function setup the Ecc Spare Command Register.
1138 * @param InstancePtr is a pointer to the XNandPsu instance.
1145 ******************************************************************************/
1146 static void XNandPsu_SetEccSpareCmd(XNandPsu *InstancePtr, u16 SpareCmd,
1149 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
1150 (u32)XNANDPSU_ECC_SPR_CMD_OFFSET,
1151 (u32)SpareCmd | ((u32)AddrCycles << 28U));
1154 /*****************************************************************************/
1157 * This function sets the flash bus width in memory address2 register.
1159 * @param InstancePtr is a pointer to the XNandPsu instance.
1166 ******************************************************************************/
1167 static void XNandPsu_SetBusWidth(XNandPsu *InstancePtr)
1170 * Update Memory Address2 register with bus width
1172 XNandPsu_ReadModifyWrite(InstancePtr, XNANDPSU_MEM_ADDR2_OFFSET,
1173 XNANDPSU_MEM_ADDR2_BUS_WIDTH_MASK,
1174 (InstancePtr->Features.BusWidth <<
1175 XNANDPSU_MEM_ADDR2_BUS_WIDTH_SHIFT));
1179 /*****************************************************************************/
1182 * This function sets the chip select value in memory address2 register.
1184 * @param InstancePtr is a pointer to the XNandPsu instance.
1185 * @param Target is the chip select value.
1192 ******************************************************************************/
1193 static void XNandPsu_SelectChip(XNandPsu *InstancePtr, u32 Target)
1196 * Update Memory Address2 register with chip select
1198 XNandPsu_ReadModifyWrite(InstancePtr, XNANDPSU_MEM_ADDR2_OFFSET,
1199 XNANDPSU_MEM_ADDR2_CHIP_SEL_MASK,
1200 ((Target << XNANDPSU_MEM_ADDR2_CHIP_SEL_SHIFT) &
1201 XNANDPSU_MEM_ADDR2_CHIP_SEL_MASK));
1204 /*****************************************************************************/
1207 * This function sends ONFI Reset command to the flash.
1209 * @param InstancePtr is a pointer to the XNandPsu instance.
1210 * @param Target is the chip select value.
1213 * - XST_SUCCESS if successful.
1214 * - XST_FAILURE if failed.
1218 ******************************************************************************/
1219 static s32 XNandPsu_OnfiReset(XNandPsu *InstancePtr, u32 Target)
1221 s32 Status = XST_FAILURE;
1224 * Assert the input arguments.
1226 Xil_AssertNonvoid(Target < XNANDPSU_MAX_TARGETS);
1229 * Enable Transfer Complete Interrupt in Interrupt Status Register
1231 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1232 XNANDPSU_INTR_STS_EN_OFFSET,
1233 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
1235 * Program Command Register
1237 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RST, ONFI_CMD_INVALID, 0U,
1240 * Program Memory Address Register2 for chip select
1242 XNandPsu_SelectChip(InstancePtr, Target);
1244 * Set Reset in Program Register
1246 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1247 XNANDPSU_PROG_OFFSET, XNANDPSU_PROG_RST_MASK);
1250 * Poll for Transfer Complete event
1252 Status = XNandPsu_PollRegTimeout(
1254 XNANDPSU_INTR_STS_OFFSET,
1255 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK,
1256 XNANDPSU_INTR_POLL_TIMEOUT);
1257 if (Status != XST_SUCCESS) {
1258 #ifdef XNANDPSU_DEBUG
1259 xil_printf("%s: Poll for xfer complete timeout\r\n",
1265 * Clear Transfer Complete Interrupt in Interrupt Status Enable
1268 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1269 (XNANDPSU_INTR_STS_EN_OFFSET), 0U);
1271 * Clear Transfer Complete Interrupt in Interrupt Status Register
1273 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1274 XNANDPSU_INTR_STS_OFFSET,
1275 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK);
1281 /*****************************************************************************/
1284 * This function sends ONFI Read Status command to the flash.
1286 * @param InstancePtr is a pointer to the XNandPsu instance.
1287 * @param Target is the chip select value.
1288 * @param OnfiStatus is the ONFI status value to return.
1291 * - XST_SUCCESS if successful.
1292 * - XST_FAILURE if failed.
1296 ******************************************************************************/
1297 static s32 XNandPsu_OnfiReadStatus(XNandPsu *InstancePtr, u32 Target,
1300 s32 Status = XST_FAILURE;
1303 * Assert the input arguments.
1305 Xil_AssertNonvoid(Target < XNANDPSU_MAX_TARGETS);
1306 Xil_AssertNonvoid(OnfiStatus != NULL);
1308 * Enable Transfer Complete Interrupt in Interrupt Status Register
1310 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1311 XNANDPSU_INTR_STS_EN_OFFSET,
1312 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
1314 * Program Command Register
1316 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RD_STS, ONFI_CMD_INVALID,
1319 * Program Memory Address Register2 for chip select
1321 XNandPsu_SelectChip(InstancePtr, Target);
1323 * Program Packet Size and Packet Count
1325 if(InstancePtr->DataInterface == XNANDPSU_SDR){
1326 XNandPsu_SetPktSzCnt(InstancePtr, 1U, 1U);
1329 XNandPsu_SetPktSzCnt(InstancePtr, 2U, 1U);
1333 * Set Read Status in Program Register
1335 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1336 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_STS_MASK);
1338 * Poll for Transfer Complete event
1340 Status = XNandPsu_PollRegTimeout(
1342 XNANDPSU_INTR_STS_OFFSET,
1343 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK,
1344 XNANDPSU_INTR_POLL_TIMEOUT);
1345 if (Status != XST_SUCCESS) {
1346 #ifdef XNANDPSU_DEBUG
1347 xil_printf("%s: Poll for xfer complete timeout\r\n",
1353 * Clear Transfer Complete Interrupt in Interrupt Status Enable
1356 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1357 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
1359 * Clear Transfer Complete Interrupt in Interrupt Status Register
1361 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1362 XNANDPSU_INTR_STS_OFFSET,
1363 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK);
1367 *OnfiStatus = (u8) XNandPsu_ReadReg(InstancePtr->Config.BaseAddress,
1368 XNANDPSU_FLASH_STS_OFFSET);
1375 /*****************************************************************************/
1378 * This function sends ONFI Read ID command to the flash.
1380 * @param InstancePtr is a pointer to the XNandPsu instance.
1381 * @param Target is the chip select value.
1382 * @param Buf is the ONFI ID value to return.
1385 * - XST_SUCCESS if successful.
1386 * - XST_FAILURE if failed.
1390 ******************************************************************************/
1391 static s32 XNandPsu_OnfiReadId(XNandPsu *InstancePtr, u32 Target, u8 IdAddr,
1394 s32 Status = XST_FAILURE;
1397 u32 *BufPtr = (u32 *)(void *)Buf;
1402 * Assert the input arguments.
1404 Xil_AssertNonvoid(Target < XNANDPSU_MAX_TARGETS);
1405 Xil_AssertNonvoid(Buf != NULL);
1408 * Enable Buffer Read Ready Interrupt in Interrupt Status Enable
1411 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1412 XNANDPSU_INTR_STS_EN_OFFSET,
1413 XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK);
1417 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RD_ID, ONFI_CMD_INVALID, 0U,
1418 0U, ONFI_READ_ID_ADDR_CYCLES);
1421 * Program Column, Page, Block address
1423 XNandPsu_SetPageColAddr(InstancePtr, 0U, IdAddr);
1425 * Program Memory Address Register2 for chip select
1427 XNandPsu_SelectChip(InstancePtr, Target);
1429 * Program Packet Size and Packet Count
1431 XNandPsu_SetPktSzCnt(InstancePtr, IdLen, 1U);
1433 * Set Read ID in Program Register
1435 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1436 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_ID_MASK);
1439 * Poll for Buffer Read Ready event
1441 Status = XNandPsu_PollRegTimeout(
1443 XNANDPSU_INTR_STS_OFFSET,
1444 XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK,
1445 XNANDPSU_INTR_POLL_TIMEOUT);
1446 if (Status != XST_SUCCESS) {
1447 #ifdef XNANDPSU_DEBUG
1448 xil_printf("%s: Poll for buf read ready timeout\r\n",
1454 * Enable Transfer Complete Interrupt in Interrupt
1455 * Status Enable Register
1458 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1459 XNANDPSU_INTR_STS_EN_OFFSET,
1460 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
1463 * Clear Buffer Read Ready Interrupt in Interrupt Status
1466 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1467 XNANDPSU_INTR_STS_OFFSET,
1468 XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK);
1470 * Read Packet Data from Data Port Register
1472 for (Index = 0U; Index < (IdLen/4); Index++) {
1473 BufPtr[Index] = XNandPsu_ReadReg(
1474 InstancePtr->Config.BaseAddress,
1475 XNANDPSU_BUF_DATA_PORT_OFFSET);
1479 RegVal = XNandPsu_ReadReg(
1480 InstancePtr->Config.BaseAddress,
1481 XNANDPSU_BUF_DATA_PORT_OFFSET);
1482 for (RemIdx = 0U; RemIdx < Rem; RemIdx++) {
1483 Buf[(Index * 4U) + RemIdx] = (u8) (RegVal >>
1484 (RemIdx * 8U)) & 0xFFU;
1489 * Poll for Transfer Complete event
1491 Status = XNandPsu_PollRegTimeout(
1493 XNANDPSU_INTR_STS_OFFSET,
1494 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK,
1495 XNANDPSU_INTR_POLL_TIMEOUT);
1496 if (Status != XST_SUCCESS) {
1497 #ifdef XNANDPSU_DEBUG
1498 xil_printf("%s: Poll for xfer complete timeout\r\n",
1504 * Clear Transfer Complete Interrupt in Interrupt Status Enable
1507 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1508 XNANDPSU_INTR_STS_EN_OFFSET,0U);
1510 * Clear Transfer Complete Interrupt in Interrupt Status Register
1512 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1513 XNANDPSU_INTR_STS_OFFSET,
1514 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK);
1520 /*****************************************************************************/
1523 * This function sends the ONFI Read Parameter Page command to flash.
1525 * @param InstancePtr is a pointer to the XNandPsu instance.
1526 * @param Target is the chip select value.
1527 * @param PrmIndex is the index of parameter page.
1528 * @param Buf is the parameter page information to return.
1531 * - XST_SUCCESS if successful.
1532 * - XST_FAILURE if failed.
1536 ******************************************************************************/
1537 static s32 XNandPsu_OnfiReadParamPage(XNandPsu *InstancePtr, u32 Target,
1540 s32 Status = XST_FAILURE;
1541 u32 *BufPtr = (u32 *)(void *)Buf;
1545 * Assert the input arguments.
1547 Xil_AssertNonvoid(Target < XNANDPSU_MAX_TARGETS);
1548 Xil_AssertNonvoid(Buf != NULL);
1551 * Enable Buffer Read Ready Interrupt in Interrupt Status Enable
1554 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1555 XNANDPSU_INTR_STS_EN_OFFSET,
1556 XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK);
1560 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RD_PRM_PG, ONFI_CMD_INVALID,
1561 0U, 0U, ONFI_PRM_PG_ADDR_CYCLES);
1563 * Program Column, Page, Block address
1565 XNandPsu_SetPageColAddr(InstancePtr, 0U, 0U);
1567 * Program Memory Address Register2 for chip select
1569 XNandPsu_SelectChip(InstancePtr, Target);
1571 * Program Packet Size and Packet Count
1573 XNandPsu_SetPktSzCnt(InstancePtr, ONFI_PRM_PG_LEN, 1U);
1575 * Set Read Parameter Page in Program Register
1577 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1578 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_PRM_PG_MASK);
1581 * Poll for Buffer Read Ready event
1583 Status = XNandPsu_PollRegTimeout(
1585 XNANDPSU_INTR_STS_OFFSET,
1586 XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK,
1587 XNANDPSU_INTR_POLL_TIMEOUT);
1588 if (Status != XST_SUCCESS) {
1589 #ifdef XNANDPSU_DEBUG
1590 xil_printf("%s: Poll for buf read ready timeout\r\n",
1598 * Enable Transfer Complete Interrupt in Interrupt
1599 * Status Enable Register
1601 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1602 (XNANDPSU_INTR_STS_EN_OFFSET),
1603 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
1605 * Clear Buffer Read Ready Interrupt in Interrupt Status
1608 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1609 XNANDPSU_INTR_STS_OFFSET,
1610 XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK);
1612 * Read Packet Data from Data Port Register
1614 for (Index = 0U; Index < (ONFI_PRM_PG_LEN/4); Index++) {
1615 BufPtr[Index] = XNandPsu_ReadReg(
1616 InstancePtr->Config.BaseAddress,
1617 XNANDPSU_BUF_DATA_PORT_OFFSET);
1621 * Poll for Transfer Complete event
1623 Status = XNandPsu_PollRegTimeout(
1625 XNANDPSU_INTR_STS_OFFSET,
1626 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK,
1627 XNANDPSU_INTR_POLL_TIMEOUT);
1628 if (Status != XST_SUCCESS) {
1629 #ifdef XNANDPSU_DEBUG
1630 xil_printf("%s: Poll for xfer complete timeout\r\n",
1636 * Clear Transfer Complete Interrupt in Interrupt Status Enable
1639 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1640 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
1642 * Clear Transfer Complete Interrupt in Interrupt Status Register
1644 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
1645 XNANDPSU_INTR_STS_OFFSET,
1646 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK);
1652 /*****************************************************************************/
1655 * This function returns the length including bad blocks from a given offset and
1658 * @param InstancePtr is the pointer to the XNandPsu instance.
1659 * @param Offset is the flash data address to read from.
1660 * @param Length is number of bytes to read.
1663 * - Return actual length including bad blocks.
1667 ******************************************************************************/
1668 static s32 XNandPsu_CalculateLength(XNandPsu *InstancePtr, u64 Offset,
1676 u64 OffsetVar = Offset;
1678 BlockSize = InstancePtr->Geometry.BlockSize;
1680 while (TempLen < Length) {
1681 Block = (u32) ((u32)OffsetVar/BlockSize);
1682 BlockLen = BlockSize - ((u32)OffsetVar % BlockSize);
1684 * Check if the block is bad
1686 Status = XNandPsu_IsBlockBad(InstancePtr, Block);
1687 if (Status != XST_SUCCESS) {
1691 TempLen += BlockLen;
1693 if (OffsetVar >= InstancePtr->Geometry.DeviceSize) {
1694 Status = XST_FAILURE;
1697 OffsetVar += BlockLen;
1700 Status = XST_SUCCESS;
1705 /*****************************************************************************/
1708 * This function writes to the flash.
1710 * @param InstancePtr is a pointer to the XNandPsu instance.
1711 * @param Offset is the starting offset of flash to write.
1712 * @param Length is the number of bytes to write.
1713 * @param SrcBuf is the source data buffer to write.
1716 * - XST_SUCCESS if successful.
1717 * - XST_FAILURE if failed.
1721 ******************************************************************************/
1722 s32 XNandPsu_Write(XNandPsu *InstancePtr, u64 Offset, u64 Length, u8 *SrcBuf)
1724 s32 Status = XST_FAILURE;
1729 u32 PartialBytes = 0;
1733 u8 *Ptr = (u8 *)SrcBuf;
1735 u64 OffsetVar = Offset;
1736 u64 LengthVar = Length;
1739 * Assert the input arguments.
1741 Xil_AssertNonvoid(InstancePtr != NULL);
1742 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
1743 Xil_AssertNonvoid(SrcBuf != NULL);
1744 Xil_AssertNonvoid(LengthVar != 0U);
1745 Xil_AssertNonvoid((OffsetVar + LengthVar) <
1746 InstancePtr->Geometry.DeviceSize);
1749 * Check if write operation exceeds flash size when including
1752 Status = XNandPsu_CalculateLength(InstancePtr, OffsetVar, LengthVar);
1753 if (Status != XST_SUCCESS) {
1757 while (LengthVar > 0U) {
1758 Block = (u32) (OffsetVar/InstancePtr->Geometry.BlockSize);
1760 * Skip the bad blocks. Increment the offset by block size.
1761 * For better results, always program the flash starting at
1764 if (XNandPsu_IsBlockBad(InstancePtr, Block) == XST_SUCCESS) {
1765 OffsetVar += (u64)InstancePtr->Geometry.BlockSize;
1769 * Calculate Page and Column address values
1771 Page = (u32) (OffsetVar/InstancePtr->Geometry.BytesPerPage);
1772 Col = (u32) (OffsetVar &
1773 (InstancePtr->Geometry.BytesPerPage - 1U));
1776 * Check if partial write.
1777 * If column address is > 0 or Length is < page size
1780 (LengthVar < InstancePtr->Geometry.BytesPerPage)) {
1781 RemLen = InstancePtr->Geometry.BytesPerPage - Col;
1782 PartialBytes = (RemLen < (u32)LengthVar) ?
1783 RemLen : (u32)LengthVar;
1786 Target = (u32) (OffsetVar/InstancePtr->Geometry.TargetSize);
1787 if (Page > InstancePtr->Geometry.NumTargetPages) {
1788 Page %= InstancePtr->Geometry.NumTargetPages;
1792 * Check if partial write
1794 if (PartialBytes > 0U) {
1795 BufPtr = &InstancePtr->PartialDataBuf[0];
1796 memset(BufPtr, 0xFF,
1797 InstancePtr->Geometry.BytesPerPage);
1798 memcpy(BufPtr + Col, Ptr, PartialBytes);
1800 NumBytes = PartialBytes;
1803 NumBytes = (InstancePtr->Geometry.BytesPerPage <
1805 InstancePtr->Geometry.BytesPerPage :
1811 Status = XNandPsu_ProgramPage(InstancePtr, Target, Page, 0U,
1813 if (Status != XST_SUCCESS) {
1820 Status = XNandPsu_OnfiReadStatus(InstancePtr, Target,
1822 if (Status != XST_SUCCESS) {
1825 if ((OnfiStatus & (1U << 6U)) != 0U) {
1826 if ((OnfiStatus & (1U << 0U)) != 0U) {
1827 Status = XST_FAILURE;
1831 } while (((OnfiStatus >> 6U) & 0x1U) == 0U);
1834 OffsetVar += NumBytes;
1835 LengthVar -= NumBytes;
1838 Status = XST_SUCCESS;
1843 /*****************************************************************************/
1846 * This function reads from the flash.
1848 * @param InstancePtr is a pointer to the XNandPsu instance.
1849 * @param Offset is the starting offset of flash to read.
1850 * @param Length is the number of bytes to read.
1851 * @param DestBuf is the destination data buffer to fill in.
1854 * - XST_SUCCESS if successful.
1855 * - XST_FAILURE if failed.
1859 ******************************************************************************/
1860 s32 XNandPsu_Read(XNandPsu *InstancePtr, u64 Offset, u64 Length, u8 *DestBuf)
1862 s32 Status = XST_FAILURE;
1867 u32 PartialBytes = 0U;
1871 u8 *Ptr = (u8 *)DestBuf;
1872 u64 OffsetVar = Offset;
1873 u64 LengthVar = Length;
1876 * Assert the input arguments.
1878 Xil_AssertNonvoid(InstancePtr != NULL);
1879 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
1880 Xil_AssertNonvoid(LengthVar != 0U);
1881 Xil_AssertNonvoid((OffsetVar + LengthVar) <
1882 InstancePtr->Geometry.DeviceSize);
1885 * Check if read operation exceeds flash size when including
1888 Status = XNandPsu_CalculateLength(InstancePtr, OffsetVar, LengthVar);
1889 if (Status != XST_SUCCESS) {
1893 while (LengthVar > 0U) {
1894 Block = (u32) (OffsetVar/InstancePtr->Geometry.BlockSize);
1896 * Skip the bad block. Increment the offset by block size.
1897 * The flash programming utility must make sure to start
1898 * writing always at a block boundary and skip blocks if any.
1900 if (XNandPsu_IsBlockBad(InstancePtr, Block) == XST_SUCCESS) {
1901 OffsetVar += (u64)InstancePtr->Geometry.BlockSize;
1905 * Calculate Page and Column address values
1907 Page = (u32) (OffsetVar/InstancePtr->Geometry.BytesPerPage);
1908 Col = (u32) (OffsetVar &
1909 (InstancePtr->Geometry.BytesPerPage - 1U));
1912 * Check if partial write.
1913 * If column address is > 0 or Length is < page size
1916 (LengthVar < InstancePtr->Geometry.BytesPerPage)) {
1917 RemLen = InstancePtr->Geometry.BytesPerPage - Col;
1918 PartialBytes = ((u32)RemLen < (u32)LengthVar) ?
1919 (u32)RemLen : (u32)LengthVar;
1922 Target = (u32) (OffsetVar/InstancePtr->Geometry.TargetSize);
1923 if (Page > InstancePtr->Geometry.NumTargetPages) {
1924 Page %= InstancePtr->Geometry.NumTargetPages;
1927 * Check if partial read
1929 if (PartialBytes > 0U) {
1930 BufPtr = &InstancePtr->PartialDataBuf[0];
1931 NumBytes = PartialBytes;
1934 NumBytes = (InstancePtr->Geometry.BytesPerPage <
1936 InstancePtr->Geometry.BytesPerPage :
1942 Status = XNandPsu_ReadPage(InstancePtr, Target, Page, 0U,
1944 if (Status != XST_SUCCESS) {
1947 if (PartialBytes > 0U) {
1948 memcpy(Ptr, BufPtr + Col, NumBytes);
1951 OffsetVar += NumBytes;
1952 LengthVar -= NumBytes;
1955 Status = XST_SUCCESS;
1960 /*****************************************************************************/
1963 * This function erases the flash.
1965 * @param InstancePtr is a pointer to the XNandPsu instance.
1966 * @param Offset is the starting offset of flash to erase.
1967 * @param Length is the number of bytes to erase.
1970 * - XST_SUCCESS if successful.
1971 * - XST_FAILURE if failed.
1974 * The Offset and Length should be aligned to block size boundary
1975 * to get better results.
1977 ******************************************************************************/
1978 s32 XNandPsu_Erase(XNandPsu *InstancePtr, u64 Offset, u64 Length)
1980 s32 Status = XST_FAILURE;
1989 u64 OffsetVar = Offset;
1990 u64 LengthVar = Length;
1993 * Assert the input arguments.
1995 Xil_AssertNonvoid(InstancePtr != NULL);
1996 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
1997 Xil_AssertNonvoid(LengthVar != 0U);
1998 Xil_AssertNonvoid((OffsetVar + LengthVar) <
1999 InstancePtr->Geometry.DeviceSize);
2002 * Check if erase operation exceeds flash size when including
2005 Status = XNandPsu_CalculateLength(InstancePtr, OffsetVar, LengthVar);
2006 if (Status != XST_SUCCESS) {
2010 * Calculate number of blocks to erase
2012 StartBlock = (u32) (OffsetVar/InstancePtr->Geometry.BlockSize);
2014 while (LengthVar > 0U) {
2015 Block = (u32) (OffsetVar/InstancePtr->Geometry.BlockSize);
2016 if (XNandPsu_IsBlockBad(InstancePtr, Block) ==
2018 OffsetVar += (u64)InstancePtr->Geometry.BlockSize;
2023 AlignOff = (u32)OffsetVar &
2024 (InstancePtr->Geometry.BlockSize - (u32)1);
2025 if (AlignOff > 0U) {
2026 BlockRemLen = InstancePtr->Geometry.BlockSize -
2028 EraseLen = (BlockRemLen < (u32)LengthVar) ?
2029 BlockRemLen :(u32)LengthVar;
2031 EraseLen = (InstancePtr->Geometry.BlockSize <
2033 InstancePtr->Geometry.BlockSize:
2037 OffsetVar += EraseLen;
2038 LengthVar -= EraseLen;
2041 for (Block = StartBlock; Block < (StartBlock + NumBlocks); Block++) {
2042 Target = Block/InstancePtr->Geometry.NumTargetBlocks;
2043 Block %= InstancePtr->Geometry.NumTargetBlocks;
2044 if (XNandPsu_IsBlockBad(InstancePtr, Block) ==
2047 * Don't erase bad block
2054 Status = XNandPsu_EraseBlock(InstancePtr, Target, Block);
2055 if (Status != XST_SUCCESS) {
2062 Status = XNandPsu_OnfiReadStatus(InstancePtr, Target,
2064 if (Status != XST_SUCCESS) {
2067 if ((OnfiStatus & (1U << 6U)) != 0U) {
2068 if ((OnfiStatus & (1U << 0U)) != 0U) {
2069 Status = XST_FAILURE;
2073 } while (((OnfiStatus >> 6U) & 0x1U) == 0U);
2076 Status = XST_SUCCESS;
2081 /*****************************************************************************/
2084 * This function sends ONFI Program Page command to flash.
2086 * @param InstancePtr is a pointer to the XNandPsu instance.
2087 * @param Target is the chip select value.
2088 * @param Page is the page address value to program.
2089 * @param Col is the column address value to program.
2090 * @param Buf is the data buffer to program.
2093 * - XST_SUCCESS if successful.
2094 * - XST_FAILURE if failed.
2098 ******************************************************************************/
2099 static s32 XNandPsu_ProgramPage(XNandPsu *InstancePtr, u32 Target, u32 Page,
2102 u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles +
2103 InstancePtr->Geometry.ColAddrCycles;
2107 u32 *BufPtr = (u32 *)(void *)Buf;
2108 s32 Status = XST_FAILURE;
2112 * Assert the input arguments.
2114 Xil_AssertNonvoid(Page < InstancePtr->Geometry.NumPages);
2115 Xil_AssertNonvoid(Buf != NULL);
2117 if (InstancePtr->EccCfg.CodeWordSize > 9U) {
2122 PktCount = InstancePtr->Geometry.BytesPerPage/PktSize;
2124 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_PG_PROG1, ONFI_CMD_PG_PROG2,
2125 1U, 1U, (u8)AddrCycles);
2127 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
2130 * Enable DMA boundary Interrupt in Interrupt Status
2133 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2134 XNANDPSU_INTR_STS_EN_OFFSET,
2135 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK |
2136 XNANDPSU_INTR_STS_EN_DMA_INT_STS_EN_MASK);
2139 * Enable Buffer Write Ready Interrupt in Interrupt Status
2142 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2143 XNANDPSU_INTR_STS_EN_OFFSET,
2144 XNANDPSU_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK);
2149 XNandPsu_SetPageSize(InstancePtr);
2151 * Program Packet Size and Packet Count
2153 XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
2155 * Program DMA system address and DMA buffer boundary
2157 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
2159 * Flush the Data Cache
2161 Xil_DCacheFlushRange((INTPTR)Buf, (PktSize * PktCount));
2164 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
2165 XNANDPSU_DMA_SYS_ADDR1_OFFSET,
2166 (u32) (((INTPTR)Buf >> 32) & 0xFFFFFFFFU));
2168 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
2169 XNANDPSU_DMA_SYS_ADDR0_OFFSET,
2170 (u32) ((INTPTR)(void *)Buf & 0xFFFFFFFFU));
2173 * Program Column, Page, Block address
2175 XNandPsu_SetPageColAddr(InstancePtr, Page, (u16)Col);
2179 XNandPsu_SetBusWidth(InstancePtr);
2181 * Program Memory Address Register2 for chip select
2183 XNandPsu_SelectChip(InstancePtr, Target);
2187 if (InstancePtr->EccMode == XNANDPSU_HWECC) {
2188 XNandPsu_SetEccSpareCmd(InstancePtr, ONFI_CMD_CHNG_WR_COL,
2189 InstancePtr->Geometry.ColAddrCycles);
2192 * Set Page Program in Program Register
2194 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2195 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_PG_PROG_MASK);
2197 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
2201 while (BufWrCnt < PktCount) {
2203 * Poll for Buffer Write Ready event
2205 Status = XNandPsu_PollRegTimeout(
2207 XNANDPSU_INTR_STS_OFFSET,
2208 XNANDPSU_INTR_STS_BUFF_WR_RDY_STS_EN_MASK,
2209 XNANDPSU_INTR_POLL_TIMEOUT);
2210 if (Status != XST_SUCCESS) {
2211 #ifdef XNANDPSU_DEBUG
2212 xil_printf("%s: Poll for buf write ready timeout\r\n",
2218 * Increment Buffer Write Interrupt Count
2222 if (BufWrCnt == PktCount) {
2224 * Enable Transfer Complete Interrupt in Interrupt
2225 * Status Enable Register
2227 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2228 XNANDPSU_INTR_STS_EN_OFFSET,
2229 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
2232 * Clear Buffer Write Ready Interrupt in Interrupt
2233 * Status Enable Register
2235 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2236 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
2240 * Clear Buffer Write Ready Interrupt in Interrupt Status
2243 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2244 XNANDPSU_INTR_STS_OFFSET,
2245 XNANDPSU_INTR_STS_BUFF_WR_RDY_STS_EN_MASK);
2247 * Write Packet Data to Data Port Register
2249 for (Index = 0U; Index < (PktSize/4U); Index++) {
2250 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
2251 XNANDPSU_BUF_DATA_PORT_OFFSET,
2254 BufPtr += (PktSize/4U);
2256 if (BufWrCnt < PktCount) {
2258 * Enable Buffer Write Ready Interrupt in Interrupt
2259 * Status Enable Register
2261 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2262 XNANDPSU_INTR_STS_EN_OFFSET,
2263 XNANDPSU_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK);
2270 * Poll for Transfer Complete event
2272 Status = XNandPsu_PollRegTimeout(
2274 XNANDPSU_INTR_STS_OFFSET,
2275 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK,
2276 XNANDPSU_INTR_POLL_TIMEOUT);
2277 if (Status != XST_SUCCESS) {
2278 #ifdef XNANDPSU_DEBUG
2279 xil_printf("%s: Poll for xfer complete timeout\r\n",
2285 * Clear Transfer Complete Interrupt in Interrupt Status Enable
2288 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2289 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
2292 * Clear Transfer Complete Interrupt in Interrupt Status Register
2294 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2295 XNANDPSU_INTR_STS_OFFSET,
2296 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK);
2302 /*****************************************************************************/
2305 * This function sends ONFI Program Page command to flash.
2307 * @param InstancePtr is a pointer to the XNandPsu instance.
2308 * @param Target is the chip select value.
2309 * @param Page is the page address value to program.
2310 * @param Col is the column address value to program.
2311 * @param Buf is the data buffer to program.
2314 * - XST_SUCCESS if successful.
2315 * - XST_FAILURE if failed.
2319 ******************************************************************************/
2320 s32 XNandPsu_WriteSpareBytes(XNandPsu *InstancePtr, u32 Page, u8 *Buf)
2322 u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles +
2323 InstancePtr->Geometry.ColAddrCycles;
2324 u32 Col = InstancePtr->Geometry.BytesPerPage;
2325 u32 Target = Page/InstancePtr->Geometry.NumTargetPages;
2326 u32 PktSize = InstancePtr->Geometry.SpareBytesPerPage;
2329 u32 *BufPtr = (u32 *)(void *)Buf;
2330 u16 PreEccSpareCol = 0U;
2331 u16 PreEccSpareWrCnt = 0U;
2332 u16 PostEccSpareCol = 0U;
2333 u16 PostEccSpareWrCnt = 0U;
2336 s32 Status = XST_FAILURE;
2341 * Assert the input arguments.
2343 Xil_AssertNonvoid(InstancePtr != NULL);
2344 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
2345 Xil_AssertNonvoid(PageVar < InstancePtr->Geometry.NumPages);
2346 Xil_AssertNonvoid(Buf != NULL);
2348 PageVar %= InstancePtr->Geometry.NumTargetPages;
2350 if (InstancePtr->EccMode == XNANDPSU_HWECC) {
2352 * Calculate ECC free positions before and after ECC code
2354 PreEccSpareCol = 0x0U;
2355 PreEccSpareWrCnt = InstancePtr->EccCfg.EccAddr -
2356 (u16)InstancePtr->Geometry.BytesPerPage;
2358 PostEccSpareCol = PreEccSpareWrCnt +
2359 InstancePtr->EccCfg.EccSize;
2360 PostEccSpareWrCnt = InstancePtr->Geometry.SpareBytesPerPage -
2363 PreEccSpareWrCnt = (PreEccSpareWrCnt/4U) * 4U;
2364 PostEccSpareWrCnt = (PostEccSpareWrCnt/4U) * 4U;
2366 if (PreEccSpareWrCnt > 0U) {
2367 PktSize = PreEccSpareWrCnt;
2369 Col = InstancePtr->Geometry.BytesPerPage +
2371 BufPtr = (u32 *)(void *)Buf;
2372 if (PostEccSpareWrCnt > 0U) {
2375 } else if (PostEccSpareWrCnt > 0U) {
2376 PktSize = PostEccSpareWrCnt;
2378 Col = InstancePtr->Geometry.BytesPerPage +
2380 BufPtr = (u32 *)(void *)&Buf[Col];
2383 * No free spare bytes available for writing
2385 Status = XST_FAILURE;
2390 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
2392 * Enable Transfer Complete Interrupt in Interrupt Status
2395 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2396 XNANDPSU_INTR_STS_EN_OFFSET,
2397 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
2401 * Enable Buffer Write Ready Interrupt in Interrupt Status
2404 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2405 XNANDPSU_INTR_STS_EN_OFFSET,
2406 XNANDPSU_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK);
2410 * Program Command hack for change write column
2412 if (PostWrite > 0U) {
2413 Cmd.Command1 = 0x80U;
2414 Cmd.Command2 = 0x00U;
2415 XNandPsu_Prepare_Cmd(InstancePtr, Cmd.Command1, Cmd.Command2,
2416 0U , 1U, (u8)AddrCycles);
2419 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_PG_PROG1,
2420 ONFI_CMD_PG_PROG2, 0U , 1U, (u8)AddrCycles);
2425 XNandPsu_SetPageSize(InstancePtr);
2427 * Program Packet Size and Packet Count
2429 XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
2431 * Program DMA system address and DMA buffer boundary
2433 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
2435 * Flush the Data Cache
2437 Xil_DCacheFlushRange((INTPTR)BufPtr, (PktSize * PktCount));
2440 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
2441 XNANDPSU_DMA_SYS_ADDR1_OFFSET,
2442 (u32) (((INTPTR)BufPtr >> 32) & 0xFFFFFFFFU));
2444 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
2445 XNANDPSU_DMA_SYS_ADDR0_OFFSET,
2446 (u32) ((INTPTR)(void *)BufPtr & 0xFFFFFFFFU));
2448 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
2449 XNANDPSU_DMA_BUF_BND_OFFSET,
2450 XNANDPSU_DMA_BUF_BND_512K);
2453 * Program Column, Page, Block address
2455 XNandPsu_SetPageColAddr(InstancePtr, PageVar, (u16)Col);
2459 XNandPsu_SetBusWidth(InstancePtr);
2461 * Program Memory Address Register2 for chip select
2463 XNandPsu_SelectChip(InstancePtr, Target);
2465 * Set Page Program in Program Register
2467 if (PostWrite > 0U) {
2468 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2469 XNANDPSU_PROG_OFFSET,((u32)XNANDPSU_PROG_PG_PROG_MASK |
2470 (u32)XNANDPSU_PROG_CHNG_ROW_ADDR_MASK));
2472 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2473 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_PG_PROG_MASK);
2476 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
2480 while (BufWrCnt < PktCount) {
2482 * Poll for Buffer Write Ready event
2484 Status = XNandPsu_PollRegTimeout(
2486 XNANDPSU_INTR_STS_OFFSET,
2487 XNANDPSU_INTR_STS_BUFF_WR_RDY_STS_EN_MASK,
2488 XNANDPSU_INTR_POLL_TIMEOUT);
2489 if (Status != XST_SUCCESS) {
2490 #ifdef XNANDPSU_DEBUG
2491 xil_printf("%s: Poll for buf write ready timeout\r\n",
2497 * Increment Buffer Write Interrupt Count
2501 if (BufWrCnt == PktCount) {
2503 * Enable Transfer Complete Interrupt in Interrupt
2504 * Status Enable Register
2506 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2507 XNANDPSU_INTR_STS_EN_OFFSET,
2508 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
2512 * Clear Buffer Write Ready Interrupt in Interrupt
2513 * Status Enable Register
2515 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2516 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
2519 * Clear Buffer Write Ready Interrupt in Interrupt Status
2522 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2523 XNANDPSU_INTR_STS_OFFSET,
2524 XNANDPSU_INTR_STS_BUFF_WR_RDY_STS_EN_MASK);
2526 * Write Packet Data to Data Port Register
2528 for (Index = 0U; Index < (PktSize/4U); Index++) {
2529 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
2530 XNANDPSU_BUF_DATA_PORT_OFFSET,
2533 BufPtr += (PktSize/4U);
2535 if (BufWrCnt < PktCount) {
2537 * Enable Buffer Write Ready Interrupt in Interrupt
2538 * Status Enable Register
2540 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2541 XNANDPSU_INTR_STS_EN_OFFSET,
2542 XNANDPSU_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK);
2549 * Poll for Transfer Complete event
2551 Status = XNandPsu_PollRegTimeout(
2553 XNANDPSU_INTR_STS_OFFSET,
2554 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK,
2555 XNANDPSU_INTR_POLL_TIMEOUT);
2556 if (Status != XST_SUCCESS) {
2557 #ifdef XNANDPSU_DEBUG
2558 xil_printf("%s: Poll for xfer complete timeout\r\n",
2564 * Clear Transfer Complete Interrupt in Interrupt Status Enable
2567 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2568 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
2571 * Clear Transfer Complete Interrupt in Interrupt Status Register
2573 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2574 XNANDPSU_INTR_STS_OFFSET,
2575 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK);
2577 if (InstancePtr->EccMode == XNANDPSU_HWECC) {
2578 if (PostWrite > 0U) {
2579 BufPtr = (u32 *)(void *)&Buf[PostEccSpareCol];
2580 Status = XNandPsu_ChangeWriteColumn(InstancePtr,
2582 PostEccSpareCol, PostEccSpareWrCnt, 1U,
2583 (u8 *)(void *)BufPtr);
2584 if (Status != XST_SUCCESS) {
2594 /*****************************************************************************/
2597 * This function sends ONFI Read Page command to flash.
2599 * @param InstancePtr is a pointer to the XNandPsu instance.
2600 * @param Target is the chip select value.
2601 * @param Page is the page address value to read.
2602 * @param Col is the column address value to read.
2603 * @param Buf is the data buffer to fill in.
2606 * - XST_SUCCESS if successful.
2607 * - XST_FAILURE if failed.
2611 ******************************************************************************/
2612 static s32 XNandPsu_ReadPage(XNandPsu *InstancePtr, u32 Target, u32 Page,
2615 u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles +
2616 InstancePtr->Geometry.ColAddrCycles;
2620 u32 *BufPtr = (u32 *)(void *)Buf;
2621 s32 Status = XST_FAILURE;
2625 * Assert the input arguments.
2627 Xil_AssertNonvoid(Page < InstancePtr->Geometry.NumPages);
2628 Xil_AssertNonvoid(Target < XNANDPSU_MAX_TARGETS);
2630 if (InstancePtr->EccCfg.CodeWordSize > 9U) {
2635 PktCount = InstancePtr->Geometry.BytesPerPage/PktSize;
2637 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RD1, ONFI_CMD_RD2,
2638 1U, 1U, (u8)AddrCycles);
2640 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
2643 * Enable DMA boundary Interrupt in Interrupt Status
2646 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2647 XNANDPSU_INTR_STS_EN_OFFSET,
2648 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK |
2649 XNANDPSU_INTR_STS_EN_DMA_INT_STS_EN_MASK);
2653 * Enable Buffer Read Ready Interrupt in Interrupt Status
2656 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2657 XNANDPSU_INTR_STS_EN_OFFSET,
2658 XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK);
2662 * Enable Single bit error and Multi bit error
2664 if (InstancePtr->EccMode == XNANDPSU_HWECC) {
2666 * Interrupt Status Enable Register
2668 XNandPsu_IntrStsEnable(InstancePtr,
2669 (XNANDPSU_INTR_STS_EN_MUL_BIT_ERR_STS_EN_MASK |
2670 XNANDPSU_INTR_STS_EN_ERR_INTR_STS_EN_MASK));
2675 XNandPsu_SetPageSize(InstancePtr);
2677 * Program Column, Page, Block address
2679 XNandPsu_SetPageColAddr(InstancePtr, Page, (u16)Col);
2681 * Program Packet Size and Packet Count
2683 XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
2685 * Program DMA system address and DMA buffer boundary
2687 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
2689 * Invalidate the Data Cache
2691 Xil_DCacheInvalidateRange((INTPTR)Buf, (PktSize * PktCount));
2694 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
2695 XNANDPSU_DMA_SYS_ADDR1_OFFSET,
2696 (u32) (((INTPTR)(void *)Buf >> 32) &
2699 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
2700 XNANDPSU_DMA_SYS_ADDR0_OFFSET,
2701 (u32) ((INTPTR)(void *)Buf & 0xFFFFFFFFU));
2706 XNandPsu_SetBusWidth(InstancePtr);
2708 * Program Memory Address Register2 for chip select
2710 XNandPsu_SelectChip(InstancePtr, Target);
2714 if (InstancePtr->EccMode == XNANDPSU_HWECC) {
2715 XNandPsu_SetEccSpareCmd(InstancePtr,
2716 (ONFI_CMD_CHNG_RD_COL1 |
2717 (ONFI_CMD_CHNG_RD_COL2 << (u8)8U)),
2718 InstancePtr->Geometry.ColAddrCycles);
2722 * Set Read command in Program Register
2724 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2725 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_MASK);
2727 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
2731 while (BufRdCnt < PktCount) {
2733 * Poll for Buffer Read Ready event
2735 Status = XNandPsu_PollRegTimeout(
2737 XNANDPSU_INTR_STS_OFFSET,
2738 XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK,
2739 XNANDPSU_INTR_POLL_TIMEOUT);
2740 if (Status != XST_SUCCESS) {
2741 #ifdef XNANDPSU_DEBUG
2742 xil_printf("%s: Poll for buf read ready timeout\r\n",
2748 * Increment Buffer Read Interrupt Count
2752 if (BufRdCnt == PktCount) {
2754 * Enable Transfer Complete Interrupt in Interrupt
2755 * Status Enable Register
2757 RegVal = XNandPsu_ReadReg(
2758 (InstancePtr)->Config.BaseAddress,
2759 XNANDPSU_INTR_STS_EN_OFFSET);
2760 RegVal &= ~XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK;
2761 RegVal |= XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK;
2762 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2763 XNANDPSU_INTR_STS_EN_OFFSET, RegVal);
2766 * Clear Buffer Read Ready Interrupt in Interrupt
2767 * Status Enable Register
2769 RegVal = XNandPsu_ReadReg(
2770 (InstancePtr)->Config.BaseAddress,
2771 XNANDPSU_INTR_STS_EN_OFFSET);
2772 RegVal &= ~XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK;
2773 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2774 XNANDPSU_INTR_STS_EN_OFFSET, RegVal);
2777 * Clear Buffer Read Ready Interrupt in Interrupt Status
2780 RegVal = XNandPsu_ReadReg(
2781 (InstancePtr)->Config.BaseAddress,
2782 XNANDPSU_INTR_STS_OFFSET);
2783 RegVal |= XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK;
2784 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2785 XNANDPSU_INTR_STS_OFFSET, RegVal);
2787 * Read Packet Data from Data Port Register
2789 for (Index = 0U; Index < (PktSize/4); Index++) {
2790 BufPtr[Index] = XNandPsu_ReadReg(
2791 InstancePtr->Config.BaseAddress,
2792 XNANDPSU_BUF_DATA_PORT_OFFSET);
2794 BufPtr += (PktSize/4);
2796 if (BufRdCnt < PktCount) {
2798 * Enable Buffer Read Ready Interrupt in Interrupt
2799 * Status Enable Register
2801 RegVal = XNandPsu_ReadReg(
2802 (InstancePtr)->Config.BaseAddress,
2803 XNANDPSU_INTR_STS_EN_OFFSET);
2804 RegVal |= XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK;
2805 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2806 XNANDPSU_INTR_STS_EN_OFFSET, RegVal);
2813 * Poll for Transfer Complete event
2815 Status = XNandPsu_PollRegTimeout(
2817 XNANDPSU_INTR_STS_OFFSET,
2818 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK,
2819 XNANDPSU_INTR_POLL_TIMEOUT);
2820 if (Status != XST_SUCCESS) {
2821 #ifdef XNANDPSU_DEBUG
2822 xil_printf("%s: Poll for xfer complete timeout\r\n",
2828 * Clear Transfer Complete Interrupt in Interrupt Status Enable
2831 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2832 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
2835 * Clear Transfer Complete Interrupt in Interrupt Status Register
2837 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2838 XNANDPSU_INTR_STS_OFFSET,
2839 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK);
2845 if (InstancePtr->EccMode == XNANDPSU_HWECC) {
2847 * Hamming Multi Bit Errors
2849 if (((u32)XNandPsu_ReadReg(InstancePtr->Config.BaseAddress,
2850 XNANDPSU_INTR_STS_OFFSET) &
2851 (u32)XNANDPSU_INTR_STS_MUL_BIT_ERR_STS_EN_MASK) != 0U) {
2853 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2854 XNANDPSU_INTR_STS_OFFSET,
2855 XNANDPSU_INTR_STS_MUL_BIT_ERR_STS_EN_MASK);
2857 #ifdef XNANDPSU_DEBUG
2858 xil_printf("%s: ECC Hamming multi bit error\r\n",
2861 InstancePtr->Ecc_Stat_PerPage_flips =
2863 InstancePtr->Config.BaseAddress,
2864 XNANDPSU_ECC_ERR_CNT_OFFSET) &
2866 InstancePtr->Ecc_Stats_total_flips +=
2867 InstancePtr->Ecc_Stat_PerPage_flips;
2868 Status = XST_FAILURE;
2871 * Hamming Single Bit or BCH Errors
2873 if (((u32)XNandPsu_ReadReg(InstancePtr->Config.BaseAddress,
2874 XNANDPSU_INTR_STS_OFFSET) &
2875 (u32)XNANDPSU_INTR_STS_ERR_INTR_STS_EN_MASK) != 0U) {
2877 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2878 XNANDPSU_INTR_STS_OFFSET,
2879 XNANDPSU_INTR_STS_ERR_INTR_STS_EN_MASK);
2881 if (InstancePtr->EccCfg.IsBCH == 1U) {
2882 InstancePtr->Ecc_Stat_PerPage_flips =
2884 InstancePtr->Config.BaseAddress,
2885 XNANDPSU_ECC_ERR_CNT_OFFSET)&
2887 InstancePtr->Ecc_Stats_total_flips +=
2888 InstancePtr->Ecc_Stat_PerPage_flips;
2889 Status = XST_SUCCESS;
2897 /*****************************************************************************/
2900 * This function reads spare bytes from flash.
2902 * @param InstancePtr is a pointer to the XNandPsu instance.
2903 * @param Target is the chip select value.
2904 * @param Page is the page address value to read.
2905 * @param Buf is the data buffer to fill in.
2908 * - XST_SUCCESS if successful.
2909 * - XST_FAILURE if failed.
2913 ******************************************************************************/
2914 s32 XNandPsu_ReadSpareBytes(XNandPsu *InstancePtr, u32 Page, u8 *Buf)
2916 u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles +
2917 InstancePtr->Geometry.ColAddrCycles;
2918 u32 Col = InstancePtr->Geometry.BytesPerPage;
2919 u32 Target = Page/InstancePtr->Geometry.NumTargetPages;
2920 u32 PktSize = InstancePtr->Geometry.SpareBytesPerPage;
2923 u32 *BufPtr = (u32 *)(void *)Buf;
2924 s32 Status = XST_FAILURE;
2929 * Assert the input arguments.
2931 Xil_AssertNonvoid(InstancePtr != NULL);
2932 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
2933 Xil_AssertNonvoid(PageVar < InstancePtr->Geometry.NumPages);
2934 Xil_AssertNonvoid(Buf != NULL);
2936 PageVar %= InstancePtr->Geometry.NumTargetPages;
2938 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
2940 * Enable Transfer Complete Interrupt in Interrupt Status
2943 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2944 XNANDPSU_INTR_STS_EN_OFFSET,
2945 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
2948 * Enable Buffer Read Ready Interrupt in Interrupt Status
2951 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
2952 XNANDPSU_INTR_STS_EN_OFFSET,
2953 XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK);
2958 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RD1, ONFI_CMD_RD2, 0U,
2959 1U, (u8)AddrCycles);
2963 XNandPsu_SetPageSize(InstancePtr);
2965 * Program Column, Page, Block address
2967 XNandPsu_SetPageColAddr(InstancePtr, PageVar, (u16)Col);
2969 * Program Packet Size and Packet Count
2971 XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
2973 * Program DMA system address and DMA buffer boundary
2975 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
2978 * Invalidate the Data Cache
2980 Xil_DCacheInvalidateRange((INTPTR)Buf, (PktSize * PktCount));
2982 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
2983 XNANDPSU_DMA_SYS_ADDR1_OFFSET,
2984 (u32) (((INTPTR)(void *)Buf >> 32) &
2987 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
2988 XNANDPSU_DMA_SYS_ADDR0_OFFSET,
2989 (u32) ((INTPTR)(void *)Buf & 0xFFFFFFFFU));
2994 XNandPsu_SetBusWidth(InstancePtr);
2996 * Program Memory Address Register2 for chip select
2998 XNandPsu_SelectChip(InstancePtr, Target);
3000 * Set Read command in Program Register
3002 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3003 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_MASK);
3005 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
3009 while (BufRdCnt < PktCount) {
3011 * Poll for Buffer Read Ready event
3013 Status = XNandPsu_PollRegTimeout(
3015 XNANDPSU_INTR_STS_OFFSET,
3016 XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK,
3017 XNANDPSU_INTR_POLL_TIMEOUT);
3018 if (Status != XST_SUCCESS) {
3019 #ifdef XNANDPSU_DEBUG
3020 xil_printf("%s: Poll for buf read ready timeout\r\n",
3026 * Increment Buffer Read Interrupt Count
3030 if (BufRdCnt == PktCount) {
3032 * Enable Transfer Complete Interrupt in Interrupt
3033 * Status Enable Register
3035 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3036 XNANDPSU_INTR_STS_EN_OFFSET,
3037 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
3041 * Clear Buffer Read Ready Interrupt in Interrupt
3042 * Status Enable Register
3044 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3045 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
3049 * Clear Buffer Read Ready Interrupt in Interrupt Status
3052 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3053 XNANDPSU_INTR_STS_OFFSET,
3054 XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK);
3056 * Read Packet Data from Data Port Register
3058 for (Index = 0U; Index < (PktSize/4); Index++) {
3059 BufPtr[Index] = XNandPsu_ReadReg(
3060 InstancePtr->Config.BaseAddress,
3061 XNANDPSU_BUF_DATA_PORT_OFFSET);
3063 BufPtr += (PktSize/4);
3065 if (BufRdCnt < PktCount) {
3067 * Enable Buffer Read Ready Interrupt in Interrupt
3068 * Status Enable Register
3070 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3071 XNANDPSU_INTR_STS_EN_OFFSET,
3072 XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK);
3079 * Poll for Transfer Complete event
3081 Status = XNandPsu_PollRegTimeout(
3083 XNANDPSU_INTR_STS_OFFSET,
3084 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK,
3085 XNANDPSU_INTR_POLL_TIMEOUT);
3086 if (Status != XST_SUCCESS) {
3087 #ifdef XNANDPSU_DEBUG
3088 xil_printf("%s: Poll for xfer complete timeout\r\n",
3094 * Clear Transfer Complete Interrupt in Interrupt Status Enable
3097 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3098 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
3101 * Clear Transfer Complete Interrupt in Interrupt Status Register
3103 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3104 XNANDPSU_INTR_STS_OFFSET,
3105 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK);
3111 /*****************************************************************************/
3114 * This function sends ONFI block erase command to the flash.
3116 * @param InstancePtr is a pointer to the XNandPsu instance.
3117 * @param Target is the chip select value.
3118 * @param Block is the block to erase.
3121 * - XST_SUCCESS if successful.
3122 * - XST_FAILURE if failed.
3126 ******************************************************************************/
3127 s32 XNandPsu_EraseBlock(XNandPsu *InstancePtr, u32 Target, u32 Block)
3129 s32 Status = XST_FAILURE;
3130 u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles;
3136 * Assert the input arguments.
3138 Xil_AssertNonvoid(InstancePtr != NULL);
3139 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
3140 Xil_AssertNonvoid(Target < XNANDPSU_MAX_TARGETS);
3141 Xil_AssertNonvoid(Block < InstancePtr->Geometry.NumBlocks);
3143 Page = Block * InstancePtr->Geometry.PagesPerBlock;
3144 ErasePage = (Page >> 16U) & 0xFFFFU;
3145 EraseCol = Page & 0xFFFFU;
3148 * Enable Transfer Complete Interrupt in Interrupt Status Enable
3151 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3152 XNANDPSU_INTR_STS_EN_OFFSET,
3153 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
3158 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_BLK_ERASE1,
3159 ONFI_CMD_BLK_ERASE2, 0U , 0U, (u8)AddrCycles);
3161 * Program Column, Page, Block address
3163 XNandPsu_SetPageColAddr(InstancePtr, ErasePage, (u16)EraseCol);
3165 * Program Memory Address Register2 for chip select
3167 XNandPsu_SelectChip(InstancePtr, Target);
3169 * Set Block Erase in Program Register
3171 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3172 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_BLK_ERASE_MASK);
3174 * Poll for Transfer Complete event
3176 Status = XNandPsu_PollRegTimeout(
3178 XNANDPSU_INTR_STS_OFFSET,
3179 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK,
3180 XNANDPSU_INTR_POLL_TIMEOUT);
3181 if (Status != XST_SUCCESS) {
3182 #ifdef XNANDPSU_DEBUG
3183 xil_printf("%s: Poll for xfer complete timeout\r\n",
3189 * Clear Transfer Complete Interrupt in Interrupt Status Enable
3192 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3193 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
3196 * Clear Transfer Complete Interrupt in Interrupt Status Register
3198 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3199 XNANDPSU_INTR_STS_OFFSET,
3200 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK);
3206 /*****************************************************************************/
3209 * This function sends ONFI Get Feature command to flash.
3211 * @param InstancePtr is a pointer to the XNandPsu instance.
3212 * @param Target is the chip select value.
3213 * @param Feature is the feature selector.
3214 * @param Buf is the buffer to fill feature value.
3217 * - XST_SUCCESS if successful.
3218 * - XST_FAILURE if failed.
3222 ******************************************************************************/
3223 s32 XNandPsu_GetFeature(XNandPsu *InstancePtr, u32 Target, u8 Feature,
3230 u32 *BufPtr = (u32 *)(void *)Buf;
3233 * Assert the input arguments.
3235 Xil_AssertNonvoid(Buf != NULL);
3237 if (InstancePtr->DataInterface == XNANDPSU_NVDDR) {
3242 * Enable Buffer Read Ready Interrupt in Interrupt Status
3245 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3246 XNANDPSU_INTR_STS_EN_OFFSET,
3247 XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK);
3251 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_GET_FEATURES,
3252 ONFI_CMD_INVALID, 0U, 0U, 1U);
3254 * Program Column, Page, Block address
3256 XNandPsu_SetPageColAddr(InstancePtr, 0x0U, Feature);
3258 * Program Memory Address Register2 for chip select
3260 XNandPsu_SelectChip(InstancePtr, Target);
3262 * Program Packet Size and Packet Count
3264 XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
3266 * Set Read Parameter Page in Program Register
3268 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3269 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_GET_FEATURES_MASK);
3271 * Poll for Buffer Read Ready event
3273 Status = XNandPsu_PollRegTimeout(
3275 XNANDPSU_INTR_STS_OFFSET,
3276 XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK,
3277 XNANDPSU_INTR_POLL_TIMEOUT);
3278 if (Status != XST_SUCCESS) {
3279 #ifdef XNANDPSU_DEBUG
3280 xil_printf("%s: Poll for buf read ready timeout\r\n",
3286 * Clear Buffer Read Ready Interrupt in Interrupt Status Enable
3289 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3290 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
3293 * Clear Buffer Read Ready Interrupt in Interrupt Status Register
3295 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3296 XNANDPSU_INTR_STS_OFFSET,
3297 XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK);
3299 * Enable Transfer Complete Interrupt in Interrupt Status Enable
3302 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3303 XNANDPSU_INTR_STS_EN_OFFSET,
3304 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
3307 * Read Data from Data Port Register
3309 for (Index = 0U; Index < (PktSize/4U); Index++) {
3310 BufPtr[Index] = XNandPsu_ReadReg(
3311 InstancePtr->Config.BaseAddress,
3312 XNANDPSU_BUF_DATA_PORT_OFFSET);
3315 * Poll for Transfer Complete event
3317 Status = XNandPsu_PollRegTimeout(
3319 XNANDPSU_INTR_STS_OFFSET,
3320 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK,
3321 XNANDPSU_INTR_POLL_TIMEOUT);
3322 if (Status != XST_SUCCESS) {
3323 #ifdef XNANDPSU_DEBUG
3324 xil_printf("%s: Poll for xfer complete timeout\r\n",
3330 * Clear Transfer Complete Interrupt in Interrupt Status Enable
3333 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3334 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
3337 * Clear Transfer Complete Interrupt in Interrupt Status Register
3339 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3340 XNANDPSU_INTR_STS_OFFSET,
3341 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK);
3347 /*****************************************************************************/
3350 * This function sends ONFI Set Feature command to flash.
3352 * @param InstancePtr is a pointer to the XNandPsu instance.
3353 * @param Target is the chip select value.
3354 * @param Feature is the feature selector.
3355 * @param Buf is the feature value to send.
3358 * - XST_SUCCESS if successful.
3359 * - XST_FAILURE if failed.
3363 ******************************************************************************/
3364 s32 XNandPsu_SetFeature(XNandPsu *InstancePtr, u32 Target, u8 Feature,
3371 u32 *BufPtr = (u32 *)(void *)Buf;
3374 * Assert the input arguments.
3376 Xil_AssertNonvoid(Buf != NULL);
3377 if (InstancePtr->DataInterface == XNANDPSU_NVDDR) {
3381 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3382 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
3385 * Enable Buffer Write Ready Interrupt in Interrupt Status
3388 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3389 XNANDPSU_INTR_STS_EN_OFFSET,
3390 XNANDPSU_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK);
3395 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_SET_FEATURES,
3396 ONFI_CMD_INVALID, 0U , 0U, 1U);
3398 * Program Column, Page, Block address
3400 XNandPsu_SetPageColAddr(InstancePtr, 0x0U, Feature);
3402 * Program Memory Address Register2 for chip select
3404 XNandPsu_SelectChip(InstancePtr, Target);
3406 * Program Packet Size and Packet Count
3408 XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
3410 * Set Read Parameter Page in Program Register
3412 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3413 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_SET_FEATURES_MASK);
3415 * Poll for Buffer Write Ready event
3417 Status = XNandPsu_PollRegTimeout(
3419 XNANDPSU_INTR_STS_OFFSET,
3420 XNANDPSU_INTR_STS_BUFF_WR_RDY_STS_EN_MASK,
3421 XNANDPSU_INTR_POLL_TIMEOUT);
3422 if (Status != XST_SUCCESS) {
3423 #ifdef XNANDPSU_DEBUG
3424 xil_printf("%s: Poll for buf write ready timeout\r\n",
3430 * Clear Buffer Write Ready Interrupt in Interrupt Status Enable
3433 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3434 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
3437 * Clear Buffer Write Ready Interrupt in Interrupt Status Register
3439 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3440 XNANDPSU_INTR_STS_OFFSET,
3441 XNANDPSU_INTR_STS_BUFF_WR_RDY_STS_EN_MASK);
3443 * Enable Transfer Complete Interrupt in Interrupt Status Enable
3446 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3447 (XNANDPSU_INTR_STS_EN_OFFSET),
3448 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
3450 * Write Data to Data Port Register
3452 for (Index = 0U; Index < (PktSize/4U); Index++) {
3453 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
3454 XNANDPSU_BUF_DATA_PORT_OFFSET,
3458 * Poll for Transfer Complete event
3460 Status = XNandPsu_PollRegTimeout(
3462 XNANDPSU_INTR_STS_OFFSET,
3463 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK,
3464 XNANDPSU_INTR_POLL_TIMEOUT);
3465 if (Status != XST_SUCCESS) {
3466 #ifdef XNANDPSU_DEBUG
3467 xil_printf("%s: Poll for xfer complete timeout\r\n",
3473 * Clear Transfer Complete Interrupt in Interrupt Status Enable
3476 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3477 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
3480 * Clear Transfer Complete Interrupt in Interrupt Status Register
3482 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3483 XNANDPSU_INTR_STS_OFFSET,
3484 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK);
3490 /*****************************************************************************/
3493 * This function changes clock frequency of flash controller.
3495 * @param InstancePtr is a pointer to the XNandPsu instance.
3496 * @param ClockFreq is the clock frequency to change.
3503 ******************************************************************************/
3504 static void XNandPsu_ChangeClockFreq(XNandPsu *InstancePtr, u32 ClockFreq)
3510 /*****************************************************************************/
3513 * This function changes the data interface and timing mode.
3515 * @param InstancePtr is a pointer to the XNandPsu instance.
3516 * @param NewIntf is the new data interface.
3517 * @param NewMode is the new timing mode.
3520 * - XST_SUCCESS if successful.
3521 * - XST_FAILURE if failed.
3525 ******************************************************************************/
3526 s32 XNandPsu_ChangeTimingMode(XNandPsu *InstancePtr,
3527 XNandPsu_DataInterface NewIntf,
3528 XNandPsu_TimingMode NewMode)
3536 u32 *Feature = (u32 *)(void *)&Buf[0];
3537 u32 SetFeature = 0U;
3538 u32 NewModeVar = NewMode;
3541 * Assert the input arguments.
3543 Xil_AssertNonvoid(InstancePtr != NULL);
3544 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
3547 * Check for valid input arguments
3549 if((NewIntf != XNANDPSU_SDR && NewIntf != XNANDPSU_NVDDR) ||
3551 Status = XST_FAILURE;
3555 if(NewIntf == XNANDPSU_NVDDR){
3556 NewModeVar = NewModeVar | 0x10U;
3559 * Get current data interface type and timing mode
3561 XNandPsu_DataInterface CurIntf = InstancePtr->DataInterface;
3562 XNandPsu_TimingMode CurMode = InstancePtr->TimingMode;
3565 * Check if the flash is in same mode
3567 if ((CurIntf == NewIntf) && (CurMode == NewModeVar)) {
3568 Status = XST_SUCCESS;
3572 if ((CurIntf == XNANDPSU_NVDDR) && (NewIntf == XNANDPSU_SDR)) {
3574 NewModeVar = XNANDPSU_SDR0;
3577 * Change the clock frequency
3579 XNandPsu_ChangeClockFreq(InstancePtr, XNANDPSU_SDR_CLK);
3582 * Update Data Interface Register
3584 RegVal = ((NewModeVar % 6U) << ((NewIntf == XNANDPSU_NVDDR) ? 3U : 0U)) |
3585 ((u32)NewIntf << XNANDPSU_DATA_INTF_DATA_INTF_SHIFT);
3586 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
3587 XNANDPSU_DATA_INTF_OFFSET, RegVal);
3589 for (Target = 0U; Target < InstancePtr->Geometry.NumTargets;
3591 Status = XNandPsu_OnfiReset(InstancePtr, Target);
3592 if (Status != XST_SUCCESS) {
3600 for (Target = 0U; Target < InstancePtr->Geometry.NumTargets;
3602 Status = XNandPsu_SetFeature(InstancePtr, Target, 0x01U,
3604 if (Status != XST_SUCCESS) {
3609 InstancePtr->DataInterface = NewIntf;
3610 InstancePtr->TimingMode = NewModeVar;
3612 for (Target = 0U; Target < InstancePtr->Geometry.NumTargets;
3614 Status = XNandPsu_GetFeature(InstancePtr, Target, 0x01U,
3616 if (Status != XST_SUCCESS) {
3620 * Check if set_feature was successful
3622 if ((u32)*Feature != (u32)NewModeVar) {
3623 Status = XST_FAILURE;
3631 SetFeature = NewModeVar;
3632 if(CurIntf == XNANDPSU_NVDDR && NewIntf == XNANDPSU_NVDDR){
3633 SetFeature |= SetFeature << 8U;
3638 for (Target = 0U; Target < InstancePtr->Geometry.NumTargets;
3640 Status = XNandPsu_SetFeature(InstancePtr, Target, 0x01U,
3642 if (Status != XST_SUCCESS) {
3647 InstancePtr->DataInterface = NewIntf;
3648 InstancePtr->TimingMode = NewModeVar;
3650 * Update Data Interface Register
3652 RegVal = ((NewMode % 6U) << ((NewIntf == XNANDPSU_NVDDR) ? 3U : 0U)) |
3653 ((u32)NewIntf << XNANDPSU_DATA_INTF_DATA_INTF_SHIFT);
3654 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
3655 XNANDPSU_DATA_INTF_OFFSET, RegVal);
3660 for (Target = 0U; Target < InstancePtr->Geometry.NumTargets;
3662 Status = XNandPsu_GetFeature(InstancePtr, Target, 0x01U,
3664 if (Status != XST_SUCCESS) {
3669 * Check if set_feature was successful
3671 if (*Feature != NewModeVar) {
3672 Status = XST_FAILURE;
3677 Status = XST_SUCCESS;
3682 /*****************************************************************************/
3685 * This function issues change read column and reads the data into buffer
3686 * specified by user.
3688 * @param InstancePtr is a pointer to the XNandPsu instance.
3689 * @param Target is the chip select value.
3690 * @param Col is the coulmn address.
3691 * @param PktSize is the number of bytes to read.
3692 * @param PktCount is the number of transactions to read.
3693 * @param Buf is the data buffer to fill in.
3696 * - XST_SUCCESS if successful.
3697 * - XST_FAILURE if failed.
3701 ******************************************************************************/
3702 static s32 XNandPsu_ChangeReadColumn(XNandPsu *InstancePtr, u32 Target,
3703 u32 Col, u32 PktSize, u32 PktCount,
3706 u32 AddrCycles = InstancePtr->Geometry.ColAddrCycles;
3708 u32 *BufPtr = (u32 *)(void *)Buf;
3709 s32 Status = XST_FAILURE;
3713 * Assert the input arguments.
3715 Xil_AssertNonvoid(Target < XNANDPSU_MAX_TARGETS);
3716 Xil_AssertNonvoid(Buf != NULL);
3718 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
3720 * Enable DMA boundary Interrupt in Interrupt Status
3723 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3724 XNANDPSU_INTR_STS_EN_OFFSET,
3725 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK |
3726 XNANDPSU_INTR_STS_EN_DMA_INT_STS_EN_MASK);
3729 * Enable Buffer Read Ready Interrupt in Interrupt Status
3732 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3733 XNANDPSU_INTR_STS_EN_OFFSET,
3734 XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK);
3739 XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_CHNG_RD_COL1,
3740 ONFI_CMD_CHNG_RD_COL2, 0U , 1U, (u8)AddrCycles);
3744 XNandPsu_SetPageSize(InstancePtr);
3746 * Program Column, Page, Block address
3748 XNandPsu_SetPageColAddr(InstancePtr, 0U, (u16)Col);
3750 * Program Packet Size and Packet Count
3752 XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
3754 * Program DMA system address and DMA buffer boundary
3756 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
3758 * Invalidate the Data Cache
3760 Xil_DCacheInvalidateRange((INTPTR)Buf, (PktSize * PktCount));
3762 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
3763 XNANDPSU_DMA_SYS_ADDR1_OFFSET,
3764 (u32) (((INTPTR)Buf >> 32) & 0xFFFFFFFFU));
3766 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
3767 XNANDPSU_DMA_SYS_ADDR0_OFFSET,
3768 (u32) ((INTPTR)(void *)Buf & 0xFFFFFFFFU));
3773 XNandPsu_SetBusWidth(InstancePtr);
3775 * Program Memory Address Register2 for chip select
3777 XNandPsu_SelectChip(InstancePtr, Target);
3779 * Set Read command in Program Register
3781 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3782 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_MASK);
3784 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
3788 while (BufRdCnt < PktCount) {
3790 * Poll for Buffer Read Ready event
3792 Status = XNandPsu_PollRegTimeout(
3794 XNANDPSU_INTR_STS_OFFSET,
3795 XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK,
3796 XNANDPSU_INTR_POLL_TIMEOUT);
3797 if (Status != XST_SUCCESS) {
3798 #ifdef XNANDPSU_DEBUG
3799 xil_printf("%s: Poll for buf read ready timeout\r\n",
3805 * Increment Buffer Read Interrupt Count
3809 if (BufRdCnt == PktCount) {
3811 * Enable Transfer Complete Interrupt in Interrupt
3812 * Status Enable Register
3814 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3815 XNANDPSU_INTR_STS_EN_OFFSET,
3816 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
3819 * Clear Buffer Read Ready Interrupt in Interrupt
3820 * Status Enable Register
3822 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3823 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
3827 * Clear Buffer Read Ready Interrupt in Interrupt Status
3830 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3831 XNANDPSU_INTR_STS_OFFSET,
3832 XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK);
3834 * Read Packet Data from Data Port Register
3836 for (Index = 0U; Index < (PktSize/4); Index++) {
3837 BufPtr[Index] = XNandPsu_ReadReg(
3838 InstancePtr->Config.BaseAddress,
3839 XNANDPSU_BUF_DATA_PORT_OFFSET);
3841 BufPtr += (PktSize/4U);
3843 if (BufRdCnt < PktCount) {
3845 * Enable Buffer Read Ready Interrupt in Interrupt
3846 * Status Enable Register
3848 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3849 XNANDPSU_INTR_STS_EN_OFFSET,
3850 XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK);
3857 * Poll for Transfer Complete event
3859 Status = XNandPsu_PollRegTimeout(
3861 XNANDPSU_INTR_STS_OFFSET,
3862 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK,
3863 XNANDPSU_INTR_POLL_TIMEOUT);
3864 if (Status != XST_SUCCESS) {
3865 #ifdef XNANDPSU_DEBUG
3866 xil_printf("%s: Poll for xfer complete timeout\r\n",
3872 * Clear Transfer Complete Interrupt in Interrupt Status Enable
3875 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3876 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
3879 * Clear Transfer Complete Interrupt in Interrupt Status Register
3881 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3882 XNANDPSU_INTR_STS_OFFSET,
3883 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK);
3888 /*****************************************************************************/
3891 * This function issues change read column and reads the data into buffer
3892 * specified by user.
3894 * @param InstancePtr is a pointer to the XNandPsu instance.
3895 * @param Target is the chip select value.
3896 * @param Col is the coulmn address.
3897 * @param PktSize is the number of bytes to read.
3898 * @param PktCount is the number of transactions to read.
3899 * @param Buf is the data buffer to fill in.
3902 * - XST_SUCCESS if successful.
3903 * - XST_FAILURE if failed.
3907 ******************************************************************************/
3908 static s32 XNandPsu_ChangeWriteColumn(XNandPsu *InstancePtr, u32 Target,
3909 u32 Col, u32 PktSize, u32 PktCount,
3912 u32 AddrCycles = InstancePtr->Geometry.ColAddrCycles;
3914 u32 *BufPtr = (u32 *)(void *)Buf;
3915 s32 Status = XST_FAILURE;
3916 OnfiCmdFormat OnfiCommand;
3920 * Assert the input arguments.
3922 Xil_AssertNonvoid(Target < XNANDPSU_MAX_TARGETS);
3923 Xil_AssertNonvoid(Buf != NULL);
3925 if (PktCount == 0U) {
3929 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
3931 * Enable DMA boundary Interrupt in Interrupt Status
3934 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3935 XNANDPSU_INTR_STS_EN_OFFSET,
3936 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK |
3937 XNANDPSU_INTR_STS_EN_DMA_INT_STS_EN_MASK);
3940 * Enable Buffer Write Ready Interrupt in Interrupt Status
3943 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3944 XNANDPSU_INTR_STS_EN_OFFSET,
3945 XNANDPSU_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK);
3948 * Change write column hack
3950 OnfiCommand.Command1 = 0x85U;
3951 OnfiCommand.Command2 = 0x10U;
3952 XNandPsu_Prepare_Cmd(InstancePtr, OnfiCommand.Command1,
3953 OnfiCommand.Command2, 0U , 0U, (u8)AddrCycles);
3958 XNandPsu_SetPageSize(InstancePtr);
3960 * Program Column, Page, Block address
3962 XNandPsu_SetPageColAddr(InstancePtr, 0U, (u16)Col);
3964 * Program Packet Size and Packet Count
3966 XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
3968 * Program DMA system address and DMA buffer boundary
3970 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
3972 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
3973 XNANDPSU_DMA_SYS_ADDR1_OFFSET,
3974 (u32) (((INTPTR)Buf >> 32U) & 0xFFFFFFFFU));
3976 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
3977 XNANDPSU_DMA_SYS_ADDR0_OFFSET,
3978 (u32) ((INTPTR)(void *)Buf & 0xFFFFFFFFU));
3983 XNandPsu_SetBusWidth(InstancePtr);
3985 * Program Memory Address Register2 for chip select
3987 XNandPsu_SelectChip(InstancePtr, Target);
3989 * Set Page Program in Program Register
3991 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
3992 XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_CHNG_ROW_ADDR_END_MASK);
3994 if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
3998 while (BufWrCnt < PktCount) {
4000 * Poll for Buffer Write Ready event
4002 Status = XNandPsu_PollRegTimeout(
4004 XNANDPSU_INTR_STS_OFFSET,
4005 XNANDPSU_INTR_STS_BUFF_WR_RDY_STS_EN_MASK,
4006 XNANDPSU_INTR_POLL_TIMEOUT);
4007 if (Status != XST_SUCCESS) {
4008 #ifdef XNANDPSU_DEBUG
4009 xil_printf("%s: Poll for buf write ready timeout\r\n",
4015 * Increment Buffer Write Interrupt Count
4019 if (BufWrCnt == PktCount) {
4021 * Enable Transfer Complete Interrupt in Interrupt
4022 * Status Enable Register
4024 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
4025 XNANDPSU_INTR_STS_EN_OFFSET,
4026 XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
4029 * Clear Buffer Write Ready Interrupt in Interrupt
4030 * Status Enable Register
4032 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
4033 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
4036 * Clear Buffer Write Ready Interrupt in Interrupt Status
4039 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
4040 XNANDPSU_INTR_STS_OFFSET,
4041 XNANDPSU_INTR_STS_BUFF_WR_RDY_STS_EN_MASK);
4043 * Write Packet Data to Data Port Register
4045 for (Index = 0U; Index < (PktSize/4U); Index++) {
4046 XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
4047 XNANDPSU_BUF_DATA_PORT_OFFSET,
4050 BufPtr += (PktSize/4U);
4052 if (BufWrCnt < PktCount) {
4054 * Enable Buffer Write Ready Interrupt in Interrupt
4055 * Status Enable Register
4057 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
4058 XNANDPSU_INTR_STS_EN_OFFSET,
4059 XNANDPSU_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK);
4066 * Poll for Transfer Complete event
4068 Status = XNandPsu_PollRegTimeout(
4070 XNANDPSU_INTR_STS_OFFSET,
4071 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK,
4072 XNANDPSU_INTR_POLL_TIMEOUT);
4073 if (Status != XST_SUCCESS) {
4074 #ifdef XNANDPSU_DEBUG
4075 xil_printf("%s: Poll for xfer complete timeout\r\n",
4081 * Clear Transfer Complete Interrupt in Interrupt Status Enable
4084 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
4085 XNANDPSU_INTR_STS_EN_OFFSET, 0U);
4088 * Clear Transfer Complete Interrupt in Interrupt Status Register
4090 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
4091 XNANDPSU_INTR_STS_OFFSET,
4092 XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK);
4098 /*****************************************************************************/
4101 * This function initializes extended parameter page ECC information.
4103 * @param InstancePtr is a pointer to the XNandPsu instance.
4104 * @param ExtPrm is the Extended parameter page buffer.
4107 * - XST_SUCCESS if successful.
4108 * - XST_FAILURE if failed.
4112 ******************************************************************************/
4113 static s32 XNandPsu_InitExtEcc(XNandPsu *InstancePtr, OnfiExtPrmPage *ExtPrm)
4115 s32 Status = XST_FAILURE;
4121 OnfiExtEccBlock *EccBlock;
4123 if (ExtPrm->Section0Type != 0x2U) {
4124 Offset += (u32)ExtPrm->Section0Len;
4125 if (ExtPrm->Section1Type != 0x2U) {
4126 #ifdef XNANDPSU_DEBUG
4127 xil_printf("%s: Extended ECC section not found\r\n",__func__);
4129 Status = XST_FAILURE;
4138 EccBlock = (OnfiExtEccBlock *)&ExtPrm->SectionData[Offset];
4139 Xil_AssertNonvoid(EccBlock != NULL);
4140 if (EccBlock->CodeWordSize == 0U) {
4141 Status = XST_FAILURE;
4143 InstancePtr->Geometry.NumBitsECC =
4144 EccBlock->NumBitsEcc;
4145 InstancePtr->Geometry.EccCodeWordSize =
4146 (u32)EccBlock->CodeWordSize;
4147 Status = XST_SUCCESS;
4153 /*****************************************************************************/
4156 * This function prepares command to be written into command register.
4158 * @param InstancePtr is a pointer to the XNandPsu instance.
4159 * @param Cmd1 is the first Onfi Command.
4160 * @param Cmd1 is the second Onfi Command.
4161 * @param EccState is the flag to set Ecc State.
4162 * @param DmaMode is the flag to set DMA mode.
4169 ******************************************************************************/
4170 void XNandPsu_Prepare_Cmd(XNandPsu *InstancePtr, u8 Cmd1, u8 Cmd2, u8 EccState,
4171 u8 DmaMode, u8 AddrCycles)
4175 Xil_AssertVoid(InstancePtr != NULL);
4177 RegValue = (u32)Cmd1 | (((u32)Cmd2 << (u32)XNANDPSU_CMD_CMD2_SHIFT) &
4178 (u32)XNANDPSU_CMD_CMD2_MASK);
4180 if ((EccState != 0U) && (InstancePtr->EccMode == XNANDPSU_HWECC)) {
4181 RegValue |= 1U << XNANDPSU_CMD_ECC_ON_SHIFT;
4184 if ((DmaMode != 0U) && (InstancePtr->DmaMode == XNANDPSU_MDMA)) {
4185 RegValue |= XNANDPSU_MDMA << XNANDPSU_CMD_DMA_EN_SHIFT;
4188 if (AddrCycles != 0U) {
4189 RegValue |= (u32)AddrCycles <<
4190 (u32)XNANDPSU_CMD_ADDR_CYCLES_SHIFT;
4193 XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
4194 XNANDPSU_CMD_OFFSET, RegValue);