/** * \brief Configure SMC timing for static memory (LCD) */ static void _ILI9488_ConfigureSmc( void ) { /* Enable peripheral clock */ PMC_EnablePeripheral( ID_SMC ) ; /* Configure SMC, NCS3 is assigned to LCD */ SMC->SMC_CS_NUMBER[SMC_EBI_LCD_CS].SMC_SETUP = SMC_SETUP_NWE_SETUP(2) | SMC_SETUP_NCS_WR_SETUP(0) | SMC_SETUP_NRD_SETUP(0) | SMC_SETUP_NCS_RD_SETUP(0); SMC->SMC_CS_NUMBER[SMC_EBI_LCD_CS].SMC_PULSE = SMC_PULSE_NWE_PULSE(6) | SMC_PULSE_NCS_WR_PULSE(0xA) | SMC_PULSE_NRD_PULSE(0xA) | SMC_PULSE_NCS_RD_PULSE(0xA); SMC->SMC_CS_NUMBER[SMC_EBI_LCD_CS].SMC_CYCLE = SMC_CYCLE_NWE_CYCLE(0xA) | SMC_CYCLE_NRD_CYCLE(0xA); SMC->SMC_CS_NUMBER[SMC_EBI_LCD_CS].SMC_MODE = SMC_MODE_READ_MODE | SMC_MODE_WRITE_MODE | SMC_MODE_DBW_16_BIT | SMC_MODE_EXNW_MODE_DISABLED | SMC_MODE_TDF_CYCLES(0xF); }
/** * \brief Configures the EBI for %NorFlash access. */ extern void BOARD_ConfigureNorFlash( Smc* pSmc ) { /* Enable peripheral clock */ PMC_EnablePeripheral( ID_SMC ) ; /* Configure SMC, NCS0 is assigned to a norflash */ pSmc->SMC_CS_NUMBER[0].SMC_SETUP = SMC_SETUP_NWE_SETUP(2) | SMC_SETUP_NCS_WR_SETUP(0) | SMC_SETUP_NRD_SETUP(0) | SMC_SETUP_NCS_RD_SETUP(0); pSmc->SMC_CS_NUMBER[0].SMC_PULSE = SMC_PULSE_NWE_PULSE(6) | SMC_PULSE_NCS_WR_PULSE(0xA) | SMC_PULSE_NRD_PULSE(0xA) | SMC_PULSE_NCS_RD_PULSE(0xA); pSmc->SMC_CS_NUMBER[0].SMC_CYCLE = SMC_CYCLE_NWE_CYCLE(0xA) | SMC_CYCLE_NRD_CYCLE(0xA); pSmc->SMC_CS_NUMBER[0].SMC_MODE = SMC_MODE_READ_MODE | SMC_MODE_WRITE_MODE | SMC_MODE_EXNW_MODE_DISABLED | SMC_MODE_TDF_CYCLES(0x1); }
/** * \brief Configures the EBI for %NorFlash access. */ void BOARD_ConfigureNorFlash( void ) { /* Configure SMC, NCS3 is assigned to a norflash */ SMC->SMC_CS_NUMBER[3].SMC_SETUP = 0x00000002; SMC->SMC_CS_NUMBER[3].SMC_PULSE = 0x0A0A0A06; SMC->SMC_CS_NUMBER[3].SMC_CYCLE = 0x000A000A; SMC->SMC_CS_NUMBER[3].SMC_MODE = SMC_MODE_WRITE_MODE | SMC_MODE_DBW(0) | SMC_MODE_EXNW_MODE(0) | SMC_MODE_TDF_CYCLES(1); }
void at91_smc_setup(int id, int cs, const struct at91_smc_init *smc) { // Need a generic way to get this address for all SoCs... Assume 9260 for now... uint32_t base = AT91SAM9260_SMC_BASE + SMC_CS_OFF(cs); WR4HW(base, SMC_SETUP, SMC_SETUP_NCS_RD_SETUP(smc->ncs_rd_setup) | SMC_SETUP_NRD_SETUP(smc->nrd_setup) | SMC_SETUP_NCS_WR_SETUP(smc->ncs_wr_setup) | SMC_SETUP_NWE_SETUP(smc->nwe_setup)); WR4HW(base, SMC_PULSE, SMC_PULSE_NCS_RD_PULSE(smc->ncs_rd_pulse) | SMC_PULSE_NRD_PULSE(smc->nrd_pulse) | SMC_PULSE_NCS_WR_PULSE(smc->ncs_wr_pulse) | SMC_PULSE_NWE_PULSE(smc->nwe_pulse)); WR4HW(base, SMC_CYCLE, SMC_CYCLE_NRD_CYCLE(smc->nrd_cycle) | SMC_CYCLE_NWE_CYCLE(smc->nwe_cycle)); WR4HW(base, SMC_MODE, smc->mode | SMC_MODE_TDF_CYCLES(smc->tdf_cycles)); }
/** * \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; unsigned int bufferSize, bufferAddr, memoryOffset, bytesToWrite; unsigned int bytesRead = 0; unsigned int nbBadBlocks = 0; unsigned int nbBlocks = 0; /* Temporary buffer used for non block aligned read / write */ unsigned int tempBufferAddr; unsigned short block, page, offset, i; /* Index in source buffer during buffer copy */ unsigned int offsetInSourceBuff; /* Index in destination buffer during buffer copy */ unsigned int offsetInTargetBuff; /* Errors returned by SkipNandFlash functions */ unsigned char error = 0; /* Communication type with SAM-BA GUI. */ unsigned char comType; /* current pmecc parameter header value */ unsigned int currentPmeccHeaderValue; /* Index and value of pmecc command */ unsigned int nIndex, nValue; /* Number of ECC bits required */ unsigned char eccBitReq2TT [5] = {2, 4, 8, 12, 24}; /* Ecc mode to be swtich */ unsigned int eccMode; unsigned int trimPage; /* Save communication link type */ comType = pMailbox->argument.inputInit.comType; /* ---------------------------------------------------------- */ /* INIT: */ /* ---------------------------------------------------------- */ if (pMailbox->command == APPLET_CMD_INIT) { #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) */ BOARD_ConfigureNandFlash(nfBusWidth); PIO_Configure(pPinsNf, PIO_LISTSIZE(pPinsNf)); /* Tries to detect NAND Flash device connected to EBI CS3, with data lines connected to D0-D7, then on NAND Flash connected to D16-D23. */ if (!NandEbiDetect()) { pMailbox->status = APPLET_DEV_UNKNOWN; TRACE_INFO("\tDevice Unknown\n\r"); goto exit; } memset(&skipBlockNf, 0, sizeof(skipBlockNf)); NandGetOnfiPageParam (&OnfiPageParameter); 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) { SMC->SMC_CS_NUMBER[3].SMC_MODE = SMC_MODE_READ_MODE | SMC_MODE_WRITE_MODE | SMC_MODE_DBW(nfBusWidth/16) | SMC_MODE_TDF_CYCLES(1); } TRACE_INFO("\tNandflash driver initialized\n\r"); pMailbox->argument.outputInit.bufferAddress = (unsigned int) &_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", pageSize, blockSize, 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)); NandSwitchEcc(ECC_PMECC); pMailbox->status = APPLET_SUCCESS; }
/** \brief Configures the EBI for NandFlash access at 133Mhz. */ void BOARD_ConfigureNandFlash( uint8_t busWidth ) { #ifdef BOARD_REV_A_EK *ADDR_CCFG_EBICSA &= ~(3u << 24); *ADDR_CCFG_EBICSA |= (1 << 3); /* EBI Chip Select 3 is assigned to the Static Memory Controller and the NAND Flash Logic is activated */ #endif #ifdef BOARD_REV_A_VB *ADDR_CCFG_EBICSA |= (1 << 3) /* EBI Chip Select 3 is assigned to the Static Memory Controller and the NAND Flash Logic is activated */ | (1 << 24); /* NAND Flash I/O are connected to D16-D31 in case VDDIOM do not equals VDDNF */ // | (1 << 25); /* DDR Multi-port is enabled, performances are increased when using DDR2 (or LP-DDR) and 8-bit NAND Flash */ #endif #ifdef BOARD_REV_B_EK *ADDR_CCFG_EBICSA |= (1 << 3) /* EBI Chip Select 3 is assigned to the Static Memory Controller and the NAND Flash Logic is activated */ | (1 << 24); /* NAND Flash I/O are connected to D16-D31 in case VDDIOM do not equals VDDNF */ // | (1 << 25); /* DDR Multi-port is enabled, performances are increased when using DDR2 (or LP-DDR) and 8-bit NAND Flash */ #endif SMC->SMC_CS_NUMBER[3].SMC_SETUP = 0 | SMC_SETUP_NWE_SETUP(1) | SMC_SETUP_NCS_WR_SETUP(0) | SMC_SETUP_NRD_SETUP(2) | SMC_SETUP_NCS_RD_SETUP(0); SMC->SMC_CS_NUMBER[3].SMC_PULSE = 0 | SMC_PULSE_NWE_PULSE(3) | SMC_PULSE_NCS_WR_PULSE(5) | SMC_PULSE_NRD_PULSE(4) | SMC_PULSE_NCS_RD_PULSE(6); SMC->SMC_CS_NUMBER[3].SMC_CYCLE = 0 | SMC_CYCLE_NWE_CYCLE(5) | SMC_CYCLE_NRD_CYCLE(7); SMC->SMC_CS_NUMBER[3].SMC_MODE = SMC_MODE_READ_MODE | SMC_MODE_WRITE_MODE | SMC_MODE_DBW(busWidth/16) | SMC_MODE_TDF_CYCLES(1); }