]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M7_SAMV71_Xplained/libchip_samv7/source/smc.c
Update version number ready for V8.2.1 release.
[freertos] / FreeRTOS / Demo / CORTEX_M7_SAMV71_Xplained / libchip_samv7 / source / smc.c
1 /* ----------------------------------------------------------------------------\r
2  *         ATMEL Microcontroller Software Support\r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2010, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\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
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\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
16  *\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
28  */\r
29 /**\r
30   *  \file\r
31   *\r
32   *  Implementation of NFC functions.\r
33   */\r
34 \r
35 /*----------------------------------------------------------------------------\r
36  *        Headers\r
37  *----------------------------------------------------------------------------*/\r
38 \r
39 #include "chip.h"\r
40 \r
41 static SmcStatus smcStatus;\r
42 /*----------------------------------------------------------------------------\r
43  *        Local functions\r
44  *----------------------------------------------------------------------------*/\r
45 \r
46 /**\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
49  */\r
50 static unsigned char CountBitsInByte(unsigned char byte)\r
51 {\r
52     unsigned char count = 0;\r
53     while (byte > 0) {\r
54 \r
55         if (byte & 1) {\r
56 \r
57             count++;\r
58         }\r
59         byte >>= 1;\r
60     }\r
61 \r
62     return count;\r
63 }\r
64 \r
65 /**\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
68  */\r
69 static unsigned char CountBitsInCode(unsigned char *code)\r
70 {\r
71     return CountBitsInByte(code[0])\r
72            + CountBitsInByte(code[1])\r
73            + CountBitsInByte(code[2]);\r
74 }\r
75 \r
76 /**\r
77   * \brief Clear the corresponding interrupt flag.\r
78  */\r
79 static void SMC_Clear_Status (void)\r
80 {\r
81     smcStatus.BStatus = 0;\r
82 }\r
83 \r
84 /**\r
85  * \brief Check the STATUS and set the corresponding interrupt flag.\r
86  */\r
87 static void SMC_Handler(void)\r
88 {\r
89     uint32_t status;\r
90     status = SMC->SMC_SR;\r
91 #if 0\r
92     if ((status & SMC_SR_SMCSTS) == SMC_SR_SMCSTS) \r
93     /* NAND Flash Controller is enabled */\r
94         smcStatus.bStatus.smcSts = 1; \r
95 #endif\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
98        operation. */\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
102        operation.*/\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
110        operation.*/\r
111         smcStatus.bStatus.hammingReady = 1; \r
112 }\r
113 \r
114 /*----------------------------------------------------------------------------\r
115  *        Exported functions\r
116  *----------------------------------------------------------------------------*/\r
117 \r
118 /**\r
119  * \brief Sets NFC configuration.\r
120  * \param cfg  NFC configuration.\r
121  */\r
122 void SMC_NFC_Configure(uint32_t cfg)\r
123 {\r
124     SMC->SMC_CFG = cfg;\r
125 }\r
126 \r
127 /**\r
128  * \brief Reset NFC controller.\r
129  */\r
130 void SMC_NFC_Reset(void)\r
131 {\r
132     /* Disable all the SMC NFC interrupts */\r
133     SMC->SMC_IDR = 0xFFFFFFFF;\r
134     SMC->SMC_CTRL = 0;\r
135 }\r
136 \r
137 /**\r
138  * \brief Enable NFC controller.\r
139  */\r
140 void SMC_NFC_EnableNfc(void)\r
141 {\r
142     SMC->SMC_CTRL |= SMC_CTRL_NFCEN;\r
143 }\r
144 \r
145 /**\r
146  * \brief Enable NFC controller reads both main and spare area in read mode.\r
147  */\r
148 void SMC_NFC_EnableSpareRead(void)\r
149 {\r
150     SMC->SMC_CFG |= SMC_CFG_RSPARE;\r
151 }\r
152 \r
153 /**\r
154  * \brief The NFC controller skips spare area in read mode.\r
155  */\r
156 void SMC_NFC_DisableSpareRead(void)\r
157 {\r
158     SMC->SMC_CFG &= (~SMC_CFG_RSPARE);\r
159 }\r
160 \r
161 /**\r
162  * \brief Enables the NFC controller writes both main and spare area in write\r
163  */\r
164 void SMC_NFC_EnableSpareWrite(void)\r
165 {\r
166     SMC->SMC_CFG |= SMC_CFG_WSPARE;\r
167 }\r
168 \r
169 /**\r
170  * \brief The NFC controller skips spare area in write mode.\r
171  */\r
172 void SMC_NFC_DisableSpareWrite(void)\r
173 {\r
174     SMC->SMC_CFG &= (~SMC_CFG_WSPARE);\r
175 }\r
176 \r
177 /**\r
178  * \brief Check if spare area be read in read mode.\r
179  *\r
180  * \return Returns 1 if NFC controller reads both main and spare area in\r
181  *         read mode, otherwise returns 0.\r
182  */\r
183 uint8_t SMC_NFC_isSpareRead(void)\r
184 {\r
185     return (((SMC->SMC_CFG) >> 9) & 0x1);\r
186 }\r
187 \r
188 /**\r
189  * \brief Check if spare area be written in write mode.\r
190  *\r
191  * \return Returns 1 if NFC controller writes both main and spare area in\r
192  *         write mode, otherwise returns 0.\r
193  */\r
194 uint8_t SMC_NFC_isSpareWrite(void)\r
195 {\r
196     return (((SMC->SMC_CFG) >> 8) & 0x1);\r
197 }\r
198 \r
199 /**\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
203  */\r
204 uint8_t SMC_NFC_isTransferComplete(void)\r
205 {\r
206     return ((SMC->SMC_SR & SMC_SR_XFRDONE) == SMC_SR_XFRDONE);\r
207 }\r
208 \r
209 /**\r
210  * \brief Check Ready/Busy line.\r
211  *\r
212  * \return Returns 1 if  edge has been detected on the Ready/Busy line,\r
213  *         otherwise returns 0.\r
214  */\r
215 uint8_t SMC_NFC_isReadyBusy(void)\r
216 {\r
217     return ((SMC->SMC_SR & SMC_SR_RB_EDGE0) == SMC_SR_RB_EDGE0);\r
218 }\r
219 \r
220 /**\r
221  * \brief Check if NFC Controller is busy.\r
222  *\r
223  * \return Returns 1 if NFC Controller is activated and accesses the memory device,\r
224  *         otherwise returns 0.\r
225  */\r
226 uint8_t SMC_NFC_isNfcBusy(void)\r
227 {\r
228     return ((SMC->SMC_SR & SMC_SR_NFCBUSY) == SMC_SR_NFCBUSY);\r
229 }\r
230 \r
231 /**\r
232  * \brief Get NFC Status.\r
233  *\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
237  */\r
238 uint32_t SMC_NFC_GetStatus(void)\r
239 {\r
240     return SMC->SMC_SR;\r
241 }\r
242 \r
243 /*\r
244  * HOST command functions\r
245  */\r
246 \r
247 /**\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
250  */\r
251 static uint8_t SMC_NFC_isHostBusy(void)\r
252 {\r
253     return (((*((volatile uint32_t *) (NFC_CMD_BASE_ADDR + NFCADDR_CMD_NFCCMD))) & 0x8000000) == 0x8000000);\r
254 }\r
255 \r
256 /**\r
257  * \brief Wait for NFC command has done.\r
258 */\r
259 void SMC_NFC_Wait_CommandDone(void)\r
260 {\r
261     while (smcStatus.bStatus.cmdDone == 0)\r
262     {\r
263         SMC_Handler();\r
264     }\r
265 }\r
266 \r
267 /**\r
268  * \brief Wait for NFC Data Transfer Terminated.\r
269 */\r
270 void SMC_NFC_Wait_XfrDone(void)\r
271 {\r
272     while (smcStatus.bStatus.xfrDone == 0)\r
273     {\r
274         SMC_Handler();\r
275     }\r
276 }\r
277 \r
278 /**\r
279  * \brief Wait for NFC Data Transfer Terminated.\r
280 */\r
281 void SMC_NFC_Wait_HammingReady(void)\r
282 {\r
283     while (smcStatus.bStatus.hammingReady ==0)\r
284     {\r
285         SMC_Handler();\r
286     }\r
287 }\r
288 \r
289 /**\r
290  * \brief Wait for NFC Ready/Busy Line 3 Edge Detected.\r
291 */\r
292 void SMC_NFC_Wait_RBbusy(void)\r
293 {\r
294     while (smcStatus.bStatus.rbEdge == 0)\r
295     {\r
296         SMC_Handler();\r
297     }\r
298 }\r
299 \r
300 /**\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
305  */\r
306 void SMC_NFC_SendCommand(uint32_t cmd, uint32_t addressCycle, uint32_t cycle0)\r
307 {\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
317 }\r
318 \r
319 /* ECC function */\r
320 \r
321 /**\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
325  *\r
326  * \param size  Data size in bytes.\r
327  * \param code  Codes buffer.\r
328  */\r
329 static void _smc_ecc_GetW9BitPer512Ecc(uint32_t pageDataSize, uint8_t *code)\r
330 {\r
331     uint8_t i;\r
332     uint8_t numEcc;\r
333     uint32_t eccParity;\r
334     uint32_t ecc[16];\r
335 \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
348     }\r
349 }\r
350 \r
351 /**\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
355  *\r
356  * \param size  Data size in bytes.\r
357  * \param code  Codes buffer.\r
358  */\r
359 static void _smc_ecc_GetW8BitPer256Ecc(uint32_t pageDataSize, uint8_t *code)\r
360 {\r
361     uint8_t i;\r
362     uint8_t numEcc;\r
363     uint32_t eccParity;\r
364     uint32_t ecc[16];\r
365 \r
366     SMC_ECC_GetValue(ecc);\r
367     numEcc = pageDataSize / 256;\r
368 \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
380     }\r
381 }\r
382 \r
383 /**\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
387  *\r
388  * \param size  Data size in bytes.\r
389  * \param code  Codes buffer.\r
390  */\r
391 static void _smc_ecc_GetW12BitPerPageEcc(uint32_t pageDataSize, uint8_t *code)\r
392 {\r
393     uint32_t eccParity;\r
394     uint32_t eccNparity;\r
395     uint32_t ecc[16];\r
396 \r
397     pageDataSize = pageDataSize; /* stop warning */\r
398     /* Get Parity value. */\r
399     SMC_ECC_GetValue(ecc);\r
400 \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
405 \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
413 }\r
414 \r
415 \r
416 /**\r
417  * \brief Configures ECC mode.\r
418  * \param type  Type of correction.\r
419  * \param pageSize  Page size of NAND flash device.\r
420  */\r
421 void SMC_ECC_Configure(uint32_t type, uint32_t pageSize)\r
422 {\r
423     /* Software Reset ECC. */\r
424     SMC->SMC_ECC_CTRL = (0x1 <<  1) ;\r
425     SMC->SMC_ECC_MD = type | pageSize;\r
426 }\r
427 \r
428 /**\r
429  * \brief Get ECC correction type.\r
430  *\r
431  * \return Returns type of ECC correction setting.\r
432  */\r
433 uint32_t SMC_ECC_GetCorrectoinType(void)\r
434 {\r
435     return ((SMC->SMC_ECC_MD)& SMC_ECC_MD_TYPCORREC_Msk);\r
436 }\r
437 \r
438 /**\r
439  * \brief Get ECC status.\r
440  * \param eccNumber  ecc parity number from 0 to 15.\r
441  *\r
442  * \return Returns ECC status by giving ecc number.\r
443  */\r
444 uint8_t SMC_ECC_GetStatus(uint8_t eccNumber)\r
445 {\r
446     uint32_t status;\r
447 \r
448     if (eccNumber < 8){\r
449         status = SMC->SMC_ECC_SR1;\r
450     }\r
451     else {\r
452         status = SMC->SMC_ECC_SR2;\r
453         eccNumber -=8;\r
454     }\r
455     return ((status >> (eccNumber * 4)) & 0x07);\r
456 }\r
457 \r
458 /**\r
459  * \brief Get all ECC parity and Nparity value.\r
460  */\r
461 void SMC_ECC_GetValue(uint32_t *ecc)\r
462 {\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
479 }\r
480 \r
481 /**\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
491  */\r
492 static uint8_t _smc_ecc_VerifyW12BitPerPageEcc(\r
493     uint8_t *data,\r
494     const uint8_t *originalCode,\r
495     const uint8_t *verifyCode)\r
496 {\r
497     uint8_t correctionCode[4];\r
498     uint8_t bitCount;\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
511 \r
512         return 0;\r
513     }\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
524         /* Correct bit */\r
525         printf("Correcting byte #%d at bit %d\n\r", byte, bit);\r
526         data[byte] ^= (1 << bit);\r
527 \r
528         return Hsiao_ERROR_SINGLEBIT;\r
529     }\r
530    \r
531     /* Check if ECC has been corrupted */\r
532     if (bitCount == 1) {\r
533         return Hsiao_ERROR_ECC;\r
534     }\r
535     /* Otherwise, this is a multi-bit error */\r
536     else {\r
537         return Hsiao_ERROR_MULTIPLEBITS;\r
538     }\r
539 }\r
540 \r
541 /**\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
551  */\r
552 static uint8_t _smc_ecc_VerifyW8BitPer256Ecc(\r
553     uint8_t *data,\r
554     uint32_t size,\r
555     const uint8_t *originalCode,\r
556     const uint8_t *verifyCode)\r
557 {\r
558     uint8_t correctionCode[3];\r
559     uint32_t position = 0;\r
560     uint8_t byte;\r
561     uint8_t bit;\r
562     uint8_t error = 0;\r
563     \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
572             \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
581                 /* Correct bit */\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
585             }\r
586             /* Check if ECC has been corrupted */\r
587             else if (CountBitsInCode(correctionCode) == 1) {\r
588                 return Hsiao_ERROR_ECC;\r
589             }\r
590             else {\r
591                 /* Otherwise, this is a multi-bit error */\r
592                 return Hsiao_ERROR_MULTIPLEBITS;\r
593             }\r
594         }\r
595         data += 256;\r
596         originalCode += 3;\r
597         verifyCode += 3;\r
598         position += 256;\r
599     }\r
600     return error;\r
601 }\r
602 \r
603 /**\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
613  */\r
614 static uint8_t _smc_ecc_VerifyW9BitPer512Ecc(\r
615     uint8_t *data,\r
616     uint32_t size,\r
617     const uint8_t *originalCode,\r
618     const uint8_t *verifyCode)\r
619 {\r
620     uint8_t correctionCode[3];\r
621     uint32_t position = 0;\r
622     uint16_t byte;\r
623     uint8_t bit;\r
624     uint8_t error = 0;\r
625     \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
634             \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
643                 /* Correct bit */\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
647             }\r
648             /* Check if ECC has been corrupted */\r
649             else if (CountBitsInCode(correctionCode) == 1) {\r
650                 return Hsiao_ERROR_ECC;\r
651             }\r
652             else {\r
653                 /* Otherwise, this is a multi-bit error */\r
654                 return Hsiao_ERROR_MULTIPLEBITS;\r
655             }\r
656         }\r
657         data += 512;\r
658         originalCode += 3;\r
659         verifyCode += 3;\r
660         position += 512;\r
661     }\r
662     return error;\r
663 }\r
664 \r
665 /**\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
669  *\r
670  * \param size  Data size in bytes.\r
671  * \param code  Codes buffer.\r
672  * \param busWidth 8bit/16bit data path.\r
673  */\r
674 void SMC_ECC_GetEccParity(uint32_t pageDataSize, uint8_t *code, uint8_t busWidth)\r
675 {\r
676     uint8_t correctionType;\r
677 \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
683     else {\r
684         switch (correctionType){\r
685             case SMC_ECC_MD_TYPCORREC_CPAGE:\r
686                 _smc_ecc_GetW12BitPerPageEcc(pageDataSize, code);\r
687                 break;\r
688             case SMC_ECC_MD_TYPCORREC_C256B:\r
689                  _smc_ecc_GetW8BitPer256Ecc(pageDataSize, code);\r
690                  break;\r
691             case SMC_ECC_MD_TYPCORREC_C512B:\r
692                 _smc_ecc_GetW9BitPer512Ecc(pageDataSize, code);\r
693                 break;\r
694         }\r
695     }\r
696 }\r
697 \r
698 \r
699 /**\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
711 */\r
712 uint8_t SMC_ECC_VerifyHsiao(\r
713     uint8_t *data,\r
714     uint32_t size,\r
715     const uint8_t *originalCode,\r
716     const uint8_t *verifyCode,\r
717     uint8_t busWidth)\r
718 {\r
719     uint8_t correctionType;\r
720     uint8_t error = 0;\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
725     }\r
726     /* For 8-bit data path */\r
727     else {\r
728         switch (correctionType){\r
729             case SMC_ECC_MD_TYPCORREC_CPAGE:\r
730                 error = _smc_ecc_VerifyW12BitPerPageEcc(data, originalCode, verifyCode);\r
731 \r
732                 break;\r
733             case SMC_ECC_MD_TYPCORREC_C256B:\r
734                  error = _smc_ecc_VerifyW8BitPer256Ecc(data, size, originalCode, verifyCode);\r
735                  break;\r
736             case SMC_ECC_MD_TYPCORREC_C512B:\r
737                 error = _smc_ecc_VerifyW9BitPer512Ecc(data, size, originalCode, verifyCode);\r
738                 break;\r
739         }\r
740     }\r
741     return error;\r
742 }