[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