BeRTOS
|
00001 00038 #include "mt29f_sam3.h" 00039 #include "cfg/cfg_mt29f.h" 00040 00041 // Define log settings for cfg/log.h 00042 #define LOG_LEVEL CONFIG_MT29F_LOG_LEVEL 00043 #define LOG_FORMAT CONFIG_MT29F_LOG_FORMAT 00044 00045 #include <cfg/log.h> 00046 #include <cfg/macros.h> 00047 00048 #include <io/sam3.h> 00049 00050 #include <drv/timer.h> 00051 #include <drv/mt29f.h> 00052 00053 #include <cpu/power.h> /* cpu_relax() */ 00054 #include <cpu/types.h> 00055 00056 #include <string.h> /* memcpy() */ 00057 00058 // Timeout for NAND operations in ms 00059 #define MT29F_TMOUT 100 00060 00061 // NAND flash status codes 00062 #define MT29F_STATUS_READY BV(6) 00063 #define MT29F_STATUS_ERROR BV(0) 00064 00065 // NAND flash commands 00066 #define MT29F_CMD_READ_1 0x00 00067 #define MT29F_CMD_READ_2 0x30 00068 #define MT29F_CMD_COPYBACK_READ_1 0x00 00069 #define MT29F_CMD_COPYBACK_READ_2 0x35 00070 #define MT29F_CMD_COPYBACK_PROGRAM_1 0x85 00071 #define MT29F_CMD_COPYBACK_PROGRAM_2 0x10 00072 #define MT29F_CMD_RANDOM_OUT 0x05 00073 #define MT29F_CMD_RANDOM_OUT_2 0xE0 00074 #define MT29F_CMD_RANDOM_IN 0x85 00075 #define MT29F_CMD_READID 0x90 00076 #define MT29F_CMD_WRITE_1 0x80 00077 #define MT29F_CMD_WRITE_2 0x10 00078 #define MT29F_CMD_ERASE_1 0x60 00079 #define MT29F_CMD_ERASE_2 0xD0 00080 #define MT29F_CMD_STATUS 0x70 00081 #define MT29F_CMD_RESET 0xFF 00082 00083 // Addresses for sending command, addresses and data bytes to flash 00084 #define MT29F_CMD_ADDR 0x60400000 00085 #define MT29F_ADDR_ADDR 0x60200000 00086 #define MT29F_DATA_ADDR 0x60000000 00087 00088 // Get chip select mask for command register 00089 #define MT29F_CSID(chip) (((chip)->chip_select << NFC_CMD_CSID_SHIFT) & NFC_CMD_CSID_MASK) 00090 00091 00092 /* 00093 * Translate flash page index plus a byte offset 00094 * in the five address cycles format needed by NAND. 00095 * 00096 * Cycles in x8 mode as the MT29F2G08AAD 00097 * CA = column addr, PA = page addr, BA = block addr 00098 * 00099 * Cycle I/O7 I/O6 I/O5 I/O4 I/O3 I/O2 I/O1 I/O0 00100 * ------------------------------------------------------- 00101 * First CA7 CA6 CA5 CA4 CA3 CA2 CA1 CA0 00102 * Second LOW LOW LOW LOW CA11 CA10 CA9 CA8 00103 * Third BA7 BA6 PA5 PA4 PA3 PA2 PA1 PA0 00104 * Fourth BA15 BA14 BA13 BA12 BA11 BA10 BA9 BA8 00105 * Fifth LOW LOW LOW LOW LOW LOW LOW BA16 00106 */ 00107 static void getAddrCycles(uint32_t page, uint16_t offset, uint32_t *cycle0, uint32_t *cycle1234) 00108 { 00109 ASSERT(offset < MT29F_PAGE_SIZE); 00110 00111 *cycle0 = offset & 0xff; 00112 *cycle1234 = (page << 8) | ((offset >> 8) & 0xf); 00113 00114 LOG_INFO("mt29f addr: %lx %lx\n", *cycle1234, *cycle0); 00115 } 00116 00117 00118 INLINE bool nfcIsBusy(void) 00119 { 00120 return HWREG(NFC_CMD_BASE_ADDR + NFC_CMD_NFCCMD) & 0x8000000; 00121 } 00122 00123 INLINE bool isCmdDone(void) 00124 { 00125 return SMC_SR & SMC_SR_CMDDONE; 00126 } 00127 00128 static bool waitReadyBusy(void) 00129 { 00130 time_t start = timer_clock(); 00131 00132 while (!(SMC_SR & SMC_SR_RB_EDGE0)) 00133 { 00134 cpu_relax(); 00135 if (timer_clock() - start > MT29F_TMOUT) 00136 { 00137 LOG_INFO("mt29f: R/B timeout\n"); 00138 return false; 00139 } 00140 } 00141 00142 return true; 00143 } 00144 00145 /* 00146 * Wait for transfer to complete until timeout. 00147 * If transfer completes return true, false in case of timeout. 00148 */ 00149 static bool waitTransferComplete(void) 00150 { 00151 time_t start = timer_clock(); 00152 00153 while (!(SMC_SR & SMC_SR_XFRDONE)) 00154 { 00155 cpu_relax(); 00156 if (timer_clock() - start > MT29F_TMOUT) 00157 { 00158 LOG_INFO("mt29f: xfer complete timeout\n"); 00159 return false; 00160 } 00161 } 00162 00163 return true; 00164 } 00165 00166 00167 /* 00168 * Send command to NAND and wait for completion. 00169 */ 00170 static void sendCommand(uint32_t cmd, 00171 int num_cycles, uint32_t cycle0, uint32_t cycle1234) 00172 { 00173 reg32_t *cmd_addr; 00174 00175 while (nfcIsBusy()); 00176 00177 if (num_cycles == 5) 00178 SMC_ADDR = cycle0; 00179 00180 cmd_addr = (reg32_t *)(NFC_CMD_BASE_ADDR + cmd); 00181 *cmd_addr = cycle1234; 00182 00183 while (!isCmdDone()); 00184 } 00185 00186 00187 static bool isOperationComplete(Mt29f *chip) 00188 { 00189 uint8_t status; 00190 00191 sendCommand(MT29F_CSID(chip) | 00192 NFC_CMD_NFCCMD | NFC_CMD_ACYCLE_NONE | 00193 MT29F_CMD_STATUS << 2, 00194 0, 0, 0); 00195 00196 status = (uint8_t)HWREG(MT29F_DATA_ADDR); 00197 return (status & MT29F_STATUS_READY) && !(status & MT29F_STATUS_ERROR); 00198 } 00199 00200 00201 static void chipReset(Mt29f *chip) 00202 { 00203 sendCommand(MT29F_CSID(chip) | 00204 NFC_CMD_NFCCMD | NFC_CMD_ACYCLE_NONE | 00205 MT29F_CMD_RESET << 2, 00206 0, 0, 0); 00207 00208 waitReadyBusy(); 00209 } 00210 00211 00215 int mt29f_blockErase(Mt29f *chip, uint32_t page) 00216 { 00217 uint32_t cycle0; 00218 uint32_t cycle1234; 00219 00220 getAddrCycles(page, 0, &cycle0, &cycle1234); 00221 00222 sendCommand(MT29F_CSID(chip) | 00223 NFC_CMD_NFCCMD | NFC_CMD_ACYCLE_THREE | NFC_CMD_VCMD2 | 00224 (MT29F_CMD_ERASE_2 << 10) | (MT29F_CMD_ERASE_1 << 2), 00225 3, 0, cycle1234 >> 8); 00226 00227 waitReadyBusy(); 00228 00229 if (!isOperationComplete(chip)) 00230 { 00231 LOG_ERR("mt29f: error erasing block\n"); 00232 chip->status |= MT29F_ERR_ERASE; 00233 return -1; 00234 } 00235 00236 return 0; 00237 } 00238 00239 00243 bool mt29f_getDevId(Mt29f *chip, uint8_t dev_id[5]) 00244 { 00245 sendCommand(MT29F_CSID(chip) | 00246 NFC_CMD_NFCCMD | NFC_CMD_NFCEN | NFC_CMD_ACYCLE_ONE | 00247 MT29F_CMD_READID << 2, 00248 1, 0, 0); 00249 00250 waitReadyBusy(); 00251 if (!waitTransferComplete()) 00252 { 00253 LOG_ERR("mt29f: getDevId timeout\n"); 00254 chip->status |= MT29F_ERR_RD_TMOUT; 00255 return false; 00256 } 00257 00258 memcpy(dev_id, (void *)NFC_SRAM_BASE_ADDR, 5); 00259 return true; 00260 } 00261 00262 00263 static bool checkEcc(void) 00264 { 00265 uint32_t sr1 = SMC_ECC_SR1; 00266 00267 if (sr1) 00268 { 00269 LOG_INFO("ECC error, ECC_SR1=0x%lx\n", sr1); 00270 return false; 00271 } 00272 else 00273 return true; 00274 } 00275 00276 00277 static bool mt29f_readPage(Mt29f *chip, uint32_t page, uint16_t offset) 00278 { 00279 uint32_t cycle0; 00280 uint32_t cycle1234; 00281 00282 LOG_INFO("mt29f_readPage: page 0x%lx off 0x%x\n", page, offset); 00283 00284 getAddrCycles(page, offset, &cycle0, &cycle1234); 00285 00286 sendCommand(MT29F_CSID(chip) | 00287 NFC_CMD_NFCCMD | NFC_CMD_NFCEN | NFC_CMD_ACYCLE_FIVE | NFC_CMD_VCMD2 | 00288 (MT29F_CMD_READ_2 << 10) | (MT29F_CMD_READ_1 << 2), 00289 5, cycle0, cycle1234); 00290 00291 waitReadyBusy(); 00292 if (!waitTransferComplete()) 00293 { 00294 LOG_ERR("mt29f: read timeout\n"); 00295 chip->status |= MT29F_ERR_RD_TMOUT; 00296 return false; 00297 } 00298 00299 return true; 00300 } 00301 00302 00303 /* 00304 * Read page data and ECC, checking for errors. 00305 * TODO: fix errors with ECC when possible. 00306 */ 00307 bool mt29f_read(Mt29f *chip, uint32_t page, void *buf, uint16_t size) 00308 { 00309 ASSERT(size <= MT29F_DATA_SIZE); 00310 00311 if (!mt29f_readPage(chip, page, 0)) 00312 return false; 00313 00314 memcpy(buf, (void *)NFC_SRAM_BASE_ADDR, size); 00315 00316 return checkEcc(); 00317 } 00318 00319 00320 /* 00321 * Write data in NFC SRAM buffer to a NAND page, starting at a given offset. 00322 * Usually offset will be 0 to write data or MT29F_DATA_SIZE to write the spare 00323 * area. 00324 * 00325 * According to datasheet to get ECC computed by hardware is sufficient 00326 * to write the main area. But it seems that in that way the last ECC_PR 00327 * register is not generated. The workaround is to write data and dummy (ff) 00328 * spare data in one write, at this point the last ECC_PR is correct and 00329 * ECC data can be written in the spare area with a second program operation. 00330 */ 00331 static bool mt29f_writePage(Mt29f *chip, uint32_t page, uint16_t offset) 00332 { 00333 uint32_t cycle0; 00334 uint32_t cycle1234; 00335 00336 LOG_INFO("mt29f_writePage: page 0x%lx off 0x%x\n", page, offset); 00337 00338 getAddrCycles(page, offset, &cycle0, &cycle1234); 00339 00340 sendCommand(MT29F_CSID(chip) | 00341 NFC_CMD_NFCCMD | NFC_CMD_NFCWR | NFC_CMD_NFCEN | NFC_CMD_ACYCLE_FIVE | 00342 MT29F_CMD_WRITE_1 << 2, 00343 5, cycle0, cycle1234); 00344 00345 if (!waitTransferComplete()) 00346 { 00347 LOG_ERR("mt29f: write timeout\n"); 00348 chip->status |= MT29F_ERR_WR_TMOUT; 00349 return false; 00350 } 00351 00352 sendCommand(MT29F_CSID(chip) | 00353 NFC_CMD_NFCCMD | NFC_CMD_ACYCLE_NONE | 00354 MT29F_CMD_WRITE_2 << 2, 00355 0, 0, 0); 00356 00357 waitReadyBusy(); 00358 00359 if (!isOperationComplete(chip)) 00360 { 00361 LOG_ERR("mt29f: error writing page\n"); 00362 chip->status |= MT29F_ERR_WRITE; 00363 return false; 00364 } 00365 00366 return true; 00367 } 00368 00369 00370 /* 00371 * Write data in a page. 00372 */ 00373 static bool mt29f_writePageData(Mt29f *chip, uint32_t page, const void *buf, uint16_t size) 00374 { 00375 ASSERT(size <= MT29F_DATA_SIZE); 00376 00377 memset((void *)NFC_SRAM_BASE_ADDR, 0xff, MT29F_PAGE_SIZE); 00378 memcpy((void *)NFC_SRAM_BASE_ADDR, buf, size); 00379 00380 return mt29f_writePage(chip, page, 0); 00381 } 00382 00383 00384 /* 00385 * Write the ECC for a page. 00386 * 00387 * ECC data are extracted from ECC_PRx registers and written 00388 * in the page's spare area. 00389 * For 2048 bytes pages and 1 ECC word each 256 bytes, 00390 * 24 bytes of ECC data are stored. 00391 */ 00392 static bool mt29f_writePageEcc(Mt29f *chip, uint32_t page) 00393 { 00394 int i; 00395 uint32_t *buf = (uint32_t *)NFC_SRAM_BASE_ADDR; 00396 00397 memset((void *)NFC_SRAM_BASE_ADDR, 0xff, MT29F_SPARE_SIZE); 00398 00399 for (i = 0; i < MT29F_ECC_NWORDS; i++) 00400 buf[i] = *((reg32_t *)(SMC_BASE + SMC_ECC_PR0_OFF) + i); 00401 00402 return mt29f_writePage(chip, page, MT29F_DATA_SIZE); 00403 } 00404 00405 00406 bool mt29f_write(Mt29f *chip, uint32_t page, const void *buf, uint16_t size) 00407 { 00408 return 00409 mt29f_writePageData(chip, page, buf, size) && 00410 mt29f_writePageEcc(chip, page); 00411 } 00412 00413 00414 int mt29f_error(Mt29f *chip) 00415 { 00416 return chip->status; 00417 } 00418 00419 00420 void mt29f_clearError(Mt29f *chip) 00421 { 00422 chip->status = 0; 00423 } 00424 00425 00426 static void initPio(void) 00427 { 00428 /* 00429 * TODO: put following stuff in hw_ file dependent 00430 * Parameters for MT29F8G08AAD 00431 */ 00432 pmc_periphEnable(PIOA_ID); 00433 pmc_periphEnable(PIOC_ID); 00434 pmc_periphEnable(PIOD_ID); 00435 00436 PIO_PERIPH_SEL(PIOA_BASE, MT29F_PINS_PORTA, MT29F_PERIPH_PORTA); 00437 PIOA_PDR = MT29F_PINS_PORTA; 00438 PIOA_PUER = MT29F_PINS_PORTA; 00439 00440 PIO_PERIPH_SEL(PIOC_BASE, MT29F_PINS_PORTC, MT29F_PERIPH_PORTC); 00441 PIOC_PDR = MT29F_PINS_PORTC; 00442 PIOC_PUER = MT29F_PINS_PORTC; 00443 00444 PIO_PERIPH_SEL(PIOD_BASE, MT29F_PINS_PORTD, MT29F_PERIPH_PORTD); 00445 PIOD_PDR = MT29F_PINS_PORTD; 00446 PIOD_PUER = MT29F_PINS_PORTD; 00447 00448 pmc_periphEnable(SMC_SDRAMC_ID); 00449 } 00450 00451 00452 static void initSmc(void) 00453 { 00454 SMC_SETUP0 = SMC_SETUP_NWE_SETUP(0) 00455 | SMC_SETUP_NCS_WR_SETUP(0) 00456 | SMC_SETUP_NRD_SETUP(0) 00457 | SMC_SETUP_NCS_RD_SETUP(0); 00458 00459 SMC_PULSE0 = SMC_PULSE_NWE_PULSE(2) 00460 | SMC_PULSE_NCS_WR_PULSE(3) 00461 | SMC_PULSE_NRD_PULSE(2) 00462 | SMC_PULSE_NCS_RD_PULSE(3); 00463 00464 SMC_CYCLE0 = SMC_CYCLE_NWE_CYCLE(3) 00465 | SMC_CYCLE_NRD_CYCLE(3); 00466 00467 SMC_TIMINGS0 = SMC_TIMINGS_TCLR(1) 00468 | SMC_TIMINGS_TADL(6) 00469 | SMC_TIMINGS_TAR(4) 00470 | SMC_TIMINGS_TRR(2) 00471 | SMC_TIMINGS_TWB(9) 00472 | SMC_TIMINGS_RBNSEL(7) 00473 | SMC_TIMINGS_NFSEL; 00474 00475 SMC_MODE0 = SMC_MODE_READ_MODE 00476 | SMC_MODE_WRITE_MODE; 00477 00478 SMC_CFG = SMC_CFG_PAGESIZE_PS2048_64 00479 | SMC_CFG_EDGECTRL 00480 | SMC_CFG_DTOMUL_X1048576 00481 | SMC_CFG_DTOCYC(0xF) 00482 | SMC_CFG_WSPARE 00483 | SMC_CFG_RSPARE; 00484 00485 // Disable SMC interrupts, reset and enable NFC controller 00486 SMC_IDR = ~0; 00487 SMC_CTRL = 0; 00488 SMC_CTRL = SMC_CTRL_NFCEN; 00489 00490 // Enable ECC, 1 ECC per 256 bytes 00491 SMC_ECC_CTRL = SMC_ECC_CTRL_SWRST; 00492 SMC_ECC_MD = SMC_ECC_MD_ECC_PAGESIZE_PS2048_64 | SMC_ECC_MD_TYPCORREC_C256B; 00493 } 00494 00495 00496 void mt29f_init(Mt29f *chip, uint8_t chip_select) 00497 { 00498 memset(chip, 0, sizeof(Mt29f)); 00499 00500 chip->chip_select = chip_select; 00501 00502 initPio(); 00503 initSmc(); 00504 chipReset(chip); 00505 } 00506