//============================================================================= // File Name : InitSystem.c // Function : Initialize DRAM, Clock and LCD setting value. // // //============================================================================= #include <windows.h> #include <pehdr.h> #include <romldr.h> #include "soc_cfg.h" #include "S5PC100_dramcon.h" #include "S5PC100_base_regs.h" #include "S5PC100_Syscon.h" #include "S5PC100_regs_for_BL.h" #ifdef SMDKC100_POP_NONE #define SMDKC100_POP POP_NONE #elif defined(SMDKC100_POP_A) #define SMDKC100_POP POP_A #elif defined(SMDKC100_POP_D) #define SMDKC100_POP POP_D #else #define SMDKC100_POP POP_NONE // Invalid POP type, set with POP_NONE. #endif #define LPCON_MAXPOWER 0 #define LPCON_MAXPERFORMANCE 1 #define LPCON_BALANCE 2 //------------------------------------------------------------------------------ // Define LPCON level // // LPCON_MAXPOWER Maximum power saving state // LPCON_MAXPERFORMANCE Maximum performance state // LPCON_BALANCE Balanced state #define LPCON_LEVEL LPCON_MAXPERFORMANCE // We only use max performance void InitClockCONforBL(void); void InitClockCONforOS(void); void InitLPCON(void); void InitClockCONforBL(void) { unsigned int ReadVal; // SetClockDiviReadValer //SetReg32(rCLK_DIV1, 0x00011110); SetReg32(rCLK_DIV1, ((HCLK12PCLK1_RATIO-1)<<BP_PCLKD1_RATIO) | ((MPLL2HCLK1_RATIO-1)<<BP_D1_BUS_RATIO) | (0<<BP_MPLL2_RATIO) | //< To make External Camera Clock 24Mhz, this must be 0 (0<<BP_MPLL_RATIO) | //< To increase FIMC,LCD clock to 264Mhz, this must be 0 (0<<BP_AM_RATIO) ); // bit[18:16] - PCLKD1 // bit[14:12] - HCLKD1 // bit[8] - MPLL2 // bit[5:4] - MPLL SetReg32(rCLK_DIV2, ((HCLK12PCLK1_RATIO-1)<<0)); // bit[3:0] - UART //SetReg32(rCLK_DIV0, 0x00011301) SetReg32(rCLK_DIV0, (1<<16)|((HCLK02PCLK0_RATIO_BL-1)<<12)|((ARM2HCLK0_RATIO_BL-1)<<8)|(0<<4)|((APLL2ARM_RATIO-1)<<0)); // bit[28:24] - CAM_DIV :0 // bit[21:20] - ONENAND :0 // bit[18:16] - SECSS // bit[14:12] - PCLKD0 // bit[10:8] - HCLKD0 // bit[6:4] - ARMCLK // bit[0] - APLL // SetLockTime & StartPLL SetReg32(rAPLL_LOCK, 0x00000e10); // Lock Time = 300us*12Mhz = 3600(=0xe10) //SetReg32(rAPLL_CON, 0x81BC0400); SetReg32(rAPLL_CON, (1u<<31)|(APLL_MDIV_BL<<16)|(APLL_PDIV_BL<<8)|(APLL_SDIV_BL<<0)); SetReg32(rMPLL_LOCK, 0x00000e10); // Lock Time = 300us*12Mhz = 3600(=0xe10) //SetReg32(rMPLL_CON, 0x80850302); SetReg32(rMPLL_CON, (1u<<31)|(MPLL_MDIV<<16)|(MPLL_PDIV<<8)|(MPLL_SDIV<<0)); SetReg32(rEPLL_LOCK, 0x00000e10); // Lock Time = 300us*12Mhz = 3600(=0xe10) SetReg32(rEPLL_CON, (1u<<31)|(EPLL_MDIV<<16)|(EPLL_PDIV<<8)|(EPLL_SDIV<<0)); GetReg32(rCLK_SRC0, ReadVal); //SetReg32(rCLK_SRC0, 0x00000011); SetReg32(rCLK_SRC0, (ReadVal&~(1<<20))|(0<<20)); // HPLL source clock = HREF_FIN27M SetReg32(rHPLL_LOCK, 0x00000e10); // Lock Time = 300us*12Mhz = 3600(=0xe10) SetReg32(rHPLL_CON, (1u<<31)|(HPLL_MDIV<<16)|(HPLL_PDIV<<8)|(HPLL_SDIV<<0)); // SetSourceClock GetReg32(rCLK_SRC0, ReadVal); SetReg32(rCLK_SRC0, (ReadVal&~(0x11111))|(0<<16)|(1<<12)|(1<<8)|(1<<4)|(1<<0)); // bit[16] - muxAM (0: MOUTMPLL, 1: DOUTAPLL2) // bit[12] - muxHPLL (0: CLK27M, 1: FOUTHPLL) // bit[8] - muxEPLL (0: FINEPLL, 1: FOUTEPLL) // bit[4] - muxMPLL (0: FINMPLL, 1: FOUTMPLL) // bit[0] - muxAPLL (0: FINAPLL, 1: FOUTAPLL) SetReg32(rCLK_SRC1, (1<<24)|(1<<0)); // bit[24] - muxCLK48M (0: XUSBXTI, 1: OTG_PHY) // bit[0] - muxUART (0: MOUTEPLL, 1: DOUTMPLL) // Internal clock can be monitored through XCLKOUT PAD. // * SMDKC100 Single(none POP): TP80 on CPU B'd(EVM) // * SMDKC100 POP A type : TP73 on CPU B'd(EVM) SetReg32(rCLK_OUT, (0<<20)|(6<<12)); // bit[23:20] - DiviReadValer value // bit[16:12] - Clock out type (6: PCLKD1) } void InitClockCONforOS(void) { unsigned int ReadVal; // SetClockDiviReadValer SetReg32(rCLK_DIV1, ((HCLK12PCLK1_RATIO-1)<<BP_PCLKD1_RATIO) | ((MPLL2HCLK1_RATIO-1)<<BP_D1_BUS_RATIO) | (0<<BP_MPLL2_RATIO) | //< To make External Camera Clock 24Mhz, this must be 0 (0<<BP_MPLL_RATIO) | //< To increase FIMC,LCD clock to 264Mhz, this must be 0 (0<<BP_AM_RATIO) ); // bit[18:16] - PCLKD1 // bit[14:12] - HCLKD1 // bit[8] - MPLL2 // bit[5:4] - MPLL SetReg32(rCLK_DIV2, ((HCLK12PCLK1_RATIO-1)<<0)); // bit[3:0] - UART // SetLockTime & StartPLL SetReg32(rAPLL_LOCK, 0x00000e10); // Lock Time = 300us*12Mhz = 3600(=0xe10) SetReg32(rAPLL_CON, (1u<<31)|(APLL_MDIV<<16)|(APLL_PDIV<<8)|(APLL_SDIV<<0)); SetReg32(rCLK_DIV0, (1<<16)|((HCLK02PCLK0_RATIO-1)<<12)|((ARM2HCLK0_RATIO-1)<<8)|(0<<4)|((APLL2ARM_RATIO-1)<<0)); // bit[28:24] - CAM_DIV :0 // bit[21:20] - ONENAND :0 // bit[18:16] - SECSS // bit[14:12] - PCLKD0 // bit[10:8] - HCLKD0 // bit[6:4] - ARMCLK // bit[0] - APLL SetReg32(rMPLL_LOCK, 0x00000e10); // Lock Time = 300us*12Mhz = 3600(=0xe10) SetReg32(rMPLL_CON, (1u<<31)|(MPLL_MDIV<<16)|(MPLL_PDIV<<8)|(MPLL_SDIV<<0)); SetReg32(rEPLL_LOCK, 0x00000e10); // Lock Time = 300us*12Mhz = 3600(=0xe10) SetReg32(rEPLL_CON, (1u<<31)|(EPLL_MDIV<<16)|(EPLL_PDIV<<8)|(EPLL_SDIV<<0)); GetReg32(rCLK_SRC0, ReadVal); SetReg32(rCLK_SRC0, (ReadVal&~(1<<20))|(0<<20)); // HPLL source clock = HREF_FIN27M SetReg32(rHPLL_LOCK, 0x00000e10); // Lock Time = 300us*12Mhz = 3600(=0xe10) SetReg32(rHPLL_CON, (1u<<31)|(HPLL_MDIV<<16)|(HPLL_PDIV<<8)|(HPLL_SDIV<<0)); // SetSourceClock GetReg32(rCLK_SRC0, ReadVal); SetReg32(rCLK_SRC0, (ReadVal&~(0x11111))|(0<<16)|(1<<12)|(1<<8)|(1<<4)|(1<<0)); // bit[16] - muxAM (0: MOUTMPLL, 1: DOUTAPLL2) // bit[12] - muxHPLL (0: CLK27M, 1: FOUTHPLL) // bit[8] - muxEPLL (0: FINEPLL, 1: FOUTEPLL) // bit[4] - muxMPLL (0: FINMPLL, 1: FOUTMPLL) // bit[0] - muxAPLL (0: FINAPLL, 1: FOUTAPLL) SetReg32(rCLK_SRC1, (1<<24)|(1<<0)); // bit[24] - muxCLK48M (0: XUSBXTI, 1: OTG_PHY) // bit[0] - muxUART (0: MOUTEPLL, 1: DOUTMPLL) // Internal clock can be monitored through XCLKOUT PAD. // * SMDKC100 Single(none POP): TP80 on CPU B'd // * SMDKC100 POP A type : TP73 on CPU B'd SetReg32(rCLK_OUT, (0<<20)|(9<<12)); // bit[23:20] - DiviReadValer value // bit[16:12] - Clock out type (9: ARMCLK_DIV4) } // We only need to care about performance. void InitLPCON() { UINT32 ReadVal; UINT32 ReadValStat; #if INIT_QoS volatile unsigned int *rTMP; #endif // --------------------------------------------------------------- // 1. Config PHY // --------------------------------------------------------------- // [ 1. Config PHY ] #if ENABLE_PHY_DLL // Now, we use ENABLE_PHY_DLL SetReg32(rLPCON_PHY_CONTROL0, 0x50101008); //SetReg32(rLPCON_PHY_CONTROL0, 0x50<<24|0x10<<16|0x10<<8|0<<4|1<<3|0<<2|0<<1|0<<0); // [31:24] DLL force delay // [23:16] DLL delay increment // [15:8] DLL lock start point // [7:5] Should be zero. // [4] DLL CRC // [3] ctrl_dfdqs // [2] ctrl_half // [1] ctrl_dll_on // [0] ctrl_start SetReg32(rLPCON_PHY_CONTROL1, 0xf6<<0); //SetReg32(rLPCON_PHY_CONTROL1, 0xf4<<0); SetReg32(rLPCON_PHY_CONTROL2, 0<<24|0<<16|0<<8|0<<0); GetReg32(rLPCON_PHY_CONTROL0, ReadVal); SetReg32(rLPCON_PHY_CONTROL0, ReadVal|=(1<<1)); // DLL on SetReg32(rLPCON_PHY_CONTROL0, ReadVal|=(1<<0)); // DLL start do { GetReg32(rLPCON_PHY_STATUS0, ReadVal); } while ((ReadVal&0x4) != 0x4); // wait until PLL lock. GetReg32(rLPCON_PHY_STATUS0, ReadValStat); ReadValStat = (ReadValStat>>6)&0xff; // locked delay GetReg32(rLPCON_PHY_CONTROL0, ReadVal); ReadVal &= ~(0xff<<24); SetReg32(rLPCON_PHY_CONTROL0, ReadVal|=(ReadValStat<<24)); // force locking value for DLL off SetReg32(rLPCON_PHY_CONTROL0, ReadVal&=~(1<<1)); // DLL off #endif // --------------------------------------------------------------- // 2. Config DMC itself // --------------------------------------------------------------- SetReg32(rLPCON_CON_CONTROL, 0xFF001010); //SetReg32(rLPCON_CON_CONTROL, 0xff<<16|1<<12|0<<10|0<<9|0<<8|0<<7|0<<6|0<<5|1<<4|0<<1|0<<0); // [27:16] Default timeout cycles (n aclk cycles) // [15:12] Read data fetch cycles (n mclk cycles) // [10] DQ swap // [9] Command queue status of chip1 (RO) // [8] Command queue status of chip0 (RO) // [7] PHY driving // [6] Read cycle gap for two different chips (0=disable, 1=enable) // [5] Auto refresh counter (0=disable, 1=enable) // [4] Out of order scheduling (0=disable, 1=enable) // [3:1] aclk:mclk (0=1:1, 3=2:1) // [0] (0=sync, 1=async) SetReg32(rLPCON_MEM_CONTROL, 0x00212400); //SetReg32(rLPCON_MEM_CONTROL, 2<<20|1<<16|2<<12|MEM_TYPE<<8|0<<6|1<<5|1<<4|0<<2|0<<1|0<<0); // [22:20] Memory burst length (1=2, 2=4, 3=8, 4=16) // [19:16] Number of Memory chips (0=1chip, 1=2chips) // [15:12] Width of Memory data bus (1=16bit, 2=32bit) // [11:8] Type of Memory (1=LPDDR, 2=LPDDR2, 3=DDR, 4=DDR2) // [7:6] Additional latency for PALL // [5] Dynamic self refresh (0=disable, 1=enable) // [4] Force precharge (1=Auto-precharge) // [3:2] Type of dynamic power down // [1] Dynamic power down // [0] Dynamic clock control #if (SMDKC100_POP == POP_A) SetReg32(rLPCON_MEM_CONFIG0, 0x28<<24|0xf8<<16|0<<12|2<<8|2<<4|2<<0); // OneDRAM SetReg32(rLPCON_MEM_CONFIG1, 0x20<<24|0xf8<<16|1<<12|2<<8|2<<4|2<<0); // mDDR #elif (SMDKC100_POP == POP_D) SetReg32(rLPCON_MEM_CONFIG0, 0x30<<24|0xf0<<16|1<<12|3<<8|1<<4|2<<0); // mDDR 128MB 13bit, COL:10bit, 4banks SetReg32(rLPCON_MEM_CONFIG1, 0x20<<24|0xf0<<16|1<<12|3<<8|2<<4|2<<0); // mDDR 256MB 14bit, COL:10bit, 4banks #elif (SMDKC100_POP == POP_NONE) SetReg32(rLPCON_MEM_CONFIG0, 0x20F00313); //SetReg32(rLPCON_MEM_CONFIG0, 0x20<<24|0xf0<<16|1<<12|3<<8|1<<4|3<<0); SetReg32(rLPCON_MEM_CONFIG1, 0x40F00313); //SetReg32(rLPCON_MEM_CONFIG1, 0x40<<24|0xf0<<16|1<<12|3<<8|1<<4|3<<0); #else #error // Invalid POP type #endif // [31:24] AXI base address // [23:16] AXI base address mask // [15:12] Address mapping methid (0=bank/row/col, 1=row/bank/col) // [11:8] Number of column address bits (0=7bits, 1=8bits, 2=9bits, 3=10bits, ... 5=12bits) // [7:4] Number of row address bits (0=12bits, 1=13bits, 2=14bits, 3=15bits) // [3:0] Number of banks (0=1banks, 1=2banks, 2=4banks, 3=8banks) SetReg32(rLPCON_PRECH_CONFIG, 0x20<<24|0<<8|0<<0); // [31:24] Force precharge cycle (if MEM_CONTROL[4] is set.) // [15:8] Memory chip1 precharge bank selective policy (1=close page policy) ??? // [7:0] Memory chip0 precharge bank selective policy (1=close page policy) ??? //SetReg32(rLPCON_PWRDN_CONFIG, 0x10<<16|4); /// // [31:16] Number of cycles for dynamic self refresh entry // [7:0] Number of cycles for dynamic power down entry //#ifdef SLOWAHB //SetReg32(rLPCON_TIMING_AREF, 0x287); // 7.8us*83MHz=0x287 //#else SetReg32(rLPCON_TIMING_AREF, 0x50e); // 7.8us*166MHz=0x50e //#endif // S5PCxxx_SLOWAHB // [15:0] Average periodic refresh interval SetReg32(rLPCON_TIMING_ROW, 0x16233288); //SetReg32(rLPCON_TIMING_ROW, 22<<24|2<<20|3<<16|3<<12|10<<6|8<<0); // [31:24] tRFC = 132ns/6ns = 22 // [23:20] tRRD = 12ns/6ns = 2 // [19:16] tRP = 18ns/6ns = 3 // [15:12] tRCD = 18ns/6ns = 3 // [11:6] tRC = 60ns/6ns = 10 // [5:0] tRAS = 48ns/6ns = 8 SetReg32(rLPCON_TIMING_DATA, 0x23260304); //SetReg32(rLPCON_TIMING_DATA, 2<<28|3<<24|2<<20|CAS_DELAY<<16|3<<8|4<<0); // [31:28] tWTR (Internal write to Read command delay) (at least 2) // [27:24] tWR = 18ns/6ns = 3 // [23:20] tRTP (Internal read to Precharge command delay) (maybe 3) // [19:16] CL = 5 // [11:8] WL (for only LPDDR2) // [3:0] RL (for only LPDDR2) SetReg32(rLPCON_TIMING_POWER, 0x09C80232); //SetReg32(rLPCON_TIMING_POWER, 9<<24|200<<16|2<<8|3<<4|2<<0); // [29:24] tFAW = Four active window (maybe 50ns) // [23:16] tXSR = 200 // [15:8] tXP (Exit power down to next valid command delay) (2) // [7:4] tCKE = CLE minimun pulse width (3) // [3:0] tMRD = 2 #if INIT_QoS // --------------------------------------------------------------- // 3.Initialize QoS // --------------------------------------------------------------- rTMP = rLPCON_QOS_CONTROL0; for (ReadVal=0; ReadVal<8; rTMP++) SetReg32(rTMP, 0x00ff0000); rTMP = rLPCON_QOS_CONFIG0; for (ReadVal=0; ReadVal<8; rTMP++) SetReg32(rTMP, 0x00000000); #endif // --------------------------------------------------------------- // 4.Initialize DRAM (rLPCON_DIRECT_CMD) // --------------------------------------------------------------- // [27:24] Type of direct command (0=MRS/EMRS, 1=PALL, 2=PRE, 3=DPD, 4=REFS, 5=REFA, 6=CKEL, 7=NOP, 8=REFSX, 9=MRR) // [20] The chip number to send the direct command to (0=chip0, 1=chip1) // [18:16] Bits mapped to the bank address pins // [14:0] Bits mapped to the address pins // for chip 0 SetReg32(rLPCON_DIRECT_CMD, 7<<24); // chip0 Deselect (NOP) SetReg32(rLPCON_DIRECT_CMD, 1<<24); // chip0 PALL SetReg32(rLPCON_DIRECT_CMD, 0x02<<16); // chip0 EMRS2 SetReg32(rLPCON_DIRECT_CMD, 0x03<<16); // chip0 EMRS3 SetReg32(rLPCON_DIRECT_CMD, 1<<16 | 4<<8); // chip0 EMRS1 SetReg32(rLPCON_DIRECT_CMD, 0x762<<0); // chip0 MRS SetReg32(rLPCON_DIRECT_CMD, 1<<24); // chip0 PALL SetReg32(rLPCON_DIRECT_CMD, 5<<24); // chip0 REFA SetReg32(rLPCON_DIRECT_CMD, 5<<24); // chip0 REFA SetReg32(rLPCON_DIRECT_CMD, 0x662<<0); // chip0 MRS SetReg32(rLPCON_DIRECT_CMD, 0x10780<<0); // chip0 EMRS1 SetReg32(rLPCON_DIRECT_CMD, 0x01<<16 | 4<<8); // chip0 EMRS1 //SetReg32(rLPCON_DIRECT_CMD, 0<<24 | 0<<16 | CAS_DELAY<<4 | 2<<0); // chip0 MRS // for chip 1 SetReg32(rLPCON_DIRECT_CMD, 7<<24 | 1<<20); // chip1 Deselect (NOP) SetReg32(rLPCON_DIRECT_CMD, 1<<24 | 1<<20); // chip1 PALL SetReg32(rLPCON_DIRECT_CMD, 0x02<<16 | 1<<20); // chip1 EMRS2 SetReg32(rLPCON_DIRECT_CMD, 0x03<<16 | 1<<20); // chip1 EMRS3 SetReg32(rLPCON_DIRECT_CMD, 0x104<<8 | 4<<8 | 1<<20); // chip1 EMRS1 SetReg32(rLPCON_DIRECT_CMD, 0x762<<0 | 1<<20); // chip1 MRS SetReg32(rLPCON_DIRECT_CMD, 1<<24 | 1<<20); // chip1 PALL SetReg32(rLPCON_DIRECT_CMD, 0x51<<20 | 1<<20); // chip1 REFA SetReg32(rLPCON_DIRECT_CMD, 0x51<<20 | 1<<20); // chip1 REFA SetReg32(rLPCON_DIRECT_CMD, 0x662<<20 | 1<<20); // chip1 MRS SetReg32(rLPCON_DIRECT_CMD, 0x117080<<0 | 1<<20); // chip1 EMRS1 SetReg32(rLPCON_DIRECT_CMD, 0x110400<<0 | 1<<20); // chip1 EMRS1 // SetReg32(rLPCON_DIRECT_CMD, 5<<24 | 1<<20); // chip1 REFA // SetReg32(rLPCON_DIRECT_CMD, 5<<24 | 1<<20); // chip1 REFA // SetReg32(rLPCON_DIRECT_CMD, 0<<24 | 1<<20 | 0<<16 | CAS_DELAY<<4 | 2<<0); // chip1 MRS // [8] DLL Reset, // [6:4] CAS Delay // [3] 0=Sequential // [2:0] Burst (1=2, 2=4, 3=8) //SetReg32(rLPCON_DIRECT_CMD, 0<<24|4<<16|0<<5|0<<0); // chip0 EMRS /// // [17:16] 4 for DDR2 // [6:5] Drive strength (0=full, 1=half, 2=quater, 3=octant) // [2:0] Partial Self Refresh (0=full array, 1=half array, 2=quater array) //SetReg32(rLPCON_DIRECT_CMD, 7<<24); // chip0 Deselect (NOP) /// // --------------------------------------------------------------- // 5. Start the DMC. // --------------------------------------------------------------- SetReg32(rLPCON_CON_CONTROL, 0x0FF01030); // auto fresh on //GetReg32(rLPCON_CON_CONTROL, ReadVal); //SetReg32(rLPCON_CON_CONTROL, ReadVal|=(1<<5)); SetReg32(rLPCON_PWRDN_CONFIG, 0x10<<16|4); // add // [31:16] Number of cycles for dynamic self refresh entry // [7:0] Number of cycles for dynamic power down entry //GetReg32(rLPCON_MEM_CONTROL, ReadVal); //SetReg32(rLPCON_MEM_CONTROL, ReadVal&=(~0xff)); SetReg32(rLPCON_MEM_CONTROL, 0x00212400); }