00001
00061 #include "nand.h"
00062 #include <cfg/log.h>
00063 #include <struct/heap.h>
00064 #include <string.h>
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 struct RemapInfo
00076 {
00077 uint32_t tag;
00078 uint16_t mapped_blk;
00079 };
00080
00081
00082 #define NAND_REMAP_TAG_OFFSET (CONFIG_NAND_SPARE_SIZE - sizeof(struct RemapInfo))
00083
00084
00085 #define NAND_REMAP_TAG 0x3e10c8ed
00086
00087
00088
00089
00090
00091
00092
00093 #define NAND_ECC_NWORDS (CONFIG_NAND_DATA_SIZE / 256)
00094
00095
00096 #define NAND_PAGE_SIZE (CONFIG_NAND_DATA_SIZE + CONFIG_NAND_SPARE_SIZE)
00097
00098
00099 #define NAND_BLOCK_SIZE (CONFIG_NAND_DATA_SIZE * CONFIG_NAND_PAGES_PER_BLOCK)
00100
00101
00102 #define NAND_NUM_USER_BLOCKS (CONFIG_NAND_NUM_BLOCK - CONFIG_NAND_NUM_REMAP_BLOCKS)
00103
00104
00105 #define NAND_STATUS_READY BV(6)
00106 #define NAND_STATUS_ERROR BV(0)
00107
00108
00109
00110 #define PAGE(blk) ((blk) * CONFIG_NAND_PAGES_PER_BLOCK)
00111
00112
00113 #define BLOCK(page) ((uint16_t)((page) / CONFIG_NAND_PAGES_PER_BLOCK))
00114 #define PAGE_IN_BLOCK(page) ((uint16_t)((page) % CONFIG_NAND_PAGES_PER_BLOCK))
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 static void getAddrCycles(uint32_t page, uint16_t offset, uint32_t *cycle0, uint32_t *cycle1234)
00133 {
00134 ASSERT(offset < NAND_PAGE_SIZE);
00135
00136 *cycle0 = offset & 0xff;
00137 *cycle1234 = (page << 8) | ((offset >> 8) & 0xf);
00138 }
00139
00140
00141 static void chipReset(Nand *chip)
00142 {
00143 nand_sendCommand(chip, NAND_CMD_RESET, 0, 0, 0, 0);
00144 nand_waitReadyBusy(chip, CONFIG_NAND_TMOUT);
00145 }
00146
00147
00148 static bool isOperationComplete(Nand *chip)
00149 {
00150 uint8_t status;
00151
00152 nand_sendCommand(chip, NAND_CMD_STATUS, 0, 0, 0, 0);
00153
00154 status = nand_getChipStatus(chip);
00155 return (status & NAND_STATUS_READY) && !(status & NAND_STATUS_ERROR);
00156 }
00157
00158
00162 int nand_blockErase(Nand *chip, uint16_t block)
00163 {
00164 uint32_t cycle0;
00165 uint32_t cycle1234;
00166
00167 uint16_t remapped_block = chip->block_map[block];
00168 if (block != remapped_block)
00169 {
00170 LOG_INFO("nand_blockErase: remapped block: blk %d->%d\n", block, remapped_block);
00171 block = remapped_block;
00172 }
00173
00174 getAddrCycles(PAGE(block), 0, &cycle0, &cycle1234);
00175
00176 nand_sendCommand(chip, NAND_CMD_ERASE_1, NAND_CMD_ERASE_2, 3, 0, cycle1234 >> 8);
00177
00178 nand_waitReadyBusy(chip, CONFIG_NAND_TMOUT);
00179
00180 if (!isOperationComplete(chip))
00181 {
00182 LOG_ERR("nand: error erasing block\n");
00183 chip->status |= NAND_ERR_ERASE;
00184 return -1;
00185 }
00186
00187 return 0;
00188 }
00189
00190
00194 bool nand_getDevId(Nand *chip, uint8_t dev_id[5])
00195 {
00196 nand_sendCommand(chip, NAND_CMD_READID, 0, 1, 0, 0);
00197
00198 nand_waitReadyBusy(chip, CONFIG_NAND_TMOUT);
00199 if (!nand_waitTransferComplete(chip, CONFIG_NAND_TMOUT))
00200 {
00201 LOG_ERR("nand: getDevId timeout\n");
00202 chip->status |= NAND_ERR_RD_TMOUT;
00203 return false;
00204 }
00205
00206 memcpy(dev_id, nand_dataBuffer(chip), sizeof(dev_id));
00207 return true;
00208 }
00209
00210
00211 static bool nand_readPage(Nand *chip, uint32_t page, uint16_t offset)
00212 {
00213 uint32_t cycle0;
00214 uint32_t cycle1234;
00215
00216
00217
00218 getAddrCycles(page, offset, &cycle0, &cycle1234);
00219
00220 nand_sendCommand(chip, NAND_CMD_READ_1, NAND_CMD_READ_2, 5, cycle0, cycle1234);
00221
00222 nand_waitReadyBusy(chip, CONFIG_NAND_TMOUT);
00223 if (!nand_waitTransferComplete(chip, CONFIG_NAND_TMOUT))
00224 {
00225 LOG_ERR("nand: read timeout\n");
00226 chip->status |= NAND_ERR_RD_TMOUT;
00227 return false;
00228 }
00229
00230 return true;
00231 }
00232
00233
00234
00235
00236
00237
00238 static bool nand_read(Nand *chip, uint32_t page, void *buf, uint16_t offset, uint16_t size)
00239 {
00240 struct RemapInfo remap_info;
00241 uint32_t remapped_page = PAGE(chip->block_map[BLOCK(page)]) + PAGE_IN_BLOCK(page);
00242
00243
00244
00245 if (page != remapped_page)
00246 {
00247 LOG_INFO("nand_read: remapped block: blk %d->%d, pg %ld->%ld\n",
00248 BLOCK(page), chip->block_map[BLOCK(page)], page, remapped_page);
00249 page = remapped_page;
00250 }
00251
00252 if (!nand_readPage(chip, page, 0))
00253 return false;
00254
00255 memcpy(buf, (char *)nand_dataBuffer(chip) + offset, size);
00256
00257
00258
00259
00260
00261 memcpy(&remap_info, (char *)buf + NAND_REMAP_TAG_OFFSET, sizeof(remap_info));
00262 if (remap_info.tag == NAND_REMAP_TAG && !nand_checkEcc(chip))
00263 {
00264 chip->status |= NAND_ERR_ECC;
00265 return false;
00266 }
00267 else
00268 return true;
00269 }
00270
00271
00272
00273
00274
00275
00276
00277 static bool nand_writePage(Nand *chip, uint32_t page, uint16_t offset)
00278 {
00279 uint32_t cycle0;
00280 uint32_t cycle1234;
00281
00282
00283
00284 getAddrCycles(page, offset, &cycle0, &cycle1234);
00285
00286 nand_sendCommand(chip, NAND_CMD_WRITE_1, 0, 5, cycle0, cycle1234);
00287
00288 if (!nand_waitTransferComplete(chip, CONFIG_NAND_TMOUT))
00289 {
00290 LOG_ERR("nand: write timeout\n");
00291 chip->status |= NAND_ERR_WR_TMOUT;
00292 return false;
00293 }
00294
00295 nand_sendCommand(chip, NAND_CMD_WRITE_2, 0, 0, 0, 0);
00296
00297 nand_waitReadyBusy(chip, CONFIG_NAND_TMOUT);
00298
00299 if (!isOperationComplete(chip))
00300 {
00301 LOG_ERR("nand: error writing page\n");
00302 chip->status |= NAND_ERR_WRITE;
00303 return false;
00304 }
00305
00306 return true;
00307 }
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 static bool nand_write(Nand *chip, uint32_t page, const void *buf, size_t size)
00324 {
00325 struct RemapInfo remap_info;
00326 uint32_t *nand_buf = (uint32_t *)nand_dataBuffer(chip);
00327 uint32_t remapped_page = PAGE(chip->block_map[BLOCK(page)]) + PAGE_IN_BLOCK(page);
00328
00329 ASSERT(size <= CONFIG_NAND_DATA_SIZE);
00330
00331 if (page != remapped_page)
00332 LOG_INFO("nand_write: remapped block: blk %d->%d, pg %ld->%ld\n",
00333 BLOCK(page), chip->block_map[BLOCK(page)], page, remapped_page);
00334
00335
00336 memset(nand_buf, 0xff, NAND_PAGE_SIZE);
00337 memcpy(nand_buf, buf, size);
00338 if (!nand_writePage(chip, remapped_page, 0))
00339 return false;
00340
00341
00342 memset(nand_buf, 0xff, CONFIG_NAND_SPARE_SIZE);
00343 nand_computeEcc(chip, buf, size, nand_buf, NAND_ECC_NWORDS);
00344
00345
00346 remap_info.tag = NAND_REMAP_TAG;
00347 remap_info.mapped_blk = BLOCK(page);
00348 memcpy((char *)nand_buf + NAND_REMAP_TAG_OFFSET, &remap_info, sizeof(remap_info));
00349
00350 return nand_writePage(chip, remapped_page, CONFIG_NAND_DATA_SIZE);
00351 }
00352
00353
00354
00355
00356
00357
00358
00359 static bool blockIsGood(Nand *chip, uint16_t blk)
00360 {
00361 uint8_t *first_byte = (uint8_t *)nand_dataBuffer(chip);
00362 bool good;
00363
00364
00365 nand_readPage(chip, PAGE(blk), CONFIG_NAND_DATA_SIZE);
00366 good = *first_byte != 0;
00367
00368 if (!good)
00369 LOG_INFO("nand: bad block %d\n", blk);
00370
00371 return good;
00372 }
00373
00374
00375
00376
00377
00378
00379 static int getBadBlockFromRemapBlock(Nand *chip, uint16_t dest_blk)
00380 {
00381 struct RemapInfo *remap_info = (struct RemapInfo *)nand_dataBuffer(chip);
00382
00383 if (!nand_readPage(chip, PAGE(dest_blk), CONFIG_NAND_DATA_SIZE + NAND_REMAP_TAG_OFFSET))
00384 return -1;
00385
00386 if (remap_info->tag == NAND_REMAP_TAG)
00387 return remap_info->mapped_blk;
00388 else
00389 return -1;
00390 }
00391
00392
00393
00394
00395
00396
00397 static bool setMapping(Nand *chip, uint32_t src_blk, uint32_t dest_blk)
00398 {
00399 struct RemapInfo *remap_info = (struct RemapInfo *)nand_dataBuffer(chip);
00400
00401 LOG_INFO("nand, setMapping(): src=%ld dst=%ld\n", src_blk, dest_blk);
00402
00403 if (!nand_readPage(chip, PAGE(dest_blk), CONFIG_NAND_DATA_SIZE + NAND_REMAP_TAG_OFFSET))
00404 return false;
00405
00406 remap_info->tag = NAND_REMAP_TAG;
00407 remap_info->mapped_blk = src_blk;
00408
00409 return nand_writePage(chip, PAGE(dest_blk), CONFIG_NAND_DATA_SIZE + NAND_REMAP_TAG_OFFSET);
00410 }
00411
00412
00413
00414
00415
00416
00417 static uint16_t getFreeRemapBlock(Nand *chip)
00418 {
00419 int blk;
00420
00421 for (blk = chip->remap_start; blk < CONFIG_NAND_NUM_BLOCK; blk++)
00422 {
00423 if (blockIsGood(chip, blk))
00424 {
00425 chip->remap_start = blk + 1;
00426 return blk;
00427 }
00428 }
00429
00430 LOG_ERR("nand: reserved blocks for bad block remapping exhausted!\n");
00431 return 0;
00432 }
00433
00434
00435
00436
00437
00438 static bool chipIsMarked(Nand *chip)
00439 {
00440 return getBadBlockFromRemapBlock(chip, NAND_NUM_USER_BLOCKS) != -1;
00441 }
00442
00443
00444
00445
00446
00447
00448
00449 static void initBlockMap(Nand *chip)
00450 {
00451 int b, last;
00452
00453
00454 for (b = 0; b < CONFIG_NAND_NUM_BLOCK; b++)
00455 chip->block_map[b] = b;
00456 chip->remap_start = NAND_NUM_USER_BLOCKS;
00457
00458 if (chipIsMarked(chip))
00459 {
00460 LOG_INFO("nand: found initialized NAND, searching for remapped blocks\n");
00461
00462
00463 for (b = last = NAND_NUM_USER_BLOCKS; b < CONFIG_NAND_NUM_BLOCK; b++)
00464 {
00465 int remapped_blk = getBadBlockFromRemapBlock(chip, b);
00466 if (remapped_blk != -1 && remapped_blk != b)
00467 {
00468 LOG_INFO("nand: found remapped block %d->%d\n", remapped_blk, b);
00469 chip->block_map[remapped_blk] = b;
00470 last = b + 1;
00471 }
00472 }
00473 chip->remap_start = last;
00474 }
00475 else
00476 {
00477 bool remapped_anything = false;
00478
00479 LOG_INFO("nand: found new NAND, searching for bad blocks\n");
00480
00481 for (b = 0; b < NAND_NUM_USER_BLOCKS; b++)
00482 {
00483 if (!blockIsGood(chip, b))
00484 {
00485 chip->block_map[b] = getFreeRemapBlock(chip);
00486 setMapping(chip, b, chip->block_map[b]);
00487 remapped_anything = true;
00488 LOG_WARN("nand: found new bad block %d, remapped to %d\n", b, chip->block_map[b]);
00489 }
00490 }
00491
00492
00493
00494
00495
00496 if (!remapped_anything)
00497 {
00498 setMapping(chip, NAND_NUM_USER_BLOCKS, NAND_NUM_USER_BLOCKS);
00499 LOG_INFO("nand: no bad block founds, marked NAND\n");
00500 }
00501 }
00502 }
00503
00504
00511 void nand_format(Nand *chip)
00512 {
00513 int b;
00514
00515 for (b = 0; b < CONFIG_NAND_NUM_BLOCK; b++)
00516 {
00517 LOG_INFO("nand: erasing block %d\n", b);
00518 chip->block_map[b] = b;
00519 nand_blockErase(chip, b);
00520 }
00521 chip->remap_start = NAND_NUM_USER_BLOCKS;
00522 }
00523
00524 #ifdef _DEBUG
00525
00526
00527
00528
00529 void nand_ruinSomeBlocks(Nand *chip)
00530 {
00531 int bads[] = { 7, 99, 555, 1003, 1004, 1432 };
00532 unsigned i;
00533
00534 LOG_INFO("nand: erasing mark\n");
00535 nand_blockErase(chip, NAND_NUM_USER_BLOCKS);
00536
00537 for (i = 0; i < countof(bads); i++)
00538 {
00539 LOG_INFO("nand: erasing block %d\n", bads[i]);
00540 nand_blockErase(chip, bads[i]);
00541
00542 LOG_INFO("nand: marking page %d as bad\n", PAGE(bads[i]));
00543 memset(nand_dataBuffer(chip), 0, CONFIG_NAND_SPARE_SIZE);
00544 nand_writePage(chip, PAGE(bads[i]), CONFIG_NAND_DATA_SIZE);
00545 }
00546 }
00547
00548 #endif
00549
00550 static bool commonInit(Nand *chip, struct Heap *heap, unsigned chip_select)
00551 {
00552 memset(chip, 0, sizeof(Nand));
00553
00554 DB(chip->fd.priv.type = KBT_NAND);
00555 chip->fd.blk_size = NAND_BLOCK_SIZE;
00556 chip->fd.blk_cnt = NAND_NUM_USER_BLOCKS;
00557
00558 chip->chip_select = chip_select;
00559 chip->block_map = heap_allocmem(heap, CONFIG_NAND_NUM_BLOCK * sizeof(*chip->block_map));
00560 if (!chip->block_map)
00561 {
00562 LOG_ERR("nand: error allocating block map\n");
00563 return false;
00564 }
00565
00566 nand_hwInit(chip);
00567 chipReset(chip);
00568 initBlockMap(chip);
00569
00570 return true;
00571 }
00572
00573
00574
00575
00576
00577 static size_t nand_writeDirect(struct KBlock *kblk, block_idx_t idx, const void *buf, size_t offset, size_t size)
00578 {
00579 ASSERT(offset <= NAND_BLOCK_SIZE);
00580 ASSERT(offset % CONFIG_NAND_DATA_SIZE == 0);
00581 ASSERT(size <= NAND_BLOCK_SIZE);
00582 ASSERT(size % CONFIG_NAND_DATA_SIZE == 0);
00583
00584 LOG_INFO("nand_writeDirect: idx=%ld offset=%d size=%d\n", idx, offset, size);
00585
00586 nand_blockErase(NAND_CAST(kblk), idx);
00587
00588 while (offset < size)
00589 {
00590 uint32_t page = PAGE(idx) + (offset / CONFIG_NAND_DATA_SIZE);
00591
00592 if (!nand_write(NAND_CAST(kblk), page, buf, CONFIG_NAND_DATA_SIZE))
00593 break;
00594
00595 offset += CONFIG_NAND_DATA_SIZE;
00596 buf = (const char *)buf + CONFIG_NAND_DATA_SIZE;
00597 }
00598
00599 return offset;
00600 }
00601
00602
00603 static size_t nand_readDirect(struct KBlock *kblk, block_idx_t idx, void *buf, size_t offset, size_t size)
00604 {
00605 uint32_t page;
00606 size_t read_size;
00607 size_t read_offset;
00608 size_t nread = 0;
00609
00610 ASSERT(offset < NAND_BLOCK_SIZE);
00611 ASSERT(size <= NAND_BLOCK_SIZE);
00612
00613 LOG_INFO("nand_readDirect: idx=%ld offset=%d size=%d\n", idx, offset, size);
00614
00615 while (nread < size)
00616 {
00617 page = PAGE(idx) + (offset / CONFIG_NAND_DATA_SIZE);
00618 read_offset = offset % CONFIG_NAND_DATA_SIZE;
00619 read_size = MIN(size, CONFIG_NAND_DATA_SIZE - read_offset);
00620
00621 if (!nand_read(NAND_CAST(kblk), page, (char *)buf + nread, read_offset, read_size))
00622 break;
00623
00624 offset += read_size;
00625 nread += read_size;
00626 }
00627
00628 return nread;
00629 }
00630
00631
00632 static int nand_error(struct KBlock *kblk)
00633 {
00634 Nand *chip = NAND_CAST(kblk);
00635 return chip->status;
00636 }
00637
00638
00639 static void nand_clearError(struct KBlock *kblk)
00640 {
00641 Nand *chip = NAND_CAST(kblk);
00642 chip->status = 0;
00643 }
00644
00645
00646 static const KBlockVTable nand_buffered_vt =
00647 {
00648 .readDirect = nand_readDirect,
00649 .writeDirect = nand_writeDirect,
00650
00651 .readBuf = kblock_swReadBuf,
00652 .writeBuf = kblock_swWriteBuf,
00653 .load = kblock_swLoad,
00654 .store = kblock_swStore,
00655
00656 .error = nand_error,
00657 .clearerr = nand_clearError,
00658 };
00659
00660 static const KBlockVTable nand_unbuffered_vt =
00661 {
00662 .readDirect = nand_readDirect,
00663 .writeDirect = nand_writeDirect,
00664
00665 .error = nand_error,
00666 .clearerr = nand_clearError,
00667 };
00668
00669
00673 bool nand_init(Nand *chip, struct Heap *heap, unsigned chip_select)
00674 {
00675 if (!commonInit(chip, heap, chip_select))
00676 return false;
00677
00678 chip->fd.priv.vt = &nand_buffered_vt;
00679 chip->fd.priv.flags |= KB_BUFFERED;
00680
00681 chip->fd.priv.buf = heap_allocmem(heap, NAND_BLOCK_SIZE);
00682 if (!chip->fd.priv.buf)
00683 {
00684 LOG_ERR("nand: error allocating block buffer\n");
00685 return false;
00686 }
00687
00688
00689 return nand_readDirect(&chip->fd, 0, chip->fd.priv.buf, 0, chip->fd.blk_size);
00690 }
00691
00692
00696 bool nand_initUnbuffered(Nand *chip, struct Heap *heap, unsigned chip_select)
00697 {
00698 if (!commonInit(chip, heap, chip_select))
00699 return false;
00700
00701 chip->fd.priv.vt = &nand_unbuffered_vt;
00702 return true;
00703 }
00704