/**************************************************************************//** * @file NandLoader.c * @brief NandLoader source code. * * SPDX-License-Identifier: Apache-2.0 * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. *****************************************************************************/ #include <string.h> #include "wblib.h" #include "turbowriter.h" #include "N9H20_VPOST.h" // define DATE CODE and show it when running to make maintaining easy. #define DATE_CODE "20201214" /* global variable */ typedef struct nand_info { unsigned int startBlock; unsigned int endBlock; unsigned int fileLen; unsigned int executeAddr; } NVT_NAND_INFO_T; extern void spuDacOn(UINT8 level); #ifdef __USER_DEFINE_FUNC extern VOID user_define_func(void); #endif INT MoveData(NVT_NAND_INFO_T *image, BOOL IsExecute) { unsigned int page_count, block_count, curBlock, addr; int volatile i, j; void (*fw_func)(void); sysprintf("Load file length 0x%x, execute address 0x%x\n", image->fileLen, image->executeAddr); page_count = image->fileLen / pSM0->nPageSize; if ((image->fileLen % pSM0->nPageSize) != 0) page_count++; block_count = page_count / pSM0->uPagePerBlock; curBlock = image->startBlock; addr = image->executeAddr; j=0; while(1) { if (j >= block_count) break; if (CheckBadBlockMark(curBlock) == Successful) { for (i=0; i<pSM0->uPagePerBlock; i++) { sicSMpread(0, curBlock, i, (UINT8 *)addr); addr += pSM0->nPageSize; } j++; } curBlock++; } if ((page_count % pSM0->uPagePerBlock) != 0) { page_count = page_count - block_count * pSM0->uPagePerBlock; _read_: if (CheckBadBlockMark(curBlock) == Successful) { for (i=0; i<page_count; i++) { sicSMpread(0, curBlock, i, (UINT8 *)addr); addr += pSM0->nPageSize; } } else { curBlock++; goto _read_; } } if (IsExecute == TRUE) { /* disable NAND control pin used */ outpw(REG_GPDFUN, inpw(REG_GPDFUN) & ~0x0003FC00); // disable NAND NWR/NRD/RB0/RB1 pins outpw(REG_GPEFUN, inpw(REG_GPEFUN) & ~0x00FF0000); // disable NAND ALE/CLE/CS0/CS1 pins // disable SD Card Host Controller operation and driving clock. outpw(REG_GPEFUN, inpw(REG_GPEFUN)&(~0x0000FFF0)); // disable SD0_CLK/CMD/DAT0_3 pins selected fw_func = (void(*)(void))(image->executeAddr); fw_func(); } return 0; } #if defined (__GNUC__) UINT8 image_buffer[4096] __attribute__((aligned (32))); #else __align(32) UINT8 image_buffer[4096]; #endif unsigned char *imagebuf; unsigned int *pImageList; UINT32 g_u32ExtClk; #ifdef _DEBUG_AIC_ UINT32 u3210ms=0; void timer0_callback(void) { u3210ms = u3210ms +1; sysprintf("u3210ms = %d\n", u3210ms); } void initTimer(void) { UINT32 u32ExtFreq; u32ExtFreq = sysGetExternalClock(); /* KHz unit */ sysSetTimerReferenceClock (TIMER0, u32ExtFreq*1000); /* Hz unit */ sysStartTimer(TIMER0, 100, PERIODIC_MODE); /* 100 tick/1s ==> 1 tick = 10ms*/ sysSetTimerEvent(TIMER0, 1, (PVOID)timer0_callback); /* Each 10 ticks = 100ms call back */ } #endif #define E_CLKSKEW 0x00888800 #ifdef N9H20K5 #define __DDR2__ // N9H20K5 use DDR2 #else #define __DDR_6__ #endif void initClock(void) { UINT32 u32ExtFreq; u32ExtFreq = sysGetExternalClock(); /* KHz unit */ outp32(REG_DQSODS, 0x1010); outp32(REG_CKDQSDS, E_CLKSKEW); if(u32ExtFreq==12000) { outp32(REG_SDREF, 0x805A); } else { outp32(REG_SDREF, 0x80C0); } #ifdef __UPLL_192__ if((inp32(REG_CHIPCFG) & SDRAMSEL) == 0x20) // Power On Setting SDRAM type is DDR2 { outp32(REG_SDMR, 0x432); outp32(REG_DQSODS, 0x00001010); outp32(REG_MISCPCR,0x00000001); // Driving strength outp32(REG_SDTIME, 0x21667525); } else if((inp32(REG_CHIPCFG) & SDRAMSEL) == 0x30) // Power On Setting SDRAM type is DDR { #ifdef __DDR_75__ outp32(REG_SDTIME, 0x098E7549); // DDR Speed grade-75 #endif #ifdef __DDR_6__ outp32(REG_SDTIME, 0x094E7425); // DDR Speed grade-6 #endif #ifdef __DDR_5__ outp32(REG_SDTIME, 0x094E6425); // DDR Speed grade-5 #endif outp32(REG_SDMR, 0x22); // Cas Latency = 2 } sysSetSystemClock(eSYS_UPLL, //E_SYS_SRC_CLK eSrcClk, 192000, //UINT32 u32PllKHz, 192000, //UINT32 u32SysKHz, 192000, //UINT32 u32CpuKHz, 192000/2, //UINT32 u32HclkKHz, 192000/4); //UINT32 u32ApbKHz #endif #ifdef __UPLL_96__ #ifdef __DDR_75__ outp32(REG_SDTIME, 0x098E7549); // DDR Speed grade-75 #endif #ifdef __DDR_6__ outp32(REG_SDTIME, 0x094E7425); // DDR Speed grade-6 #endif #ifdef __DDR_5__ outp32(REG_SDTIME, 0x094E6425); // DDR Speed grade-5 #endif #ifdef __DDR2__ outp32(REG_SDMR, 0x32); //Cas Latency = 3 outp32(REG_DQSODS, 0x00001212); outp32(REG_MISCPCR,0x00000001); //Driving strength outp32(REG_SDTIME, 0x2BDE9649); #else outp32(REG_SDMR, 0x22); //Cas Latency = 2 #endif sysSetSystemClock(eSYS_UPLL, //E_SYS_SRC_CLK eSrcClk, 96000, //UINT32 u32PllKHz, 96000, //UINT32 u32SysKHz, 96000, //UINT32 u32CpuKHz, 96000/2, //UINT32 u32HclkKHz, 96000/4); //UINT32 u32ApbKHz #endif #ifdef __UPLL_120__ #ifdef __DDR_75__ outp32(REG_SDTIME, 0x0A129649); // DDR Speed grade-75 #endif #ifdef __DDR_6__ outp32(REG_SDTIME, 0x0A149529); // DDR Speed grade-6 #endif #ifdef __DDR_5__ outp32(REG_SDTIME, 0x09928525); // DDR Speed grade-5 #endif outp32(REG_SDMR, 0x32); //Cas Latency = 3 sysSetSystemClock(eSYS_UPLL, //E_SYS_SRC_CLK eSrcClk, 120000, //UINT32 u32PllKHz, 120000, //UINT32 u32SysKHz, 120000, //UINT32 u32CpuKHz, 120000/2, //UINT32 u32HclkKHz, 120000/4); //UINT32 u32ApbKHz #endif } int main() { NVT_NAND_INFO_T image; int count, i; WB_UART_T uart; E_SYS_SRC_CLK eSrcClk; UINT32 u32PllKHz, u32SysKHz, u32CpuKHz, u32HclkKHz, u32ApbKHz; /* Clear Boot Code Header in SRAM to avoid booting fail issue */ outp32(0xFF000000, 0); spuDacOn(2); /* PLL clock setting */ initClock(); #ifdef _DEBUG_AIC_ initTimer(); #endif // sysSetLocalInterrupt(ENABLE_IRQ); #ifndef __DISABLE_RTC__ // RTC H/W Power Off Function Configuration */ outp32(AER,0x0000a965); while(1) { if((inp32(AER) & 0x10000) ==0x10000) break; } outp32(PWRON, 0x60005); /* Press Power Key during 6 sec to Power off (0x'6'0005) */ outp32(RIIR,0x4); #endif uart.uiFreq = sysGetExternalClock()*1000; /*Use external clock*/ uart.uiBaudrate = 115200; uart.uiDataBits = WB_DATA_BITS_8; uart.uiStopBits = WB_STOP_BITS_1; uart.uiParity = WB_PARITY_NONE; uart.uiRxTriggerLevel = LEVEL_1_BYTE; sysInitializeUART(&uart); sysprintf("N9H20 Nand Boot Loader entry (%s).\n", DATE_CODE); #ifdef __DISABLE_RTC__ sysprintf("Disable RTC feature.\n"); #endif sysGetSystemClock(&eSrcClk, &u32PllKHz, &u32SysKHz, &u32CpuKHz, &u32HclkKHz, &u32ApbKHz); sysprintf("System clock = %dKHz\nAHB clock = %dKHz\nREG_SDTIME = 0x%08X\n", u32SysKHz, u32HclkKHz, inp32(REG_SDTIME)); imagebuf = (UINT8 *)((UINT32)image_buffer | 0x80000000); pImageList=((unsigned int *)(((unsigned int)image_buffer)|0x80000000)); /* Initial DMAC and NAND interface */ fmiInitDevice(); sicSMInit(); memset((char *)&image, 0, sizeof(NVT_NAND_INFO_T)); /* read physical block 0 - image information */ #if 1 for (i=0; i<4; i++) { if (!sicSMpread(0, i, pSM0->uPagePerBlock-2, imagebuf)) { if (((*(pImageList+0)) == 0x574255aa) && ((*(pImageList+3)) == 0x57425963)) { sysprintf("Get NANDLoader image from block 0x%x ..\n", i); break; } } } #else sicSMpread(0, 0, pSM0->uPagePerBlock-2, imagebuf); #endif if (((*(pImageList+0)) == 0x574255aa) && ((*(pImageList+3)) == 0x57425963)) { count = *(pImageList+1); /* load logo first */ pImageList = pImageList+4; for (i=0; i<count; i++) { if (((*(pImageList) >> 16) & 0xffff) == 4) // logo { image.startBlock = *(pImageList + 1) & 0xffff; image.endBlock = (*(pImageList + 1) & 0xffff0000) >> 16; image.executeAddr = *(pImageList + 2); image.fileLen = *(pImageList + 3); MoveData(&image, FALSE); break; } /* pointer to next image */ pImageList = pImageList+12; } pImageList=((unsigned int*)(((unsigned int)image_buffer)|0x80000000)); memset((char *)&image, 0, sizeof(NVT_NAND_INFO_T)); #ifdef __USER_DEFINE_FUNC //--- call user define function before jump to next application. user_define_func(); #endif /* load execution file */ pImageList = pImageList+4; for (i=0; i<count; i++) { if (((*(pImageList) >> 16) & 0xffff) == 1) // execute { image.startBlock = *(pImageList + 1) & 0xffff; image.endBlock = (*(pImageList + 1) & 0xffff0000) >> 16; image.executeAddr = *(pImageList + 2); image.fileLen = *(pImageList + 3); MoveData(&image, TRUE); break; } /* pointer to next image */ pImageList = pImageList+12; } } return 0; }