1 /* ----------------------------------------------------------------------------
\r
2 * ATMEL Microcontroller Software Support
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2010, Atmel Corporation
\r
6 * All rights reserved.
\r
8 * Redistribution and use in source and binary forms, with or without
\r
9 * modification, are permitted provided that the following conditions are met:
\r
11 * - Redistributions of source code must retain the above copyright notice,
\r
12 * this list of conditions and the disclaimer below.
\r
14 * Atmel's name may not be used to endorse or promote products derived from
\r
15 * this software without specific prior written permission.
\r
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
\r
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
\r
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
\r
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
\r
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
\r
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
\r
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
\r
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
\r
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
27 * ----------------------------------------------------------------------------
\r
32 * Implementation of NFC functions.
\r
35 /*----------------------------------------------------------------------------
\r
37 *----------------------------------------------------------------------------*/
\r
41 static SmcStatus smcStatus;
\r
42 /*----------------------------------------------------------------------------
\r
44 *----------------------------------------------------------------------------*/
\r
47 * \brief Counts and return the number of bits set to '1' in the given hsiao code.
\r
48 * \param code Hsizo code.
\r
50 static unsigned char CountBitsInByte(unsigned char byte)
\r
52 unsigned char count = 0;
\r
66 * \brief Counts and return the number of bits set to '1' in the given hsiao code.
\r
67 * \param code Hsizo code.
\r
69 static unsigned char CountBitsInCode(unsigned char *code)
\r
71 return CountBitsInByte(code[0])
\r
72 + CountBitsInByte(code[1])
\r
73 + CountBitsInByte(code[2]);
\r
77 * \brief Clear the corresponding interrupt flag.
\r
79 static void SMC_Clear_Status (void)
\r
81 smcStatus.BStatus = 0;
\r
85 * \brief Check the STATUS and set the corresponding interrupt flag.
\r
87 static void SMC_Handler(void)
\r
90 status = SMC->SMC_SR;
\r
92 if ((status & SMC_SR_SMCSTS) == SMC_SR_SMCSTS)
\r
93 /* NAND Flash Controller is enabled */
\r
94 smcStatus.bStatus.smcSts = 1;
\r
96 if ((status & SMC_SR_XFRDONE) == SMC_SR_XFRDONE)
\r
97 /* When set to one, this flag indicates that the NFC has terminated the Data Transfer. This flag is reset after a status read
\r
99 smcStatus.bStatus.xfrDone = 1;
\r
100 if ((status & SMC_SR_CMDDONE) == SMC_SR_CMDDONE)
\r
101 /* When set to one, this flag indicates that the NFC has terminated the Command. This flag is reset after a status read
\r
103 smcStatus.bStatus.cmdDone = 1;
\r
104 if ((status & (1<<24)) == (1<<24))
\r
105 /* If set to one, this flag indicates that an edge has been detected on the Ready/Busy Line x. Depending on the EDGE CTRL
\r
106 field located in the SMC_CFG register, only rising or falling edge is detected. This flag is reset after a status read operation. */
\r
107 smcStatus.bStatus.rbEdge = 1;
\r
108 if ((status & SMC_SR_ECCRDY) == SMC_SR_ECCRDY)
\r
109 /* When set to one, this flag indicates that the Hamming ECC computation is completed. This flag is reset after a status read
\r
111 smcStatus.bStatus.hammingReady = 1;
\r
114 /*----------------------------------------------------------------------------
\r
115 * Exported functions
\r
116 *----------------------------------------------------------------------------*/
\r
119 * \brief Sets NFC configuration.
\r
120 * \param cfg NFC configuration.
\r
122 void SMC_NFC_Configure(uint32_t cfg)
\r
124 SMC->SMC_CFG = cfg;
\r
128 * \brief Reset NFC controller.
\r
130 void SMC_NFC_Reset(void)
\r
132 /* Disable all the SMC NFC interrupts */
\r
133 SMC->SMC_IDR = 0xFFFFFFFF;
\r
138 * \brief Enable NFC controller.
\r
140 void SMC_NFC_EnableNfc(void)
\r
142 SMC->SMC_CTRL |= SMC_CTRL_NFCEN;
\r
146 * \brief Enable NFC controller reads both main and spare area in read mode.
\r
148 void SMC_NFC_EnableSpareRead(void)
\r
150 SMC->SMC_CFG |= SMC_CFG_RSPARE;
\r
154 * \brief The NFC controller skips spare area in read mode.
\r
156 void SMC_NFC_DisableSpareRead(void)
\r
158 SMC->SMC_CFG &= (~SMC_CFG_RSPARE);
\r
162 * \brief Enables the NFC controller writes both main and spare area in write
\r
164 void SMC_NFC_EnableSpareWrite(void)
\r
166 SMC->SMC_CFG |= SMC_CFG_WSPARE;
\r
170 * \brief The NFC controller skips spare area in write mode.
\r
172 void SMC_NFC_DisableSpareWrite(void)
\r
174 SMC->SMC_CFG &= (~SMC_CFG_WSPARE);
\r
178 * \brief Check if spare area be read in read mode.
\r
180 * \return Returns 1 if NFC controller reads both main and spare area in
\r
181 * read mode, otherwise returns 0.
\r
183 uint8_t SMC_NFC_isSpareRead(void)
\r
185 return (((SMC->SMC_CFG) >> 9) & 0x1);
\r
189 * \brief Check if spare area be written in write mode.
\r
191 * \return Returns 1 if NFC controller writes both main and spare area in
\r
192 * write mode, otherwise returns 0.
\r
194 uint8_t SMC_NFC_isSpareWrite(void)
\r
196 return (((SMC->SMC_CFG) >> 8) & 0x1);
\r
200 * \brief Check if NFC transfer complete.
\r
201 * \return Returns 1 if NFC controller has terminated the data transmission,
\r
202 * otherwise returns 0.
\r
204 uint8_t SMC_NFC_isTransferComplete(void)
\r
206 return ((SMC->SMC_SR & SMC_SR_XFRDONE) == SMC_SR_XFRDONE);
\r
210 * \brief Check Ready/Busy line.
\r
212 * \return Returns 1 if edge has been detected on the Ready/Busy line,
\r
213 * otherwise returns 0.
\r
215 uint8_t SMC_NFC_isReadyBusy(void)
\r
217 return ((SMC->SMC_SR & SMC_SR_RB_EDGE0) == SMC_SR_RB_EDGE0);
\r
221 * \brief Check if NFC Controller is busy.
\r
223 * \return Returns 1 if NFC Controller is activated and accesses the memory device,
\r
224 * otherwise returns 0.
\r
226 uint8_t SMC_NFC_isNfcBusy(void)
\r
228 return ((SMC->SMC_SR & SMC_SR_NFCBUSY) == SMC_SR_NFCBUSY);
\r
232 * \brief Get NFC Status.
\r
234 * \return Returns the current status register of SMC NFC Status Register.
\r
235 * This resets the internal value of the status register, so further
\r
236 * read may yield different values.
\r
238 uint32_t SMC_NFC_GetStatus(void)
\r
240 return SMC->SMC_SR;
\r
244 * HOST command functions
\r
248 * \brief Check if the host controller is busy.
\r
249 * \return Returns 1 if the host controller is busy, otherwise returns 0.
\r
251 static uint8_t SMC_NFC_isHostBusy(void)
\r
253 return (((*((volatile uint32_t *) (NFC_CMD_BASE_ADDR + NFCADDR_CMD_NFCCMD))) & 0x8000000) == 0x8000000);
\r
257 * \brief Wait for NFC command has done.
\r
259 void SMC_NFC_Wait_CommandDone(void)
\r
261 while (smcStatus.bStatus.cmdDone == 0)
\r
268 * \brief Wait for NFC Data Transfer Terminated.
\r
270 void SMC_NFC_Wait_XfrDone(void)
\r
272 while (smcStatus.bStatus.xfrDone == 0)
\r
279 * \brief Wait for NFC Data Transfer Terminated.
\r
281 void SMC_NFC_Wait_HammingReady(void)
\r
283 while (smcStatus.bStatus.hammingReady ==0)
\r
290 * \brief Wait for NFC Ready/Busy Line 3 Edge Detected.
\r
292 void SMC_NFC_Wait_RBbusy(void)
\r
294 while (smcStatus.bStatus.rbEdge == 0)
\r
301 * \brief Uses the HOST nandflash conntroller to send a command to the NFC.
\r
302 * \param cmd command to send.
\r
303 * \param addressCycle address cycle when command access id decoded.
\r
304 * \param cycle0 address at first cycle.
\r
306 void SMC_NFC_SendCommand(uint32_t cmd, uint32_t addressCycle, uint32_t cycle0)
\r
308 volatile uint32_t *pCommandAddress;
\r
309 SMC_Clear_Status();
\r
310 /* Wait until host controller is not busy. */
\r
311 while(SMC_NFC_isHostBusy());
\r
312 /* Send the command plus the ADDR_CYCLE */
\r
313 pCommandAddress = (volatile uint32_t *) (cmd + NFC_CMD_BASE_ADDR);
\r
314 SMC->SMC_ADDR = cycle0;
\r
315 *pCommandAddress = addressCycle;
\r
316 SMC_NFC_Wait_CommandDone();
\r
322 * \brief Get 24-bit ECC code for 8-bit data path NAND flash.
\r
323 * 24-bit ECC is generated in order to perform one bit correction
\r
324 * for 512 byte in page 512/1024/2048/4096 for 8-bit words
\r
326 * \param size Data size in bytes.
\r
327 * \param code Codes buffer.
\r
329 static void _smc_ecc_GetW9BitPer512Ecc(uint32_t pageDataSize, uint8_t *code)
\r
333 uint32_t eccParity;
\r
336 SMC_ECC_GetValue(ecc);
\r
337 numEcc = pageDataSize / 512;
\r
338 /* P2048' P1024' P512' P256' P128' P64' P32' P16' --- 3rd. Ecc Byte to store */
\r
339 /* P8' P4' P2' P1' P2048 P1024 P512 P256 --- 2nd. Ecc Byte to store */
\r
340 /* P128 P64 P32 P16 P8 P4 P2 P1 --- 1st. Ecc Byte to store */
\r
341 for (i = 0; i < numEcc; i++) {
\r
342 /* Get Parity and NParity value. */
\r
343 eccParity = ecc[i];
\r
344 eccParity = ~eccParity;
\r
345 code[i * 3] = eccParity & 0xff;
\r
346 code[i * 3 + 1] = (eccParity >> 8) & 0xff;
\r
347 code[i * 3 + 2] = (eccParity >> 16) & 0xff;
\r
352 * \brief Get 24-bit ECC code for 8-bit data path NAND flash.
\r
353 * 24-bit ECC is generated in order to perform one bit correction
\r
354 * for 256 byte in page 512/1024/2048/4096 for 8-bit words
\r
356 * \param size Data size in bytes.
\r
357 * \param code Codes buffer.
\r
359 static void _smc_ecc_GetW8BitPer256Ecc(uint32_t pageDataSize, uint8_t *code)
\r
363 uint32_t eccParity;
\r
366 SMC_ECC_GetValue(ecc);
\r
367 numEcc = pageDataSize / 256;
\r
369 /* P2048' P1024' P512' P256' P128' P64' P32' P16' --- 3rd. Ecc Byte to store */
\r
370 /* P8' P4' P2' P1' P2048 P1024 P512 P256 --- 2nd. Ecc Byte to store */
\r
371 /* P128 P64 P32 P16 P8 P4 P2 P1 --- 1st. Ecc Byte to store */
\r
372 for (i = 0; i < numEcc; i++) {
\r
373 /* Get Parity and NParity value. */
\r
374 eccParity = ecc[i];
\r
375 eccParity = ~eccParity;
\r
376 TRACE_DEBUG("ecc Parity%d is 0x%08x \n\r", (int)i, (uint32_t)eccParity);
\r
377 code[i * 3] = eccParity & 0xff;
\r
378 code[i * 3 + 1] = (eccParity >> 8) & 0xff;
\r
379 code[i * 3 + 2] = (eccParity >> 16) & 0xff;
\r
384 * \breif Get 32-bit ECC code for 16-bit data path NAND flash.
\r
385 * 32-bit ECC is generated in order to perform one bit correction
\r
386 * for a page in page 512/1024/2048/4096 for 16-bit words
\r
388 * \param size Data size in bytes.
\r
389 * \param code Codes buffer.
\r
391 static void _smc_ecc_GetW12BitPerPageEcc(uint32_t pageDataSize, uint8_t *code)
\r
393 uint32_t eccParity;
\r
394 uint32_t eccNparity;
\r
397 pageDataSize = pageDataSize; /* stop warning */
\r
398 /* Get Parity value. */
\r
399 SMC_ECC_GetValue(ecc);
\r
401 /* ---- P16384'P8192'P4096'P2048' P1024'P512'P256' --- 4th. Ecc Byte to store */
\r
402 /* P128' P64' P32' P16' P8' P4' P2' P1' --- 3rd. Ecc Byte to store */
\r
403 /* ---- P16384 P8192 P4096 P2048 P1024 P512 P256 --- 2nd. Ecc Byte to store */
\r
404 /* P128 P64 P32 P16 P8 P4 P2 P1 --- 1st. Ecc Byte to store */
\r
406 /* Invert codes (linux compatibility) */
\r
407 eccParity = ecc[0];
\r
408 eccNparity = ecc[1];
\r
409 code[0] = eccParity & 0xff;
\r
410 code[1] = (eccParity >> 8 )& 0xff;
\r
411 code[2] = eccNparity & 0xff;
\r
412 code[3] = (eccNparity >> 8 )& 0xff;
\r
417 * \brief Configures ECC mode.
\r
418 * \param type Type of correction.
\r
419 * \param pageSize Page size of NAND flash device.
\r
421 void SMC_ECC_Configure(uint32_t type, uint32_t pageSize)
\r
423 /* Software Reset ECC. */
\r
424 SMC->SMC_ECC_CTRL = (0x1 << 1) ;
\r
425 SMC->SMC_ECC_MD = type | pageSize;
\r
429 * \brief Get ECC correction type.
\r
431 * \return Returns type of ECC correction setting.
\r
433 uint32_t SMC_ECC_GetCorrectoinType(void)
\r
435 return ((SMC->SMC_ECC_MD)& SMC_ECC_MD_TYPCORREC_Msk);
\r
439 * \brief Get ECC status.
\r
440 * \param eccNumber ecc parity number from 0 to 15.
\r
442 * \return Returns ECC status by giving ecc number.
\r
444 uint8_t SMC_ECC_GetStatus(uint8_t eccNumber)
\r
448 if (eccNumber < 8){
\r
449 status = SMC->SMC_ECC_SR1;
\r
452 status = SMC->SMC_ECC_SR2;
\r
455 return ((status >> (eccNumber * 4)) & 0x07);
\r
459 * \brief Get all ECC parity and Nparity value.
\r
461 void SMC_ECC_GetValue(uint32_t *ecc)
\r
463 ecc[0] = SMC->SMC_ECC_PR0;
\r
464 ecc[1] = SMC->SMC_ECC_PR1;
\r
465 ecc[2] = SMC->SMC_ECC_PR2;
\r
466 ecc[3] = SMC->SMC_ECC_PR3;
\r
467 ecc[4] = SMC->SMC_ECC_PR4;
\r
468 ecc[5] = SMC->SMC_ECC_PR5;
\r
469 ecc[6] = SMC->SMC_ECC_PR6;
\r
470 ecc[7] = SMC->SMC_ECC_PR7;
\r
471 ecc[8] = SMC->SMC_ECC_PR8;
\r
472 ecc[9] = SMC->SMC_ECC_PR9;
\r
473 ecc[10] = SMC->SMC_ECC_PR10;
\r
474 ecc[11] = SMC->SMC_ECC_PR11;
\r
475 ecc[12] = SMC->SMC_ECC_PR12;
\r
476 ecc[13] = SMC->SMC_ECC_PR13;
\r
477 ecc[14] = SMC->SMC_ECC_PR14;
\r
478 ecc[15] = SMC->SMC_ECC_PR15;
\r
482 * \brief verifies 4-bytes hsiao codes for a data block whose size is a page Size
\r
483 * word. Page words block is verified between the given HSIAO code
\r
484 * generated by hardware and original HSIAO codes store has been previously stored.
\r
485 * Returns 0 if the data is correct, Hsiao_ERROR_SINGLEBIT if one or more
\r
486 * block(s) have had a single bit corrected, or either Hsiao_ERROR_ECC
\r
487 * or Hsiao_ERROR_MULTIPLEBITS.
\r
488 * \param data Data buffer to verify.
\r
489 * \param originalCode Original codes.
\r
490 * \param verifyCode codes to be verified.
\r
492 static uint8_t _smc_ecc_VerifyW12BitPerPageEcc(
\r
494 const uint8_t *originalCode,
\r
495 const uint8_t *verifyCode)
\r
497 uint8_t correctionCode[4];
\r
499 // Xor both codes together
\r
500 correctionCode[0] = verifyCode[0] ^ originalCode[0];
\r
501 correctionCode[1] = verifyCode[1] ^ originalCode[1];
\r
502 correctionCode[2] = verifyCode[2] ^ originalCode[2];
\r
503 correctionCode[3] = verifyCode[3] ^ originalCode[3];
\r
504 TRACE_DEBUG("Correction code = %02X %02X %02X %02X\n\r",
\r
505 correctionCode[0], correctionCode[1], correctionCode[2], correctionCode[3]);
\r
506 /* If all bytes are 0, there is no error */
\r
507 if ((correctionCode[0] == 0)
\r
508 && (correctionCode[1] == 0)
\r
509 && (correctionCode[2] == 0)
\r
510 && (correctionCode[3] == 0)) {
\r
514 /* If there is a single bit error, there are 15 bits set to 1 */
\r
515 bitCount = CountBitsInByte(correctionCode[0]) +
\r
516 CountBitsInByte(correctionCode[1]) +
\r
517 CountBitsInByte(correctionCode[2]) +
\r
518 CountBitsInByte(correctionCode[3]);
\r
519 if (bitCount == 15) {
\r
520 /* Get byte and bit indexes */
\r
521 uint16_t byte = (correctionCode[0] & 0xf0) >> 4;
\r
522 byte |= (correctionCode[1] & 0xff) << 4;
\r
523 uint8_t bit = correctionCode[0] & 0x0f;
\r
525 printf("Correcting byte #%d at bit %d\n\r", byte, bit);
\r
526 data[byte] ^= (1 << bit);
\r
528 return Hsiao_ERROR_SINGLEBIT;
\r
531 /* Check if ECC has been corrupted */
\r
532 if (bitCount == 1) {
\r
533 return Hsiao_ERROR_ECC;
\r
535 /* Otherwise, this is a multi-bit error */
\r
537 return Hsiao_ERROR_MULTIPLEBITS;
\r
542 * \brief erifies 3-bytes hsiao codes for a data block whose size is a page Size
\r
543 * word. Page words block is verified between the given HSIAO code
\r
544 * generated by hardware and original HSIAO codes store has been previously stored.
\r
545 * Returns 0 if the data is correct, Hsiao_ERROR_SINGLEBIT if one or more
\r
546 * block(s) have had a single bit corrected, or either Hsiao_ERROR_ECC
\r
547 * or Hsiao_ERROR_MULTIPLEBITS.
\r
548 * \param data Data buffer to verify.
\r
549 * \param originalCode Original codes.
\r
550 * \param verifyCode codes to be verified.
\r
552 static uint8_t _smc_ecc_VerifyW8BitPer256Ecc(
\r
555 const uint8_t *originalCode,
\r
556 const uint8_t *verifyCode)
\r
558 uint8_t correctionCode[3];
\r
559 uint32_t position = 0;
\r
564 TRACE_DEBUG("_smc_ecc_VerifyW8BitPer256Ecc()\n\r");
\r
565 while (position < size) {
\r
566 /* Xor both codes together */
\r
567 correctionCode[0] = verifyCode[0] ^ originalCode[0];
\r
568 correctionCode[1] = verifyCode[1] ^ originalCode[1];
\r
569 correctionCode[2] = verifyCode[2] ^ originalCode[2];
\r
570 TRACE_DEBUG("Correction code = %02X %02X %02X\n\r",
\r
571 correctionCode[0], correctionCode[1], correctionCode[2]);
\r
573 /* If all bytes are 0, there is no error */
\r
574 if ( correctionCode[0] || correctionCode[1] || correctionCode[2]) {
\r
575 /* If there is a single bit error, there are 11 bits set to 1 */
\r
576 if (CountBitsInCode(correctionCode) == 11) {
\r
577 /* Get byte and bit indexes */
\r
578 byte = (correctionCode[0] & 0xf8) >> 3;
\r
579 byte |= (correctionCode[1] & 0x07) << 5;
\r
580 bit = correctionCode[0] & 0x07;
\r
582 printf("Correcting byte #%u at bit %u\n\r", (unsigned int)(position + byte), (unsigned int)bit);
\r
583 data[byte] ^= (1 << bit);
\r
584 error = Hsiao_ERROR_SINGLEBIT;
\r
586 /* Check if ECC has been corrupted */
\r
587 else if (CountBitsInCode(correctionCode) == 1) {
\r
588 return Hsiao_ERROR_ECC;
\r
591 /* Otherwise, this is a multi-bit error */
\r
592 return Hsiao_ERROR_MULTIPLEBITS;
\r
604 * \brief 3-bytes hsiao codes for a data block whose size is multiple of
\r
605 * 512 bytes. Each 512-bytes block is verified between the given HSIAO code
\r
606 * generated by hardware and original HSIAO codes store has been previously stored.
\r
607 * Returns 0 if the data is correct, Hsiao_ERROR_SINGLEBIT if one or more
\r
608 * block(s) have had a single bit corrected, or either Hsiao_ERROR_ECC
\r
609 * or Hsiao_ERROR_MULTIPLEBITS.
\r
610 * \param data Data buffer to verify.
\r
611 * \param originalCode Original codes.
\r
612 * \param verifyCode codes to be verified.
\r
614 static uint8_t _smc_ecc_VerifyW9BitPer512Ecc(
\r
617 const uint8_t *originalCode,
\r
618 const uint8_t *verifyCode)
\r
620 uint8_t correctionCode[3];
\r
621 uint32_t position = 0;
\r
626 TRACE_DEBUG("_smc_ecc_VerifyW9BitPer512Ecc()\n\r");
\r
627 while (position < size) {
\r
628 /* Xor both codes together */
\r
629 correctionCode[0] = verifyCode[0] ^ originalCode[0];
\r
630 correctionCode[1] = verifyCode[1] ^ originalCode[1];
\r
631 correctionCode[2] = verifyCode[2] ^ originalCode[2];
\r
632 TRACE_DEBUG("Correction code = %02X %02X %02X\n\r",
\r
633 correctionCode[0], correctionCode[1], correctionCode[2]);
\r
635 /* If all bytes are 0, there is no error */
\r
636 if ( correctionCode[0] || correctionCode[1] || correctionCode[2]) {
\r
637 // If there is a single bit error, there are 11 bits set to 1
\r
638 if (CountBitsInCode(correctionCode) == 12) {
\r
639 /* Get byte and bit indexes */
\r
640 byte = (correctionCode[0] & 0xf8) >> 3;
\r
641 byte |= (correctionCode[1] & 0x0f) << 5;
\r
642 bit = correctionCode[0] & 0x07;
\r
644 printf("Correcting byte #%u at bit %u\n\r", (unsigned int)(position + byte), (unsigned int)bit);
\r
645 data[byte] ^= (1 << bit);
\r
646 error = Hsiao_ERROR_SINGLEBIT;
\r
648 /* Check if ECC has been corrupted */
\r
649 else if (CountBitsInCode(correctionCode) == 1) {
\r
650 return Hsiao_ERROR_ECC;
\r
653 /* Otherwise, this is a multi-bit error */
\r
654 return Hsiao_ERROR_MULTIPLEBITS;
\r
666 * Get ECC code for 8bit/16-bit data path NAND flash by giving data path.
\r
667 * 24-bit or 32-bit ECC is generated in order to perform one bit correction
\r
668 * for a page in page 512/1024/2048/4096.
\r
670 * \param size Data size in bytes.
\r
671 * \param code Codes buffer.
\r
672 * \param busWidth 8bit/16bit data path.
\r
674 void SMC_ECC_GetEccParity(uint32_t pageDataSize, uint8_t *code, uint8_t busWidth)
\r
676 uint8_t correctionType;
\r
678 correctionType = SMC_ECC_GetCorrectoinType();
\r
679 /* For 16-bit data path */
\r
680 if (busWidth == 16 && correctionType == SMC_ECC_MD_TYPCORREC_CPAGE )
\r
681 _smc_ecc_GetW12BitPerPageEcc(pageDataSize, code);
\r
682 /* For 8-bit data path */
\r
684 switch (correctionType){
\r
685 case SMC_ECC_MD_TYPCORREC_CPAGE:
\r
686 _smc_ecc_GetW12BitPerPageEcc(pageDataSize, code);
\r
688 case SMC_ECC_MD_TYPCORREC_C256B:
\r
689 _smc_ecc_GetW8BitPer256Ecc(pageDataSize, code);
\r
691 case SMC_ECC_MD_TYPCORREC_C512B:
\r
692 _smc_ecc_GetW9BitPer512Ecc(pageDataSize, code);
\r
700 * Verifies hsiao codes for a data block. The block is verified between the given
\r
701 * HSIAO code generated by hardware and original HSIAO codes store has been
\r
702 * previously stored.
\r
703 * Returns 0 if the data is correct, Hsiao_ERROR_SINGLEBIT if one or more
\r
704 * block(s) have had a single bit corrected, or either Hsiao_ERROR_ECC
\r
705 * or Hsiao_ERROR_MULTIPLEBITS.
\r
706 * \param data Data buffer to verify.
\r
707 * \param size Size of the data in words.
\r
708 * \param originalCode Original codes.
\r
709 * \param verifyCode codes to be verified.
\r
710 * \param dataPath 8bit/16bit data path.
\r
712 uint8_t SMC_ECC_VerifyHsiao(
\r
715 const uint8_t *originalCode,
\r
716 const uint8_t *verifyCode,
\r
719 uint8_t correctionType;
\r
721 correctionType = SMC_ECC_GetCorrectoinType();
\r
722 /* For 16-bit data path */
\r
723 if (busWidth == 16 && (correctionType == SMC_ECC_MD_TYPCORREC_CPAGE) ) {
\r
724 error = _smc_ecc_VerifyW12BitPerPageEcc((uint8_t*)data, originalCode, verifyCode);
\r
726 /* For 8-bit data path */
\r
728 switch (correctionType){
\r
729 case SMC_ECC_MD_TYPCORREC_CPAGE:
\r
730 error = _smc_ecc_VerifyW12BitPerPageEcc(data, originalCode, verifyCode);
\r
733 case SMC_ECC_MD_TYPCORREC_C256B:
\r
734 error = _smc_ecc_VerifyW8BitPer256Ecc(data, size, originalCode, verifyCode);
\r
736 case SMC_ECC_MD_TYPCORREC_C512B:
\r
737 error = _smc_ecc_VerifyW9BitPer512Ecc(data, size, originalCode, verifyCode);
\r