bool onfi_embeddedecc(FAR const struct onfi_pgparam_s *onfi, uintptr_t cmdaddr, uintptr_t addraddr, uintptr_t dataaddr, bool enable) { /* Does the NAND supported the embedded ECC function? */ if (onfi_have_embeddedecc(onfi)) { /* Yes... enable or disable it */ /* Perform common setup */ WRITE_NAND_COMMAND(NAND_CMD_SET_FEATURE, cmdaddr); WRITE_NAND_ADDRESS(0x90, addraddr); if (enable) { /* Activate the internal ECC controller */ WRITE_NAND(0x08, dataaddr); WRITE_NAND(0x00, dataaddr); WRITE_NAND(0x00, dataaddr); WRITE_NAND(0x00, dataaddr); setSmcOpEccType(SMC_ECC_INTERNAL); } else { /* De-activate the internal ECC controller */ WRITE_NAND(0x00, dataaddr); WRITE_NAND(0x00, dataaddr); WRITE_NAND(0x00, dataaddr); WRITE_NAND(0x00, dataaddr); } return true; } return false; }
/** * \brief Applet main entry. This function decodes received command and executes it. * * \param argc always 1 * \param argv Address of the argument area.. */ int main(int argc, char **argv) { struct _Mailbox *pMailbox = (struct _Mailbox *) argv; uint32_t bufferSize, bufferAddr, memoryOffset, bytesToWrite; uint32_t bytesRead = 0; uint32_t nbBadBlocks = 0; uint32_t nbBlocks = 0; /* Temporary buffer used for non block aligned read / write */ uint32_t tempBufferAddr; uint16_t block, page, offset, i; /* Index in source buffer during buffer copy */ uint32_t offsetInSourceBuff; /* Index in destination buffer during buffer copy */ uint32_t offsetInTargetBuff; /* Errors returned by SkipNandFlash functions */ uint8_t error = 0; /* current pmecc parameter header value */ uint32_t currentPmeccHeaderValue; /* Index and value of pmecc command */ uint32_t nIndex, nValue; /* Number of ECC bits required */ uint8_t eccBitReq2TT [5] = {2, 4, 8, 12, 24}; /* Ecc mode to be swtich */ uint32_t eccMode; uint32_t trimPage; /* Disable watchdog */ WDT_Disable( WDT ) ; /* ---------------------------------------------------------- */ /* INIT: */ /* ---------------------------------------------------------- */ if (pMailbox->command == APPLET_CMD_INIT) { /* Save communication link type */ comType = pMailbox->argument.inputInit.comType; #if (DYN_TRACES == 1) dwTraceLevel = pMailbox->argument.inputInit.traceLevel; #endif TRACE_INFO("-- NandFlash SAM-BA applet %s --\n\r", SAM_BA_APPLETS_VERSION); TRACE_INFO("-- %s\n\r", BOARD_NAME); TRACE_INFO("-- Compiled: %s %s --\n\r", __DATE__, __TIME__); TRACE_INFO("INIT command\n\r"); /* Configure SMC for Nandflash accesses (done each time applet is launched because of old ROM codes) */ TRACE_INFO("BOARD_ConfigureNandFlash\n\r"); BOARD_ConfigureNandFlash(nfBusWidth); Smc_OpConfigure(0); /* Device model */ /* Tries to detect NAND Flash device connected to EBI CS3*/ if (!NandEbiDetect()) { pMailbox->status = APPLET_DEV_UNKNOWN; TRACE_INFO("\tDevice Unknown\n\r"); goto exit; } memset(&skipBlockNf, 0, sizeof(skipBlockNf)); NandGetOnfiPageParam (&OnfiPageParameter); NandDisableInternalEcc(); if (SkipBlockNandFlash_Initialize(&skipBlockNf, 0, cmdBytesAddr, addrBytesAddr, dataBytesAddr, nfCePin, nfRbPin)) { pMailbox->status = APPLET_DEV_UNKNOWN; pMailbox->argument.outputInit.bufferSize = 0; pMailbox->argument.outputInit.memorySize = 0; TRACE_INFO("\tDevice Unknown\n\r"); } else { /* Check the data bus width of the NandFlash */ nfBusWidth = NandFlashModel_GetDataBusWidth((struct NandFlashModel *)&skipBlockNf); /* Reconfigure bus width */ if ( nfBusWidth != 8) { BOARD_ConfigureNandFlash(nfBusWidth); } TRACE_INFO("\tNandflash driver initialized\n\r"); pMailbox->argument.outputInit.bufferAddress = (uint32_t) &_end; /* Get device parameters */ memSize = NandFlashModel_GetDeviceSizeInBytes(&skipBlockNf.ecc.raw.model); blockSize = NandFlashModel_GetBlockSizeInBytes(&skipBlockNf.ecc.raw.model); numBlocks = NandFlashModel_GetDeviceSizeInBlocks(&skipBlockNf.ecc.raw.model); pageSize = NandFlashModel_GetPageDataSize(&skipBlockNf.ecc.raw.model); spareSize = NandFlashModel_GetPageSpareSize(&skipBlockNf.ecc.raw.model); numPagesPerBlock = NandFlashModel_GetBlockSizeInPages(&skipBlockNf.ecc.raw.model); pMailbox->status = APPLET_SUCCESS; pMailbox->argument.outputInit.bufferSize = blockSize; pMailbox->argument.outputInit.memorySize = memSize; pMailbox->argument.outputInit.pmeccParamHeader = 0; TRACE_INFO("\tpageSize : 0x%x blockSize : 0x%x blockNb : 0x%x \n\r", (unsigned int)pageSize, (unsigned int)blockSize, (unsigned int)numBlocks); } /* By default, we use pmecc, except MICRON MLC nand with internal ECC controller */ eccOffset = 2; /* By defaut, 2 error bit correction, eccOffset = 2 */ PMECC_Initialize(&pmeccDesc, 0, eccCorrectability, pageSize, spareSize, eccOffset, 0); TRACE_INFO("\tNandflash PMECC initialized\n\r"); DMAD_Initialize( &dmad, POLLING_MODE ); if ( NandFlashConfigureDmaChannels( &dmad )) { pMailbox->status =APPLET_DEV_UNKNOWN; goto exit; } /* Initialize current pmecc parameter header, This 32-bit word is configured below */ currentPmeccHeader.usePmecc = 1; currentPmeccHeader.nbSectorPerPage = pmeccDesc.pageSize >> 8; currentPmeccHeader.spareSize = spareSize; currentPmeccHeader.eccBitReq = pmeccDesc.errBitNbrCapability; currentPmeccHeader.sectorSize = pmeccDesc.sectorSize; currentPmeccHeader.eccOffset = pmeccDesc.eccStartAddr; currentPmeccHeader.reserved = 0; currentPmeccHeader.key = 12; memcpy(&backupPmeccHeader, ¤tPmeccHeader, sizeof(nfParamHeader_t)); memcpy(¤tPmeccHeaderValue, ¤tPmeccHeader, sizeof(nfParamHeader_t)); pMailbox->argument.outputInit.pmeccParamHeader = currentPmeccHeaderValue; /* The Boot Program reads the first page without ECC check, to determine if the NAND parameter header is present. The header is made of 52 times the same 32-bit word (for redundancy reasons) which must contain NAND and PMECC parameters used to correctly perform the read of the rest of the data in the NAND. */ for (i = 0; i< 52; i++) memcpy(&bootNfParamHeader[i], ¤tPmeccHeader, sizeof(nfParamHeader_t)); setSmcOpEccType(SMC_ECC_PMECC); pMailbox->status = APPLET_SUCCESS; }