Micron MT29F NAND driver
nand_MT29F_lld.c
Go to the documentation of this file.
00001 
00030 #include <string.h>
00031 
00032 #ifdef TIMEOUT_SUPPORT
00033    #include <time.h>
00034 #endif
00035 
00036 #include "nand_MT29F_lld.h"
00037 
00038 /* uncomment this line to show the address translation */
00039 /* #define DEBUG_PRINT_ADDRESS */
00040 
00041 /* state of the driver */
00042 MT_uint8 driver_status = DRIVER_STATUS_NOT_INITIALIZED;
00043 
00044 /* global structure with device info */
00045 struct parameter_page_t device_info;
00046 
00047 /******************************************************************************
00048  *                   Internal functions, not API
00049  *****************************************************************************/
00050 
00051 /* Address comparison constants */
00052 #define ADDR_A_EQ_B  0  /* A = B */
00053 #define ADDR_A_LT_B  1  /* A < B */
00054 #define ADDR_A_GT_B  2  /* A > B */
00055 
00056 /* Internal functions */
00057 MT_uint16 __as_uint16(MT_uint8 byte0, MT_uint8 byte1);
00058 MT_uint32 __as_uint32(MT_uint8 byte0, MT_uint8 byte1, MT_uint8 byte2, MT_uint8 byte3);
00059 void __as_string(MT_uint8 *src_ptr, char *dest_ptr, int start, int stop);
00060 MT_uint8 __wait_for_ready();
00061 MT_uint8 __is_valid_addr(nand_addr_t addr);
00062 MT_uint8 __compare_addr(nand_addr_t first_addr, nand_addr_t second_addr);
00063 void __build_cycle_addr(nand_addr_t addr, MT_uint8 *addr_cycle_stream);
00064 
00065 /******************************************************************************
00066  *                NAND Low Level Driver Functions
00067  *****************************************************************************/
00068 
00084 MT_uint8 Init_Driver(void) {
00085    flash_width onfi_signature[ONFI_SIGNATURE_LENGHT];
00086 
00087    /* check if the driver is previously initialized */
00088    if(DRIVER_STATUS_INITIALIZED == driver_status)
00089       return DRIVER_STATUS_INITIALIZED;
00090 
00091    /* initialize platform */
00092    PLATFORM_Init();
00093 
00094    /* reset at startup is mandatory */
00095    NAND_Reset();
00096 
00097    /* read if this device is ONFI complaint */
00098    NAND_Read_ID_ONFI(onfi_signature);
00099 
00100    /* verify ONFI signature in the first field of parameter page */
00101    if(strcmp((const char *)onfi_signature, "ONFI") &&
00102       (NAND_BAD_PARAMETER_PAGE != NAND_Read_Param_Page(&device_info)))
00103       driver_status = DRIVER_STATUS_INITIALIZED;
00104 
00105    return driver_status;
00106 }
00107 
00108 
00123 MT_uint8 NAND_Reset(void) {
00124    MT_uint8 ret;
00125 
00126    /* init board transfer */
00127    PLATFORM_Open();
00128 
00129    /* send command and/or address */
00130    PLATFORM_SendCmd(CMD_RESET);
00131 
00132    /* wait (see datasheet for details) */
00133    PLATFORM_Wait(TIME_WB);
00134    ret = __wait_for_ready();
00135 
00136    /* close board transfer */
00137    PLATFORM_Close();
00138 
00139    return ret;
00140 }
00141 
00160 MT_uint8 NAND_Read_ID(flash_width *buffer) {
00161    int i;
00162 
00163    /* verify if driver is initialized */
00164    if(DRIVER_STATUS_INITIALIZED != driver_status)
00165       return DRIVER_STATUS_NOT_INITIALIZED;
00166 
00167    /* init board transfer */
00168     PLATFORM_Open();
00169 
00170     /* send command and/or address */
00171     PLATFORM_SendCmd(CMD_READID);
00172     PLATFORM_SendAddr(ADDR_READ_ID);
00173 
00174     /* wait (see datasheet for details) */
00175     PLATFORM_Wait(TIME_WHR);
00176 
00177     /* read output */
00178     for(i=0; i<NUM_OF_READID_BYTES; i++)
00179       buffer[i] = PLATFORM_ReadData();
00180 
00181     /* close board transfer */
00182     PLATFORM_Close();
00183 
00184     return NAND_SUCCESS;
00185 }
00186 
00205 MT_uint8 NAND_Read_ID_ONFI(flash_width *buffer) {
00206    MT_uint32 i;
00207 
00208    /* init board transfer */
00209     PLATFORM_Open();
00210 
00211     /* send command and/or address */
00212     PLATFORM_SendCmd(CMD_READID);
00213     PLATFORM_SendAddr(ADDR_READ_ID_ONFI);
00214 
00215     /* wait (see datasheet for details) */
00216     PLATFORM_Wait(TIME_WHR);
00217 
00218     /* read output */
00219     for(i=0; i<NUM_OF_READIDONFI_BYTES; i++)
00220       buffer[i] = PLATFORM_ReadData();
00221 
00222     /* close board transfer */
00223     PLATFORM_Close();
00224 
00225     return NAND_SUCCESS;
00226 }
00227 
00249 MT_uint8 NAND_Read_Param_Page(param_page_t *ppage) {
00250    MT_uint8 rbuf[NUM_OF_PPAGE_BYTES];
00251    MT_uint8 ret;
00252    MT_uint32 i;
00253 
00254    /* init board transfer */
00255     PLATFORM_Open();
00256 
00257     /* send command and/or address */
00258     PLATFORM_SendCmd(CMD_READ_PARAM_PAGE);
00259     PLATFORM_SendAddr(ADDR_PARAM_PAGE);
00260 
00261     /* wait (see datasheet for details) */
00262     PLATFORM_Wait(TIME_WB);
00263     ret = __wait_for_ready();
00264 
00265     /* return if timeout */
00266     if (NAND_SUCCESS != ret)
00267       return ret;
00268 
00269     /* read output */
00270     for(i=0; i<NUM_OF_PPAGE_BYTES; i++)
00271       rbuf[i] = PLATFORM_ReadData();
00272 
00273     /* close board transfer */
00274     PLATFORM_Close();
00275 
00276     /*
00277      * Fill the parameter page data structure in the right way
00278      */
00279 
00280     /* Parameter page signature (ONFI) */
00281    __as_string(rbuf, ppage->signature, 0, 3);
00282 
00283    /* check if the buffer contains a valid ONFI parameter page */
00284    if (strcmp(ppage->signature, "ONFI"))
00285       return NAND_BAD_PARAMETER_PAGE;
00286 
00287    /* Revision number */
00288    ppage->rev_num = __as_uint16(rbuf[4], rbuf[5]);
00289 
00290    /* Features supported */
00291    ppage->feature = __as_uint16(rbuf[6], rbuf[7]);
00292 
00293    /* Optional commands supported */
00294    ppage->command = __as_uint16(rbuf[8], rbuf[9]);
00295 
00296    /* Device manufacturer */
00297    __as_string(rbuf, ppage->manufacturer, 32, 43);
00298 
00299    /* Device part number */
00300    __as_string(rbuf, ppage->model, 44, 63);
00301 
00302    /* Manufacturer ID (Micron = 2Ch) */
00303    ppage->jedec_id = rbuf[64];
00304 
00305    /* Date code */
00306    ppage->date_code = __as_uint16(rbuf[65], rbuf[66]);
00307 
00308    /* Number of data bytes per page */
00309    ppage->data_bytes_per_page = __as_uint32(rbuf[80], rbuf[81], rbuf[82], rbuf[83]);
00310 
00311    /* Number of spare bytes per page */
00312    ppage->spare_bytes_per_page = __as_uint16(rbuf[84], rbuf[85]);
00313 
00314    /* Number of data bytes per partial page */
00315    ppage->data_bytes_per_partial_page = __as_uint32(rbuf[86], rbuf[87], rbuf[88], rbuf[89]);
00316 
00317    /* Number of spare bytes per partial page */
00318    ppage->spare_bytes_per_partial_page = __as_uint16(rbuf[90], rbuf[91]);
00319 
00320    /* Number of pages per block */
00321    ppage->pages_per_block = __as_uint32(rbuf[92], rbuf[93], rbuf[94], rbuf[95]);
00322 
00323    /* Number of blocks per unit */
00324    ppage->blocks_per_lun = __as_uint32(rbuf[96], rbuf[97], rbuf[98], rbuf[99]);
00325 
00326    /* Number of logical units (LUN) per chip enable */
00327    ppage->luns_per_ce = rbuf[100];
00328 
00329    /* Number of address cycles */
00330    ppage->num_addr_cycles = rbuf[101];
00331 
00332    /* Number of bits per cell (1 = SLC; >1= MLC) */
00333    ppage->bit_per_cell = rbuf[102];
00334 
00335    /* Bad blocks maximum per unit */
00336    ppage->max_bad_blocks_per_lun = __as_uint16(rbuf[103], rbuf[104]);
00337 
00338    /* Block endurance */
00339    ppage->block_endurance = __as_uint16(rbuf[105], rbuf[106]);
00340 
00341    /* Guaranteed valid blocks at beginning of target */
00342    ppage->guarenteed_valid_blocks = rbuf[107];
00343 
00344    /* Block endurance for guaranteed valid blocks */
00345    ppage->guarenteed_valid_blocks = __as_uint16(rbuf[108], rbuf[109]);
00346 
00347    /* Number of programs per page */
00348    ppage->num_programs_per_page = rbuf[110];
00349 
00350    /* Partial programming attributes */
00351    ppage->partial_prog_attr = rbuf[111];
00352 
00353    /* Number of bits ECC bits */
00354    ppage->num_ECC_bits_correctable = rbuf[112];
00355 
00356    /* Number of interleaved address bits */
00357    ppage->num_interleaved_addr_bits = rbuf[113];
00358 
00359    /* Interleaved operation attributes */
00360    ppage->interleaved_op_attr = rbuf[114];
00361 
00362     return ret;
00363 }
00364 
00387 MT_uint8 NAND_Set_Feature(flash_width feature_address, flash_width subfeature) {
00388    MT_uint8 ret;
00389 
00390    /* verify if driver is initialized */
00391    if(DRIVER_STATUS_INITIALIZED != driver_status)
00392       return DRIVER_STATUS_NOT_INITIALIZED;
00393 
00394    /* check if this feature/command is supported */
00395    if ((device_info.command & OPTIONAL_CMD_GET_FEATURES_AND_SET_FEATURES) == 0)
00396       return NAND_UNSUPPORTED;
00397 
00398    /* init board transfer */
00399    PLATFORM_Open();
00400 
00401    /* send command and/or address */
00402    PLATFORM_SendCmd(CMD_SET_FEATURE);
00403    PLATFORM_SendAddr(feature_address);
00404 
00405     /* wait (see datasheet for details) */
00406     PLATFORM_Wait(TIME_ADL);
00407 
00408    /* send sub-feature parameter */
00409    PLATFORM_SendData(subfeature);   /* p0 */
00410    PLATFORM_SendData(0x00);      /* p1 reserved */
00411    PLATFORM_SendData(0x00);      /* p2 reserved */
00412    PLATFORM_SendData(0x00);      /* p3 reserved */
00413 
00414     PLATFORM_Wait(TIME_WB);
00415     ret = __wait_for_ready();
00416 
00417     /* return if timeout */
00418     if (NAND_SUCCESS != ret)
00419       return ret;
00420 
00421    /* close board transfer */
00422    PLATFORM_Close();
00423 
00424    return ret;
00425 }
00426 
00448 MT_uint8 NAND_Get_Feature(flash_width feature_address, flash_width *subfeature) {
00449    flash_width ret;
00450 
00451    /* verify if driver is initialized */
00452    if(DRIVER_STATUS_INITIALIZED != driver_status)
00453       return DRIVER_STATUS_NOT_INITIALIZED;
00454 
00455    /* check if this feature/command is supported */
00456    if ((device_info.command & OPTIONAL_CMD_GET_FEATURES_AND_SET_FEATURES) == 0)
00457       return NAND_UNSUPPORTED;
00458 
00459    /* init board transfer */
00460    PLATFORM_Open();
00461 
00462    /* send command and/or address */
00463    PLATFORM_SendCmd(CMD_GET_FEATURE);
00464    PLATFORM_SendAddr(feature_address);
00465 
00466     /* wait (see datasheet for details) */
00467     PLATFORM_Wait(TIME_WB);
00468     ret = __wait_for_ready();
00469 
00470     /* return if timeout */
00471     if (NAND_SUCCESS != ret)
00472       return ret;
00473 
00474    /* send sub-feature parameter */
00475     *subfeature = PLATFORM_ReadData(); /* p0 */
00476    /*
00477     * skip p1, p2 and p3 because they are reserved and their value are 00h
00478     */
00479 
00480    /* close board transfer */
00481    PLATFORM_Close();
00482 
00483    return ret;
00484 }
00485 
00501 flash_width NAND_Read_Status() {
00502    flash_width ret;
00503 
00504    /* verify if driver is initialized */
00505    if(DRIVER_STATUS_INITIALIZED != driver_status)
00506       return DRIVER_STATUS_NOT_INITIALIZED;
00507 
00508    /* init board transfer */
00509    PLATFORM_Open();
00510 
00511    /* send command and/or address */
00512    PLATFORM_SendCmd(CMD_READ_STATUS);
00513 
00514    /* wait */
00515    PLATFORM_Wait(TIME_WHR);
00516 
00517    /* read value */
00518    ret = PLATFORM_ReadData();
00519 
00520    /* close board transfer */
00521    PLATFORM_Close();
00522 
00523    return ret;
00524 }
00525 
00543 flash_width NAND_Read_Status_Enhanced(nand_addr_t addr) {
00544    flash_width ret;
00545    MT_uint8 row_address[5];
00546 
00547    /* verify if driver is initialized */
00548    if(DRIVER_STATUS_INITIALIZED != driver_status)
00549       return DRIVER_STATUS_NOT_INITIALIZED;
00550 
00551    /* check input parameters */
00552    if(NAND_SUCCESS != __is_valid_addr(addr))
00553       return NAND_INVALID_NAND_ADDRESS;
00554 
00555    /* check if this feature/command is supported */
00556    if ((device_info.command & OPTIONAL_CMD_READ_STATUS_ENHANCED) == 0)
00557       return NAND_UNSUPPORTED;
00558 
00559    __build_cycle_addr(addr, row_address);
00560 
00561    /* init board transfer */
00562    PLATFORM_Open();
00563 
00564    /* send command  */
00565    PLATFORM_SendCmd(CMD_READ_STATUS_ENHANCED);
00566 
00567    /* send row address (3rd, 4th, 5th cycle) */
00568    PLATFORM_SendAddr(row_address[2]);
00569    PLATFORM_SendAddr(row_address[3]);
00570    PLATFORM_SendAddr(row_address[4]);
00571 
00572    /* wait */
00573    PLATFORM_Wait(TIME_WHR);
00574 
00575    /* read value */
00576    ret = PLATFORM_ReadData();
00577 
00578    /* close board transfer */
00579    PLATFORM_Close();
00580 
00581    return ret;
00582 }
00583 
00605 MT_uint8 NAND_Block_Erase(nand_addr_t addr) {
00606    MT_uint8 row_address[5];
00607    MT_uint8 status_reg;
00608    MT_uint8 ret;
00609 
00610    /* verify if driver is initialized */
00611    if(DRIVER_STATUS_INITIALIZED != driver_status)
00612       return DRIVER_STATUS_NOT_INITIALIZED;
00613 
00614    /* check input parameters */
00615    if(NAND_SUCCESS != __is_valid_addr(addr))
00616       return NAND_INVALID_NAND_ADDRESS;
00617 
00618    __build_cycle_addr(addr, row_address);
00619 
00620    /* init board transfer */
00621    PLATFORM_Open();
00622 
00623    /* send command  */
00624    PLATFORM_SendCmd(CMD_ERASE_BLOCK);
00625 
00626    /* send row address (3rd, 4th, 5th cycle) */
00627    PLATFORM_SendAddr(row_address[2]);
00628    PLATFORM_SendAddr(row_address[3]);
00629    PLATFORM_SendAddr(row_address[4]);
00630 
00631    /* send confirm command */
00632    PLATFORM_SendCmd(CMD_ERASE_BLOCK_CONFIRM);
00633 
00634    /* wait */
00635    PLATFORM_Wait(TIME_WB);
00636    ret = __wait_for_ready();
00637 
00638     /* return if timeout occurs */
00639     if (NAND_SUCCESS != ret)
00640       return ret;
00641 
00642    status_reg = NAND_Read_Status();
00643 
00644    /* close board transfer */
00645    PLATFORM_Close();
00646 
00647    /* check if erase is good */
00648    if(!(status_reg & STATUS_WRITE_PROTECTED))
00649       return NAND_ERASE_FAILED_WRITE_PROTECT;
00650 
00651    if(status_reg & STATUS_FAIL)
00652       return NAND_ERASE_FAILED;
00653 
00654    return ret;
00655 }
00656 
00683 MT_uint8 NAND_Page_Read(nand_addr_t addr, flash_width *buffer, MT_uint32 lenght) {
00684    MT_uint8 row_address[5];
00685    MT_uint8 status_reg;
00686    MT_uint8 ret;
00687    int i;
00688 
00689    /* verify if driver is initialized */
00690    if(DRIVER_STATUS_INITIALIZED != driver_status)
00691       return DRIVER_STATUS_NOT_INITIALIZED;
00692 
00693    /* check input parameters */
00694    if(NAND_SUCCESS != __is_valid_addr(addr))
00695       return NAND_INVALID_NAND_ADDRESS;
00696 
00697    /* x16 */
00698    if((device_info.feature & SUPPORTED_16_BIT_DATA_BUS_WIDTH) != 0) {
00699       if(lenght > (device_info.data_bytes_per_page >> 1) )
00700          return NAND_INVALID_LENGHT;
00701    }
00702 
00703    /* x8 */
00704    if(lenght > device_info.data_bytes_per_page)
00705       return NAND_INVALID_LENGHT;
00706 
00707    __build_cycle_addr(addr, row_address);
00708 
00709    /* init board transfer */
00710    PLATFORM_Open();
00711 
00712    /* send command  */
00713    PLATFORM_SendCmd(CMD_READ_MODE);
00714 
00715    /* send address */
00716    for(i=0; i<NUM_OF_ADDR_CYCLE; i++)
00717       PLATFORM_SendAddr(row_address[i]);
00718 
00719    /* return to read mode */
00720    PLATFORM_SendCmd(CMD_READ_CONFIRM);
00721 
00722    /* wait */
00723    ret = __wait_for_ready();
00724 
00725     /* return if timeout */
00726     if (NAND_SUCCESS != ret)
00727       return ret;
00728 
00729    /* read data */
00730    for(i=0; i<lenght; i++)
00731       buffer[i] = PLATFORM_ReadData();
00732 
00733    /* read status register on exit */
00734    status_reg = NAND_Read_Status();
00735 
00736    /* close board transfer */
00737    PLATFORM_Close();
00738 
00739    if(status_reg & STATUS_FAIL)
00740       return NAND_READ_FAILED;
00741 
00742    return ret;
00743 }
00744 
00773 MT_uint8 NAND_Page_Program(nand_addr_t addr, flash_width *buffer, MT_uint32 lenght) {
00774    MT_uint8 address[5];
00775    MT_uint8 status_reg;
00776    MT_uint32 k;
00777    int i;
00778 
00779    /* verify if driver is initialized */
00780    if(DRIVER_STATUS_INITIALIZED != driver_status)
00781       return DRIVER_STATUS_NOT_INITIALIZED;
00782 
00783    /* check input parameters */
00784    if(NAND_SUCCESS != __is_valid_addr(addr))
00785       return NAND_INVALID_NAND_ADDRESS;
00786 
00787    /* x16 */
00788    if((device_info.feature & SUPPORTED_16_BIT_DATA_BUS_WIDTH) != 0) {
00789       if(lenght > (device_info.data_bytes_per_page >> 1) )
00790          return NAND_INVALID_LENGHT;
00791    }
00792 
00793    /* x8 */
00794    if(lenght > device_info.data_bytes_per_page)
00795       return NAND_INVALID_LENGHT;
00796 
00797    __build_cycle_addr(addr, address);
00798 
00799    /* init board transfer */
00800    PLATFORM_Open();
00801 
00802    /* send command */
00803    PLATFORM_SendCmd(CMD_PAGE_PROGRAM);
00804 
00805    /* send address */
00806    for(i=0; i<NUM_OF_ADDR_CYCLE; i++)
00807       PLATFORM_SendAddr(address[i]);
00808 
00809    /* send data */
00810    for(k=0; k<lenght; k++)
00811       PLATFORM_SendData(buffer[k]);
00812 
00813    /* send command */
00814    PLATFORM_SendCmd(CMD_PAGE_PROGRAM_CONFIRM);
00815 
00816    status_reg = NAND_Read_Status();
00817 
00818    /* close board transfer */
00819    PLATFORM_Close();
00820 
00821    /* check if program is good */
00822    if(!(status_reg & STATUS_WRITE_PROTECTED))
00823       return NAND_PROGRAM_FAILED_WRITE_PROTECT;
00824 
00825    if(status_reg & STATUS_FAIL)
00826       return NAND_PROGRAM_FAILED;
00827 
00828    return NAND_SUCCESS;
00829 }
00830 
00858 MT_uint8 NAND_Spare_Read(nand_addr_t addr, flash_width *buffer, MT_uint32 lenght) {
00859    MT_uint8 row_address[5];
00860    MT_uint8 status_reg;
00861    MT_uint8 ret;
00862    MT_uint32 k;
00863    int i;
00864 
00865    /* verify if driver is initialized */
00866    if(DRIVER_STATUS_INITIALIZED != driver_status)
00867       return DRIVER_STATUS_NOT_INITIALIZED;
00868 
00869    /* check input parameters */
00870    if(NAND_SUCCESS != __is_valid_addr(addr))
00871       return NAND_INVALID_NAND_ADDRESS;
00872 
00873    if((device_info.feature & SUPPORTED_16_BIT_DATA_BUS_WIDTH) != 0) {
00874       /* x16 */
00875       if(lenght > (device_info.spare_bytes_per_page >> 1) )
00876          return NAND_INVALID_LENGHT;
00877    }
00878 
00879    /* x8 */
00880    if(lenght > device_info.spare_bytes_per_page)
00881       return NAND_INVALID_LENGHT;
00882 
00883    /* spare area starts after last main area byte */
00884    if((device_info.feature & SUPPORTED_16_BIT_DATA_BUS_WIDTH) == 0)
00885       /* x8 bus width */
00886       addr.column=device_info.data_bytes_per_page;
00887    else
00888       /* x16 bus width */
00889       addr.column=device_info.data_bytes_per_page >> 1;
00890 
00891    __build_cycle_addr(addr, row_address);
00892 
00893    /* init board transfer */
00894    PLATFORM_Open();
00895 
00896    /* send command */
00897    PLATFORM_SendCmd(CMD_READ_MODE);
00898 
00899    /* send address */
00900    for(i=0; i<NUM_OF_ADDR_CYCLE; i++)
00901       PLATFORM_SendAddr(row_address[i]);
00902 
00903    /* return to read mode */
00904    PLATFORM_SendCmd(CMD_READ_CONFIRM);
00905 
00906    /* wait */
00907    ret = __wait_for_ready();
00908 
00909     /* return if timeout */
00910     if (NAND_SUCCESS != ret)
00911       return ret;
00912 
00913    /* read data */
00914    for(k=0; k<lenght; k++)
00915       buffer[k] = PLATFORM_ReadData();
00916 
00917    /* read status register on exit */
00918    status_reg = NAND_Read_Status();
00919 
00920    /* close board transfer */
00921    PLATFORM_Close();
00922 
00923    if(status_reg & STATUS_FAIL)
00924       return NAND_READ_FAILED;
00925 
00926    return ret;
00927 }
00928 
00956 MT_uint8 NAND_Spare_Program(nand_addr_t addr, flash_width *buffer, MT_uint32 lenght) {
00957    MT_uint8 address[5];
00958    MT_uint8 status_reg;
00959    MT_uint32 k;
00960    int i;
00961 
00962    /* verify if driver is initialized */
00963    if(DRIVER_STATUS_INITIALIZED != driver_status)
00964       return DRIVER_STATUS_NOT_INITIALIZED;
00965 
00966    /* check input parameters */
00967    if(NAND_SUCCESS != __is_valid_addr(addr))
00968       return NAND_INVALID_NAND_ADDRESS;
00969 
00970    if((device_info.feature & SUPPORTED_16_BIT_DATA_BUS_WIDTH) != 0) {
00971       /* x16 */
00972       if(lenght > (device_info.spare_bytes_per_page >> 1) )
00973          return NAND_INVALID_LENGHT;
00974    }
00975 
00976    /* x8 */
00977    if(lenght > device_info.spare_bytes_per_page)
00978       return NAND_INVALID_LENGHT;
00979 
00980    /* spare area starts after last main area byte */
00981    if((device_info.feature & SUPPORTED_16_BIT_DATA_BUS_WIDTH) == 0)
00982       /* x8 bus width */
00983       addr.column=device_info.data_bytes_per_page;
00984    else
00985       /* x16 bus width */
00986       addr.column=device_info.data_bytes_per_page >> 1;
00987 
00988    __build_cycle_addr(addr, address);
00989 
00990    /* init board transfer */
00991    PLATFORM_Open();
00992 
00993    /* send command */
00994    PLATFORM_SendCmd(CMD_PAGE_PROGRAM);
00995 
00996    /* send address */
00997    for(i=0; i<NUM_OF_ADDR_CYCLE; i++)
00998       PLATFORM_SendAddr(address[i]);
00999 
01000    /* send data */
01001    for(k=0; k<lenght; k++)
01002       PLATFORM_SendData(buffer[k]);
01003 
01004    /* send command */
01005    PLATFORM_SendCmd(CMD_PAGE_PROGRAM_CONFIRM);
01006 
01007    status_reg = NAND_Read_Status();
01008 
01009    /* close board transfer */
01010    PLATFORM_Close();
01011 
01012    /* check if program is good */
01013    if(!(status_reg & STATUS_WRITE_PROTECTED))
01014       return NAND_PROGRAM_FAILED_WRITE_PROTECT;
01015 
01016    if(status_reg & STATUS_FAIL)
01017       return NAND_PROGRAM_FAILED;
01018 
01019    return NAND_SUCCESS;
01020 }
01021 
01022 /*
01023  * NAND_Read_Unique_Id
01024  */
01025 MT_uint8 NAND_Read_Unique_Id(flash_width *buffer) {
01026 
01027    int i;
01028    MT_uint8 ret;
01029 
01030    /* verify if driver is initialized */
01031    if(DRIVER_STATUS_INITIALIZED != driver_status)
01032       return DRIVER_STATUS_NOT_INITIALIZED;
01033 
01034    /* init board transfer */
01035     PLATFORM_Open();
01036 
01037     /* send command and/or address */
01038     PLATFORM_SendCmd(CMD_READ_UNIQ_ID);
01039     PLATFORM_SendAddr(ADDR_READ_UNIQ_ID);
01040 
01041     /* wait (see datasheet for details) */
01042     PLATFORM_Wait(TIME_WB);
01043 
01044    ret = __wait_for_ready();
01045 
01046     /* return if timeout */
01047     if (NAND_SUCCESS != ret)
01048       return ret;
01049 
01050     /* read output */
01051     for(i=0; i<NUM_OF_UNIQUEID_BYTES; i++)
01052       buffer[i] = (MT_uint8) PLATFORM_ReadData();
01053 
01054     /* close board transfer */
01055     PLATFORM_Close();
01056 
01057     return NAND_SUCCESS;
01058 
01059 }
01060 
01090 MT_uint8 NAND_Copy_Back(nand_addr_t src_addr, nand_addr_t dest_addr) {
01091    MT_uint8 src_address_stream[NUM_OF_ADDR_CYCLE];
01092    MT_uint8 dest_address_stream[NUM_OF_ADDR_CYCLE];
01093    MT_uint8 status_reg;
01094    MT_uint8 ret;
01095    MT_uint32 k;
01096    int i;
01097 
01098    /* verify if driver is initialized */
01099    if(DRIVER_STATUS_INITIALIZED != driver_status)
01100       return driver_status;
01101 
01102    /* check if this feature/command is supported */
01103    if ((device_info.command & OPTIONAL_CMD_COPYBACK) == 0)
01104       return NAND_UNSUPPORTED;
01105 
01106    /* check input parameters */
01107    if((NAND_SUCCESS != __is_valid_addr(src_addr)) || (NAND_SUCCESS != __is_valid_addr(dest_addr)))
01108       return NAND_INVALID_NAND_ADDRESS;
01109 
01110    /* check if the source and destination address are the same */
01111    if(!__compare_addr(src_addr, dest_addr))
01112       return NAND_INVALID_NAND_ADDRESS;
01113 
01114    /* check if odd to even copy back is supported */
01115    if ((device_info.command & SUPPORTED_ODD_TO_EVEN_PAGE_COPYBACK) == 0) {
01116       if(((src_addr.page & 1) != 0) && ((dest_addr.page & 1) == 0))
01117          return NAND_INVALID_NAND_ADDRESS;
01118       if(((src_addr.page & 1) == 0) && ((dest_addr.page & 1) != 0))
01119          return NAND_INVALID_NAND_ADDRESS;
01120    }
01121 
01122    /* copy back allows to move data from one page to another on the same plane */
01123    if(((src_addr.block & 1) != 0) && ((dest_addr.block & 1) == 0))
01124       return NAND_INVALID_NAND_ADDRESS;
01125    if(((src_addr.block & 1) == 0) && ((dest_addr.block & 1) != 0))
01126       return NAND_INVALID_NAND_ADDRESS;
01127 
01128    /* copy back is allowed only at the start of a page (ignoring column) */
01129    src_addr.column = 0;
01130    dest_addr.column = 0;
01131 
01132    /* build address cycles for source and destination address */
01133    __build_cycle_addr(src_addr, src_address_stream);
01134    __build_cycle_addr(dest_addr, dest_address_stream);
01135 
01136    /* init board transfer */
01137    PLATFORM_Open();
01138 
01139    /* send command */
01140    PLATFORM_SendCmd(CMD_READ_MODE);
01141 
01142    /* send source address */
01143    for(i=0; i<NUM_OF_ADDR_CYCLE; i++)
01144       PLATFORM_SendAddr(src_address_stream[i]);
01145 
01146    /* read for internal data move */
01147 
01148    /* send command */
01149    PLATFORM_SendCmd(CMD_READ_INTERNAL_DATA_MOVE);
01150 
01151     /* wait (see datasheet for details) */
01152    PLATFORM_Wait(TIME_WB);
01153    ret = __wait_for_ready();
01154 
01155     /* return if timeout */
01156     if (NAND_SUCCESS != ret)
01157       return ret;
01158 
01159     /* program for internal data move */
01160 
01161    /* send command */
01162    PLATFORM_SendCmd(CMD_PROGRAM_INTERNAL_DATA_MOVE);
01163 
01164    /* send destination address */
01165    for(i=0; i<NUM_OF_ADDR_CYCLE; i++)
01166       PLATFORM_SendAddr(dest_address_stream[i]);
01167 
01168    PLATFORM_SendCmd(CMD_PAGE_PROGRAM_CONFIRM);
01169 
01170    /* wait (see datasheet for details) */
01171    PLATFORM_Wait(TIME_WB);
01172    ret = __wait_for_ready();
01173 
01174     /* return if timeout */
01175     if (NAND_SUCCESS != ret)
01176       return ret;
01177 
01178    status_reg = NAND_Read_Status();
01179 
01180    /* close board transfer */
01181    PLATFORM_Close();
01182 
01183    /* check if program is good */
01184    if(!(status_reg & STATUS_WRITE_PROTECTED))
01185       return NAND_PROGRAM_FAILED_WRITE_PROTECT;
01186 
01187    if(status_reg & STATUS_FAIL)
01188       return NAND_PROGRAM_FAILED;
01189 
01190    return ret;
01191 }
01192 
01193 /*
01194  * NAND_Multiplane_Copy_Back
01195  */
01196 MT_uint8 NAND_Multiplane_Copy_Back(void) {
01197 
01198    /*
01199     * TO BE IMPLEMENTED
01200     *
01201     * Please contact Micron support for any request
01202     */
01203 
01204    return NAND_UNIMPLEMENTED;
01205 
01206 }
01207 
01208 /*
01209  * NAND_Cache_Read
01210  */
01211 MT_uint8 NAND_Cache_Read(void) {
01212 
01213    /*
01214     * TO BE IMPLEMENTED
01215     *
01216     * Please contact Micron support for any request
01217     */
01218 
01219    return NAND_UNIMPLEMENTED;
01220 
01221 }
01222 
01223 /*
01224  * NAND_Cache_Program
01225  */
01226 MT_uint8 NAND_Cache_Program(void) {
01227 
01228    /*
01229     * TO BE IMPLEMENTED
01230     *
01231     * Please contact Micron support for any request
01232     */
01233 
01234    return NAND_UNIMPLEMENTED;
01235 
01236 }
01237 
01238 /*
01239  * NAND_Multiplane_Page_Program
01240  */
01241 MT_uint8 NAND_Multiplane_Page_Program(void) {
01242 
01243    /*
01244     * TO BE IMPLEMENTED
01245     *
01246     * Please contact Micron support for any request
01247     */
01248 
01249    return NAND_UNIMPLEMENTED;
01250 
01251 }
01252 
01253 /*
01254  * NAND_Multiplane_Block_Erase
01255  */
01256 MT_uint8 NAND_Multiplane_Block_Erase(void) {
01257 
01258    /*
01259     * TO BE IMPLEMENTED
01260     *
01261     * Please contact Micron support for any request
01262     */
01263 
01264    return NAND_UNIMPLEMENTED;
01265 
01266 }
01267 
01281 MT_uint8 NAND_Lock(void) {
01282 
01283    /* verify if driver is initialized */
01284    if(DRIVER_STATUS_INITIALIZED != driver_status)
01285       return DRIVER_STATUS_NOT_INITIALIZED;
01286 
01287    /* init board transfer */
01288    PLATFORM_Open();
01289 
01290    /* send command */
01291    PLATFORM_SendCmd(CMD_LOCK);
01292 
01293    /* close board transfer */
01294    PLATFORM_Close();
01295 
01296    return NAND_SUCCESS;
01297 }
01298 
01320 MT_uint8 NAND_Unlock(nand_addr_t start_block, nand_addr_t end_block) {
01321    MT_uint8 start_address_stream[NUM_OF_ADDR_CYCLE];
01322    MT_uint8 end_address_stream[NUM_OF_ADDR_CYCLE];
01323 
01324    /* verify if driver is initialized */
01325    if(DRIVER_STATUS_INITIALIZED != driver_status)
01326       return DRIVER_STATUS_NOT_INITIALIZED;
01327 
01328    /* check input parameters */
01329    if((NAND_SUCCESS != __is_valid_addr(start_block)) || (NAND_SUCCESS != __is_valid_addr(end_block)))
01330       return NAND_INVALID_NAND_ADDRESS;
01331 
01332    /* verify if start_block < end_block */
01333    if(ADDR_A_GT_B == __compare_addr(start_block, end_block) )
01334       return NAND_INVALID_NAND_ADDRESS;
01335 
01336    /* build address cycles for start and end block */
01337    __build_cycle_addr(start_block, start_address_stream);
01338    __build_cycle_addr(end_block, end_address_stream);
01339 
01340    /* init board transfer */
01341    PLATFORM_Open();
01342 
01343    /* send command */
01344    PLATFORM_SendCmd(CMD_BLOCK_UNLOCK_LOW);
01345 
01346    /* send row address (3rd, 4th, 5th cycle) */
01347    PLATFORM_SendAddr(start_address_stream[2]);
01348    PLATFORM_SendAddr(start_address_stream[3]);
01349    PLATFORM_SendAddr(start_address_stream[4]);
01350 
01351    /* send command */
01352    PLATFORM_SendCmd(CMD_BLOCK_UNLOCK_HIGH);
01353 
01354    /* send row address (3rd, 4th, 5th cycle) */
01355    PLATFORM_SendAddr(end_address_stream[2]);
01356    PLATFORM_SendAddr(end_address_stream[3]);
01357    PLATFORM_SendAddr(end_address_stream[4]);
01358 
01359    /* close board transfer */
01360    PLATFORM_Close();
01361 
01362    return NAND_SUCCESS;
01363 
01364 }
01365 
01381 MT_uint8 NAND_Read_Lock_Status(nand_addr_t block_addr) {
01382    MT_uint8 block_addr_stream[NUM_OF_ADDR_CYCLE];
01383    MT_uint8 block_lock_status_reg;
01384 
01385    /* verify if driver is initialized */
01386    if(DRIVER_STATUS_INITIALIZED != driver_status)
01387       return DRIVER_STATUS_NOT_INITIALIZED;
01388 
01389    /* check input parameters */
01390    if(NAND_SUCCESS != __is_valid_addr(block_addr))
01391       return NAND_INVALID_NAND_ADDRESS;
01392 
01393    /* build address cycles for block address */
01394    __build_cycle_addr(block_addr, block_addr_stream);
01395 
01396    /* init board transfer */
01397    PLATFORM_Open();
01398 
01399    /* send command*/
01400    PLATFORM_SendCmd(CMD_BLOCK_LOCK_READ_STATUS);
01401 
01402    /* send row address (3rd, 4th, 5th cycle) */
01403    PLATFORM_SendAddr(block_addr_stream[2]);
01404    PLATFORM_SendAddr(block_addr_stream[3]);
01405    PLATFORM_SendAddr(block_addr_stream[4]);
01406 
01407    block_lock_status_reg = PLATFORM_ReadData();
01408 
01409    /* close board transfer */
01410    PLATFORM_Close();
01411 
01412    /* return the value of block status register */
01413    return block_lock_status_reg;
01414 
01415 }
01416 
01417 /*
01418  * NAND_Lock_Down
01419  */
01420 MT_uint8 NAND_Lock_Down(void) {
01421 
01422    /*
01423     * TO BE IMPLEMENTED
01424     *
01425     * Please contact Micron support for any request
01426     */
01427 
01428    return NAND_UNIMPLEMENTED;
01429 
01430 }
01431 
01432 /*
01433  * NAND_Unlock_Down
01434  */
01435 MT_uint8 NAND_Unlock_Down(void) {
01436 
01437    /*
01438     * TO BE IMPLEMENTED
01439     *
01440     * Please contact Micron support for any request
01441     */
01442 
01443    return NAND_UNIMPLEMENTED;
01444 
01445 }
01446 
01447 /*
01448  * NAND_Enter_OTP_Mode
01449  */
01450 
01470 MT_uint8 NAND_OTP_Mode_Enter(void) {
01471    MT_uint8 ret;
01472    flash_width subfeature;
01473 
01474    /* check if driver is in a valid state */
01475    if(DRIVER_STATUS_INITIALIZED != driver_status)
01476       return DRIVER_STATUS_NOT_INITIALIZED;
01477 
01478    /* check if device is NOT in OTP status */
01479    ret = NAND_Get_Feature(ADDR_FEATURE_ARRAY_OPMODE, &subfeature);
01480 
01481    if((FEATURE_ARRAY_NORMAL != subfeature) && (FEATURE_ARRAY_OTP_PROTECTION != subfeature))
01482       return NAND_GENERIC_FAIL;
01483 
01484    /* set OTP status */
01485    ret = NAND_Set_Feature(ADDR_FEATURE_ARRAY_OPMODE, FEATURE_ARRAY_OTP_OPERATION);
01486 
01487    /* return with error if a fail occurs */
01488    if(NAND_SUCCESS != ret)
01489       return ret;
01490 
01491    /* check if device is in OTP status */
01492    ret = NAND_Get_Feature(ADDR_FEATURE_ARRAY_OPMODE, &subfeature);
01493 
01494    /* return with error if a fail occurs */
01495    if(NAND_SUCCESS != ret)
01496       return ret;
01497 
01498    if(FEATURE_ARRAY_OTP_OPERATION != subfeature)
01499       return NAND_GENERIC_FAIL;
01500 
01501    return NAND_SUCCESS;
01502 }
01503 
01518 MT_uint8 NAND_OTP_Mode_Exit(void) {
01519    MT_uint8 ret;
01520    flash_width subfeature;
01521 
01522    /* check if driver is in a valid state */
01523    if(DRIVER_STATUS_INITIALIZED != driver_status)
01524       return DRIVER_STATUS_NOT_INITIALIZED;
01525 
01526    /* check if device is NOT in normal status */
01527    ret = NAND_Get_Feature(ADDR_FEATURE_ARRAY_OPMODE, &subfeature);
01528 
01529    if((FEATURE_ARRAY_OTP_OPERATION != subfeature) && (FEATURE_ARRAY_OTP_PROTECTION != subfeature))
01530       return NAND_GENERIC_FAIL;
01531 
01532    /* exit OTP status */
01533    ret = NAND_Set_Feature(ADDR_FEATURE_ARRAY_OPMODE, FEATURE_ARRAY_NORMAL);
01534 
01535    /* return with error if a fail occurs */
01536    if(NAND_SUCCESS != ret)
01537       return ret;
01538 
01539    /* check if device is in normal status */
01540    ret = NAND_Get_Feature(ADDR_FEATURE_ARRAY_OPMODE, &subfeature);
01541 
01542    /* return with error if a fail occurs */
01543    if(NAND_SUCCESS != ret)
01544       return ret;
01545 
01546    if(FEATURE_ARRAY_NORMAL != subfeature)
01547       return NAND_GENERIC_FAIL;
01548 
01549    return NAND_SUCCESS;
01550 }
01551 
01569 MT_uint8 NAND_OTP_Mode_Protect(nand_addr_t addr) {
01570    MT_uint8 ret;
01571    flash_width subfeature;
01572    flash_width write_buf[device_info.data_bytes_per_page + device_info.spare_bytes_per_page];
01573 
01574    /* check if driver is in a valid state */
01575    if(DRIVER_STATUS_INITIALIZED != driver_status)
01576       return DRIVER_STATUS_NOT_INITIALIZED;
01577 
01578    /* check if device is NOT in normal status */
01579    ret = NAND_Get_Feature(ADDR_FEATURE_ARRAY_OPMODE, &subfeature);
01580 
01581    if(FEATURE_ARRAY_OTP_OPERATION != subfeature)
01582       return NAND_GENERIC_FAIL;
01583 
01584    /* issue protect OTP area command */
01585    ret = NAND_Set_Feature(ADDR_FEATURE_ARRAY_OPMODE, FEATURE_ARRAY_OTP_PROTECTION);
01586 
01587    /* return with error if a fail occurs */
01588    if(NAND_SUCCESS != ret)
01589       return ret;
01590 
01591    /* check if device is in normal status */
01592    ret = NAND_Get_Feature(ADDR_FEATURE_ARRAY_OPMODE, &subfeature);
01593 
01594    /* return with error if a fail occurs */
01595    if(NAND_SUCCESS != ret)
01596       return ret;
01597 
01598    if(FEATURE_ARRAY_OTP_PROTECTION != subfeature)
01599       return NAND_GENERIC_FAIL;
01600 
01601    /* issue the PROGRAM command to lock permanently the page */
01602 
01603    /* data buffer is filled with 0x00 */
01604    memset(write_buf, 0x00, device_info.data_bytes_per_page);
01605 
01606    /* x8 */
01607    if((device_info.feature & SUPPORTED_16_BIT_DATA_BUS_WIDTH) == 0)
01608       ret = NAND_OTP_Page_Program(addr, write_buf, device_info.data_bytes_per_page);
01609    /* x16 */
01610    else
01611       ret = NAND_OTP_Page_Program(addr, write_buf, (device_info.data_bytes_per_page>>2));
01612 
01613    if(NAND_SUCCESS != ret) {
01614       /* in case of program error, exit in OTP mode */
01615       NAND_OTP_Mode_Enter();
01616       return NAND_GENERIC_FAIL;
01617    }
01618 
01619    /* restore OTP mode before return */
01620    ret = NAND_OTP_Mode_Enter();
01621 
01622    if(NAND_SUCCESS != ret)
01623       return NAND_GENERIC_FAIL;
01624 
01625    return NAND_SUCCESS;
01626 }
01627 
01657 MT_uint8 NAND_OTP_Page_Program(nand_addr_t addr, flash_width *buffer, MT_uint32 lenght) {
01658    MT_uint8 address[5];
01659    MT_uint8 status_reg;
01660    MT_uint32 k;
01661    int i;
01662 
01663    /* verify if driver is initialized */
01664    if(DRIVER_STATUS_INITIALIZED != driver_status)
01665       return DRIVER_STATUS_NOT_INITIALIZED;
01666 
01667    /* x16 */
01668    if((device_info.feature & SUPPORTED_16_BIT_DATA_BUS_WIDTH) != 0) {
01669       if(lenght > (device_info.data_bytes_per_page >> 1) )
01670          return NAND_INVALID_LENGHT;
01671    }
01672 
01673    /* x8 */
01674    if(lenght > device_info.data_bytes_per_page)
01675       return NAND_INVALID_LENGHT;
01676 
01677    __build_cycle_addr(addr, address);
01678 
01679    /* init board transfer */
01680    PLATFORM_Open();
01681 
01682    /* send command */
01683    PLATFORM_SendCmd(CMD_PAGE_PROGRAM);
01684 
01685    /* send address */
01686    for(i=0; i<NUM_OF_ADDR_CYCLE; i++)
01687       PLATFORM_SendAddr(address[i]);
01688 
01689    /* send data */
01690    for(k=0; k<lenght; k++)
01691       PLATFORM_SendData(buffer[k]);
01692 
01693    /* send command */
01694    PLATFORM_SendCmd(CMD_PAGE_PROGRAM_CONFIRM);
01695 
01696    status_reg = NAND_Read_Status();
01697 
01698    /* close board transfer */
01699    PLATFORM_Close();
01700 
01701    return NAND_SUCCESS;
01702 }
01703 
01732 MT_uint8 NAND_OTP_Spare_Program(nand_addr_t addr, flash_width *buffer, MT_uint32 lenght) {
01733    MT_uint8 address[5];
01734    MT_uint8 status_reg;
01735    MT_uint32 k;
01736    int i;
01737 
01738    /* verify if driver is initialized */
01739    if(DRIVER_STATUS_INITIALIZED != driver_status)
01740       return DRIVER_STATUS_NOT_INITIALIZED;
01741 
01742    /* x16 */
01743    if((device_info.feature & SUPPORTED_16_BIT_DATA_BUS_WIDTH) != 0) {
01744       if(lenght > (device_info.spare_bytes_per_page >> 1) )
01745          return NAND_INVALID_LENGHT;
01746    }
01747 
01748    /* x8 */
01749    if(lenght > device_info.spare_bytes_per_page)
01750       return NAND_INVALID_LENGHT;
01751 
01752    /* spare area starts after last main area byte */
01753    if((device_info.feature & SUPPORTED_16_BIT_DATA_BUS_WIDTH) == 0)
01754       /* x8 bus width */
01755       addr.column=device_info.data_bytes_per_page;
01756    else
01757       /* x16 bus width */
01758       addr.column=device_info.data_bytes_per_page >> 1;
01759 
01760    __build_cycle_addr(addr, address);
01761 
01762    /* init board transfer */
01763    PLATFORM_Open();
01764 
01765    /* send command */
01766    PLATFORM_SendCmd(CMD_PAGE_PROGRAM);
01767 
01768    /* send address */
01769    for(i=0; i<NUM_OF_ADDR_CYCLE; i++)
01770       PLATFORM_SendAddr(address[i]);
01771 
01772    /* send data */
01773    for(k=0; k<lenght; k++)
01774       PLATFORM_SendData(buffer[k]);
01775 
01776    /* send command */
01777    PLATFORM_SendCmd(CMD_PAGE_PROGRAM_CONFIRM);
01778 
01779    status_reg = NAND_Read_Status();
01780 
01781    /* close board transfer */
01782    PLATFORM_Close();
01783 
01784    /* check if program is good */
01785    if(status_reg & STATUS_FAIL)
01786       return NAND_PROGRAM_FAILED;
01787 
01788    return NAND_SUCCESS;
01789 }
01790 
01818 MT_uint8 NAND_OTP_Page_Read(nand_addr_t addr, flash_width *buffer, MT_uint32 lenght) {
01819    MT_uint8 row_address[5];
01820    MT_uint8 status_reg;
01821    MT_uint8 ret;
01822    int i;
01823 
01824    /* verify if driver is initialized */
01825    if(DRIVER_STATUS_INITIALIZED != driver_status)
01826       return DRIVER_STATUS_NOT_INITIALIZED;
01827 
01828    /* x16 */
01829    if((device_info.feature & SUPPORTED_16_BIT_DATA_BUS_WIDTH) != 0) {
01830       if(lenght > (device_info.data_bytes_per_page >> 1) )
01831          return NAND_INVALID_LENGHT;
01832    }
01833 
01834    /* x8 */
01835    if(lenght > device_info.data_bytes_per_page)
01836       return NAND_INVALID_LENGHT;
01837 
01838    __build_cycle_addr(addr, row_address);
01839 
01840    /* init board transfer */
01841    PLATFORM_Open();
01842 
01843    /* send command  */
01844    PLATFORM_SendCmd(CMD_READ_MODE);
01845 
01846    /* send address */
01847    for(i=0; i<NUM_OF_ADDR_CYCLE; i++)
01848       PLATFORM_SendAddr(row_address[i]);
01849 
01850    /* return to read mode */
01851    PLATFORM_SendCmd(CMD_READ_CONFIRM);
01852 
01853    /* wait */
01854    ret = __wait_for_ready();
01855 
01856     /* return if timeout */
01857     if (NAND_SUCCESS != ret)
01858       return ret;
01859 
01860    /* read data */
01861    for(i=0; i<lenght; i++)
01862       buffer[i] = PLATFORM_ReadData();
01863 
01864    /* read status register on exit */
01865    status_reg = NAND_Read_Status();
01866 
01867    /* close board transfer */
01868    PLATFORM_Close();
01869 
01870    if(status_reg & STATUS_FAIL)
01871       return NAND_READ_FAILED;
01872 
01873    return ret;
01874 }
01875 
01904 MT_uint8 NAND_OTP_Spare_Read(nand_addr_t addr, flash_width *buffer, MT_uint32 lenght) {
01905    MT_uint8 row_address[5];
01906    MT_uint8 status_reg;
01907    MT_uint8 ret;
01908    MT_uint32 k;
01909    int i;
01910 
01911    /* verify if driver is initialized */
01912    if(DRIVER_STATUS_INITIALIZED != driver_status)
01913       return DRIVER_STATUS_NOT_INITIALIZED;
01914 
01915    if((device_info.feature & SUPPORTED_16_BIT_DATA_BUS_WIDTH) != 0) {
01916       /* x16 */
01917       if(lenght > (device_info.spare_bytes_per_page >> 1) )
01918          return NAND_INVALID_LENGHT;
01919    }
01920 
01921    /* x8 */
01922    if(lenght > device_info.spare_bytes_per_page)
01923       return NAND_INVALID_LENGHT;
01924 
01925    /* spare area starts after last main area byte */
01926    if((device_info.feature & SUPPORTED_16_BIT_DATA_BUS_WIDTH) == 0)
01927       /* x8 bus width */
01928       addr.column=device_info.data_bytes_per_page;
01929    else
01930       /* x16 bus width */
01931       addr.column=device_info.data_bytes_per_page >> 1;
01932 
01933    __build_cycle_addr(addr, row_address);
01934 
01935    /* init board transfer */
01936    PLATFORM_Open();
01937 
01938    /* send command */
01939    PLATFORM_SendCmd(CMD_READ_MODE);
01940 
01941    /* send address */
01942    for(i=0; i<NUM_OF_ADDR_CYCLE; i++)
01943       PLATFORM_SendAddr(row_address[i]);
01944 
01945    /* return to read mode */
01946    PLATFORM_SendCmd(CMD_READ_CONFIRM);
01947 
01948    /* wait */
01949    ret = __wait_for_ready();
01950 
01951     /* return if timeout */
01952     if (NAND_SUCCESS != ret)
01953       return ret;
01954 
01955    /* read data */
01956    for(k=0; k<lenght; k++)
01957       buffer[k] = PLATFORM_ReadData();
01958 
01959    /* read status register on exit */
01960    status_reg = NAND_Read_Status();
01961 
01962    /* close board transfer */
01963    PLATFORM_Close();
01964 
01965    if(status_reg & STATUS_FAIL)
01966       return NAND_READ_FAILED;
01967 
01968    return ret;
01969 }
01970 
01971 /******************************************************************************
01972  *                   Internal functions, not API
01973  *****************************************************************************/
01974 
01975 /*
01976  * This function is used internally from the driver in order to know when
01977  * an operation (program or erase) is completed.
01978  */
01979 
01980 #define BIT_USED_TO_POLL STATUS_RDY
01981 
01982 #ifdef TIMEOUT_SUPPORT
01983    #define NUM_OF_TICKS_TO_TIMEOUT (TIME_OUT_SECOND * CLOCKS_PER_SEC)
01984 #endif
01985 
01986 MT_uint8 __wait_for_ready() {
01987    MT_uint8 ret;
01988 
01989    #ifdef TIMEOUT_SUPPORT
01990       MT_uint32 clock_start = (MT_uint32) clock();
01991    #endif
01992 
01993    PLATFORM_SendCmd(CMD_READ_STATUS);
01994 
01995    #ifndef TIMEOUT_SUPPORT
01996 
01997       while (BIT_USED_TO_POLL != (BIT_USED_TO_POLL & PLATFORM_ReadData()))
01998          { /* do nothing */   }
01999 
02000       PLATFORM_SendCmd(CMD_READ_MODE);
02001       return SUCCESS;
02002 
02003    #else
02004 
02005       while ( (BIT_USED_TO_POLL != (BIT_USED_TO_POLL & PLATFORM_ReadData())) \
02006             && ((MT_uint32) clock() < (MT_uint32) (clock_start + NUM_OF_TICKS_TO_TIMEOUT)) )
02007          {  /* do nothing */ }
02008 
02009       /* check exit condition */
02010       if(clock() >= clock_start + NUM_OF_TICKS_TO_TIMEOUT)
02011          ret = NAND_TIMEOUT;
02012       else
02013          ret = NAND_SUCCESS;
02014 
02015       PLATFORM_SendCmd(CMD_READ_MODE);
02016       return ret;
02017 
02018    #endif
02019 
02020 }
02021 
02022 /*
02023  * Verify that an address is valid with the current
02024  * device size
02025  */
02026 MT_uint8 __is_valid_addr(nand_addr_t addr) {
02027    if((addr.column < device_info.data_bytes_per_page) &&
02028          (addr.page < device_info.pages_per_block) &&
02029          (addr.block < device_info.blocks_per_lun) &&
02030          (addr.lun < device_info.luns_per_ce))
02031       return NAND_SUCCESS;
02032    return NAND_INVALID_NAND_ADDRESS;
02033 }
02034 
02035 /*
02036  * Compare two address
02037  */
02038 MT_uint8 __compare_addr(nand_addr_t first_addr, nand_addr_t second_addr) {
02039 
02040    /* first_addr = second_addr */
02041    if((first_addr.lun == second_addr.lun) && \
02042       (first_addr.block == second_addr.block) && \
02043       (first_addr.page == second_addr.page) && \
02044       (first_addr.column == first_addr.column))
02045          return ADDR_A_EQ_B;
02046 
02047    /* first_addr > second_addr */
02048    if((first_addr.lun > second_addr.lun) && \
02049       (first_addr.block > second_addr.block) && \
02050       (first_addr.page > second_addr.page) && \
02051       (first_addr.column > first_addr.column))
02052          return ADDR_A_GT_B;
02053 
02054    /* first_addr < second_addr */
02055    return ADDR_A_LT_B;
02056 }
02057 
02058 /*
02059  * __as_uint16
02060  */
02061 MT_uint16 __as_uint16(MT_uint8 byte1, MT_uint8 byte0) {
02062    #ifdef LITTLE_ENDIAN
02063       return ((MT_uint16) ((byte0 << 8) | byte1));
02064    #endif
02065    #ifdef BIG_ENDIAN
02066       return ((MT_uint16) ((byte1 << 8) | byte0));
02067    #endif
02068 }
02069 
02070 /*
02071  * __as_uint32
02072  */
02073 MT_uint32 __as_uint32(MT_uint8 byte3, MT_uint8 byte2, MT_uint8 byte1, MT_uint8 byte0) {
02074    #ifdef LITTLE_ENDIAN
02075       return ((MT_uint32) ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3));
02076    #endif
02077    #ifdef BIG_ENDIAN
02078       return ((MT_uint32) ((byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0));
02079    #endif
02080 }
02081 /*
02082  * __as_string
02083  */
02084 void __as_string(MT_uint8 *src_ptr, char *dest_ptr, int start, int stop) {
02085    #ifdef LITTLE_ENDIAN
02086       strncpy((char *)dest_ptr, (const char *)src_ptr+start, stop-start+1);
02087       dest_ptr[stop-start+1] = '\0';
02088    #endif
02089    #ifdef BIG_ENDIAN
02090       strncpy((char *)dest_ptr, (const char *)src_ptr+start, stop-start+1);
02091       dest_ptr[stop-start+1] = '\0';
02092    #endif
02093 }
02094 
02095 /*
02096  * __build_cycle_addr
02097  */
02098 void __build_cycle_addr(nand_addr_t addr, MT_uint8 *addr_cycle_stream) {
02099    #define LOW          0
02100    #define HIGH         1
02101 
02102    /* extract n-th bit from a value */
02103    #define CHECK_BIT(val, n) ((val & (1 << n)) >> n)
02104 
02105    /* extract from column address */
02106    #define COL(n)          CHECK_BIT(addr.column, n)
02107 
02108    /* extract from page address */
02109    #define PAGE(n)      CHECK_BIT(addr.page, n)
02110 
02111    /* extract from block address */
02112    #define BLOCK(n)     CHECK_BIT(addr.block, n)
02113 
02114    /* extract from lun number */
02115    #define LUN(n)          CHECK_BIT(addr.lun, n)
02116 
02117    /* build a single row of address cycle */
02118    #define BUILD_ADDR_ROW(i_07, i_06, i_05, i_04, i_03, i_02, i_01, i_00) (\
02119        ((i_07) << 7) \
02120       | ((i_06) << 6) \
02121       | ((i_05) << 5) \
02122       | ((i_04) << 4) \
02123       | ((i_03) << 3) \
02124       | ((i_02) << 2) \
02125       | ((i_01) << 1) \
02126       | ((i_00) << 0) \
02127    );
02128 
02129    int cycle;
02130 
02131    /* build the address cycle stream (64 pages per block) */
02132    if (64 == device_info.pages_per_block) {
02133 
02134       /* Col 1 - I cycle */
02135       addr_cycle_stream[0] =
02136             (MT_uint8) BUILD_ADDR_ROW(COL(7), COL(6), COL(5), COL(4), COL(3), COL(2), COL(1), COL(0));
02137 
02138       /* Col 2 - II cycle */
02139       addr_cycle_stream[1] =
02140             (MT_uint8) BUILD_ADDR_ROW(LOW, LOW, COL(13), COL(12), COL(11), COL(10),COL(9),COL(8));
02141 
02142       /* Row 1 - III cycle */
02143       addr_cycle_stream[2] =
02144             (MT_uint8) BUILD_ADDR_ROW(BLOCK(1), BLOCK(0), PAGE(5), PAGE(4), PAGE(3), PAGE(2), PAGE(1), PAGE(0));
02145 
02146       /* Row 2 - IV cycle */
02147       addr_cycle_stream[3] =
02148             (MT_uint8) BUILD_ADDR_ROW(BLOCK(9), BLOCK(8), BLOCK(7), BLOCK(6), BLOCK(5), BLOCK(4), BLOCK(3), BLOCK(2));
02149 
02150       /* Row 3 - V cycle */
02151       addr_cycle_stream[4] =
02152             (MT_uint8) BUILD_ADDR_ROW(LOW, LOW, LOW, LOW, LUN(0), BLOCK(12), BLOCK(11), BLOCK(10));
02153 
02154    }
02155 
02156    /* build the address cycle stream (128 pages per block) */
02157    if (128 == device_info.pages_per_block) {
02158 
02159       /* Col 1 - I cycle */
02160       addr_cycle_stream[0] =
02161             (MT_uint8) BUILD_ADDR_ROW(COL(7), COL(6), COL(5), COL(4), COL(3), COL(2), COL(1), COL(0));
02162 
02163       /* Col 2 - II cycle */
02164       addr_cycle_stream[1] =
02165             (MT_uint8) BUILD_ADDR_ROW(LOW, LOW, COL(13), COL(12), COL(11), COL(10),COL(9),COL(8));
02166 
02167       /* Row 1 - III cycle */
02168       addr_cycle_stream[2] =
02169             (MT_uint8) BUILD_ADDR_ROW(BLOCK(0), PAGE(6), PAGE(5), PAGE(4), PAGE(3), PAGE(2), PAGE(1), PAGE(0));
02170 
02171       /* Row 2 - IV cycle */
02172       addr_cycle_stream[3] =
02173             (MT_uint8) BUILD_ADDR_ROW(BLOCK(8), BLOCK(7), BLOCK(6), BLOCK(5), BLOCK(4), BLOCK(3), BLOCK(2), BLOCK(1));
02174 
02175       /* Row 3 - V cycle */
02176       addr_cycle_stream[4] =
02177             (MT_uint8) BUILD_ADDR_ROW(LOW, LOW, LOW, LOW, LUN(0), BLOCK(11), BLOCK(10), BLOCK(9));
02178 
02179    }
02180 
02181    #ifdef DEBUG_PRINT_ADDRESS
02182    printf("DEBUG: addr: LUN=%x, BLOCK=%x, PAGE=%x, COL=%x\n", \
02183          addr.lun, addr.block, addr.page, addr.column);
02184    printf("DEBUG: addr_cycl = I=%x II=%x III=%x IV=%x V=%x\n", \
02185          addr_cycle_stream[0], addr_cycle_stream[1], addr_cycle_stream[2], addr_cycle_stream[3], addr_cycle_stream[4]);
02186    #endif
02187 }