[processor-sdk/performance-audio-sr.git] / psdk_cust / pdk_k2g_1_0_1_2_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 */
100 }
102 /**
103 * \brief This Function does the Hamming code ECC related setting for Read.\n
104 *
105 * \param nandInfo : Pointer to structure containing controller and
106 * device information.\n
107 *
108 * \return none.\n
109 *
110 */
111 static void nandHammingCodeReadSet(NandInfo_t *nandInfo)
112 {
113 /* No special setting required in Hamming code for Read */
114 }
116 /**
117 * \brief This function reads/calculates the 1-bit hamming code ECC values.\n
118 *
119 * \param hGpmc : Handle to base address of the GPMC controller.\n
120 *
121 * \param eccResReg : ECC Result register value.\n
122 *
123 * \param ptrEccData : Pointer where read ECC data has to store.\n
124 *
125 * \return none.\n
126 *
127 */
128 static void nandHammingCodeECCCalculate(gpmcHandle hGpmc, Uint32 eccResReg,
129 Uint8 *ptrEccData)
130 {
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;
144 }
146 /**
147 * \brief This function checks for ECC errors using 1-bit hamming code algorithm
148 * and correct if any ECC errors.\n
149 *
150 * \param nandInfo : Pointer to structure containing controller and
151 * device information.\n
152 *
153 * \param eccRead : Pointer to the ECC data which is read from the spare
154 * area.\n
155 *
156 * \param data : Pointer to the data, where if an ecc error need to
157 * correct.\n
158 *
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
163 *
164 */
165 static NandStatus_t nandHammingCodeECCCheckAndCorrect(NandInfo_t *nandInfo,
166 Uint8 *eccRead,
167 Uint8 *data)
168 {
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);
229 }
231 /**
232 * \brief This function does the BCH ECC related initializes to the NAND
233 * controller.\n
234 *
235 * \param nandInfo : Pointer to structure containing controller and
236 * device information.\n
237 *
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
242 *
243 */
244 static NandStatus_t nandBCHECCInit(NandInfo_t *nandInfo)
245 {
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);
310 }
312 /**
313 * \brief This Function does the BCH ECC related setting for write.\n
314 *
315 * \param nandInfo : Pointer to structure containing controller and
316 * device information.\n
317 *
318 * \return none.\n
319 *
320 */
321 static void nandBCHWriteSet(NandInfo_t *nandInfo)
322 {
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);
341 }
343 /**
344 * \brief This Function does the BCH ECC related setting for read.\n
345 *
346 * \param nandInfo : Pointer to structure containing controller and
347 * device information.\n
348 *
349 * \return none.\n
350 *
351 */
352 static void nandBCHReadSet(NandInfo_t *nandInfo)
353 {
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);
373 }
375 /**
376 * \brief This function reads/calculates the BCH 4-bit andc 8-bit ECC values.\n
377 *
378 * \param nandInfo : Pointer to structure containing controller and
379 * device information.\n
380 *
381 * \param ptrEccData : Pointer where read ECC data has to store.\n
382 *
383 *
384 * \return none.\n
385 *
386 */
387 static void nandBCHECCCalculate(NandInfo_t *nandInfo, Uint8 *ptrEccData)
388 {
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 }
422 }
424 /**
425 * \brief This function checks for ECC errors using BCH algorithm and corrects
426 * if any ECC errors. \n
427 *
428 * \param nandInfo : Pointer to structure containing controller and
429 * device information.\n
430 *
431 * \param eccRead : Pointer to the ECC data which is read from the spare
432 * area.\n
433 *
434 * \param data : Pointer to the data, where if an ecc error need to
435 * correct.\n
436 *
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
441 *
442 */
443 static NandStatus_t nandBCHECCCheckAndCorrect(NandInfo_t *nandInfo,
444 Uint8 *eccRead,
445 Uint8 *data)
446 {
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);
565 }
568 /******************************************************************************
569 ** GLOBAL FUNCTION DEFINITIONS
570 *******************************************************************************/
572 /**
573 * \brief Function to get the wait pin status.\n
574 *
575 * \param nandInfo : Pointer to structure containing controller and
576 * device information.\n
577 *
578 * \return Wait pin status.\n
579 *
580 * 0 : If the status is active low.\n
581 * 1 : If the status is active high.\n
582 *
583 */
584 Uint32 nandWaitPinStatusGet(NandInfo_t *nandInfo)
585 {
586 Uint32 pinStatus;
588 pinStatus = GPMCWaitPinStatusGet(nandInfo->hNandCtrlInfo->hGpmc,
589 nandInfo->hNandCtrlInfo->waitPin);
590 return(pinStatus);
591 }
593 /**
594 * \brief Function to get the GPMC FIFO status.\n
595 *
596 * \param nandInfo : Pointer to structure containing controller and
597 * device information.\n
598 *
599 * \return GPMC FIFO buffer status.\n
600 *
601 * 0 : If the FIFO is full.\n
602 * 1 : If the FIFO is empty and ready to accept data.\n
603 *
604 */
605 Uint32 nandWriteBufReady(NandInfo_t *nandInfo)
606 {
607 Uint32 status;
609 status = GPMCEmptyWriteBuffStatusGet(nandInfo->hNandCtrlInfo->hGpmc);
611 return(status);
612 }
614 /**
615 * \brief Function to initialize the NAND controller.\n
616 *
617 * \param nandCtrlInfo : Pointer to structure containing controller info.\n
618 *
619 * \return
620 *
621 * NAND_STATUS_PASSED : On success.\n
622 * NAND_STATUS_FAILED : On failure.\n
623 *
624 */
625 NandStatus_t nandCtrlInit(NandInfo_t *nandInfo)
626 {
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);
738 }
740 /**
741 * \brief This function does the ECC related initializes to the NAND controller
742 * depending on the ecc type.\n
743 *
744 * \param nandInfo : Pointer to structure containing controller and
745 * device information.\n
746 *
747 * \return
748 * NAND_STATUS_PASSED : On success.\n
749 * NAND_STATUS_FAILED : On failure.\n
750 *
751 */
752 NandStatus_t nandECCInit(NandInfo_t *nandInfo)
753 {
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);
769 }
771 /**
772 * \brief This function enables the ECC.\n
773 *
774 * \param nandInfo : Pointer to structure containing controller and
775 * device information.\n
776 *
777 * \return none.\n
778 *
779 */
780 void nandECCEnable(NandInfo_t *nandInfo)
781 {
782 gpmcHandle hGpmc = nandInfo->hNandCtrlInfo->hGpmc;
784 GPMCECCResultRegClear(hGpmc);
785 GPMCECCEnable(hGpmc);
786 }
788 /**
789 * \brief This function disables the ECC.\n
790 *
791 * \param nandInfo : Pointer to structure containing controller and
792 * device information.\n
793 *
794 * \return none.\n
795 *
796 */
797 void nandECCDisable(NandInfo_t *nandInfo)
798 {
799 gpmcHandle hGpmc = nandInfo->hNandCtrlInfo->hGpmc;
801 GPMCECCDisable(hGpmc);
802 }
804 /**
805 * \brief This Function does the ECC setting for write.\n
806 *
807 * \param nandInfo : Pointer to structure containing controller and
808 * device information.\n
809 *
810 * \return none.\n
811 *
812 */
813 void nandECCWriteSet(NandInfo_t *nandInfo)
814 {
815 if(nandInfo->eccType == NAND_ECC_ALGO_HAMMING_1BIT)
816 {
817 nandHammingCodeWriteSet(nandInfo);
818 }
819 else
820 {
821 nandBCHWriteSet(nandInfo);
822 }
823 }
825 /**
826 * \brief This Function does the ECC setting for read.\n
827 *
828 * \param nandInfo : Pointer to structure containing controller and
829 * device information.\n
830 *
831 * \return none.\n
832 *
833 */
834 void nandECCReadSet(NandInfo_t *nandInfo)
835 {
836 if(nandInfo->eccType == NAND_ECC_ALGO_HAMMING_1BIT)
837 {
838 nandHammingCodeReadSet(nandInfo);
839 }
840 else
841 {
842 nandBCHReadSet(nandInfo);
843 }
844 }
846 /**
847 * \brief This function reads the ecc data.\n
848 *
849 * \param nandInfo : Pointer to structure containing controller and
850 * device information.\n
851 *
852 * \param ptrEccData : Pointer where read ECC data has to store.\n
853 *
854 * \return none.\n
855 *
856 */
857 void nandECCCalculate(NandInfo_t *nandInfo, Uint8 *ptrEccData)
858 {
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 }
869 }
871 /**
872 * \brief This function checks and corrects ECC errors.\n
873 *
874 * \param nandInfo : Pointer to structure containing controller and
875 * device information.\n
876 *
877 * \param eccRead : Pointer to the ECC data which is read from the spare
878 * area.\n
879 *
880 * \param data : Pointer to the data, where if an ecc error need to
881 * correct.\n
882 *
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
887 *
888 */
889 NandStatus_t nandECCCheckAndCorrect(NandInfo_t *nandInfo,
890 Uint8 *eccRead,
891 Uint8 *data)
892 {
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);
909 }
911 /******************************************************************************
912 ** END OF FILE
913 *******************************************************************************/