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