]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/performance-audio-sr.git/blob - psdk_cust/pdk_k2g_1_0_1_1_eng/packages/ti/board/diag/nand/src/evmk2g_nand_gpmc.c
Modified messaging code after code review.
[processor-sdk/performance-audio-sr.git] / psdk_cust / pdk_k2g_1_0_1_1_eng / packages / ti / board / diag / nand / src / evmk2g_nand_gpmc.c
1 /*
2  * Copyright (c) 2016, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  */
34 /**
35  *
36  * \file    evmk2g_nand_gpmc.c
37  *
38  * \brief   This file contains functions for interfacing NAND device with
39  *          GPMC controller.
40  *
41  ******************************************************************************/
43 #include "platform_internal.h"
45 /******************************************************************************
46 **                      INTERNAL FUNCTION DEFINITIONS
47 *******************************************************************************/
49 /**
50 * \brief This function does the 1-bit hamming code ECC related initialization
51 *        to the NAND controller.\n
52 *
53 * \param  nandInfo      : Pointer to structure containing controller and
54 *                         device information.\n
55 *
56 * \return
57 *        NAND_STATUS_PASSED : On success.\n
58 *        NAND_STATUS_FAILED : On failure.\n
59 *
60 */
61 static NandStatus_t nandHammingCodeECCInit(NandInfo_t *nandInfo)
62 {
63     Uint32       cs;
64     NandStatus_t retVal;
65     gpmcHandle   hGpmc;
67     retVal = NAND_STATUS_PASSED;
68     cs     = nandInfo->hNandCtrlInfo->currChipSelect;
69     hGpmc  = nandInfo->hNandCtrlInfo->hGpmc;
71     GPMCECCAlgoSelect(hGpmc, GPMC_ECC_ALGORITHM_HAMMINGCODE);
72     GPMCECCColumnSelect(hGpmc, GPMC_ECC_COLUMNS_8);
73     GPMCECCCSSelect(hGpmc, cs);
74     GPMCECCDisable(hGpmc);
75     GPMCECCResultRegSelect(hGpmc, GPMC_ECCPOINTER_RESULT_1);
76     GPMCECCResultRegClear(hGpmc);
77     GPMCECCSizeValSet(hGpmc, GPMC_ECC_SIZE_0, GPMC_ECC_SIZE0_VAL);
78     GPMCECCSizeValSet(hGpmc, GPMC_ECC_SIZE_1, GPMC_ECC_SIZE1_VAL);
79     GPMCECCResultSizeSelect(hGpmc, GPMC_ECC_RESULT_1, GPMC_ECC_SIZE_0);
81     nandInfo->hNandEccInfo->eccOffSet  = nandInfo->pageSize +
82                                          NAND_ECC_1BIT_HAMMINGCODE_OOB_OFFSET;
83     nandInfo->hNandEccInfo->eccByteCnt = NAND_ECC_1BIT_HAMMINGCODE_BYTECNT;
85     return(retVal);
86 }
88 /**
89 * \brief  This Function does the Hamming code ECC related setting for write.\n
90 *
91 * \param   nandInfo     : Pointer to structure containing controller and
92 *                         device information.\n
93 *
94 * \return none.\n
95 *
96 */
97 static void nandHammingCodeWriteSet(NandInfo_t *nandInfo)
98 {
99     /* No special setting required in Hamming code for write */
102 /**
103 * \brief  This Function does the Hamming code ECC related setting for Read.\n
105 * \param   nandInfo     : Pointer to structure containing controller and
106 *                         device information.\n
108 * \return none.\n
110 */
111 static void nandHammingCodeReadSet(NandInfo_t *nandInfo)
113     /* No special setting required in Hamming code for Read */
116 /**
117 * \brief This function reads/calculates the 1-bit hamming code ECC values.\n
119 * \param  hGpmc         : Handle to base address of the GPMC controller.\n
121 * \param  eccResReg     : ECC Result register value.\n
123 * \param  ptrEccData    : Pointer where read ECC data has to store.\n
125 * \return none.\n
127 */
128 static void nandHammingCodeECCCalculate(gpmcHandle hGpmc, Uint32 eccResReg,
129                                         Uint8 *ptrEccData)
131     Uint32 eccVal;
133     eccVal = GPMCECCResultGet(hGpmc, eccResReg);
135    /* Squeeze 4 bytes ECC into 3 bytes by removing RESERVED bits
136     * and shifting. RESERVED bits are 31 to 28 and 15 to 12. */
137     eccVal = (eccVal & 0x00000fff) | ((eccVal & 0x0fff0000) >> 4);
138     /* Invert so that erased block ECC is correct */
139     eccVal = ~eccVal;
141     *ptrEccData++ = (Uint8)eccVal;
142     *ptrEccData++ = (Uint8)eccVal >>  8;
143     *ptrEccData++ = (Uint8)eccVal >> 16;
146 /**
147 * \brief This function checks for ECC errors using 1-bit hamming code algorithm
148 *        and correct if any ECC errors.\n
150 * \param   nandInfo     : Pointer to structure containing controller and
151 *                         device information.\n
153 * \param   eccRead      : Pointer to the ECC data which is read from the spare
154 *                         area.\n
156 * \param   data         : Pointer to the data, where if an ecc error need to
157 *                         correct.\n
159 * \return ECC correction Status.\n
160 *    NAND_STATUS_PASSED                        : If no ecc errors.\n
161 *    NAND_STATUS_READ_ECC_ERROR_CORRECTED      : If error are corrected.\n
162 *    NAND_STATUS_READ_ECC_UNCORRECTABLE_ERROR  : If errors are uncorrectable.\n
164 */
165 static NandStatus_t nandHammingCodeECCCheckAndCorrect(NandInfo_t *nandInfo,
166                                                       Uint8 *eccRead,
167                                                       Uint8 *data)
169     NandStatus_t retVal;
170     Uint32       readEccVal;
171     Uint32       calcEccVal;
172     Uint32       eccDiffVal;
173     Uint32       bitPos;
174     Uint32       bytePos;
175     Uint8        eccCalc[4];
177     retVal = NAND_STATUS_PASSED;
179     nandECCCalculate(nandInfo, &eccCalc[0]);
181     readEccVal = eccRead[0] | (eccRead[1] << 8) | (eccRead[2] << 16);
182     calcEccVal = eccCalc[0] | (eccCalc[1] << 8) | (eccCalc[2] << 16);
183     eccDiffVal = readEccVal ^ calcEccVal;
185     if(eccDiffVal)
186     {
187         /*
188          * No error              : The ecc diff value (eccDiffVal) is 0.
189          * Correctable error     : For 512-byte inputs, ecc diff value has
190          *                         12 bits at 1. For 256 byte ecc diff value has
191          *                         11 bits at 1.
192          * ECC error             : The ecc diff value has only 1 bit at 1.
193          * Non-correctable error : The ecc diff value provides all other results
194          */
196         /*
197          * Beow condition checks for number of 1's in eccDiffValu.
198          * Since Total ecc has 3bytes = 24 bits. Make 2 halfs and XOR.
199          * If eccDiffVal has  12 1's, it produces the result 0xFFF.
200         */
201         if ((((eccDiffVal >> 12) ^ eccDiffVal) & 0xfff) == 0xfff)
202         {
203              /* Correctable error */
204             /* Check bytePos is within NAND_BYTES_PER_TRNFS i.e 512 */
205             if ((eccDiffVal >> (12 + 3)) < NAND_BYTES_PER_TRNFS)
206             {
207                 bitPos  = 1 << ((eccDiffVal >> 12) & 7);
208                 bytePos = eccDiffVal >> (12 + 3);
209                 data[bytePos] ^= bitPos;
210                 retVal = NAND_STATUS_READ_ECC_ERROR_CORRECTED;
211             }
212             else
213             {
214                 retVal = NAND_STATUS_READ_ECC_UNCORRECTABLE_ERROR;
215             }
216         }
217         else if(!(eccDiffVal & (eccDiffVal - 1)))
218         {
219             /* Single bit ECC error in the ECC itself,nothing to fix */
220             retVal = NAND_STATUS_READ_ECC_ERROR_CORRECTED;
221         }
222         else
223         {
224             retVal = NAND_STATUS_READ_ECC_UNCORRECTABLE_ERROR;
225         }
226     }
228     return (retVal);
231 /**
232 * \brief This function does the BCH ECC related initializes to the NAND
233 *        controller.\n
235 * \param  nandInfo      : Pointer to structure containing controller and
236 *                         device information.\n
238 * \return
239 *        NAND_STATUS_PASSED          : On success.\n
240 *        NAND_STATUS_FAILED          : On failure.\n
241 *        NAND_STATUS_ECC_UNSUPPORTED : If unsupported ECC is used.\n
243 */
244 static NandStatus_t nandBCHECCInit(NandInfo_t *nandInfo)
246     gpmcHandle      hGpmc;
247     elmHandle       hElm;
248     NandStatus_t    retVal;
249     Uint32          cs;
250     volatile Uint32 timeOut;
252     timeOut = 0xFFF;
253     retVal  = NAND_STATUS_PASSED;
254     cs      = nandInfo->hNandCtrlInfo->currChipSelect;
255     hGpmc   = nandInfo->hNandCtrlInfo->hGpmc;
256     hElm    = nandInfo->hNandEccInfo->hElm;
258     GPMCECCDisable(hGpmc);
259     GPMCECCAlgoSelect(hGpmc, GPMC_ECC_ALGORITHM_BCH);
261     if(nandInfo->eccType != NAND_ECC_ALGO_BCH_8BIT)
262     {
263         retVal = NAND_STATUS_ECC_UNSUPPORTED;
264     }
265     else
266     {
267         GPMCECCBCHErrCorrectionCapSelect(hGpmc,
268                                          GPMC_ECC_BCH_ERRCORRCAP_UPTO_8BITS);
269         GPMCECCColumnSelect(hGpmc, nandInfo->busWidth);
270         GPMCECCCSSelect(hGpmc, cs);
271         GPMCECCBCHNumOfSectorsSelect(hGpmc, GPMC_ECC_BCH_NUMOFSECTS_1);
272         GPMCECCBCHWrapModeValSet(hGpmc, 1);
274         GPMCECCResultRegSelect(hGpmc, GPMC_ECCPOINTER_RESULT_1);
275         GPMCECCResultRegClear(hGpmc);
277         GPMCECCSizeValSet(hGpmc, GPMC_ECC_SIZE_0, GPMC_ECC_SIZE0_VAL);
278         GPMCECCSizeValSet(hGpmc, GPMC_ECC_SIZE_1, GPMC_ECC_SIZE1_VAL);
279         GPMCECCResultSizeSelect(hGpmc, GPMC_ECC_RESULT_1, GPMC_ECC_SIZE_0);
281         /* ELM Module configuration */
282         elmModuleReset(hElm);
283         while((elmModuleResetStatusGet(hElm) != 1) && (timeOut != 0))
284         {
285             timeOut--;
286         }
288         if(timeOut == 0)
289         {
290             retVal = NAND_STATUS_FAILED;
291         }
292         else
293         {
294             elmAutoGatingConfig(hElm, ELM_AUTOGATING_OCP_FREE);
295             elmIdleModeSelect(hElm, ELM_IDLEMODE_NOIDLE);
296             elmOCPClkActivityConfig(hElm, ELM_CLOCKACTIVITYOCP_OCP_ON);
297             elmIntStatusClear(hElm, ELM_LOC_VALID_0_STATUS);
298             elmIntConfig(hElm, ELM_LOC_VALID_0_STATUS, ELM_INT_ENALBLE);
299             elmErrCorrectionLevelSet(hElm, ELM_ECC_BCH_LEVEL_8BITS);
300             elmECCSizeSet(hElm, 0x7FF);
301             elmModeSet(hElm, ELM_MODE_PAGE, ELM_PAGEMODE_SECTOR_0);
303             nandInfo->hNandEccInfo->eccOffSet  = NAND_ECC_BCH_8BIT_OOB_OFFSET +
304                                                  nandInfo->pageSize;
305             nandInfo->hNandEccInfo->eccByteCnt = NAND_ECC_BCH_8BIT_BYTECNT;
306         }
307     }
309     return (retVal);
312 /**
313 * \brief  This Function does the BCH ECC related setting for write.\n
315 * \param  nandInfo      : Pointer to structure containing controller and
316 *                         device information.\n
318 * \return none.\n
320 */
321 static void nandBCHWriteSet(NandInfo_t *nandInfo)
323     Uint32 size1;
324     Uint32 size0;
326     size1 = 0;
327     size0 = 0;
329     if(nandInfo->eccType == NAND_ECC_ALGO_BCH_4BIT)
330     {
331        /* Not Supported */
332     }
333     else if(nandInfo->eccType == NAND_ECC_ALGO_BCH_8BIT)
334     {
335         size1 = (NAND_ECC_BCH_8BIT_BYTECNT * 2);
336         size0 = 0;
337     }
339     GPMCECCSizeValSet(nandInfo->hNandCtrlInfo->hGpmc, GPMC_ECC_SIZE_0, size0);
340     GPMCECCSizeValSet(nandInfo->hNandCtrlInfo->hGpmc, GPMC_ECC_SIZE_1, size1);
343 /**
344 * \brief  This Function does the BCH ECC related setting for read.\n
346 * \param  nandInfo      : Pointer to structure containing controller and
347 *                         device information.\n
349 * \return none.\n
351 */
352 static void nandBCHReadSet(NandInfo_t *nandInfo)
354     Uint32 size1;
355     Uint32 size0;
357     size1 = 0;
358     size0 = 0;
360     if(nandInfo->eccType == NAND_ECC_ALGO_BCH_4BIT)
361     {
362        /* Not Supported */
363     }
364     else if(nandInfo->eccType == NAND_ECC_ALGO_BCH_8BIT)
365     {
366         size0 = ((NAND_ECC_BCH_8BIT_BYTECNT * 2) -
367                   NAND_ECC_BCH_8BIT_UNUSED_BYTECNT);
368         size1 = NAND_ECC_BCH_8BIT_UNUSED_BYTECNT;
369     }
371     GPMCECCSizeValSet(nandInfo->hNandCtrlInfo->hGpmc, GPMC_ECC_SIZE_0, size0);
372     GPMCECCSizeValSet(nandInfo->hNandCtrlInfo->hGpmc, GPMC_ECC_SIZE_1, size1);
375 /**
376 * \brief This function reads/calculates the BCH 4-bit andc 8-bit ECC values.\n
378 * \param  nandInfo      : Pointer to structure containing controller and
379 *                         device information.\n
381 * \param  ptrEccData    : Pointer where read ECC data has to store.\n
384 * \return none.\n
386 */
387 static void nandBCHECCCalculate(NandInfo_t *nandInfo, Uint8 *ptrEccData)
389         gpmcHandle hGpmc;
390     Uint32     eccRes;
391     Uint32     eccType;
392     Uint32     cs;
394     cs      = nandInfo->hNandCtrlInfo->currChipSelect;
395     hGpmc   = nandInfo->hNandCtrlInfo->hGpmc;
396     eccType = nandInfo->eccType;
398     if(eccType == NAND_ECC_ALGO_BCH_4BIT)
399     {
400        /* Not Supported */
401     }
402     else if(eccType == NAND_ECC_ALGO_BCH_8BIT)
403     {
404         eccRes = GPMCECCBCHResultGet(hGpmc, GPMC_BCH_RESULT_3, cs);
405         ptrEccData[0] = (eccRes & 0xFF);
406         eccRes = GPMCECCBCHResultGet(hGpmc, GPMC_BCH_RESULT_2, cs);
407         ptrEccData[1] = ((eccRes >> 24) & 0xFF);
408         ptrEccData[2] = ((eccRes >> 16) & 0xFF);
409         ptrEccData[3] = ((eccRes >> 8) & 0xFF);
410         ptrEccData[4] = (eccRes & 0xFF);
411         eccRes = GPMCECCBCHResultGet(hGpmc, GPMC_BCH_RESULT_1, cs);
412         ptrEccData[5] = ((eccRes >> 24) & 0xFF);
413         ptrEccData[6] = ((eccRes >> 16) & 0xFF);
414         ptrEccData[7] = ((eccRes >> 8) & 0xFF);
415         ptrEccData[8] = (eccRes & 0xFF);
416         eccRes = GPMCECCBCHResultGet(hGpmc, GPMC_BCH_RESULT_0, cs);
417         ptrEccData[9] = ((eccRes >> 24) & 0xFF);
418         ptrEccData[10] = ((eccRes >> 16) & 0xFF);
419         ptrEccData[11] = ((eccRes >> 8) & 0xFF);
420         ptrEccData[12] = (eccRes & 0xFF);
421     }
424 /**
425 * \brief This function checks for ECC errors using BCH algorithm and corrects
426 *        if any ECC errors. \n
428 * \param  nandInfo      : Pointer to structure containing controller and
429 *                         device information.\n
431 * \param   eccRead      : Pointer to the ECC data which is read from the spare
432 *                         area.\n
434 * \param   data         : Pointer to the data, where if an ecc error need to
435 *                         correct.\n
437 * \return ECC correction Status.\n
438 *    NAND_STATUS_PASSED                        : If no ecc errors.\n
439 *    NAND_STATUS_READ_ECC_ERROR_CORRECTED      : If error are corrected.\n
440 *    NAND_STATUS_READ_ECC_UNCORRECTABLE_ERROR  : If errors are uncorrectable.\n
442 */
443 static NandStatus_t nandBCHECCCheckAndCorrect(NandInfo_t *nandInfo,
444                                               Uint8 *eccRead,
445                                               Uint8 *data)
447     NandStatus_t retVal;
448     elmHandle    hElm;
449     Uint32       intStatus;
450     Uint32       eccVal;
451     Uint32       count;
452     Uint32       errNum;
453     Uint32       numOfErrs;
454     Uint32       errLoc;
455     Uint32       lastECCBit;
456     Uint32       lastDataBit;
457     Uint32       errBitMask;
458     Uint32       errBytePos;
459     Uint32       numBytes;
460     Uint32       index;
461     Uint32       result;
462     Uint32       cs;
463     Uint8        eccCalc[NAND_ECC_BCH_8BIT_BYTECNT * 4];
464     Uint8        syndrome[NAND_ECC_BCH_8BIT_BYTECNT * 4];
466     retVal    = NAND_STATUS_PASSED;
467     hElm      = nandInfo->hNandEccInfo->hElm;
468     cs        = nandInfo->hNandCtrlInfo->currChipSelect;
469     intStatus = 0;
470     index     = 0;
471     numBytes  = 0;
473     if(nandInfo->eccType == NAND_ECC_ALGO_BCH_4BIT)
474     {
475        /* Not Supported */
476     }
477     else if(nandInfo->eccType == NAND_ECC_ALGO_BCH_8BIT)
478     {
479         numBytes    = ((NAND_ECC_BCH_8BIT_BYTECNT) - 1);
480         lastECCBit  = NAND_ECC_BCH_8BIT_LASTECCBIT;
481         lastDataBit = NAND_ECC_BCH_8BIT_LASTDATABIT;
482     }
484     nandECCCalculate(nandInfo, &eccCalc[0]);
485     /* while reading ECC result we read it in big endian.
486      * Hence while loading to ELM we have rotate to get the right endian.
487      */
489     /* Rotate the syndrome bytes */
490     for (count = 0, index = (numBytes-1); count < numBytes; count++, index--)
491     {
492         syndrome[count] = eccCalc[index];
493         }
495     /* Load the BCH syndrome */
496     eccVal = (syndrome[0] | (syndrome[1] << 8) | (syndrome[2] << 16) |
497               (syndrome[3] << 24));
498     elmSyndromeFrgmtSet(hElm, ELM_SYNDROME_FRGMT_0, eccVal, cs);
500     eccVal = (syndrome[4] | (syndrome[5] << 8) | (syndrome[6] << 16) |
501               (syndrome[7] << 24));
502     elmSyndromeFrgmtSet(hElm, ELM_SYNDROME_FRGMT_1, eccVal, cs);
504     if(nandInfo->eccType == NAND_ECC_ALGO_BCH_8BIT)
505     {
506         eccVal = (syndrome[8] | (syndrome[9] << 8) | (syndrome[10] << 16) |
507                  (syndrome[11] << 24));
508         elmSyndromeFrgmtSet(hElm, ELM_SYNDROME_FRGMT_2, eccVal, cs);
510         eccVal = (syndrome[12] | (syndrome[13] << 8) | (syndrome[14] << 16) |
511                  (syndrome[15] << 24));
512         elmSyndromeFrgmtSet(hElm, ELM_SYNDROME_FRGMT_3, eccVal, cs);
513     }
515     elmErrLocProcessingStart(hElm, cs);
517     while(intStatus == 0)
518     {
519         intStatus = elmIntStatusGet(hElm, ELM_LOC_VALID_0_STATUS);
520     }
522     elmIntStatusClear(hElm, ELM_LOC_VALID_0_STATUS);
524     result = elmErrLocProcessingStatusGet(hElm, cs);
526     if(result == 0)
527     {
528         retVal = NAND_STATUS_READ_ECC_UNCORRECTABLE_ERROR;
529     }
530     else
531     {
532         numOfErrs = elmNumOfErrsGet(hElm, cs);
533         if(numOfErrs == 0)
534         {
535             retVal = NAND_STATUS_PASSED;
536         }
537         else
538         {
539             errNum = ELM_ERROR_NUM_0;
540              /* Get the error location and correct the same */
541             for(count=0; count < numOfErrs; count++)
542             {
543                 errLoc = elmErrLocBitAddrGet(hElm, errNum, cs);
544                 if (errLoc >= (lastECCBit - 1))
545                 {
546                    /* Error is at the Data bytes */
547                     errBytePos = ((lastDataBit - 1) - errLoc) / 8;
548                     /* Error Bit mask */
549                     errBitMask = 0x1 << (errLoc % 8);
550                     /* Toggle the error bit to make the correction. */
551                     data[errBytePos] ^= errBitMask;
552                     retVal = NAND_STATUS_READ_ECC_ERROR_CORRECTED;
553                 }
554                 else
555                 {
556                     /* Error is at the ECC bytes which we are not handling */
557                 }
559                 errNum++;
560             }
561         }
562     }
564     return (retVal);
568 /******************************************************************************
569 **                       GLOBAL FUNCTION DEFINITIONS
570 *******************************************************************************/
572 /**
573 * \brief  Function to get the wait pin status.\n
575 * \param  nandInfo      : Pointer to structure containing controller and
576 *                         device information.\n
578 * \return Wait pin status.\n
580 *         0 : If the status is active low.\n
581 *         1 : If the status is active high.\n
583 */
584 Uint32 nandWaitPinStatusGet(NandInfo_t *nandInfo)
586     Uint32 pinStatus;
588     pinStatus = GPMCWaitPinStatusGet(nandInfo->hNandCtrlInfo->hGpmc,
589                                      nandInfo->hNandCtrlInfo->waitPin);
590     return(pinStatus);
593 /**
594 * \brief  Function to get the GPMC FIFO status.\n
596 * \param  nandInfo      : Pointer to structure containing controller and
597 *                         device information.\n
599 * \return GPMC FIFO buffer status.\n
601 *         0 : If the FIFO is full.\n
602 *         1 : If the FIFO is empty and ready to accept data.\n
604 */
605 Uint32 nandWriteBufReady(NandInfo_t *nandInfo)
607     Uint32 status;
609     status = GPMCEmptyWriteBuffStatusGet(nandInfo->hNandCtrlInfo->hGpmc);
611     return(status);
614 /**
615 * \brief  Function to initialize the NAND controller.\n
617 * \param  nandCtrlInfo  : Pointer to structure containing controller info.\n
619 * \return
621 *        NAND_STATUS_PASSED          : On success.\n
622 *        NAND_STATUS_FAILED          : On failure.\n
624 */
625 NandStatus_t nandCtrlInit(NandInfo_t *nandInfo)
627     Uint32           conf;
628     Uint32           cs;
629     volatile Uint32  timeOut;
630     NandTimingInfo_t *nandTimingInfo;
631     gpmcHandle       hGpmc;
633     cs = nandInfo->hNandCtrlInfo->currChipSelect;
634     nandTimingInfo = (NandTimingInfo_t *) nandInfo->hNandCtrlInfo->hNandTimingInfo;
636     conf     = 0;
637     timeOut  = 0xFFF;
638     hGpmc = nandInfo->hNandCtrlInfo->hGpmc;
640     /* GPMC Module configuration */
641     GPMCModuleSoftReset(hGpmc);
642     while((GPMCModuleResetStatusGet(hGpmc) != 1) && (timeOut != 0))
643     {
644         timeOut--;
645     }
647     if(timeOut == 0)
648     {
649         return (NAND_STATUS_FAILED);
650     }
652     GPMCIdleModeSelect(hGpmc, GPMC_IDLEMODE_NOIDLE);
654     /* Disable all interrupts */
655     GPMCIntDisable(hGpmc, GPMC_FIFOEVENT_INT);
656     GPMCIntDisable(hGpmc, GPMC_TERMINALCOUNT_INT);
657     GPMCIntDisable(hGpmc, GPMC_WAIT0EDGEDETECTION_INT);
658     GPMCIntDisable(hGpmc, GPMC_WAIT1EDGEDETECTION_INT);
660     /* Timeout control disable */
661     GPMCTimeOutFeatureConfig(hGpmc, GPMC_TIMEOUTFEATURE_DISABLE);
663     /* Set the wait pin polarity */
664     GPMCWaitPinSelect(hGpmc, cs, nandInfo->hNandCtrlInfo->waitPin);
665     GPMCWaitPinPolaritySelect(hGpmc, nandInfo->hNandCtrlInfo->waitPin,
666                               nandInfo->hNandCtrlInfo->waitPinPol);
667     GPMCWriteProtectPinLevelCtrl(hGpmc, nandInfo->hNandCtrlInfo->wpPinPol);
668     GPMCLimitedAddrDevSupportConfig(hGpmc,
669                                     GPMC_LIMITEDADDRESS_SUPPORT_ENABLE);
671     GPMCCSConfig(hGpmc, cs, GPMC_CS_DISABLE);
672     //GPMCTimeParaGranularitySelect(hGpmc, cs, GPMC_TIMEPARAGRANULARITY_X2);
673     GPMCDevTypeSelect(hGpmc, cs, GPMC_DEVICETYPE_NANDLIKE);
674     if(nandInfo->busWidth == NAND_BUSWIDTH_8BIT)
675     {
676         GPMCDevSizeSelect(hGpmc, cs, GPMC_DEVICESIZE_8BITS);
677     }
678     else
679     {
680         GPMCDevSizeSelect(hGpmc, cs, GPMC_DEVICESIZE_16BITS);
681     }
682     GPMCAddrDataMuxProtocolSelect(hGpmc, cs, GPMC_MUXADDDATA_NOMUX);
684     GPMCWriteTypeSelect(hGpmc, cs, GPMC_WRITETYPE_ASYNC);
685     GPMCReadTypeSelect(hGpmc, cs, GPMC_READTYPE_ASYNC);
686     GPMCAccessTypeSelect(hGpmc, cs, GPMC_MODE_WRITE, GPMC_ACCESSTYPE_SINGLE);
687     GPMCAccessTypeSelect(hGpmc, cs, GPMC_MODE_READ, GPMC_ACCESSTYPE_SINGLE);
689     GPMCBaseAddrSet(hGpmc, cs, (nandInfo->hNandCtrlInfo->chipSelectBaseAddr[cs]) >>
690                                    NAND_BASE_ADDR_SHIFT);
691     GPMCMaskAddrSet(hGpmc, cs, (nandInfo->hNandCtrlInfo->chipSelectRegionSize[cs]));
693     conf = GPMC_CS_TIMING_CONFIG(nandTimingInfo->CSWrOffTime,
694                                  nandTimingInfo->CSRdOffTime,
695                                  nandTimingInfo->CSExtDelayFlag,
696                                  nandTimingInfo->CSOnTime);
697     GPMCCSTimingConfig(hGpmc, cs, conf);
699     conf = GPMC_ADV_TIMING_CONFIG(nandTimingInfo->ADVAADMuxWrOffTime,
700                                   nandTimingInfo->ADVAADMuxRdOffTime,
701                                   nandTimingInfo->ADVWrOffTime,
702                                   nandTimingInfo->ADVRdOffTime,
703                                   nandTimingInfo->ADVExtDelayFlag,
704                                   nandTimingInfo->ADVAADMuxOnTime,
705                                   nandTimingInfo->ADVOnTime);
706     GPMCADVTimingConfig(hGpmc, cs, conf);
708     conf = GPMC_WE_OE_TIMING_CONFIG(nandTimingInfo->WEOffTime,
709                                     nandTimingInfo->WEExtDelayFlag,
710                                     nandTimingInfo->WEOnTime,
711                                     nandTimingInfo->OEAADMuxOffTime,
712                                     nandTimingInfo->OEOffTime,
713                                     nandTimingInfo->OEExtDelayFlag,
714                                     nandTimingInfo->OEAADMuxOnTime,
715                                     nandTimingInfo->OEOnTime);
716     GPMCWEAndOETimingConfig(hGpmc, cs, conf);
718     conf = GPMC_RDACCESS_CYCLETIME_TIMING_CONFIG(
719                                    nandTimingInfo->rdCycleTime,
720                                    nandTimingInfo->wrCycleTime,
721                                    nandTimingInfo->rdAccessTime,
722                                    nandTimingInfo->pageBurstAccessTime);
723     GPMCRdAccessAndCycleTimeTimingConfig(hGpmc, cs, conf);
725     conf = GPMC_CYCLE2CYCLE_BUSTURNAROUND_TIMING_CONFIG(
726                                   nandTimingInfo->cycle2CycleDelay,
727                                   nandTimingInfo->cycle2CycleDelaySameCSCfg,
728                                   nandTimingInfo->cycle2CycleDelayDiffCSCfg,
729                                   nandTimingInfo->busTAtime);
730     GPMCycle2CycleAndTurnArndTimeTimingConfig(hGpmc, cs, conf);
732     GPMCWrAccessAndWrDataOnADMUXBusTimingConfig(hGpmc, cs,
733                                                 nandTimingInfo->wrAccessTime,
734                                                 nandTimingInfo->wrDataOnADMux);
735     GPMCCSConfig(hGpmc, cs, GPMC_CS_ENABLE);
737     return(NAND_STATUS_PASSED);
740 /**
741 * \brief This function does the ECC related initializes to the NAND controller
742 *        depending on the ecc type.\n
744 * \param  nandInfo      : Pointer to structure containing controller and
745 *                         device information.\n
747 * \return
748 *        NAND_STATUS_PASSED : On success.\n
749 *        NAND_STATUS_FAILED : On failure.\n
751 */
752 NandStatus_t nandECCInit(NandInfo_t *nandInfo)
754     NandStatus_t retVal;
756     retVal = NAND_STATUS_PASSED;
758     if(nandInfo->eccType == NAND_ECC_ALGO_HAMMING_1BIT)
759     {
760         retVal = nandHammingCodeECCInit(nandInfo);
761     }
762     else if(nandInfo->eccType == NAND_ECC_ALGO_BCH_4BIT ||
763             nandInfo->eccType == NAND_ECC_ALGO_BCH_8BIT)
764     {
765         retVal = nandBCHECCInit(nandInfo);
766     }
768     return(retVal);
771 /**
772 * \brief This function enables the ECC.\n
774 * \param  nandInfo      : Pointer to structure containing controller and
775 *                         device information.\n
777 * \return none.\n
779 */
780 void nandECCEnable(NandInfo_t *nandInfo)
782     gpmcHandle hGpmc = nandInfo->hNandCtrlInfo->hGpmc;
784     GPMCECCResultRegClear(hGpmc);
785     GPMCECCEnable(hGpmc);
788 /**
789 * \brief This function disables the ECC.\n
791 * \param  nandInfo      : Pointer to structure containing controller and
792 *                         device information.\n
794 * \return none.\n
796 */
797 void nandECCDisable(NandInfo_t *nandInfo)
799     gpmcHandle hGpmc = nandInfo->hNandCtrlInfo->hGpmc;
801     GPMCECCDisable(hGpmc);
804 /**
805 * \brief  This Function does the ECC setting for write.\n
807 * \param  nandInfo      : Pointer to structure containing controller and
808 *                         device information.\n
810 * \return none.\n
812 */
813 void nandECCWriteSet(NandInfo_t *nandInfo)
815     if(nandInfo->eccType == NAND_ECC_ALGO_HAMMING_1BIT)
816     {
817         nandHammingCodeWriteSet(nandInfo);
818     }
819     else
820     {
821         nandBCHWriteSet(nandInfo);
822     }
825 /**
826 * \brief  This Function does the ECC setting for read.\n
828 * \param  nandInfo      : Pointer to structure containing controller and
829 *                         device information.\n
831 * \return none.\n
833 */
834 void nandECCReadSet(NandInfo_t *nandInfo)
836     if(nandInfo->eccType == NAND_ECC_ALGO_HAMMING_1BIT)
837     {
838         nandHammingCodeReadSet(nandInfo);
839     }
840     else
841     {
842         nandBCHReadSet(nandInfo);
843     }
846 /**
847 * \brief This function reads the ecc data.\n
849 * \param  nandInfo      : Pointer to structure containing controller and
850 *                         device information.\n
852 * \param  ptrEccData    : Pointer where read ECC data has to store.\n
854 * \return none.\n
856 */
857 void nandECCCalculate(NandInfo_t *nandInfo, Uint8 *ptrEccData)
859     if(nandInfo->eccType == NAND_ECC_ALGO_HAMMING_1BIT)
860     {
861         nandHammingCodeECCCalculate(nandInfo->hNandCtrlInfo->hGpmc,
862                                     GPMC_ECC_RESULT_1, ptrEccData);
863     }
864     else if(nandInfo->eccType == NAND_ECC_ALGO_BCH_4BIT ||
865             nandInfo->eccType == NAND_ECC_ALGO_BCH_8BIT)
866     {
867         nandBCHECCCalculate(nandInfo, ptrEccData);
868     }
871 /**
872 * \brief This function checks and corrects ECC errors.\n
874 * \param   nandInfo     : Pointer to structure containing controller and
875 *                         device information.\n
877 * \param   eccRead      : Pointer to the ECC data which is read from the spare
878 *                         area.\n
880 * \param   data         : Pointer to the data, where if an ecc error need to
881 *                         correct.\n
883 * \return ECC correction Status.\n
884 *    NAND_STATUS_PASSED                        : If no ecc errors.\n
885 *    NAND_STATUS_READ_ECC_ERROR_CORRECTED      : If error are corrected.\n
886 *    NAND_STATUS_READ_ECC_UNCORRECTABLE_ERROR  : If errors are uncorrectable.\n
888 */
889 NandStatus_t nandECCCheckAndCorrect(NandInfo_t *nandInfo,
890                                     Uint8 *eccRead,
891                                     Uint8 *data)
893     NandStatus_t retVal;
895     retVal = NAND_STATUS_PASSED;
897     if(nandInfo->eccType == NAND_ECC_ALGO_HAMMING_1BIT)
898     {
899         retVal = nandHammingCodeECCCheckAndCorrect(nandInfo, eccRead, data);
900     }
901     else if(nandInfo->eccType == NAND_ECC_ALGO_BCH_4BIT ||
902             nandInfo->eccType == NAND_ECC_ALGO_BCH_8BIT)
904     {
905         retVal = nandBCHECCCheckAndCorrect(nandInfo, eccRead, data);
906     }
908     return(retVal);
911 /******************************************************************************
912 **                              END OF FILE
913 *******************************************************************************/