00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "chip.h"
00041
00042 static SmcStatus smcStatus;
00043
00044
00045
00046
00047
00048
00049
00050
00051 static unsigned char CountBitsInByte(unsigned char byte)
00052 {
00053 unsigned char count = 0;
00054
00055 while (byte > 0) {
00056 if (byte & 1)
00057 count++;
00058
00059 byte >>= 1;
00060 }
00061
00062 return count;
00063 }
00064
00065
00066
00067
00068
00069 static unsigned char CountBitsInCode(unsigned char *code)
00070 {
00071 return CountBitsInByte(code[0])
00072 + CountBitsInByte(code[1])
00073 + CountBitsInByte(code[2]);
00074 }
00075
00076
00077
00078
00079 static void SMC_Clear_Status (void)
00080 {
00081 smcStatus.BStatus = 0;
00082 }
00083
00084
00085
00086
00087 static void SMC_Handler(void)
00088 {
00089 uint32_t status;
00090 status = SMC->SMC_SR;
00091 #if 0
00092
00093 if ((status & SMC_SR_SMCSTS) == SMC_SR_SMCSTS)
00094
00095 smcStatus.bStatus.smcSts = 1;
00096
00097 #endif
00098
00099 if ((status & SMC_SR_XFRDONE) == SMC_SR_XFRDONE)
00100
00101
00102 smcStatus.bStatus.xfrDone = 1;
00103
00104 if ((status & SMC_SR_CMDDONE) == SMC_SR_CMDDONE)
00105
00106
00107 smcStatus.bStatus.cmdDone = 1;
00108
00109 if ((status & (1 << 24)) == (1 << 24))
00110
00111
00112
00113
00114 smcStatus.bStatus.rbEdge = 1;
00115
00116 if ((status & SMC_SR_ECCRDY) == SMC_SR_ECCRDY)
00117
00118
00119
00120 smcStatus.bStatus.hammingReady = 1;
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 void SMC_NFC_Configure(uint32_t cfg)
00132 {
00133 SMC->SMC_CFG = cfg;
00134 }
00135
00136
00137
00138
00139 void SMC_NFC_Reset(void)
00140 {
00141
00142 SMC->SMC_IDR = 0xFFFFFFFF;
00143 SMC->SMC_CTRL = 0;
00144 }
00145
00146
00147
00148
00149 void SMC_NFC_EnableNfc(void)
00150 {
00151 SMC->SMC_CTRL |= SMC_CTRL_NFCEN;
00152 }
00153
00154
00155
00156
00157 void SMC_NFC_EnableSpareRead(void)
00158 {
00159 SMC->SMC_CFG |= SMC_CFG_RSPARE;
00160 }
00161
00162
00163
00164
00165 void SMC_NFC_DisableSpareRead(void)
00166 {
00167 SMC->SMC_CFG &= (~SMC_CFG_RSPARE);
00168 }
00169
00170
00171
00172
00173 void SMC_NFC_EnableSpareWrite(void)
00174 {
00175 SMC->SMC_CFG |= SMC_CFG_WSPARE;
00176 }
00177
00178
00179
00180
00181 void SMC_NFC_DisableSpareWrite(void)
00182 {
00183 SMC->SMC_CFG &= (~SMC_CFG_WSPARE);
00184 }
00185
00186
00187
00188
00189
00190
00191
00192 uint8_t SMC_NFC_isSpareRead(void)
00193 {
00194 return (((SMC->SMC_CFG) >> 9) & 0x1);
00195 }
00196
00197
00198
00199
00200
00201
00202
00203 uint8_t SMC_NFC_isSpareWrite(void)
00204 {
00205 return (((SMC->SMC_CFG) >> 8) & 0x1);
00206 }
00207
00208
00209
00210
00211
00212
00213 uint8_t SMC_NFC_isTransferComplete(void)
00214 {
00215 return ((SMC->SMC_SR & SMC_SR_XFRDONE) == SMC_SR_XFRDONE);
00216 }
00217
00218
00219
00220
00221
00222
00223
00224 uint8_t SMC_NFC_isReadyBusy(void)
00225 {
00226 return ((SMC->SMC_SR & SMC_SR_RB_EDGE0) == SMC_SR_RB_EDGE0);
00227 }
00228
00229
00230
00231
00232
00233
00234
00235 uint8_t SMC_NFC_isNfcBusy(void)
00236 {
00237 return ((SMC->SMC_SR & SMC_SR_NFCBUSY) == SMC_SR_NFCBUSY);
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247 uint32_t SMC_NFC_GetStatus(void)
00248 {
00249 return SMC->SMC_SR;
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 static uint8_t SMC_NFC_isHostBusy(void)
00261 {
00262 return (((*((volatile uint32_t *) (NFC_CMD_BASE_ADDR + NFCADDR_CMD_NFCCMD)))
00263 & 0x8000000) == 0x8000000);
00264 }
00265
00266
00267
00268
00269 void SMC_NFC_Wait_CommandDone(void)
00270 {
00271 while (smcStatus.bStatus.cmdDone == 0)
00272 SMC_Handler();
00273 }
00274
00275
00276
00277
00278 void SMC_NFC_Wait_XfrDone(void)
00279 {
00280 while (smcStatus.bStatus.xfrDone == 0)
00281 SMC_Handler();
00282 }
00283
00284
00285
00286
00287 void SMC_NFC_Wait_HammingReady(void)
00288 {
00289 while (smcStatus.bStatus.hammingReady == 0)
00290 SMC_Handler();
00291 }
00292
00293
00294
00295
00296 void SMC_NFC_Wait_RBbusy(void)
00297 {
00298 while (smcStatus.bStatus.rbEdge == 0)
00299 SMC_Handler();
00300 }
00301
00302
00303
00304
00305
00306
00307
00308 void SMC_NFC_SendCommand(uint32_t cmd, uint32_t addressCycle, uint32_t cycle0)
00309 {
00310 volatile uint32_t *pCommandAddress;
00311 SMC_Clear_Status();
00312
00313
00314 while (SMC_NFC_isHostBusy());
00315
00316
00317 pCommandAddress = (volatile uint32_t *) (cmd + NFC_CMD_BASE_ADDR);
00318 SMC->SMC_ADDR = cycle0;
00319 *pCommandAddress = addressCycle;
00320 SMC_NFC_Wait_CommandDone();
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 static void _smc_ecc_GetW9BitPer512Ecc(uint32_t pageDataSize, uint8_t *code)
00334 {
00335 uint8_t i;
00336 uint8_t numEcc;
00337 uint32_t eccParity;
00338 uint32_t ecc[16];
00339
00340 SMC_ECC_GetValue(ecc);
00341 numEcc = pageDataSize / 512;
00342
00343
00344
00345
00346 for (i = 0; i < numEcc; i++) {
00347
00348 eccParity = ecc[i];
00349 eccParity = ~eccParity;
00350 code[i * 3] = eccParity & 0xff;
00351 code[i * 3 + 1] = (eccParity >> 8) & 0xff;
00352 code[i * 3 + 2] = (eccParity >> 16) & 0xff;
00353 }
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 static void _smc_ecc_GetW8BitPer256Ecc(uint32_t pageDataSize, uint8_t *code)
00365 {
00366 uint8_t i;
00367 uint8_t numEcc;
00368 uint32_t eccParity;
00369 uint32_t ecc[16];
00370
00371 SMC_ECC_GetValue(ecc);
00372 numEcc = pageDataSize / 256;
00373
00374
00375
00376
00377 for (i = 0; i < numEcc; i++) {
00378
00379 eccParity = ecc[i];
00380 eccParity = ~eccParity;
00381 TRACE_DEBUG("ecc Parity%d is 0x%08x \n\r", (int)i, (uint32_t)eccParity);
00382 code[i * 3] = eccParity & 0xff;
00383 code[i * 3 + 1] = (eccParity >> 8) & 0xff;
00384 code[i * 3 + 2] = (eccParity >> 16) & 0xff;
00385 }
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 static void _smc_ecc_GetW12BitPerPageEcc(uint32_t pageDataSize, uint8_t *code)
00397 {
00398 uint32_t eccParity;
00399 uint32_t eccNparity;
00400 uint32_t ecc[16];
00401
00402 pageDataSize = pageDataSize;
00403
00404 SMC_ECC_GetValue(ecc);
00405
00406
00407
00408
00409
00410
00411
00412 eccParity = ecc[0];
00413 eccNparity = ecc[1];
00414 code[0] = eccParity & 0xff;
00415 code[1] = (eccParity >> 8) & 0xff;
00416 code[2] = eccNparity & 0xff;
00417 code[3] = (eccNparity >> 8) & 0xff;
00418 }
00419
00420
00421
00422
00423
00424
00425
00426 void SMC_ECC_Configure(uint32_t type, uint32_t pageSize)
00427 {
00428
00429 SMC->SMC_ECC_CTRL = (0x1 << 1);
00430 SMC->SMC_ECC_MD = type | pageSize;
00431 }
00432
00433
00434
00435
00436
00437
00438 uint32_t SMC_ECC_GetCorrectoinType(void)
00439 {
00440 return ((SMC->SMC_ECC_MD)& SMC_ECC_MD_TYPCORREC_Msk);
00441 }
00442
00443
00444
00445
00446
00447
00448
00449 uint8_t SMC_ECC_GetStatus(uint8_t eccNumber)
00450 {
00451 uint32_t status;
00452
00453 if (eccNumber < 8)
00454 status = SMC->SMC_ECC_SR1;
00455 else {
00456 status = SMC->SMC_ECC_SR2;
00457 eccNumber -= 8;
00458 }
00459
00460 return ((status >> (eccNumber * 4)) & 0x07);
00461 }
00462
00463
00464
00465
00466 void SMC_ECC_GetValue(uint32_t *ecc)
00467 {
00468 ecc[0] = SMC->SMC_ECC_PR0;
00469 ecc[1] = SMC->SMC_ECC_PR1;
00470 ecc[2] = SMC->SMC_ECC_PR2;
00471 ecc[3] = SMC->SMC_ECC_PR3;
00472 ecc[4] = SMC->SMC_ECC_PR4;
00473 ecc[5] = SMC->SMC_ECC_PR5;
00474 ecc[6] = SMC->SMC_ECC_PR6;
00475 ecc[7] = SMC->SMC_ECC_PR7;
00476 ecc[8] = SMC->SMC_ECC_PR8;
00477 ecc[9] = SMC->SMC_ECC_PR9;
00478 ecc[10] = SMC->SMC_ECC_PR10;
00479 ecc[11] = SMC->SMC_ECC_PR11;
00480 ecc[12] = SMC->SMC_ECC_PR12;
00481 ecc[13] = SMC->SMC_ECC_PR13;
00482 ecc[14] = SMC->SMC_ECC_PR14;
00483 ecc[15] = SMC->SMC_ECC_PR15;
00484 }
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 static uint8_t _smc_ecc_VerifyW12BitPerPageEcc(
00498 uint8_t *data,
00499 const uint8_t *originalCode,
00500 const uint8_t *verifyCode)
00501 {
00502 uint8_t correctionCode[4];
00503 uint8_t bitCount;
00504
00505 correctionCode[0] = verifyCode[0] ^ originalCode[0];
00506 correctionCode[1] = verifyCode[1] ^ originalCode[1];
00507 correctionCode[2] = verifyCode[2] ^ originalCode[2];
00508 correctionCode[3] = verifyCode[3] ^ originalCode[3];
00509 TRACE_DEBUG("Correction code = %02X %02X %02X %02X\n\r",
00510 correctionCode[0], correctionCode[1], correctionCode[2], correctionCode[3]);
00511
00512
00513 if ((correctionCode[0] == 0)
00514 && (correctionCode[1] == 0)
00515 && (correctionCode[2] == 0)
00516 && (correctionCode[3] == 0))
00517
00518 return 0;
00519
00520
00521 bitCount = CountBitsInByte(correctionCode[0]) +
00522 CountBitsInByte(correctionCode[1]) +
00523 CountBitsInByte(correctionCode[2]) +
00524 CountBitsInByte(correctionCode[3]);
00525
00526 if (bitCount == 15) {
00527
00528 uint16_t byte = (correctionCode[0] & 0xf0) >> 4;
00529 byte |= (correctionCode[1] & 0xff) << 4;
00530 uint8_t bit = correctionCode[0] & 0x0f;
00531
00532 printf("Correcting byte #%d at bit %d\n\r", byte, bit);
00533 data[byte] ^= (1 << bit);
00534
00535 return Hsiao_ERROR_SINGLEBIT;
00536 }
00537
00538
00539 if (bitCount == 1)
00540 return Hsiao_ERROR_ECC;
00541
00542 else
00543 return Hsiao_ERROR_MULTIPLEBITS;
00544 }
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 static uint8_t _smc_ecc_VerifyW8BitPer256Ecc(
00558 uint8_t *data,
00559 uint32_t size,
00560 const uint8_t *originalCode,
00561 const uint8_t *verifyCode)
00562 {
00563 uint8_t correctionCode[3];
00564 uint32_t position = 0;
00565 uint8_t byte;
00566 uint8_t bit;
00567 uint8_t error = 0;
00568
00569 TRACE_DEBUG("_smc_ecc_VerifyW8BitPer256Ecc()\n\r");
00570
00571 while (position < size) {
00572
00573 correctionCode[0] = verifyCode[0] ^ originalCode[0];
00574 correctionCode[1] = verifyCode[1] ^ originalCode[1];
00575 correctionCode[2] = verifyCode[2] ^ originalCode[2];
00576 TRACE_DEBUG("Correction code = %02X %02X %02X\n\r",
00577 correctionCode[0], correctionCode[1], correctionCode[2]);
00578
00579
00580 if (correctionCode[0] || correctionCode[1] || correctionCode[2]) {
00581
00582 if (CountBitsInCode(correctionCode) == 11) {
00583
00584 byte = (correctionCode[0] & 0xf8) >> 3;
00585 byte |= (correctionCode[1] & 0x07) << 5;
00586 bit = correctionCode[0] & 0x07;
00587
00588 printf("Correcting byte #%u at bit %u\n\r", (unsigned int)(position + byte),
00589 (unsigned int)bit);
00590 data[byte] ^= (1 << bit);
00591 error = Hsiao_ERROR_SINGLEBIT;
00592 }
00593
00594 else if (CountBitsInCode(correctionCode) == 1)
00595 return Hsiao_ERROR_ECC;
00596 else {
00597
00598 return Hsiao_ERROR_MULTIPLEBITS;
00599 }
00600 }
00601
00602 data += 256;
00603 originalCode += 3;
00604 verifyCode += 3;
00605 position += 256;
00606 }
00607
00608 return error;
00609 }
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622 static uint8_t _smc_ecc_VerifyW9BitPer512Ecc(
00623 uint8_t *data,
00624 uint32_t size,
00625 const uint8_t *originalCode,
00626 const uint8_t *verifyCode)
00627 {
00628 uint8_t correctionCode[3];
00629 uint32_t position = 0;
00630 uint16_t byte;
00631 uint8_t bit;
00632 uint8_t error = 0;
00633
00634 TRACE_DEBUG("_smc_ecc_VerifyW9BitPer512Ecc()\n\r");
00635
00636 while (position < size) {
00637
00638 correctionCode[0] = verifyCode[0] ^ originalCode[0];
00639 correctionCode[1] = verifyCode[1] ^ originalCode[1];
00640 correctionCode[2] = verifyCode[2] ^ originalCode[2];
00641 TRACE_DEBUG("Correction code = %02X %02X %02X\n\r",
00642 correctionCode[0], correctionCode[1], correctionCode[2]);
00643
00644
00645 if (correctionCode[0] || correctionCode[1] || correctionCode[2]) {
00646
00647 if (CountBitsInCode(correctionCode) == 12) {
00648
00649 byte = (correctionCode[0] & 0xf8) >> 3;
00650 byte |= (correctionCode[1] & 0x0f) << 5;
00651 bit = correctionCode[0] & 0x07;
00652
00653 printf("Correcting byte #%u at bit %u\n\r",
00654 (unsigned int)(position + byte), (unsigned int)bit);
00655 data[byte] ^= (1 << bit);
00656 error = Hsiao_ERROR_SINGLEBIT;
00657 }
00658
00659 else if (CountBitsInCode(correctionCode) == 1)
00660 return Hsiao_ERROR_ECC;
00661 else {
00662
00663 return Hsiao_ERROR_MULTIPLEBITS;
00664 }
00665 }
00666
00667 data += 512;
00668 originalCode += 3;
00669 verifyCode += 3;
00670 position += 512;
00671 }
00672
00673 return error;
00674 }
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685 void SMC_ECC_GetEccParity(uint32_t pageDataSize, uint8_t *code,
00686 uint8_t busWidth)
00687 {
00688 uint8_t correctionType;
00689
00690 correctionType = SMC_ECC_GetCorrectoinType();
00691
00692
00693 if (busWidth == 16 && correctionType == SMC_ECC_MD_TYPCORREC_CPAGE)
00694 _smc_ecc_GetW12BitPerPageEcc(pageDataSize, code);
00695
00696 else {
00697 switch (correctionType) {
00698 case SMC_ECC_MD_TYPCORREC_CPAGE:
00699 _smc_ecc_GetW12BitPerPageEcc(pageDataSize, code);
00700 break;
00701
00702 case SMC_ECC_MD_TYPCORREC_C256B:
00703 _smc_ecc_GetW8BitPer256Ecc(pageDataSize, code);
00704 break;
00705
00706 case SMC_ECC_MD_TYPCORREC_C512B:
00707 _smc_ecc_GetW9BitPer512Ecc(pageDataSize, code);
00708 break;
00709 }
00710 }
00711 }
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727 uint8_t SMC_ECC_VerifyHsiao(
00728 uint8_t *data,
00729 uint32_t size,
00730 const uint8_t *originalCode,
00731 const uint8_t *verifyCode,
00732 uint8_t busWidth)
00733 {
00734 uint8_t correctionType;
00735 uint8_t error = 0;
00736 correctionType = SMC_ECC_GetCorrectoinType();
00737
00738
00739 if (busWidth == 16 && (correctionType == SMC_ECC_MD_TYPCORREC_CPAGE))
00740 error = _smc_ecc_VerifyW12BitPerPageEcc((uint8_t *)data, originalCode,
00741 verifyCode);
00742
00743 else {
00744 switch (correctionType) {
00745 case SMC_ECC_MD_TYPCORREC_CPAGE:
00746 error = _smc_ecc_VerifyW12BitPerPageEcc(data, originalCode, verifyCode);
00747 break;
00748
00749 case SMC_ECC_MD_TYPCORREC_C256B:
00750 error = _smc_ecc_VerifyW8BitPer256Ecc(data, size, originalCode, verifyCode);
00751 break;
00752
00753 case SMC_ECC_MD_TYPCORREC_C512B:
00754 error = _smc_ecc_VerifyW9BitPer512Ecc(data, size, originalCode, verifyCode);
00755 break;
00756 }
00757 }
00758
00759 return error;
00760 }