From 135634466e22e0cc2f2773c05ae75b3721d30d41 Mon Sep 17 00:00:00 2001 From: yangkai Date: Wed, 16 Mar 2011 21:20:01 +0800 Subject: [PATCH] ddr3 function support --- arch/arm/mach-rk29/ddr.c | 2487 +++++++++++++++++++------------------- arch/arm/mach-rk29/pm.c | 94 +- 2 files changed, 1324 insertions(+), 1257 deletions(-) mode change 100644 => 100755 arch/arm/mach-rk29/ddr.c mode change 100644 => 100755 arch/arm/mach-rk29/pm.c diff --git a/arch/arm/mach-rk29/ddr.c b/arch/arm/mach-rk29/ddr.c old mode 100644 new mode 100755 index 93961ea50738..89a9fd43c9c9 --- a/arch/arm/mach-rk29/ddr.c +++ b/arch/arm/mach-rk29/ddr.c @@ -1,1255 +1,1232 @@ -/**************************************************************** -* CopyRight(C) 2010 by Rock-Chip Fuzhou -* All Rights Reserved -* File name :ddr.c -* Description: ddr driver implement -* Author :hcy -* Create date :2011-01-04 -* Change log: -* Current version:1.00 20110104 hcy -****************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - - -#include - -// save_sp must be static global variable - -static unsigned long save_sp; - - -//CCR; //Controller Configuration Register -#define ECCEN (1) -#define NOMRWR (1<<1) -#define HOSTEN (1<<2) -#define RRB (1<<13) -#define DQSCFG (1<<14) -#define DFTLM_NO (0<<15) -#define DFTLM_90 (1<<15) -#define DFTLM_180 (2<<15) -#define DFTLM_270 (3<<15) -#define DFTCMP (1<<17) -#define FLUSH (1<<27) -#define ITMRST (1<<28) -#define IB (1<<29) -#define DTT (1<<30) -#define IT (1<<31) -//DCR; //DRAM Configuration Register -#define DDRII (0) -#define DDR3 (1) -#define Mobile_DDR (2) - -#define DIO_8 (1<<2) -#define DIO_16 (2<<2) -#define DIO_32 (3<<2) - -#define DSIZE_64Mb (0<<4) -#define DSIZE_128Mb (1<<4) -#define DSIZE_256Mb (2<<4) -#define DSIZE_512Mb (3<<4) -#define DSIZE_1Gb (4<<4) -#define DSIZE_2Gb (5<<4) -#define DSIZE_4Gb (6<<4) -#define DSIZE_8Gb (7<<4) - -#define SIO(n) (((n)-1)<<7) -#define PIO (1<<10) -#define RANKS(n) ((((n)-1)&0x3)<<11) -#define RNKALL (1<<13) - -#define AMAP_RBRC (0<<14) //rank,bank,row,column -#define AMAP_RRBC (1<<14) //rank,row,bank,column -#define AMAP_BRRC (2<<14) //bank,row,rank,column -#define AMAP_FIX (3<<14) //Fixed address - -#define PDQ(n) (((n)&0x7)<<16) -#define MPRDQ (1<<19) -#define MVAR (1<<20) -#define RDIMM (1<<21) -#define DO_INIT (1<<24) -#define EXE_RANK(n) (((n)&3)<<25) - -#define CMD_NOP (0<<27) -#define CMD_ClockStop (1<<27) -#define CMD_SelfRefresh (2<<27) -#define CMD_Refresh (3<<27) -#define CMD_DDR3_Reset (4<<27) -#define CMD_PrechargeAll (5<<27) -#define CMD_DeepPowerDown (6<<27) -#define CMD_SDRAM_Mode_Exit (7<<27) -#define CMD_SDRAM_ZQ_Calibration_Short (0xB<<27) -#define CMD_SDRAM_ZQ_Calibration_Long (0xC<<27) -#define CMD_PowerDown (0xE<<27) -#define CMD_SDRAM_NOP (0xF<<27) - -#define EXE (1<<31) - -//IOCR; //IO Configuration Register -#define DQ_ODT (1) -#define DQS_ODT (1<<1) -#define TESTEN (1<<2) -#define DQ_RTT_DIS (0<<3) -#define DQ_RTT_150 (1<<3) -#define DQ_RTT_75 (2<<3) -#define DQ_RTT_50 (3<<3) -#define DQS_RTT_DIS (0<<5) -#define DQS_RTT_150 (1<<5) -#define DQS_RTT_75 (2<<5) -#define DQS_RTT_50 (3<<5) -#define DQ_DS_FULL (1<<7) -#define DQ_DS_REDUCE (0<<7) -#define DQS_DS_FULL (1<<8) -#define DQS_DS_REDUCE (0<<8) -#define ADD_DS_FULL (1<<9) -#define ADD_DS_REDUCE (0<<9) -#define CK_DS_FULL (1<<10) -#define CK_DS_REDUCE (0<<10) - -#define AUTO_CMD_IOPD(n) (((n)&0x3)<<18) -#define AUTO_DATA_IOPD(n) (((n)&0x3)<<22) -#define RTTOH(n) (((n)&0x7)<<26) -#define RTTOE (1<<29) -#define DQRTT (1<<30) -#define DQSRTT (1<<31) - -//CSR; //Controller Status Register -#define DFTERR (1<<18) -#define ECCERR (1<<19) -#define DTERR (1<<20) -#define DTIERR (1<<21) -#define ECCSEC (1<<22) -#define TQ (1<<23) - -//DRR; //DRAM Refresh Register -#define TRFC(n) ((n)&0xFF) -#define TRFPRD(n) (((n)&0xFFFF)<<8) -#define RFBURST(n) ((((n)-1)&0xF)<<24) -#define RD (1<<31) - -//TPR[3]; //SDRAM Timing Parameters Registers -//TPR0 -#define TMRD(n) ((n)&0x3) -#define TRTP(n) (((n)&0x7)<<2) -#define TWTR(n) (((n)&0x7)<<5) -#define TRP(n) (((n)&0xF)<<8) -#define TRCD(n) (((n)&0xF)<<12) -#define TRAS(n) (((n)&0x1F)<<16) -#define TRRD(n) (((n)&0xF)<<21) -#define TRC(n) (((n)&0x3F)<<25) -#define TCCD (1<<31) -//TPR1 -#define TAOND_2 (0) -#define TAOND_3 (1) -#define TAOND_4 (2) -#define TAOND_5 (3) -#define TRTW (1<<2) -#define TFAW(n) (((n)&0x3F)<<3) -#define TMOD(n) (((n)&0x3)<<9) -#define TRTODT (1<<11) -#define TRNKRTR(n) ((((n)-1)&0x3)<<12) -#define TRNKWTW(n) (((n)&0x3)<<14) -//TPR2 -#define TXS(n) ((n)&0x3FF) -#define TXP(n) (((n)&0x1F)<<10) -#define TCKE(n) (((n)&0xF)<<15) - -//DLLCR; //Global DLL Control Register -//DLLCR09[10]; //DDR Control Register 0-9 -#define DD (1<<31) - -//RSLR[4]; //Rank System Latency Register 0-3 -#define SL(n,value) (((value)&0x7)<<((n)*3)) - -//RDGR[4]; //Rank DQS Gating Register 0-3 -#define DQSSEL(n, value) (((value)&0x3)<<((n)*2)) - -//DQTR[9]; //DQ Timing Register 0-8 -#define DQDLY_DQS(n, value) (((value)&0x3)<<((n)*4)) -#define DQDLY_DQSb(n, value) (((value)&0x3)<<(((n)*4)+2)) - -//DQSTR; //DQS Timing Register -//DQSBTR; //DQS_b Timing Register -#define DQSDLY(n, value) (((value)&0x7)<<((n)*3)) - -//ODTCR; //ODT Configuration Register -#define RDODT(rank, value) (((value)&0xF)<<((rank)*4)) -#define WRODT(rank, value) (((value)&0xF)<<(((rank)*4)+16)) - -//DTR[2]; //Data Training Register 0-1 -//DTAR; //Data Training Address Register -#define DTCOL(col) ((col)&0xFFF) -#define DTROW(row) (((row)&0xFFFF)<<12) -#define DTBANK(bank) (((bank)&0x7)<<28) -#define DTMPR (1<<31) - -//ZQCR[3]; //SDRAM ZQ Control Register and SDRAM ZQCS Control Register 0-2 -//ZQCR0 -#define ZQDATA(n) ((n)&0xFFFFF) -#define ZPROG_OUT(n) (((n)&0xF)<<20) -#define ZPROG_ODT(n) (((n)&0xF)<<24) -#define ZQDEN (1<<28) -#define ZQCLK (1<<29) -#define NOICAL (1<<30) -#define ZQCAL (1<<31) -//ZQCR1 -#define ZQ_CALPRD(n) ((n)&0x7FFF) -#define ZQ_CAL_EN (1<<31) -//ZQCR2 -#define ZQCS_CALPRD(n) ((n)&0x7FFF) -#define ZQCS_CAL_EN (1<<31) - -//ZQSR; //SDRAM ZQ Status Register -//TPR3; //SDRAM Timing Parameters Register 3 -#define BL2 (0) -#define BL4 (1) -#define BL8 (2) -#define BL16 (3) -#define BLOTF_EN (1<<2) -#define CL(n) (((n)&0xF)<<3) -#define CWL(n) (((n)&0xF)<<7) -#define WR(n) (((n)&0xF)<<11) -#define AL(n) (((n)&0xF)<<15) - -//ALPMR; //Automatic Low Power Mode Register -#define LPPERIOD_CLK_STOP(n) ((n)&0xFF) -#define LPPERIOD_POWER_DOWN(n) (((n)&0xFF)<<8) -#define AUTOCS (1<<25) -#define AUTOPD (1<<26) - -//Reserved[0x7c-0x30]; -//MR; //Mode Register -#define DDR_BL4 (2) -#define DDR_BL8 (3) -#define DDR_CL(n) (((n)&0x7)<<4) -#define DDR2_WR(n) ((((n)-1)&0x7)<<9) - -//EMR; //Extended Mode Register -#define DDR2_STR_FULL (0) -#define DDR2_STR_REDUCE (1<<1) -#define DDR2_AL(n) (((n)&0x7)<<3) -#define DDR2_ODT_DIS (0) -#define DDR2_ODT_150 (0x40) -#define DDR2_ODT_75 (0x4) -#define DDR2_ODT_50 (0x44) - -//EMR2; //Extended Mode Register 2 -//EMR3; //Extended Mode Register 3 -//y Management Unit Registers -//HPCR[32]; //Host Port Configuration Register 0-31 -#define HPBL(n) ((n)&0xFF) -#define HCBP (1<<8) -#define HNPC (1<<9) - -//PQCR[8]; //Priority Queue Configuration Register 0-7 -#define TOUT(n) ((n)&0xFF) -#define TOUT_MUL_1 (0<<8) -#define TOUT_MUL_16 (1<<8) -#define TOUT_MUL_64 (2<<8) -#define TOUT_MUL_256 (3<<8) -#define LPQS(n) (((n)&0x3)<<10) -#define PQBL(n) (((n)&0xFF)<<12) -#define SWAIT(n) (((n)&0x1F)<<20) -#define INTRPT(n) (((n)&0x7)<<25) -#define APQS (1<<28) - -//MMGCR; //Memory Manager General Configuration Register -#define PORT0_NORMAL_PRIO (0) -#define PORT0_HIGH_PRIO (2) - -#define VCODEC_PRIO(n) (((n)&0x3)<<8) -#define GPU_PRIO(n) (((n)&0x3)<<6) -#define LCD_PRIO(n) (((n)&0x3)<<4) -#define PERI_PRIO(n) (((n)&0x3)<<2) -#define CPU_PRIO(n) (((n)&0x3)<<0) - -/* DDR Controller register struct */ -typedef volatile struct DDR_REG_Tag -{ - volatile unsigned int CCR; //Controller Configuration Register - volatile unsigned int DCR; //DRAM Configuration Register - volatile unsigned int IOCR; //IO Configuration Register - volatile unsigned int CSR; //Controller Status Register - volatile unsigned int DRR; //DRAM Refresh Register - volatile unsigned int TPR[3]; //SDRAM Timing Parameters Registers - volatile unsigned int DLLCR; //Global DLL Control Register - volatile unsigned int DLLCR09[10]; //DDR Control Register 0-9 - volatile unsigned int RSLR[4]; //Rank System Latency Register 0-3 - volatile unsigned int RDGR[4]; //Rank DQS Gating Register 0-3 - volatile unsigned int DQTR[9]; //DQ Timing Register 0-8 - volatile unsigned int DQSTR; //DQS Timing Register - volatile unsigned int DQSBTR; //DQS_b Timing Register - volatile unsigned int ODTCR; //ODT Configuration Register - volatile unsigned int DTR[2]; //Data Training Register 0-1 - volatile unsigned int DTAR; //Data Training Address Register - volatile unsigned int ZQCR[3]; //SDRAM ZQ Control Register and SDRAM ZQCS Control Register 0-2 - volatile unsigned int ZQSR; //SDRAM ZQ Status Register - volatile unsigned int TPR3; //SDRAM Timing Parameters Register 3 - volatile unsigned int ALPMR; //Automatic Low Power Mode Register - volatile unsigned int Reserved[0x7c-0x30]; - volatile unsigned int MR; //Mode Register - volatile unsigned int EMR; //Extended Mode Register - volatile unsigned int EMR2; //Extended Mode Register 2 - volatile unsigned int EMR3; //Extended Mode Register 3 - //Memory Management Unit Registers - volatile unsigned int HPCR[32]; //Host Port Configuration Register 0-31 - volatile unsigned int PQCR[8]; //Priority Queue Configuration Register 0-7 - volatile unsigned int MMGCR; //Memory Manager General Configuration Register -}DDR_REG_T, *pDDR_REG_T; - -typedef struct tagGPIO_IOMUX -{ - volatile unsigned int GPIOL_IOMUX; - volatile unsigned int GPIOH_IOMUX; -}GPIO_IOMUX_T; - -//GRF Registers -typedef volatile struct tagREG_FILE -{ - volatile unsigned int GRF_GPIO_DIR[6]; - volatile unsigned int GRF_GPIO_DO[6]; - volatile unsigned int GRF_GPIO_EN[6]; - GPIO_IOMUX_T GRF_GPIO_IOMUX[6]; - volatile unsigned int GRF_GPIO_PULL[7]; - volatile unsigned int GRF_UOC_CON[2]; - volatile unsigned int GRF_USB_CON; - volatile unsigned int GRF_CPU_CON[2]; - volatile unsigned int GRF_CPU_STATUS; - volatile unsigned int GRF_MEM_CON; - volatile unsigned int GRF_MEM_STATUS[3]; - volatile unsigned int GRF_SOC_CON[5]; - volatile unsigned int GRF_OS_REG[4]; -} REG_FILE, *pREG_FILE; - -//CRU Registers -typedef volatile struct tagCRU_REG -{ - volatile unsigned int CRU_APLL_CON; - volatile unsigned int CRU_DPLL_CON; - volatile unsigned int CRU_CPLL_CON; - volatile unsigned int CRU_PPLL_CON; - volatile unsigned int CRU_MODE_CON; - volatile unsigned int CRU_CLKSEL_CON[18]; - volatile unsigned int CRU_CLKGATE_CON[4]; - volatile unsigned int CRU_SOFTRST_CON[3]; -} CRU_REG, *pCRU_REG; - -typedef enum tagDDRDLLMode -{ - DLL_BYPASS=0, - DLL_NORMAL -}eDDRDLLMode_t; - - -#define pDDR_Reg ((pDDR_REG_T)RK29_DDRC_BASE) - -#define pGRF_Reg ((pREG_FILE)RK29_GRF_BASE) -#define pSCU_Reg ((pCRU_REG)RK29_CRU_BASE) - -//#define read32(address) (*((volatile unsigned int volatile*)(address))) -//#define write32(address, value) (*((volatile unsigned int volatile*)(address)) = value) - -//u32 GetDDRCL(u32 newMHz); -//void EnterDDRSelfRefresh(void); -//void ExitDDRSelfRefresh(void); -//void ChangeDDRFreqInSram(u32 oldMHz, u32 newMHz); - - -static __sramdata u32 bFreqRaise; -static __sramdata u32 capability; // one chip cs capability - -//DDR2 -static __sramdata u32 tRFC; -static __sramdata u32 tRFPRD; -static __sramdata u32 tRTP; -static __sramdata u32 tWTR; -static __sramdata u32 tRAS; -static __sramdata u32 tRRD; -static __sramdata u32 tRC; -static __sramdata u32 tFAW; -//Mobile-DDR -static __sramdata u32 tXS; -static __sramdata u32 tXP; - - -/**************************************************************************** -Internal sram us delay function -Cpu highest frequency is 1.2 GHz -1 cycle = 1/1.2 ns -1 us = 1000 ns = 1000 * 1.2 cycles = 1200 cycles -*****************************************************************************/ -void __sramfunc delayus(u32 us) -{ - u32 count; - count = us * 533; - while(count--) // 3 cycles - barrier(); - -} - -void __sramfunc DDRUpdateRef(void) -{ - volatile u32 value = 0; - - value = pDDR_Reg->DRR; - value &= ~(0xFFFF00); - pDDR_Reg->DRR = value | TRFPRD(tRFPRD); -} - - -void __sramfunc DDRUpdateTiming(void) -{ - u32 value; - u32 memType = (pDDR_Reg->DCR & 0x3); - - value = pDDR_Reg->DRR; - value &= ~(0xFF); - pDDR_Reg->DRR = TRFC(tRFC) | value; - if(memType == DDRII) - { - value = pDDR_Reg->TPR[0]; - value &= ~((0x7<<2)|(0x7<<5)|(0x1F<<16)|(0xF<<21)|(0x3F<<25)); - pDDR_Reg->TPR[0] = value | TRTP(tRTP) | TWTR(tWTR) | TRAS(tRAS) | TRRD(tRRD) | TRC(tRC); - value = pDDR_Reg->TPR[1]; - value &= ~(0x3F<<3); - pDDR_Reg->TPR[1] = value | TFAW(tFAW); - value = pDDR_Reg->TPR[2]; - value &= ~(0x1F<<10); - pDDR_Reg->TPR[2] = value | TXP(tXP); - } - else - { - value = pDDR_Reg->TPR[0]; - value &= ~((0x1F<<16)|(0xF<<21)|(0x3F<<25)); - pDDR_Reg->TPR[0] = value | TRAS(tRAS) | TRRD(tRRD) | TRC(tRC); - value = pDDR_Reg->TPR[2]; - value &= ~(0x7FFF); - pDDR_Reg->TPR[2] = value | TXS(tXS) | TXP(tXP); - } -} - - -u32 __sramfunc GetDDRCL(u32 newMHz) -{ - u32 memType = (pDDR_Reg->DCR & 0x3); - - if(memType == DDRII) - { - if(newMHz <= 266) - { - return 4; - } - else if((newMHz > 266) && (newMHz <= 333)) - { - return 5; - } - else if((newMHz > 333) && (newMHz <= 400)) - { - return 6; - } - else // > 400MHz - { - return 7; - } - } - else - { - return 3; - } -} - -/*------------------------------------------------------------------- -Name : EnterDDRSelfRefresh -Desc : DDR enter self refresh -Params : -Return : -Notes : 1. ddr enter sel-refresh must be after system enter idle ,after ddr enter sel-refresh must not access ddr - 2. ddr enter sel-refresh code must not be in ddr --------------------------------------------------------------------*/ -void __sramfunc EnterDDRSelfRefresh(void) -{ - pDDR_Reg->CCR &= ~HOSTEN; //disable host port - pDDR_Reg->CCR |= FLUSH; //flush - delayus(10); - pDDR_Reg->DCR = (pDDR_Reg->DCR & (~((0x1<<24) | (0x1<<13) | (0xF<<27) | (0x1<<31)))) | ((0x1<<13) | (0x2<<27) | (0x1<<31)); //enter Self Refresh - delayus(10); - pSCU_Reg->CRU_SOFTRST_CON[0] |= (0x1f<<19); //reset DLL - delayus(10); -} - -/*------------------------------------------------------------------- -Name : ExitDDRSelfRefresh -Desc : DDR exit self refresh -Params : -Return : -Notes : 1. ddr enter sel-refresh must be after system enter idle ,after ddr enter sel-refresh must not access ddr - 2. ddr enter sel-refresh code must not be in ddr --------------------------------------------------------------------*/ -void __sramfunc ExitDDRSelfRefresh(void) -{ - pSCU_Reg->CRU_SOFTRST_CON[0] &= ~(0x1f<<19); //de-reset DLL - delayus(10); - pDDR_Reg->DCR = (pDDR_Reg->DCR & (~((0x1<<24) | (0x1<<13) | (0xF<<27) | (0x1<<31)))) | ((0x1<<13) | (0x7<<27) | (0x1<<31)); //exit - delayus(10); //wait for exit self refresh dll lock - while(1) - { - pDDR_Reg->DRR |= RD; //auto refresh - pDDR_Reg->CCR |= DTT; - delayus(1000); - pDDR_Reg->DRR &= ~RD; - if(pDDR_Reg->CSR & (0x1<<20)) - { - pDDR_Reg->CSR &= ~(0x1<<20); - } - else - { - break; - } - } - pDDR_Reg->CCR |= HOSTEN; //enable host port -} - -static void DDRPreUpdateRef(u32 MHz) -{ - tRFPRD = ((59*MHz) >> 3) & 0x3FFF; // 62/8 = 7.75us -} - -static void DDRPreUpdateTiming(u32 MHz) -{ - u32 tmp; - u32 cl; - u32 memType = (pDDR_Reg->DCR & 0x3); - - cl = GetDDRCL(MHz); - //ʱÐò - if(memType == DDRII) - { - if(capability <= 0x2000000) // 256Mb - { - tmp = (75*MHz/1000) + ((((75*MHz)%1000) > 0) ? 1:0); - } - else if(capability <= 0x4000000) // 512Mb - { - tmp = (105*MHz/1000) + ((((105*MHz)%1000) > 0) ? 1:0); - } - else if(capability <= 0x8000000) // 1Gb - { - tmp = (128*MHz/1000) + ((((128*MHz)%1000) > 0) ? 1:0); - } - else // 4Gb - { - tmp = (328*MHz/1000) + ((((328*MHz)%1000) > 0) ? 1:0); - } - //tRFC = 75ns(256Mb)/105ns(512Mb)/127.5ns(1Gb)/327.5ns(4Gb) - tmp = (tmp > 0xFF) ? 0xFF : tmp; - tRFC = tmp; - // tRTP = 7.5ns - tmp = (8*MHz/1000) + ((((8*MHz)%1000) > 0) ? 1:0); - tmp = (tmp > 6) ? 6 : tmp; - tmp = (tmp < 2) ? 2 : tmp; - tRTP = tmp; - //tWTR = 10ns(DDR2-400), 7.5ns (DDR2-533/667/800) - if(MHz <= 200) - { - tmp = (10*MHz/1000) + ((((10*MHz)%1000) > 0) ? 1:0); - } - else - { - tmp = (8*MHz/1000) + ((((8*MHz)%1000) > 0) ? 1:0); - } - tmp = (tmp > 6) ? 6 : tmp; - tmp = (tmp < 1) ? 1 : tmp; - tWTR = tmp; - //tRAS_min = 45ns - tmp = (45*MHz/1000) + ((((45*MHz)%1000) > 0) ? 1:0); - tmp = (tmp > 31) ? 31 : tmp; - tmp = (tmp < 2) ? 2 : tmp; - tRAS = tmp; - // tRRD = 10ns - tmp = (10*MHz/1000) + ((((10*MHz)%1000) > 0) ? 1:0); - tmp = (tmp > 8) ? 8 : tmp; - tmp = (tmp < 1) ? 1 : tmp; - tRRD = tmp; - if(MHz <= 200) //tRC = 65ns - { - tmp = (65*MHz/1000) + ((((65*MHz)%1000) > 0) ? 1:0); - } - else //tRC = 60ns - { - tmp = (60*MHz/1000) + ((((60*MHz)%1000) > 0) ? 1:0); - } - tmp = (tmp > 42) ? 42 : tmp; - tmp = (tmp < 2) ? 2 : tmp; - tRC = tmp; - //tFAW = 50ns - tmp = (50*MHz/1000) + ((((50*MHz)%1000) > 0) ? 1:0); - tmp = (tmp > 31) ? 31 : tmp; - tmp = (tmp < 2) ? 2 : tmp; - tFAW = tmp; - if(MHz <= 333) - { - tXP = 7; - } - else - { - tXP = 8; - } - } - else - { - if(capability <= 0x2000000) // 128Mb,256Mb - { - // 128Mb,256Mb tRFC=80ns - tmp = (80*MHz/1000) + ((((80*MHz)%1000) > 0) ? 1:0); - } - else if(capability <= 0x4000000) // 512Mb - { - // 512Mb tRFC=110ns - tmp = (110*MHz/1000) + ((((110*MHz)%1000) > 0) ? 1:0); - } - else if(capability <= 0x8000000) // 1Gb - { - // 1Gb tRFC=140ns - tmp = (140*MHz/1000) + ((((140*MHz)%1000) > 0) ? 1:0); - } - else // 4Gb - { - // ´óÓÚ1GbûÕÒµ½£¬°´DDR2µÄ tRFC=328ns - tmp = (328*MHz/1000) + ((((328*MHz)%1000) > 0) ? 1:0); - } - //tRFC = 80ns(128Mb,256Mb)/110ns(512Mb)/140ns(1Gb) - tmp = (tmp > 0xFF) ? 0xFF : tmp; - tRFC = tmp; - if(MHz <= 100) //tRAS_min = 50ns - { - tmp = (50*MHz/1000) + ((((50*MHz)%1000) > 0) ? 1:0); - } - else //tRAS_min = 45ns - { - tmp = (45*MHz/1000) + ((((45*MHz)%1000) > 0) ? 1:0); - } - tmp = (tmp > 31) ? 31 : tmp; - tmp = (tmp < 2) ? 2 : tmp; - tRAS = tmp; - // tRRD = 15ns - tmp = (15*MHz/1000) + ((((15*MHz)%1000) > 0) ? 1:0); - tmp = (tmp > 8) ? 8 : tmp; - tmp = (tmp < 1) ? 1 : tmp; - tRRD = tmp; - if(MHz <= 100) //tRC = 80ns - { - tmp = (80*MHz/1000) + ((((80*MHz)%1000) > 0) ? 1:0); - } - else //tRC = 75ns - { - tmp = (75*MHz/1000) + ((((75*MHz)%1000) > 0) ? 1:0); - } - tmp = (tmp > 42) ? 42 : tmp; - tmp = (tmp < 2) ? 2 : tmp; - tRC = tmp; - //tXSR = 200 ns - tmp = (200*MHz/1000) + ((((200*MHz)%1000) > 0) ? 1:0); - tmp = (tmp > 1023) ? 1023 : tmp; - tmp = (tmp < 2) ? 2 : tmp; - tXS = tmp; - //tXP=25ns - tmp = (25*MHz/1000) + ((((25*MHz)%1000) > 0) ? 1:0); - tmp = (tmp > 31) ? 31 : tmp; - tmp = (tmp < 2) ? 2 : tmp; - tXP = tmp; - } -} - -static void __sramfunc StopDDR(u32 oldMHz, u32 newMHz) -{ - pDDR_Reg->CCR |= FLUSH; //flush - delayus(10); - pDDR_Reg->CCR &= ~HOSTEN; //disable host port - - EnterDDRSelfRefresh(); - if(oldMHz < newMHz) //ÉýƵ - { - DDRUpdateTiming(); - bFreqRaise = 1; - } - else //½µÆµ - { - DDRUpdateRef(); - bFreqRaise = 0; - } -} - -static void __sramfunc ResumeDDR(u32 newMHz) -{ - u32 value; - u32 memType = (pDDR_Reg->DCR & 0x3); - u32 cl; - - if(bFreqRaise) //ÉýƵ - { - DDRUpdateRef(); - } - else //½µÆµ - { - DDRUpdateTiming(); - } - ExitDDRSelfRefresh(); - - if(memType == DDRII) - { - cl = GetDDRCL(newMHz); - - value = pDDR_Reg->TPR[0]; - value &= ~((0xF<<8)|(0xF<<12)); - pDDR_Reg->TPR[0] = value | TRP(cl) | TRCD(cl); - value = pDDR_Reg->TPR3; - value &= ~((0xF<<3)|(0xF<<7)|(0xF<<11)); - pDDR_Reg->TPR3 = value | CL(cl) | CWL(cl-1) | WR(cl); - //set mode register cl - pDDR_Reg->DCR = (pDDR_Reg->DCR & (~((0x1<<13) | (0xF<<27) | (0x1<<31)))) | ((0x1<<13) | (0x5<<27) | (0x1<<31)); //precharge-all - value = pDDR_Reg->MR; - value &= ~((0x7<<4)|(0x7<<9)); - pDDR_Reg->MR = value | DDR_CL(cl) | DDR2_WR(cl); - } -} - -/*------------------------------------------------------------------- -Name : PLLSetAUXFreq -Desc : »ñÈ¡AUXƵÂÊ -Params : -Return : AUXƵÂÊ, MHz Ϊµ¥Î» -Notes : --------------------------------------------------------------------*/ -void __sramfunc PLLSetAUXFreq(u32 freq) -{ - u32 value; - - // ddr slow - value = pSCU_Reg->CRU_MODE_CON; - value &=~(0x3<<6); - pSCU_Reg->CRU_MODE_CON = value; - - delayus(10); - - pSCU_Reg->CRU_DPLL_CON |= (0x1 << 15); //power down pll - delayus(1); //delay at least 500ns - switch(freq) // ʵ¼ÊƵÂÊÒªºÍϵͳȷÈÏ ????????? - { - case 136: - pSCU_Reg->CRU_DPLL_CON = (0x1<<16) | (0x1<<15) | (1<<10) | (44<<3) | (2<<1); //high band 135 - break; - case 200: - pSCU_Reg->CRU_DPLL_CON = (0x1<<16) | (0x1<<15) | (1<<10) | (66<<3) | (2<<1); //high band 201 - break; - case 266: - pSCU_Reg->CRU_DPLL_CON = (0x1<<16) | (0x1<<15) | (1<<10) | (43<<3) | (1<<1); //high band 264 - break; - case 333: - pSCU_Reg->CRU_DPLL_CON = (0x1<<16) | (0x1<<15) | (1<<10) | ((54)<<3) | (1<<1); //high band 330 - break; - case 400: - pSCU_Reg->CRU_DPLL_CON = (0x1<<16) | (0x1<<15) | (1<<10) | ((66)<<3) | (1<<1); //high band 402 - break; - case 533: - pSCU_Reg->CRU_DPLL_CON = (0x1<<16) | (0x1<<15) | (1<<10) | (43<<3) | (0<<1); //high band 528 - break; - } - - delayus(1); //delay at least 500ns - pSCU_Reg->CRU_DPLL_CON &= ~(0x1<<15); - delayus(2000); // 7.2us*140=1.008ms - - // ddr pll normal - value = pSCU_Reg->CRU_MODE_CON; - value &=~(0x3<<6); - value |= 0x1<<6; - pSCU_Reg->CRU_MODE_CON = value; - - // ddr_pll_clk: clk_ddr=1:1 - value = pSCU_Reg->CRU_CLKSEL_CON[7]; - value &=~(0x1F<<24); - value |= (0x0 <<26)| (0x0<<24); - pSCU_Reg->CRU_CLKSEL_CON[7] = value; -} - - -static void __sramfunc DDR_ChangePrior(void) -{ - // 4_VCODEC(2) 3_GPU(1) 2_LCD(0) 1_PERI(1) 0_CPU(2) - pGRF_Reg->GRF_MEM_CON = (pGRF_Reg->GRF_MEM_CON & ~0x3FF) | VCODEC_PRIO(2) | GPU_PRIO(1) | LCD_PRIO(0) | PERI_PRIO(1) | CPU_PRIO(2); -} - -//Õâ¸öº¯ÊýµÄÇ°ÌáÌõ¼þÊÇ: -// 1, ²»ÄÜÓÐDDR·ÃÎÊ -// 2, ChangeDDRFreqº¯Êý¼°º¯ÊýÖÐËùµ÷Óõ½µÄËùÓк¯Êý¶¼²»·ÅÔÚDDRÖÐ -// 3, ¶ÑÕ»²»·ÅÔÚDDRÖÐ -// 4, ÖжϹرգ¬·ñÔò¿ÉÄÜÖжϻáÒýÆð·ÃÎÊDDR - -void __sramfunc ChangeDDRFreqInSram(u32 oldMHz, u32 newMHz) -{ - StopDDR(oldMHz, newMHz); - PLLSetAUXFreq(newMHz); - ResumeDDR(newMHz); -} - -void __sramfunc DDRDLLSetMode(eDDRDLLMode_t DLLmode, u32 freq) -{ - if( DLLmode == DLL_BYPASS ) - { - pDDR_Reg->DLLCR09[0] |= 1<<28; - pDDR_Reg->DLLCR09[1] |= 1<<28; - pDDR_Reg->DLLCR09[2] |= 1<<28; - pDDR_Reg->DLLCR09[3] |= 1<<28; - pDDR_Reg->DLLCR09[4] |= 1<<28; - if(freq <= 100) - pDDR_Reg->DLLCR &= ~(1<<23); - else if(freq <=200) - pDDR_Reg->DLLCR |= 1<<23; - } - else - { - pDDR_Reg->DLLCR09[0] &= ~(1<<28); - pDDR_Reg->DLLCR09[1] &= ~(1<<28); - pDDR_Reg->DLLCR09[2] &= ~(1<<28); - pDDR_Reg->DLLCR09[3] &= ~(1<<28); - pDDR_Reg->DLLCR09[4] &= ~(1<<28); - } -} -typedef struct DDR_CONFIG_Tag -{ - u32 row; - u32 bank; - u32 col; - u32 config; -}DDR_CONFIG_T; - -DDR_CONFIG_T ddrConfig[3][10] = { - //row, bank, col, config - { - //DDR2 - // x16 - {15, 8, 10, (DIO_16 | DSIZE_4Gb)}, - {14, 8, 10, (DIO_16 | DSIZE_2Gb)}, - {13, 8, 10, (DIO_16 | DSIZE_1Gb)}, - {13, 4, 10, (DIO_16 | DSIZE_512Mb)}, - {13, 4, 9, (DIO_16 | DSIZE_256Mb)}, - // x8 - {16, 8, 10, (DIO_8 | DSIZE_4Gb)}, - {15, 8, 10, (DIO_8 | DSIZE_2Gb)}, - {14, 8, 10, (DIO_8 | DSIZE_1Gb)}, - {14, 4, 10, (DIO_8 | DSIZE_512Mb)}, - {13, 4, 10, (DIO_8 | DSIZE_256Mb)}, - }, - { - //DDR3 - // x16 - {16, 8, 10, (DIO_16 | DSIZE_8Gb)}, - {15, 8, 10, (DIO_16 | DSIZE_4Gb)}, - {14, 8, 10, (DIO_16 | DSIZE_2Gb)}, - {13, 8, 10, (DIO_16 | DSIZE_1Gb)}, - {12, 8, 10, (DIO_16 | DSIZE_512Mb)}, - // x8 - {16, 8, 11, (DIO_16 | DSIZE_8Gb)}, - {16, 8, 10, (DIO_16 | DSIZE_4Gb)}, - {15, 8, 10, (DIO_16 | DSIZE_2Gb)}, - {14, 8, 10, (DIO_16 | DSIZE_1Gb)}, - {13, 8, 10, (DIO_16 | DSIZE_512Mb)}, - }, - { - // x32 - {14, 4, 10, (DIO_32 | DSIZE_2Gb)}, - {13, 4, 10, (DIO_32 | DSIZE_1Gb)}, - {13, 4, 9, (DIO_32 | DSIZE_512Mb)}, - {12, 4, 9, (DIO_32 | DSIZE_256Mb)}, - // x16 - {14, 4, 11, (DIO_16 | DSIZE_2Gb)}, - {14, 4, 10, (DIO_16 | DSIZE_1Gb)}, - {13, 4, 10, (DIO_16 | DSIZE_512Mb)}, - {13, 4, 9, (DIO_16 | DSIZE_256Mb)}, - {12, 4, 9, (DIO_16 | DSIZE_128Mb)}, - {0, 0, 0, 0}, - } -}; - -/*------------------------------------------------------------------- -Name : DDR_Init -Desc : ddr initialize -Params : -Return : -Notes : --------------------------------------------------------------------*/ -u32 ddrDataTraining[16]; -void DDR_Init(void) -{ - volatile u32 value = 0; - u32 addr; - u32 MHz; - unsigned long Hz; - u32 memType = (pDDR_Reg->DCR & 0x3); - u32 bw; - u32 col; - u32 row; - u32 bank; - u32 n; - - // caculate aglined physical address - addr = __pa((unsigned long)ddrDataTraining); - if(addr&0x1F) - { - addr += (32-(addr&0x1F)); - } - addr -= 0x60000000; - // caculate data width - bw = ((((pDDR_Reg->DCR >> 7) & 0x7)+1)>>1); - // find out col£¬row£¬bank - for(n=0;n<10; n++) - { - if(ddrConfig[(pDDR_Reg->DCR & 0x3)][n].config == (pDDR_Reg->DCR & 0x7c)) - { - col = ddrConfig[(pDDR_Reg->DCR & 0x3)][n].col; - row = ddrConfig[(pDDR_Reg->DCR & 0x3)][n].row; - bank = ddrConfig[(pDDR_Reg->DCR & 0x3)][n].bank; - bank >>= 2; // 8=>3, 4=>2 - bank += 1; - break; - } - } - if(n == 10) - { - //ASSERT - } - - // according different address mapping, caculate DTAR register value - value = pDDR_Reg->DTAR; - value &= ~(0x7FFFFFFF); - switch(pDDR_Reg->DCR & (0x3<<14)) - { - case AMAP_RBRC: - value |= (addr>>bw) & ((0x1<>(bw+col)) & ((0x1<>(bw+col+row)) & ((0x1<>bw) & ((0x1<>(bw+col+bank)) & ((0x1<>(bw+col)) & ((0x1<>bw) & ((0x1<DCR >> 11) & 0x3) - { - value |= ((addr>>(bw+col+1)) & ((0x1<>(bw+col+row+1)) & ((0x1<>(bw+col)) & ((0x1<>(bw+col+row)) & ((0x1<DTAR = value; - - if((memType == DDRII) || (memType == DDR3)) - { - pDDR_Reg->ALPMR = LPPERIOD_POWER_DOWN(0xFF)|AUTOPD; - } - else - { - pDDR_Reg->ALPMR = LPPERIOD_CLK_STOP(0xFF) | LPPERIOD_POWER_DOWN(0xFF) | AUTOCS | AUTOPD; - } - DDR_ChangePrior(); - value = (((pDDR_Reg->DCR >> 7) & 0x7)+1) >> ((pDDR_Reg->DCR >> 2) & 0x3); - capability = 0x800000 << (((pDDR_Reg->DCR >> 4) & 0x7) + value + ((pDDR_Reg->DCR >> 11) & 0x3)); - - Hz = clk_get_rate(clk_get(NULL,"ddr")); - MHz = Hz/1000000; //PLLGetDDRFreq()/1000; - printk("DDR_Init: freq=%dMHz\n", MHz); - if((memType == DDRII) || (memType == Mobile_DDR)) - { - DDRPreUpdateRef(MHz); - DDRPreUpdateTiming(MHz); - DDRUpdateRef(); - DDRUpdateTiming(); - } - -} - -/*------------------------------------------------------------------- -Name : DDR_ChangeFreq -Desc : change ddr frequency -Params : -Return : -Notes : close interrupt before call it - open interrupt after call it --------------------------------------------------------------------*/ -void DDR_ChangeFreq(u32 DDRoldMHz, u32 DDRnewMHz) -{ - - DDRPreUpdateRef(DDRnewMHz); - DDRPreUpdateTiming(DDRnewMHz); - DDR_SAVE_SP(save_sp); - flush_cache_all(); // 20100615,HSL@RK. - __cpuc_flush_user_all(); - ChangeDDRFreqInSram(DDRoldMHz, DDRnewMHz); - DDR_RESTORE_SP(save_sp); -} - -//////////////////////////////////////////////////////////////////////////////////// - -/*------------------------------------------------------------------- -Name : DDR_EnterSelfRefresh -Desc : DDR enter self refresh call in ddr -Params : -Return : -Notes : 1. ddr enter sel-refresh must be after system enter idle ,after ddr enter sel-refresh must not access ddr - 2. ddr enter sel-refresh code must not be in ddr --------------------------------------------------------------------*/ -void __sramfunc DDR_EnterSelfRefresh(void) -{ - EnterDDRSelfRefresh(); -#if 1 - pSCU_Reg->CRU_CLKGATE_CON[0] |= (0x1<<18); //close DDR PHY clock / DDR CPU AXI clock / DDR REG AXI clock - delayus(10); - // ddr slow - pSCU_Reg->CRU_MODE_CON &=~(0x3<<6); - delayus(10); - pSCU_Reg->CRU_DPLL_CON |= (0x1 << 15); //power down DPLL - delayus(10); //delay at least 500ns -#endif -} - -/*------------------------------------------------------------------- -Name : DDR_ExitSelfRefresh -Desc : DDR exit self refresh -Params : -Return : -Notes : 1. ddr enter sel-refresh must be after system enter idle ,after ddr enter sel-refresh must not access ddr - 2. ddr enter sel-refresh code must not be in ddr --------------------------------------------------------------------*/ -void __sramfunc DDR_ExitSelfRefresh(void) -{ - u32 value; -#if 1 - pSCU_Reg->CRU_DPLL_CON &= ~(0x1 << 15); //power on DPLL - // while(!(pGRF_Reg->GRF_SOC_CON[0] & (1<<28))); - delayus(200); // 7.2us*140=1.008ms // Ëø¶¨pll - // ddr pll normal - value = pSCU_Reg->CRU_MODE_CON; - value &=~(0x3<<6); - value |= 0x1<<6; - pSCU_Reg->CRU_MODE_CON = value; - delayus(10); - pSCU_Reg->CRU_CLKGATE_CON[0] &= ~(0x1<<18); //enable DDR PHY clock / DDR CPU AXI clock / DDR REG AXI clock - delayus(10); -#endif - ExitDDRSelfRefresh(); - -} - void preload_sram_addr(unsigned int vaddr) -{ - - __asm__( - "mcr p15,0,%0,c8,c5,1 \n\t" - "mcr p15,0,%1,c10,c0,1 \n\t" - "mcr p15,0,%0,c10,c1,1 \n\t" - "mcr p15,0,%2,c10,c0,1\n\t" - ::"r"(vaddr) , "r"(0x00000001), "r"(0x08400000)); -} -// consider cpu prefetch¡¢mmu cache -static void __sramfunc do_selfrefreshtest(void) -{ - volatile u32 n; - //local_flush_tlb_all(); - //preload_sram_addr(0xff400000); - flush_cache_all(); // 20100615,HSL@RK. - __cpuc_flush_kern_all(); - __cpuc_flush_user_all(); - - - // pSCU_Reg->CRU_CLKGATE_CON[1] |= 1<<6; // disable DDR Periph clock - // pSCU_Reg->CRU_CLKGATE_CON[3] |= 1<<1 |1<<11|1<<13|1<<16; // disable DDR LCDC / DDR VPU / DDR GPU clock - -#if 1 -volatile unsigned int * temp=(volatile unsigned int *)SRAM_CODE_OFFSET; -n=temp[0]; -barrier(); -n=temp[1024]; -barrier(); -n=temp[1024*2]; -barrier(); -n=temp[1024*3]; -barrier(); - - - -#endif - n= pDDR_Reg->CCR; - n= pSCU_Reg->CRU_SOFTRST_CON[0]; - dsb(); - - DDR_EnterSelfRefresh(); - DDR_ExitSelfRefresh(); - dsb(); -} - -static void selfrefreshtest(void) -{ - DDR_SAVE_SP(save_sp); - do_selfrefreshtest(); - DDR_RESTORE_SP(save_sp); -} - -static void changefreqtest(u32 DDRnewMHz) -{ - u32 MHz; - u32 value =0; - unsigned long Hz; - - Hz = clk_get_rate(clk_get(NULL,"ddr")); - MHz = Hz /1000000; // PLLGetDDRFreq()/1000; - DDRPreUpdateRef(DDRnewMHz); - DDRPreUpdateTiming(DDRnewMHz); - DDR_SAVE_SP(save_sp); - flush_cache_all(); // 20100615,HSL@RK. - __cpuc_flush_user_all(); - ChangeDDRFreqInSram(MHz, DDRnewMHz); - DDRDLLSetMode(DLL_BYPASS,DDRnewMHz); - DDR_RESTORE_SP(save_sp); -} - -#ifdef CONFIG_HAS_EARLYSUSPEND - - -static __sramdata u32 gfreq = 0; -static void suspend(struct early_suspend *h) -{ - u32 MHz; - unsigned long Hz; - unsigned long flags; - - local_irq_save(flags); - Hz = clk_get_rate(clk_get(NULL,"ddr")); - MHz = Hz /1000000; - gfreq = MHz; - - udelay(1000); - - DDR_ChangeFreq(MHz,200); - - local_irq_restore(flags); - - //printk("enter ddr early suspend\n"); -} - -static void resume(struct early_suspend *h) -{ - - unsigned long flags; - - local_irq_save(flags); - - udelay(1000); - - DDR_ChangeFreq(200,333); - - local_irq_restore(flags); - - //printk("enter ddr early suspend resume \n"); -} - -struct early_suspend early_suspend_info = { - .suspend = suspend, - .resume = resume, - .level = EARLY_SUSPEND_LEVEL_DISABLE_FB +1, -}; -#endif - - -void __sramfunc ddr_suspend(void) -{ - volatile u32 n; - flush_cache_all(); // 20100615,HSL@RK. - __cpuc_flush_kern_all(); - __cpuc_flush_user_all(); - - - // pSCU_Reg->CRU_CLKGATE_CON[1] |= 1<<6; // disable DDR Periph clock - // pSCU_Reg->CRU_CLKGATE_CON[3] |= 1<<1 |1<<11|1<<13|1<<16; // disable DDR LCDC / DDR VPU / DDR GPU clock - -#if 1 - volatile unsigned int * temp=(volatile unsigned int *)SRAM_CODE_OFFSET; - n=temp[0]; - barrier(); - n=temp[1024]; - barrier(); - n=temp[1024*2]; - barrier(); - n=temp[1024*3]; - barrier(); - -#endif - n= pDDR_Reg->CCR; - n= pSCU_Reg->CRU_SOFTRST_CON[0]; - // flush_cache_all(); // 20100615,HSL@RK. - //__cpuc_flush_kern_all(); - //__cpuc_flush_user_all(); - //barrier(); - dsb();//dmb(); - DDR_EnterSelfRefresh(); -} - -void __sramfunc ddr_resume(void) -{ -#if 0 - unsigned long flags; - - local_irq_save(flags); - udelay(1000); - DDR_ChangeFreq(200,333); - local_irq_restore(flags); -#else - DDR_ExitSelfRefresh(); - dsb(); -#endif -} - -static int __init ddr_update_freq(void) -{ - - DDR_Init(); - -#if 0 //#ifdef CONFIG_HAS_EARLYSUSPEND - register_early_suspend(&early_suspend_info); -#endif - - - - - return 0; -} - -core_initcall_sync(ddr_update_freq); -//late_initcall(ddr_update_freq); - +/* + * arch/arm/mach-rk29/ddr.c + * + * Function Driver for DDR controller + * + * Copyright (C) 2011 Fuzhou Rockchip Electronics Co.,Ltd + * Author: + * hcy@rock-chips.com + * yk@rock-chips.com + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + + +#include + +#define ddr_print(x...) printk( "ddr init: " x ) + +// save_sp must be static global variable + +static unsigned long save_sp; + + +//CCR; //Controller Configuration Register +#define ECCEN (1) +#define NOMRWR (1<<1) +#define HOSTEN (1<<2) +#define RRB (1<<13) +#define DQSCFG (1<<14) +#define DFTLM_NO (0<<15) +#define DFTLM_90 (1<<15) +#define DFTLM_180 (2<<15) +#define DFTLM_270 (3<<15) +#define DFTCMP (1<<17) +#define FLUSH (1<<27) +#define ITMRST (1<<28) +#define IB (1<<29) +#define DTT (1<<30) +#define IT (1<<31) +//DCR; //DRAM Configuration Register +#define DDRII (0) +#define DDR3 (1) +#define Mobile_DDR (2) + +#define DIO_8 (1<<2) +#define DIO_16 (2<<2) +#define DIO_32 (3<<2) + +#define DSIZE_64Mb (0<<4) +#define DSIZE_128Mb (1<<4) +#define DSIZE_256Mb (2<<4) +#define DSIZE_512Mb (3<<4) +#define DSIZE_1Gb (4<<4) +#define DSIZE_2Gb (5<<4) +#define DSIZE_4Gb (6<<4) +#define DSIZE_8Gb (7<<4) + +#define SIO(n) (((n)-1)<<7) +#define PIO (1<<10) +#define RANKS(n) ((((n)-1)&0x3)<<11) +#define RNKALL (1<<13) + +#define AMAP_RBRC (0<<14) //rank,bank,row,column +#define AMAP_RRBC (1<<14) //rank,row,bank,column +#define AMAP_BRRC (2<<14) //bank,row,rank,column +#define AMAP_FIX (3<<14) //Fixed address + +#define PDQ(n) (((n)&0x7)<<16) +#define MPRDQ (1<<19) +#define MVAR (1<<20) +#define RDIMM (1<<21) +#define DO_INIT (1<<24) +#define EXE_RANK(n) (((n)&3)<<25) + +#define CMD_NOP (0<<27) +#define CMD_ClockStop (1<<27) +#define CMD_SelfRefresh (2<<27) +#define CMD_Refresh (3<<27) +#define CMD_DDR3_Reset (4<<27) +#define CMD_PrechargeAll (5<<27) +#define CMD_DeepPowerDown (6<<27) +#define CMD_SDRAM_Mode_Exit (7<<27) +#define CMD_SDRAM_ZQ_Calibration_Short (0xB<<27) +#define CMD_SDRAM_ZQ_Calibration_Long (0xC<<27) +#define CMD_PowerDown (0xE<<27) +#define CMD_SDRAM_NOP (0xF<<27) + +#define EXE (1<<31) + +//IOCR; //IO Configuration Register +#define DQ_ODT (1) +#define DQS_ODT (1<<1) +#define TESTEN (1<<2) +#define DQ_RTT_DIS (0<<3) +#define DQ_RTT_150 (1<<3) +#define DQ_RTT_75 (2<<3) +#define DQ_RTT_50 (3<<3) +#define DQS_RTT_DIS (0<<5) +#define DQS_RTT_150 (1<<5) +#define DQS_RTT_75 (2<<5) +#define DQS_RTT_50 (3<<5) +#define DQ_DS_FULL (1<<7) +#define DQ_DS_REDUCE (0<<7) +#define DQS_DS_FULL (1<<8) +#define DQS_DS_REDUCE (0<<8) +#define ADD_DS_FULL (1<<9) +#define ADD_DS_REDUCE (0<<9) +#define CK_DS_FULL (1<<10) +#define CK_DS_REDUCE (0<<10) + +#define AUTO_CMD_IOPD(n) (((n)&0x3)<<18) +#define AUTO_DATA_IOPD(n) (((n)&0x3)<<22) +#define RTTOH(n) (((n)&0x7)<<26) +#define RTTOE (1<<29) +#define DQRTT (1<<30) +#define DQSRTT (1<<31) + +//CSR; //Controller Status Register +#define DFTERR (1<<18) +#define ECCERR (1<<19) +#define DTERR (1<<20) +#define DTIERR (1<<21) +#define ECCSEC (1<<22) +#define TQ (1<<23) + +//DRR; //DRAM Refresh Register +#define TRFC(n) ((n)&0xFF) +#define TRFPRD(n) (((n)&0xFFFF)<<8) +#define RFBURST(n) ((((n)-1)&0xF)<<24) +#define RD (1<<31) + +//TPR[3]; //SDRAM Timing Parameters Registers +//TPR0 +#define TMRD(n) ((n)&0x3) +#define TRTP(n) (((n)&0x7)<<2) +#define TWTR(n) (((n)&0x7)<<5) +#define TRP(n) (((n)&0xF)<<8) +#define TRCD(n) (((n)&0xF)<<12) +#define TRAS(n) (((n)&0x1F)<<16) +#define TRRD(n) (((n)&0xF)<<21) +#define TRC(n) (((n)&0x3F)<<25) +#define TCCD (1<<31) +//TPR1 +#define TAOND_2 (0) +#define TAOND_3 (1) +#define TAOND_4 (2) +#define TAOND_5 (3) +#define TRTW (1<<2) +#define TFAW(n) (((n)&0x3F)<<3) +#define TMOD(n) (((n)&0x3)<<9) +#define TRTODT (1<<11) +#define TRNKRTR(n) ((((n)-1)&0x3)<<12) +#define TRNKWTW(n) (((n)&0x3)<<14) +//TPR2 +#define TXS(n) ((n)&0x3FF) +#define TXP(n) (((n)&0x1F)<<10) +#define TCKE(n) (((n)&0xF)<<15) + +//DLLCR; //Global DLL Control Register +//DLLCR09[10]; //DDR Control Register 0-9 +#define DD (1<<31) + +//RSLR[4]; //Rank System Latency Register 0-3 +#define SL(n,value) (((value)&0x7)<<((n)*3)) + +//RDGR[4]; //Rank DQS Gating Register 0-3 +#define DQSSEL(n, value) (((value)&0x3)<<((n)*2)) + +//DQTR[9]; //DQ Timing Register 0-8 +#define DQDLY_DQS(n, value) (((value)&0x3)<<((n)*4)) +#define DQDLY_DQSb(n, value) (((value)&0x3)<<(((n)*4)+2)) + +//DQSTR; //DQS Timing Register +//DQSBTR; //DQS_b Timing Register +#define DQSDLY(n, value) (((value)&0x7)<<((n)*3)) + +//ODTCR; //ODT Configuration Register +#define RDODT(rank, value) (((value)&0xF)<<((rank)*4)) +#define WRODT(rank, value) (((value)&0xF)<<(((rank)*4)+16)) + +//DTR[2]; //Data Training Register 0-1 +//DTAR; //Data Training Address Register +#define DTCOL(col) ((col)&0xFFF) +#define DTROW(row) (((row)&0xFFFF)<<12) +#define DTBANK(bank) (((bank)&0x7)<<28) +#define DTMPR (1<<31) + +//ZQCR[3]; //SDRAM ZQ Control Register and SDRAM ZQCS Control Register 0-2 +//ZQCR0 +#define ZQDATA(n) ((n)&0xFFFFF) +#define ZPROG_OUT(n) (((n)&0xF)<<20) +#define ZPROG_ODT(n) (((n)&0xF)<<24) +#define ZQDEN (1<<28) +#define ZQCLK (1<<29) +#define NOICAL (1<<30) +#define ZQCAL (1<<31) +//ZQCR1 +#define ZQ_CALPRD(n) ((n)&0x7FFF) +#define ZQ_CAL_EN (1<<31) +//ZQCR2 +#define ZQCS_CALPRD(n) ((n)&0x7FFF) +#define ZQCS_CAL_EN (1<<31) + +//ZQSR; //SDRAM ZQ Status Register +//TPR3; //SDRAM Timing Parameters Register 3 +#define BL2 (0) +#define BL4 (1) +#define BL8 (2) +#define BL16 (3) +#define BLOTF_EN (1<<2) +#define CL(n) (((n)&0xF)<<3) +#define CWL(n) (((n)&0xF)<<7) +#define WR(n) (((n)&0xF)<<11) +#define AL(n) (((n)&0xF)<<15) + +//ALPMR; //Automatic Low Power Mode Register +#define LPPERIOD_CLK_STOP(n) ((n)&0xFF) +#define LPPERIOD_POWER_DOWN(n) (((n)&0xFF)<<8) +#define AUTOCS (1<<25) +#define AUTOPD (1<<26) + +//Reserved[0x7c-0x30]; +//MR; //Mode Register +#define DDR_BL4 (2) +#define DDR_BL8 (3) +#define DDR_CL(n) (((n)&0x7)<<4) +#define DDR2_WR(n) ((((n)-1)&0x7)<<9) + +//mr0 for ddr3 +#define DDR3_BL8 (0) +#define DDR3_BC4_8 (1) +#define DDR3_BC4 (2) +#define DDR3_BL(n) (n) +#define DDR3_CL(n) ((((n-4)&0x7)<<4)|(((n-4)&0x8)>>1)) +#define DDR3_MR0_CL(n) ((((n-4)&0x7)<<4)|(((n-4)&0x8)>>1)) +#define DDR3_MR0_WR(n) (((n)&0x7)<<9) +#define DDR3_MR0_DLL_RESET (1<<8) +#define DDR3_MR0_DLL_NOR (0<<8) + +//mr1 for ddr3 +#define DDR3_MR1_AL(n) ((n&0x7)<<3) +#define DDR3_MR1_DIC(n) (((n&1)<<1)|((n&2)<<4)) +#define DDR3_MR1_RTT_NOM(n) (((n&1)<<2)|((n&2)<<5)|((n&4)<<7)) + +//mr2 for ddr3 +#define DDR3_MR2_CWL(n) (((n-5)&0x7)<<3) + +//EMR; //Extended Mode Register +#define DDR2_STR_FULL (0) +#define DDR2_STR_REDUCE (1<<1) +#define DDR2_AL(n) (((n)&0x7)<<3) +#define DDR2_ODT_DIS (0) +#define DDR2_ODT_150 (0x40) +#define DDR2_ODT_75 (0x4) +#define DDR2_ODT_50 (0x44) + +//EMR2; //Extended Mode Register 2 +//EMR3; //Extended Mode Register 3 +//y Management Unit Registers +//HPCR[32]; //Host Port Configuration Register 0-31 +#define HPBL(n) ((n)&0xFF) +#define HCBP (1<<8) +#define HNPC (1<<9) + +//PQCR[8]; //Priority Queue Configuration Register 0-7 +#define TOUT(n) ((n)&0xFF) +#define TOUT_MUL_1 (0<<8) +#define TOUT_MUL_16 (1<<8) +#define TOUT_MUL_64 (2<<8) +#define TOUT_MUL_256 (3<<8) +#define LPQS(n) (((n)&0x3)<<10) +#define PQBL(n) (((n)&0xFF)<<12) +#define SWAIT(n) (((n)&0x1F)<<20) +#define INTRPT(n) (((n)&0x7)<<25) +#define APQS (1<<28) + +#define PLL_CLKR(i) ((((i) - 1) & 0x1f) << 10) + +#define PLL_CLKF(i) ((((i) - 1) & 0x7f) << 3) + +#define PLL_CLKOD(i) (((i) & 0x03) << 1) + +//MMGCR; //Memory Manager General Configuration Register +#define PORT0_NORMAL_PRIO (0) +#define PORT0_HIGH_PRIO (2) + +#define DDR3_800D (0) // 5-5-5 +#define DDR3_800E (1) // 6-6-6 +#define DDR3_1066E (2) // 6-6-6 +#define DDR3_1066F (3) // 7-7-7 +#define DDR3_1066G (4) // 8-8-8 +#define DDR3_1333F (5) // 7-7-7 +#define DDR3_1333G (6) // 8-8-8 +#define DDR3_1333H (7) // 9-9-9 +#define DDR3_1333J (8) // 10-10-10 +#define DDR3_1600G (9) // 8-8-8 +#define DDR3_1600H (10) // 9-9-9 +#define DDR3_1600J (11) // 10-10-10 +#define DDR3_1600K (12) // 11-11-11 +#define DDR3_1866J (13) // 10-10-10 +#define DDR3_1866K (14) // 11-11-11 +#define DDR3_1866L (15) // 12-12-12 +#define DDR3_1866M (16) // 13-13-13 +#define DDR3_2133K (17) // 11-11-11 +#define DDR3_2133L (18) // 12-12-12 +#define DDR3_2133M (19) // 13-13-13 +#define DDR3_2133N (20) // 14-14-14 +#define DDR3_DEFAULT (21) +#define DDR3_NONE (22) + +#ifdef CONFIG_RK29_DDR3_TYPE +#define DDR3_TYPE CONFIG_RK29_DDR3_TYPE +#else +#define DDR3_TYPE DDR3_DEFAULT//DDR3_NONE +#endif +/* DDR Controller register struct */ +typedef volatile struct DDR_REG_Tag +{ + volatile unsigned int CCR; //Controller Configuration Register + volatile unsigned int DCR; //DRAM Configuration Register + volatile unsigned int IOCR; //IO Configuration Register + volatile unsigned int CSR; //Controller Status Register + volatile unsigned int DRR; //DRAM Refresh Register + volatile unsigned int TPR[3]; //SDRAM Timing Parameters Registers + volatile unsigned int DLLCR; //Global DLL Control Register + volatile unsigned int DLLCR09[10]; //DDR Control Register 0-9 + volatile unsigned int RSLR[4]; //Rank System Latency Register 0-3 + volatile unsigned int RDGR[4]; //Rank DQS Gating Register 0-3 + volatile unsigned int DQTR[9]; //DQ Timing Register 0-8 + volatile unsigned int DQSTR; //DQS Timing Register + volatile unsigned int DQSBTR; //DQS_b Timing Register + volatile unsigned int ODTCR; //ODT Configuration Register + volatile unsigned int DTR[2]; //Data Training Register 0-1 + volatile unsigned int DTAR; //Data Training Address Register + volatile unsigned int ZQCR[3]; //SDRAM ZQ Control Register and SDRAM ZQCS Control Register 0-2 + volatile unsigned int ZQSR; //SDRAM ZQ Status Register + volatile unsigned int TPR3; //SDRAM Timing Parameters Register 3 + volatile unsigned int ALPMR; //Automatic Low Power Mode Register + volatile unsigned int Reserved[0x7c-0x30]; + volatile unsigned int MR; //Mode Register + volatile unsigned int EMR; //Extended Mode Register + volatile unsigned int EMR2; //Extended Mode Register 2 + volatile unsigned int EMR3; //Extended Mode Register 3 + //Memory Management Unit Registers + volatile unsigned int HPCR[32]; //Host Port Configuration Register 0-31 + volatile unsigned int PQCR[8]; //Priority Queue Configuration Register 0-7 + volatile unsigned int MMGCR; //Memory Manager General Configuration Register +}DDR_REG_T, *pDDR_REG_T; + +typedef struct tagGPIO_IOMUX +{ + volatile unsigned int GPIOL_IOMUX; + volatile unsigned int GPIOH_IOMUX; +}GPIO_IOMUX_T; + +//GRF Registers +typedef volatile struct tagREG_FILE +{ + volatile unsigned int GRF_GPIO_DIR[6]; + volatile unsigned int GRF_GPIO_DO[6]; + volatile unsigned int GRF_GPIO_EN[6]; + GPIO_IOMUX_T GRF_GPIO_IOMUX[6]; + volatile unsigned int GRF_GPIO_PULL[7]; + volatile unsigned int GRF_UOC_CON[2]; + volatile unsigned int GRF_USB_CON; + volatile unsigned int GRF_CPU_CON[2]; + volatile unsigned int GRF_CPU_STATUS; + volatile unsigned int GRF_MEM_CON; + volatile unsigned int GRF_MEM_STATUS[3]; + volatile unsigned int GRF_SOC_CON[5]; + volatile unsigned int GRF_OS_REG[4]; +} REG_FILE, *pREG_FILE; + +//CRU Registers +typedef volatile struct tagCRU_REG +{ + volatile unsigned int CRU_APLL_CON; + volatile unsigned int CRU_DPLL_CON; + volatile unsigned int CRU_CPLL_CON; + volatile unsigned int CRU_PPLL_CON; + volatile unsigned int CRU_MODE_CON; + volatile unsigned int CRU_CLKSEL_CON[18]; + volatile unsigned int CRU_CLKGATE_CON[4]; + volatile unsigned int CRU_SOFTRST_CON[3]; +} CRU_REG, *pCRU_REG; + +// controller base address +#define pDDR_Reg ((pDDR_REG_T)RK29_DDRC_BASE) +#define pGRF_Reg ((pREG_FILE)RK29_GRF_BASE) +#define pSCU_Reg ((pCRU_REG)RK29_CRU_BASE) + +typedef struct DDR_CONFIG_Tag +{ + u32 row; + u32 bank; + u32 col; + u32 config; +}DDR_CONFIG_T; + +uint32_t ddrDataTraining[16]; + +DDR_CONFIG_T ddrConfig[3][10] = { + //row, bank, col, config + { + //DDR2 + // x16 + {15, 8, 10, (DIO_16 | DSIZE_4Gb)}, + {14, 8, 10, (DIO_16 | DSIZE_2Gb)}, + {13, 8, 10, (DIO_16 | DSIZE_1Gb)}, + {13, 4, 10, (DIO_16 | DSIZE_512Mb)}, + {13, 4, 9, (DIO_16 | DSIZE_256Mb)}, + // x8 + {16, 8, 10, (DIO_8 | DSIZE_4Gb)}, + {15, 8, 10, (DIO_8 | DSIZE_2Gb)}, + {14, 8, 10, (DIO_8 | DSIZE_1Gb)}, + {14, 4, 10, (DIO_8 | DSIZE_512Mb)}, + {13, 4, 10, (DIO_8 | DSIZE_256Mb)}, + }, + { + //DDR3 + // x16 + {16, 8, 10, (DIO_16 | DSIZE_8Gb)}, + {15, 8, 10, (DIO_16 | DSIZE_4Gb)}, + {14, 8, 10, (DIO_16 | DSIZE_2Gb)}, + {13, 8, 10, (DIO_16 | DSIZE_1Gb)}, + {12, 8, 10, (DIO_16 | DSIZE_512Mb)}, + // x8 + {16, 8, 11, (DIO_16 | DSIZE_8Gb)}, + {16, 8, 10, (DIO_16 | DSIZE_4Gb)}, + {15, 8, 10, (DIO_16 | DSIZE_2Gb)}, + {14, 8, 10, (DIO_16 | DSIZE_1Gb)}, + {13, 8, 10, (DIO_16 | DSIZE_512Mb)}, + }, + { + //mobile DDR + // x32 + {14, 4, 10, (DIO_32 | DSIZE_2Gb)}, + {13, 4, 10, (DIO_32 | DSIZE_1Gb)}, + {13, 4, 9, (DIO_32 | DSIZE_512Mb)}, + {12, 4, 9, (DIO_32 | DSIZE_256Mb)}, + // x16 + {14, 4, 11, (DIO_16 | DSIZE_2Gb)}, + {14, 4, 10, (DIO_16 | DSIZE_1Gb)}, + {13, 4, 10, (DIO_16 | DSIZE_512Mb)}, + {13, 4, 9, (DIO_16 | DSIZE_256Mb)}, + {12, 4, 9, (DIO_16 | DSIZE_128Mb)}, + {0, 0, 0, 0}, + } +}; + +uint32_t __sramdata ddr3_cl_cwl[22][3]={ +/* 0~330 330~400 400~533 speed +* tCK >3 2.5~3 1.875~2.5 +* cl<<16, cwl cl<<16, cwl cl<<16, cwl */ + {((5<<16)|5), ((5<<16)|5), 0 }, //DDR3_800D + {((5<<16)|5), ((6<<16)|5), 0 }, //DDR3_800E + + {((5<<16)|5), ((5<<16)|5), ((6<<16)|6) }, //DDR3_1066E + {((5<<16)|5), ((6<<16)|5), ((7<<16)|6) }, //DDR3_1066F + {((5<<16)|5), ((6<<16)|5), ((8<<16)|6) }, //DDR3_1066G + + {((5<<16)|5), ((5<<16)|5), ((6<<16)|6) }, //DDR3_1333F + {((5<<16)|5), ((5<<16)|5), ((7<<16)|6) }, //DDR3_1333G + {((5<<16)|5), ((6<<16)|5), ((7<<16)|6) }, //DDR3_1333H + {((5<<16)|5), ((6<<16)|5), ((8<<16)|6) }, //DDR3_1333J + + {((5<<16)|5), ((5<<16)|5), ((6<<16)|6) }, //DDR3_1600G + {((5<<16)|5), ((5<<16)|5), ((6<<16)|6) }, //DDR3_1600H + {((5<<16)|5), ((5<<16)|5), ((7<<16)|6) }, //DDR3_1600J + {((5<<16)|5), ((6<<16)|5), ((7<<16)|6) }, //DDR3_1600K + + {((5<<16)|5), ((5<<16)|5), ((6<<16)|6) }, //DDR3_1866J + {((5<<16)|5), ((5<<16)|5), ((7<<16)|6) }, //DDR3_1866K + {((6<<16)|5), ((6<<16)|5), ((7<<16)|6) }, //DDR3_1866L + {((6<<16)|5), ((6<<16)|5), ((8<<16)|6) }, //DDR3_1866M + + {((5<<16)|5), ((5<<16)|5), ((6<<16)|6) }, //DDR3_2133K + {((5<<16)|5), ((5<<16)|5), ((6<<16)|6) }, //DDR3_2133L + {((5<<16)|5), ((5<<16)|5), ((7<<16)|6) }, //DDR3_2133M + {((6<<16)|5), ((6<<16)|5), ((7<<16)|6) }, //DDR3_2133N + + {((6<<16)|5), ((6<<16)|5), ((8<<16)|6) } //DDR3_DEFAULT + +}; +uint32_t __sramdata ddr3_tRC_tFAW[22]={ +/** tRC tFAW */ + ((50<<16)|50), //DDR3_800D + ((53<<16)|50), //DDR3_800E + + ((49<<16)|50), //DDR3_1066E + ((51<<16)|50), //DDR3_1066F + ((53<<16)|50), //DDR3_1066G + + ((47<<16)|45), //DDR3_1333F + ((48<<16)|45), //DDR3_1333G + ((50<<16)|45), //DDR3_1333H + ((51<<16)|45), //DDR3_1333J + + ((45<<16)|40), //DDR3_1600G + ((47<<16)|40), //DDR3_1600H + ((48<<16)|40), //DDR3_1600J + ((49<<16)|40), //DDR3_1600K + + ((45<<16)|35), //DDR3_1866J + ((46<<16)|35), //DDR3_1866K + ((47<<16)|35), //DDR3_1866L + ((48<<16)|35), //DDR3_1866M + + ((44<<16)|35), //DDR3_2133K + ((45<<16)|35), //DDR3_2133L + ((46<<16)|35), //DDR3_2133M + ((47<<16)|35), //DDR3_2133N + + ((53<<16)|50) //DDR3_DEFAULT +}; +static __sramdata uint32_t mem_type; +static __sramdata uint32_t capability; // one chip cs capability + +//DDR2 +static __sramdata uint32_t tRFC; +static __sramdata uint32_t tRFPRD; +static __sramdata uint32_t tRTP; +static __sramdata uint32_t tWTR; +static __sramdata uint32_t tRAS; +static __sramdata uint32_t tRRD; +static __sramdata uint32_t tRC; +static __sramdata uint32_t tFAW; +//Mobile-DDR +static __sramdata uint32_t tXS; +static __sramdata uint32_t tXP; +//DDR3 +static __sramdata uint32_t tWR; +static __sramdata uint32_t tWR_MR0; +static __sramdata uint32_t cl; +static __sramdata uint32_t cwl; + +static __sramdata uint32_t cpu_freq; + + + +/**************************************************************************** +Internal sram us delay function +Cpu highest frequency is 1.2 GHz +1 cycle = 1/1.2 ns +1 us = 1000 ns = 1000 * 1.2 cycles = 1200 cycles +*****************************************************************************/ +//static +void __sramlocalfunc delayus(uint32_t us) +{ + uint32_t count; + if(cpu_freq == 600) + count = us * 150;//533; + else + count = us*6; + while(count--) // 3 cycles + barrier(); + +} + +static uint32_t __sramlocalfunc ddr_get_parameter(uint32_t nMHz) +{ + uint32_t tmp; + uint32_t ret = 0; + if(nMHz>533) + { + ret = -1; + goto out; + } + if(mem_type == DDR3) + { + if(DDR3_TYPE == DDR3_NONE) + { + ret = -2; + goto out; + } + /* + * tREFI, average periodic refresh interval, 7.8us max + */ + tRFPRD = ((59*nMHz) >> 3) & 0x3FFF; // 62/8 = 7.75us + + if(capability <= 0x4000000) // 512Mb 90ns + { + tmp = (90*nMHz+999)/1000; + } + else if(capability <= 0x8000000) // 1Gb 110ns + { + tmp = (110*nMHz+999)/1000; + } + else if(capability <= 0x10000000) // 2Gb 160ns + { + tmp = (160*nMHz+999)/1000; + } + else if(capability <= 0x20000000) // 4Gb 300ns + { + tmp = (300*nMHz+999)/1000; + } + else // 8Gb 350ns + { + tmp = (350*nMHz+999)/1000; + } + /* + * tRFC DRR[7:0] + */ + if(tmp > 0xff) + { + ret = -2; + goto out; + } + else + tRFC = tmp; + + /* + * tRTP = max(4nCK,7.5ns), TPR0[4:2], valid values are 2~6 + * tWTR = max(4nCK,7.5ns), TPR0[7:5], valid values are 1~6 + * clock must <533MHz, then tRTP=tWTR=4 + */ + tRTP = 4; + tWTR = 4; + + /* + * tRAS = 33/37.5~9*tREFI, + * TPR0[20:16], valid values are 2~31 + */ + tRAS = (38*nMHz+999)/1000; + + /* + * tRRD = max(4nCK, 7.5ns), DDR3-1066(1K), DDR3-1333(2K), DDR3-1600(2K) + * max(4nCK, 10ns), DDR3-800(1K,2K), DDR3-1066(2K) + * max(4nCK, 6ns), DDR3-1333(1K), DDR3-1600(1K) + * + * TPR0[24:21], valid values are 1~8 + */ + tRRD = (10*nMHz+999)/1000; + + /* + * tRC TPR0[30:25], valid values are 2~42 + */ + tRC = ((ddr3_tRC_tFAW[DDR3_TYPE]>>16)*nMHz+999)/1000; + + /* + * tFAW TPR1[8:3], valid values are 2~31 + */ + tFAW = ((ddr3_tRC_tFAW[DDR3_TYPE]&0x0ff)*nMHz+999)/1000; + + /* + * tXS TPR2[9:0], valid values are 2~1023 + * MAX(tXS, tXSDLL) for DDR3, tXSDLL = tDLLK = 512CK + */ + tXS = 512; + + /* + * max(tXP, tXPDLL) for DDR3 + * tXP = max(3nCK, 7.5ns), DDR3-800, DDR3-1066 + * max(3nCK, 6ns), DDR3-1333, DDR3-1600, DDR3-1866, DDR3-2133 + * tXPDLL = max(10nCK, 24ns) + * TPR2[14:10], valid values are 2~31 + */ + if(nMHz <= 330) + { + tmp = 0; + tXP = 10; + } + else if(nMHz<=400) + { + tmp = 1; + tXP = 10; + } + else // 533 MHz + { + tmp = 2; + tXP = 13; + } + + /* + * tWR TPR3[14:11], valid values are 2~12, 15ns + */ + tWR = (15*nMHz+999)/1000; + if(tWR<9) + tWR_MR0 = tWR - 4; + else + tWR_MR0 = tWR>>1; + + cl = ddr3_cl_cwl[DDR3_TYPE][tmp] >> 16; + cwl = ddr3_cl_cwl[DDR3_TYPE][tmp] & 0x0ff; + } + else if(mem_type == DDRII) + { + /* + * tREFI, average periodic refresh interval, 7.8us max + */ + tRFPRD = ((59*nMHz) >> 3) & 0x3FFF; // 62/8 = 7.75us + + if(capability <= 0x2000000) // 256Mb + { + tmp = (75*nMHz/1000) + ((((75*nMHz)%1000) > 0) ? 1:0); + } + else if(capability <= 0x4000000) // 512Mb + { + tmp = (105*nMHz/1000) + ((((105*nMHz)%1000) > 0) ? 1:0); + } + else if(capability <= 0x8000000) // 1Gb + { + tmp = (128*nMHz/1000) + ((((128*nMHz)%1000) > 0) ? 1:0); + } + else // 4Gb + { + tmp = (328*nMHz/1000) + ((((328*nMHz)%1000) > 0) ? 1:0); + } + //tRFC = 75ns(256Mb)/105ns(512Mb)/127.5ns(1Gb)/327.5ns(4Gb) + tmp = (tmp > 0xFF) ? 0xFF : tmp; + tRFC = tmp; + // tRTP = 7.5ns + tmp = (8*nMHz/1000) + ((((8*nMHz)%1000) > 0) ? 1:0); + tmp = (tmp > 6) ? 6 : tmp; + tmp = (tmp < 2) ? 2 : tmp; + tRTP = tmp; + //tWTR = 10ns(DDR2-400), 7.5ns (DDR2-533/667/800) + if(nMHz <= 200) + { + tmp = (10*nMHz/1000) + ((((10*nMHz)%1000) > 0) ? 1:0); + } + else + { + tmp = (8*nMHz/1000) + ((((8*nMHz)%1000) > 0) ? 1:0); + } + tmp = (tmp > 6) ? 6 : tmp; + tmp = (tmp < 1) ? 1 : tmp; + tWTR = tmp; + //tRAS_min = 45ns + tmp = (45*nMHz/1000) + ((((45*nMHz)%1000) > 0) ? 1:0); + tmp = (tmp > 31) ? 31 : tmp; + tmp = (tmp < 2) ? 2 : tmp; + tRAS = tmp; + // tRRD = 10ns + tmp = (10*nMHz/1000) + ((((10*nMHz)%1000) > 0) ? 1:0); + tmp = (tmp > 8) ? 8 : tmp; + tmp = (tmp < 1) ? 1 : tmp; + tRRD = tmp; + if(nMHz <= 200) //tRC = 65ns + { + tmp = (65*nMHz/1000) + ((((65*nMHz)%1000) > 0) ? 1:0); + } + else //tRC = 60ns + { + tmp = (60*nMHz/1000) + ((((60*nMHz)%1000) > 0) ? 1:0); + } + tmp = (tmp > 42) ? 42 : tmp; + tmp = (tmp < 2) ? 2 : tmp; + tRC = tmp; + //tFAW = 50ns + tmp = (50*nMHz/1000) + ((((50*nMHz)%1000) > 0) ? 1:0); + tmp = (tmp > 31) ? 31 : tmp; + tmp = (tmp < 2) ? 2 : tmp; + tFAW = tmp; + if(nMHz <= 333) + { + tXP = 7; + } + else + { + tXP = 8; + } + // don't need to modify tXS, tWR, tWR_MR0, cwl + + if(nMHz <= 266) + { + cl = 4; + } + else if((nMHz > 266) && (nMHz <= 333)) + { + cl = 5; + } + else if((nMHz > 333) && (nMHz <= 400)) + { + cl = 6; + } + else // > 400MHz + { + cl = 7; + } + cwl = cl -1; + } + else + { + } +out: + return ret; +} +static uint32_t __sramlocalfunc ddr_update_timing(void) +{ + uint32_t value; + if(mem_type == DDR3) + { + pDDR_Reg->DRR = TRFC(tRFC) | TRFPRD(tRFPRD) | RFBURST(1); + value = pDDR_Reg->TPR[0]; + value &= ~((0x7<<2)|(0x7<<5)|(0x1F<<16)|(0xF<<21)|(0x3F<<25)); + pDDR_Reg->TPR[0] = value | TRTP(tRTP) | TWTR(tWTR) | TRAS(tRAS) | TRRD(tRRD) | TRC(tRC); + value = pDDR_Reg->TPR[1]; + value &= ~(0x3F<<3); + pDDR_Reg->TPR[1] = value | TFAW(tFAW); + // ddr3 tCKE should be tCKESR=tCKE+1nCK + pDDR_Reg->TPR[2] = TXS(tXS) | TXP(tXP) | TCKE(4);//0x198c8;// + + } + else if(mem_type == DDRII) + { + pDDR_Reg->DRR = TRFC(tRFC) | TRFPRD(tRFPRD) | RFBURST(1); + value = pDDR_Reg->TPR[0]; + value &= ~((0x7<<2)|(0x7<<5)|(0x1F<<16)|(0xF<<21)|(0x3F<<25)); + pDDR_Reg->TPR[0] = value | TRTP(tRTP) | TWTR(tWTR) | TRAS(tRAS) | TRRD(tRRD) | TRC(tRC); + value = pDDR_Reg->TPR[1]; + value &= ~(0x3F<<3); + pDDR_Reg->TPR[1] = value | TFAW(tFAW); + value = pDDR_Reg->TPR[2]; + value &= ~(0x1F<<10); + pDDR_Reg->TPR[2] = value | TXP(tXP); + } + return 0; +} + +static uint32_t __sramlocalfunc ddr_update_mr(void) +{ + uint32_t value; + value = pDDR_Reg->TPR[0]; + value &= ~(0x0FF<<8); + pDDR_Reg->TPR[0] = value | TRP(cl) | TRCD(cl); + value = pDDR_Reg->TPR3; + value &= ~((0xF<<3)|(0xF<<7)|(0xF<<11)); + + if(mem_type == DDR3) + { + pDDR_Reg->TPR3 = value | CL(cl) | CWL(cwl) | WR(tWR); + pDDR_Reg->MR = DDR3_BL8 | DDR3_CL(cl) | DDR3_MR0_WR(tWR_MR0)/*15 ns*/; + delayus(1); + pDDR_Reg->EMR2 = DDR3_MR2_CWL(cwl); + } + else if(mem_type == DDRII) + { + pDDR_Reg->TPR3 = value | CL(cl) | CWL(cwl) | WR(cl); + //set mode register cl + value = pDDR_Reg->MR; + value &= ~((0x7<<4)|(0x7<<9)); + pDDR_Reg->MR = value | DDR_CL(cl) | DDR2_WR(cl); + } + return 0; +} +static __sramdata uint32_t clkr; +static __sramdata uint32_t clkf; +static __sramdata uint32_t clkod; +static __sramdata uint32_t pllband = 0; +static uint32_t __sramlocalfunc ddr_set_pll(uint32_t nMHz, uint32_t set) +{ + uint32_t ret = 0; + uint32_t temp; + + // ddr_print("%s \n", __func__); + if(nMHz == 24) + { + ret = 24; + goto out; + } + + if(!set) + { + pllband = 0; + if (nMHz<38) + { + nMHz = 38; + clkr = 1; + clkod = 3; + } + else if(nMHz <= 75 ) + { + clkr = 1; + clkod = 3; + } + else if (nMHz <= 150) + { + clkr = 2; + clkod = 2; + } + else if (nMHz <= 300) + { + clkr = 2; + clkod = 1; + } + else if(nMHz <= 600) + { + clkr = 2; + clkod = 0; + } + else + { + clkr = 2; + clkod = 0; + pllband = (0x01u<<16); + } + temp = nMHz*clkr*(1<>(clkr-1))>>clkod; + } + else + { + // ddr slow + pSCU_Reg->CRU_MODE_CON &=~(0x3<<6); + + pSCU_Reg->CRU_DPLL_CON |= (0x1 << 15); //power down pll + delayus(1); //delay at least 500ns + pSCU_Reg->CRU_DPLL_CON = pllband | (0x1<<15) |(PLL_CLKR(clkr))|(PLL_CLKF(clkf))|(PLL_CLKOD(clkod)); + + delayus(1); //delay at least 500ns + pSCU_Reg->CRU_DPLL_CON &= ~(0x1<<15); + delayus(2000); // 7.2us*140=1.008ms + + // ddr pll normal + pSCU_Reg->CRU_MODE_CON |= 0x1<<6; + + // ddr_pll_clk: clk_ddr=1:1 + temp = pSCU_Reg->CRU_CLKSEL_CON[7]; + temp &= ~(0x1F<<24); + pSCU_Reg->CRU_CLKSEL_CON[7] = temp; + delayus(1); + } +out: + return ret; +} + + +void __sramlocalfunc ddr_selfrefresh_enter(void) +{ + /* 1. disables all host ports + 2. Flushes the MCTL pipelines (including current automatically-scheduled refreshes) + 3. Disables automatic scheduling of refreshes + 4. Issues a Precharge All command + 5. Waits for tRP clocks (programmable in TPR0 register) + 6. Issues a Self-Refresh command + 7. Clears the self-clearing bit DCR.EXE and waits for Mode Exit command + */ + + //ddr_print("%s \n", __func__); + pDDR_Reg->CCR &= ~HOSTEN; //disable host port + pDDR_Reg->CCR |= FLUSH; //flush + delayus(10); + pDDR_Reg->DCR = (pDDR_Reg->DCR & (~((0x1<<24) | (0x1<<13) | (0xF<<27) | (0x1<<31)))) | ((0x1<<13) | (0x2<<27) | (0x1<<31)); //enter Self Refresh + delayus(1000); //wait for exit self refresh dll lock + pSCU_Reg->CRU_SOFTRST_CON[0] |= (0x1F<<19); //reset DLL + delayus(10); +} +void __sramlocalfunc ddr_selfrefresh_exit(void) +{ + /* 1. Exits self-refresh when a Mode-Exit command is received + 2. Waits for tXS clocks (programmable in TPR2 register) + 3. Issues a Refresh command + 4. Waits for tRFC clocks (programmable in DRR) + 5. Clears the self-clearing bit DCR.EXE + 6. Re-enables all host ports + */ + pSCU_Reg->CRU_SOFTRST_CON[0] &= ~(0x1F<<19); + delayus(10); //wait for exit self refresh dll lock + pDDR_Reg->DCR = (pDDR_Reg->DCR & (~((0x1<<24) | (0x1<<13) | (0xF<<27) | (0x1<<31)))) | ((0x1<<13) | (0x7<<27) | (0x1<<31)); //exit + delayus(10); + ddr_update_mr(); + delayus(10); + + // SDRAM ZQ Calibration Short + // pDDR_Reg->DCR = (pDDR_Reg->DCR & (~((0x1<<24) | (0x1<<13) | (0xF<<27) | (0x1<<31)))) | ((0x1<<13) | (0xb<<27) | (0x1<<31)); + //delayus(10); + +refresh: + pDDR_Reg->DRR |= RD; + delayus(1); + pDDR_Reg->CCR |= DTT; + delayus(15); + //pDDR_Reg->DRR &= ~RD; + pDDR_Reg->DRR = TRFC(tRFC) | TRFPRD(tRFPRD) | RFBURST(8); + delayus(10); + pDDR_Reg->DRR = TRFC(tRFC) | TRFPRD(tRFPRD) | RFBURST(1); + delayus(10); + if(pDDR_Reg->CSR & 0x100000) + { + pDDR_Reg->CSR &= ~0x100000; + goto refresh; + } + pDDR_Reg->CCR |= HOSTEN; //enable host port +} + +void __sramfunc ddr_change_freq(uint32_t nMHz) +{ + uint32_t ret; + volatile u32 n; + unsigned long flags; + volatile unsigned int * temp=(volatile unsigned int *)SRAM_CODE_OFFSET; + + local_irq_save(flags); + //ddr_print("%s enter\n", __func__); + cpu_freq = clk_get_rate(clk_get(NULL,"core")); + cpu_freq = cpu_freq/1000000; + + ret = ddr_set_pll(nMHz, 0); + ddr_get_parameter(ret); + //while(test); + /** 1. Make sure there is no host access */ +#if 1 + flush_cache_all(); + __cpuc_flush_kern_all(); + __cpuc_flush_user_all(); + DDR_SAVE_SP(save_sp); + n=temp[0]; + barrier(); + n=temp[1024]; + barrier(); + n=temp[1024*2]; + barrier(); + n=temp[1024*3]; + barrier(); + n= pDDR_Reg->CCR; + n= pSCU_Reg->CRU_SOFTRST_CON[0]; + dsb(); +#endif + + /** 2. ddr enter self-refresh mode or precharge power-down mode */ + ddr_selfrefresh_enter(); + delayus(100); + /** 3. change frequence */ + ddr_set_pll(ret, 1); + + /** 4. update timing¶meter */ + ddr_update_timing(); + + /** 5. Issues a Mode Exit command */ + ddr_selfrefresh_exit(); + dsb(); + + DDR_RESTORE_SP(save_sp); + local_irq_restore(flags); + //ddr_print("%s exit\n", __func__); +} +void __sramfunc ddr_suspend(void) +{ + uint32_t n; + volatile unsigned int * temp=(volatile unsigned int *)SRAM_CODE_OFFSET; + + //cpu_freq = clk_get_rate(clk_get(NULL,"core")); + //cpu_freq = cpu_freq/1000000; + cpu_freq = 24; + + //while(test); + /** 1. Make sure there is no host access */ + flush_cache_all(); + __cpuc_flush_kern_all(); + __cpuc_flush_user_all(); + + n=temp[0]; + barrier(); + n=temp[1024]; + barrier(); + n=temp[1024*2]; + barrier(); + n=temp[1024*3]; + barrier(); + n= pDDR_Reg->CCR; + n= pSCU_Reg->CRU_SOFTRST_CON[0]; + dsb(); + + ddr_selfrefresh_enter(); + + pSCU_Reg->CRU_CLKGATE_CON[0] |= (0x1<<18); //close DDR PHY clock / DDR CPU AXI clock / DDR REG AXI clock + delayus(10); + // ddr slow + pSCU_Reg->CRU_MODE_CON &=~(0x3<<6); + delayus(10); + pSCU_Reg->CRU_DPLL_CON |= (0x1 << 15); //power down DPLL + delayus(10); //delay at least 500ns + +} +void __sramfunc ddr_resume(void) +{ + uint32_t value; +#if 1 + pSCU_Reg->CRU_DPLL_CON &= ~(0x1 << 15); //power on DPLL + // while(!(pGRF_Reg->GRF_SOC_CON[0] & (1<<28))); + delayus(200); // 7.2us*140=1.008ms // Ëø¶¨pll + // ddr pll normal + value = pSCU_Reg->CRU_MODE_CON; + value &=~(0x3<<6); + value |= 0x1<<6; + pSCU_Reg->CRU_MODE_CON = value; + delayus(10); + pSCU_Reg->CRU_CLKGATE_CON[0] &= ~(0x1<<18); //enable DDR PHY clock / DDR CPU AXI clock / DDR REG AXI clock + delayus(10); +#endif + + ddr_selfrefresh_exit(); + dsb(); +} +static void inline ddr_change_host_priority(void) +{ + /* + DMC AXI host N priority + 00:higheset priority + 01:second high priority + 10:third high priority + + GRF_MEM_CON[1:0]: CPU (host 0) + [3:2]: PERI (host 1) + [5:4]: DISPLAY (host 2) + [7:6]: GPU (host 3) + [9:8]: VCODEC (host 4) + */ + pGRF_Reg->GRF_MEM_CON = (pGRF_Reg->GRF_MEM_CON & ~0x3FF) | ((2<<0)|(1<<2)|(0<<4)|(1<<6)|(2<<8)); +} +static int __init ddr_probe(void) +{ + volatile uint32_t value = 0; + uint32_t addr; + uint32_t MHz; + unsigned long Hz; + uint32_t bw; + uint32_t col = 0; + uint32_t row = 0; + uint32_t bank = 0; + uint32_t n; + + ddr_print("%s \n", __func__); + + mem_type = (pDDR_Reg->DCR & 0x3); +// ddr_debug = 0; + + // caculate aglined physical address + addr = __pa((unsigned long)ddrDataTraining); + if(addr&0x1F) + { + addr += (32-(addr&0x1F)); + } + addr -= 0x60000000; + // caculate data width + bw = ((((pDDR_Reg->DCR >> 7) & 0x7)+1)>>1); + // find out col£¬row£¬bank + for(n=0;n<10; n++) + { + if(ddrConfig[(pDDR_Reg->DCR & 0x3)][n].config == (pDDR_Reg->DCR & 0x7c)) + { + col = ddrConfig[(pDDR_Reg->DCR & 0x3)][n].col; + row = ddrConfig[(pDDR_Reg->DCR & 0x3)][n].row; + bank = ddrConfig[(pDDR_Reg->DCR & 0x3)][n].bank; + bank >>= 2; // 8=>3, 4=>2 + bank += 1; + break; + } + } + if(n == 10) + { + //ASSERT + } + + // according different address mapping, caculate DTAR register value + value = pDDR_Reg->DTAR; + value &= ~(0x7FFFFFFF); + switch(pDDR_Reg->DCR & (0x3<<14)) + { + case AMAP_RBRC: + value |= (addr>>bw) & ((0x1<>(bw+col)) & ((0x1<>(bw+col+row)) & ((0x1<>bw) & ((0x1<>(bw+col+bank)) & ((0x1<>(bw+col)) & ((0x1<>bw) & ((0x1<DCR >> 11) & 0x3) + { + value |= ((addr>>(bw+col+1)) & ((0x1<>(bw+col+row+1)) & ((0x1<>(bw+col)) & ((0x1<>(bw+col+row)) & ((0x1<DTAR = value; + + if((mem_type == DDRII) || (mem_type == DDR3)) + { + pDDR_Reg->ALPMR = LPPERIOD_POWER_DOWN(0xFF);// | AUTOPD; + } + else + { + pDDR_Reg->ALPMR = LPPERIOD_CLK_STOP(0xFF) | LPPERIOD_POWER_DOWN(0xFF) | AUTOCS | AUTOPD; + } + ddr_change_host_priority(); + value = (((pDDR_Reg->DCR >> 7) & 0x7)+1) >> ((pDDR_Reg->DCR >> 2) & 0x3); + capability = 0x800000 << (((pDDR_Reg->DCR >> 4) & 0x7) + value + ((pDDR_Reg->DCR >> 11) & 0x3)); + + Hz = clk_get_rate(clk_get(NULL,"ddr")); + MHz = Hz/1000000; + + ddr_change_freq(MHz); + ddr_print("ddr pll freq=%dMHz\n", MHz); + + return 0; +} +core_initcall_sync(ddr_probe); diff --git a/arch/arm/mach-rk29/pm.c b/arch/arm/mach-rk29/pm.c old mode 100644 new mode 100755 index 9fbf1bfd5c2c..db339c485cdf --- a/arch/arm/mach-rk29/pm.c +++ b/arch/arm/mach-rk29/pm.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include #ifdef CONFIG_RK29_PWM_REGULATOR #include #endif @@ -44,9 +46,11 @@ static inline void delay_300us(void) extern void ddr_suspend(void); extern void ddr_resume(void); +extern void delayus(uint32_t us); +extern void ddr_change_freq(uint32_t nMHz); #ifdef DEBUG -static void inline printch(char byte) +static void/* inline*/ __sramfunc printch(char byte) { unsigned long flags; u32 gate1, gate2; @@ -79,7 +83,7 @@ static void inline printascii(const char *s) } } -static void inline printhex(unsigned int hex) +static void /* inline*/ __sramfunc printhex(unsigned int hex) { int i = 8; printch('0'); @@ -132,11 +136,96 @@ static void __sramfunc rk29_set_core_voltage(int uV) cru_writel(gate1, CRU_CLKGATE1_CON); } #endif /* CONFIG_RK29_PWM_REGULATOR */ +/*volatile __sramdata */int ddr_debug; +module_param(ddr_debug, int, 0644); +#if 1 +static int inline calc_crc32(u32 addr, size_t len) +{ + return crc32_le(~0,(const unsigned char *)addr,len); +} +void __sramfunc ddr_testmode(void) +{ + int32_t g_crc1,g_crc2; + uint32_t nMHz; + uint32_t n = 0; + extern char _stext[], _etext[]; + if(ddr_debug == 1) + { + for (;;) + { + printch(' '); + printch('8'); + printch('8'); + printch('8'); + printch(' '); + g_crc1 = calc_crc32((u32)_stext, (size_t)(_etext-_stext)); + nMHz = 333 + (random32()>>25); + if(nMHz > 402) + nMHz = 402; + printhex(nMHz); + printch(' '); + printhex(n++); + //ddr_print("%s change freq to: %d MHz\n", __func__, nMHz); + ddr_change_freq(nMHz); + g_crc2 = calc_crc32((u32)_stext, (size_t)(_etext-_stext)); + if (g_crc1!=g_crc2) + { + printch(' '); + printch('f'); + printch('a'); + printch('i'); + printch('l'); + } + //ddr_print("check image crc32 success--crc value = 0x%x!, count:%d\n",g_crc1, n++); + // printascii("change freq success\n"); + } + } + else if(ddr_debug == 2) + { + for (;;) + { + printch(' '); + printch('9'); + printch('9'); + printch('9'); + printch(' '); + g_crc1 = calc_crc32((u32)_stext, (size_t)(_etext-_stext)); + nMHz = (random32()>>13);// 16.7s max + ddr_suspend(); + delayus(nMHz); + ddr_resume(); + printhex(nMHz); + printch(' '); + printhex(n++); + g_crc2 = calc_crc32((u32)_stext, (size_t)(_etext-_stext)); + if (g_crc1!=g_crc2) + { + printch(' '); + printch('f'); + printch('a'); + printch('i'); + printch('l'); + } + // ddr_print("check image crc32 fail!, count:%d\n", n++); + // printascii("self refresh fail\n"); + //else + //ddr_print("check image crc32 success--crc value = 0x%x!, count:%d\n",g_crc1, n++); + // printascii("self refresh success\n"); + } + } + +} +#else +void __sramfunc ddr_testmode(void) +{} +#endif static void __sramfunc rk29_sram_suspend(void) { u32 clksel0; + if(ddr_debug) + ddr_testmode(); printch('5'); ddr_suspend(); @@ -350,6 +439,7 @@ static int __init rk29_pm_init(void) /* set idle function */ pm_idle = rk29_idle; + ddr_debug = 0; return 0; } -- 2.34.1