nand.c

Go to the documentation of this file.
00001 
00061 #include "nand.h"
00062 #include <cfg/log.h>
00063 #include <struct/heap.h>
00064 #include <string.h> // memset
00065 
00066 
00067 /*
00068  * Remap info written in the first page of each block.
00069  *
00070  * This structure is used in blocks of the reserved area to store
00071  * which block the block containing the structure is remapping.
00072  * It's stored in all other blocks too to mark a formatted block.
00073  * In this case the member mapped_blk has non meaning.
00074  */
00075 struct RemapInfo
00076 {
00077     uint32_t tag;         // Magic number to detect valid info
00078     uint16_t mapped_blk;  // Bad block the block containing this info is remapping
00079 };
00080 
00081 // Where RemapInfo is stored in the spare area
00082 #define NAND_REMAP_TAG_OFFSET  (CONFIG_NAND_SPARE_SIZE - sizeof(struct RemapInfo))
00083 
00084 // Fixed tag to detect RemapInfo
00085 #define NAND_REMAP_TAG         0x3e10c8ed
00086 
00087 /*
00088  * Number of ECC words computed for a page.
00089  *
00090  * For 2048 bytes pages and 1 ECC word each 256 bytes,
00091  * 24 bytes of ECC data are stored.
00092  */
00093 #define NAND_ECC_NWORDS        (CONFIG_NAND_DATA_SIZE / 256)
00094 
00095 // Total page size (user data + spare) in bytes
00096 #define NAND_PAGE_SIZE         (CONFIG_NAND_DATA_SIZE + CONFIG_NAND_SPARE_SIZE)
00097 
00098 // Erase block size in bytes
00099 #define NAND_BLOCK_SIZE        (CONFIG_NAND_DATA_SIZE * CONFIG_NAND_PAGES_PER_BLOCK)
00100 
00101 // Number of usable blocks, and index of first remapping block
00102 #define NAND_NUM_USER_BLOCKS   (CONFIG_NAND_NUM_BLOCK - CONFIG_NAND_NUM_REMAP_BLOCKS)
00103 
00104 // ONFI NAND status codes
00105 #define NAND_STATUS_READY  BV(6)
00106 #define NAND_STATUS_ERROR  BV(0)
00107 
00108 
00109 // Get block from page
00110 #define PAGE(blk)            ((blk) * CONFIG_NAND_PAGES_PER_BLOCK)
00111 
00112 // Page from block and page in block
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  * Translate page index plus a byte offset
00119  * in the five address cycles format needed by NAND.
00120  *
00121  * Cycles in x8 mode.
00122  * CA = column addr, PA = page addr, BA = block addr
00123  *
00124  * Cycle    I/O7  I/O6  I/O5  I/O4  I/O3  I/O2  I/O1  I/O0
00125  * -------------------------------------------------------
00126  * First    CA7   CA6   CA5   CA4   CA3   CA2   CA1   CA0
00127  * Second   LOW   LOW   LOW   LOW   CA11  CA10  CA9   CA8
00128  * Third    BA7   BA6   PA5   PA4   PA3   PA2   PA1   PA0
00129  * Fourth   BA15  BA14  BA13  BA12  BA11  BA10  BA9   BA8
00130  * Fifth    LOW   LOW   LOW   LOW   LOW   LOW   LOW   BA16
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     //LOG_INFO("nand_readPage: page 0x%lx off 0x%x\n", page, offset);
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  * Read page data and ECC, checking for errors.
00236  * TODO: fix errors with ECC when possible.
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     //LOG_INFO("nand_read: page=%ld, offset=%d, size=%d\n", page, offset, size);
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      * Check for ECC hardware status only if a valid RemapInfo structure is found.
00259      * That guarantees the page is written by us and a valid ECC is present.
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  * Write data stored in nand_dataBuffer() to a NAND page, starting at a given offset.
00274  * Usually offset will be 0 to write data or CONFIG_NAND_DATA_SIZE to write the spare
00275  * area.
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     //LOG_INFO("nand_writePage: page 0x%lx off 0x%x\n", page, offset);
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  * Write data, ECC and remap block info.
00312  *
00313  * \param page           the page to be written
00314  * \parma original_page  if different from page, it's the page that's being remapped
00315  *
00316  * Implementation note for SAM3 NFC controller:
00317  * according to datasheet to get ECC computed by hardware is sufficient
00318  * to write the main area.  But it seems that in that way the last ECC_PR
00319  * register is not generated.  The workaround is to write data and dummy (ff)
00320  * spare data in one write, at this point the last ECC_PR is correct and
00321  * ECC data can be written in the spare area with a second program operation.
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     // Data
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     // ECC
00342     memset(nand_buf, 0xff, CONFIG_NAND_SPARE_SIZE);
00343     nand_computeEcc(chip, buf, size, nand_buf, NAND_ECC_NWORDS);
00344 
00345     // Remap info
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  * Check if the given block is marked bad: ONFI standard mandates
00356  * that bad block are marked with "00" bytes on the spare area of the
00357  * first page in block.
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     // Check first byte in spare area of first page in block
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  * Return the main partition block remapped on given block in the remap
00377  * partition (dest_blk).
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  * Set a block remapping: src_blk (a block in main data partition) is remapped
00395  * on dest_blk (block in reserved remapped blocks partition).
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  * Get a new block from the remap partition to use as a substitute
00415  * for a bad block.
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  * Check if NAND is initialized.
00437  */
00438 static bool chipIsMarked(Nand *chip)
00439 {
00440     return getBadBlockFromRemapBlock(chip, NAND_NUM_USER_BLOCKS) != -1;
00441 }
00442 
00443 
00444 /*
00445  * Initialize NAND (format). Scan NAND for factory marked bad blocks.
00446  * All found bad blocks are remapped to the remap partition: each
00447  * block in the remap partition used to remap bad blocks is marked.
00448  */
00449 static void initBlockMap(Nand *chip)
00450 {
00451     int b, last;
00452 
00453     // Default is for each block to not be remapped
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         // Scan for assigned blocks in remap area
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          * If no bad blocks are found (we're lucky!) write anyway a dummy
00494          * remap to mark NAND and detect we already scanned it next time.
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  * Create some bad blocks, erasing them and writing the bad block mark.
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 /**************** Kblock interface ****************/
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     // Load the first block in the cache
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