mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 21:07:02 +09:00
rk30: ddr.c support for rk3066b
This commit is contained in:
@@ -133,8 +133,8 @@ void __init rk30_map_io(void)
|
||||
rk29_sram_init();
|
||||
board_clock_init();
|
||||
rk30_l2_cache_init();
|
||||
#if !defined(CONFIG_ARCH_RK3066B)
|
||||
ddr_init(DDR_TYPE, DDR_FREQ);
|
||||
#if !defined(CONFIG_ARCH_RK3066B)
|
||||
clk_disable_unused();
|
||||
#endif
|
||||
rk30_iomux_init();
|
||||
|
||||
@@ -38,6 +38,7 @@ typedef uint32_t uint32;
|
||||
#define SysSrv_DdrTiming (RK30_CPU_AXI_BUS_BASE+0x0c)
|
||||
#define SysSrv_DdrMode (RK30_CPU_AXI_BUS_BASE+0x10)
|
||||
#define SysSrv_ReadLatency (RK30_CPU_AXI_BUS_BASE+0x14)
|
||||
#define ROM_CHIP_ID_ADDR (RK30_ROM_BASE+0x27f0)
|
||||
|
||||
#define ddr_print(x...) printk( "DDR DEBUG: " x )
|
||||
|
||||
@@ -228,6 +229,14 @@ typedef volatile struct tagPMU_FILE
|
||||
#define NO(n) ((0xF<<16) | ((n)-1))
|
||||
#define NF(n) ((0x1FFF<<16) | ((n)-1))
|
||||
#define NB(n) ((0xFFF<<16) | ((n)-1))
|
||||
|
||||
//RK3066B
|
||||
#define PLL_RESET_RK3066B (((0x1<<1)<<16) | (0x1<<1))
|
||||
#define PLL_DE_RESET_RK3066B (((0x1<<1)<<16) | (0x0<<1))
|
||||
#define NR_RK3066B(n) ((0x3F<<(8+16)) | (((n)-1)<<8))
|
||||
#define NO_RK3066B(n) ((0x3F<<16) | ((n)-1))
|
||||
#define NF_RK3066B(n) ((0xFFFF<<16) | ((n)-1))
|
||||
|
||||
//CRU Registers
|
||||
typedef volatile struct tagCRU_STRUCT
|
||||
{
|
||||
@@ -288,6 +297,33 @@ typedef volatile struct tagREG_FILE
|
||||
|
||||
#define pGRF_Reg ((pREG_FILE)REG_FILE_BASE_ADDR)
|
||||
|
||||
//REG FILE registers
|
||||
typedef volatile struct tagREG_FILE_RK3066B
|
||||
{
|
||||
GPIO_LH_T GRF_GPIO_DIR[4];
|
||||
GPIO_LH_T GRF_GPIO_DO[4];
|
||||
GPIO_LH_T GRF_GPIO_EN[4];
|
||||
GPIO_IOMUX_T GRF_GPIO_IOMUX[4];
|
||||
uint32 GRF_SOC_CON[3];
|
||||
uint32 GRF_SOC_STATUS0;
|
||||
uint32 GRF_DMAC0_CON[3];
|
||||
uint32 GRF_DMAC1_CON[4];
|
||||
uint32 reserved0[(0xec-0xcc)/4];
|
||||
uint32 GRF_DDRC_CON0;
|
||||
uint32 GRF_DDRC_STAT;
|
||||
uint32 GRF_IO_CON[5];
|
||||
uint32 reserved1;
|
||||
uint32 GRF_UOC0_CON[4];
|
||||
uint32 GRF_UOC1_CON[4];
|
||||
uint32 GRF_UOC2_CON[2];
|
||||
uint32 reserved2;
|
||||
uint32 GRF_UOC3_CON[2];
|
||||
uint32 GRF_HSIC_STAT;
|
||||
uint32 GRF_OS_REG[8];
|
||||
} REG_FILE_RK3066B, *pREG_FILE_RK3066B;
|
||||
|
||||
#define pGRF_Reg_RK3066B ((pREG_FILE_RK3066B)REG_FILE_BASE_ADDR)
|
||||
|
||||
//SCTL
|
||||
#define INIT_STATE (0)
|
||||
#define CFG_STATE (1)
|
||||
@@ -981,7 +1017,9 @@ uint32_t __sramdata ddr3_tRC_tFAW[22]={
|
||||
|
||||
((53<<16)|50) //DDR3_DEFAULT
|
||||
};
|
||||
|
||||
__sramdata uint32_t mem_type; // 0:LPDDR, 1:DDR, 2:DDR2, 3:DDR3, 4:LPDDR2
|
||||
__sramdata bool chip_rk3066b_flag=false;
|
||||
static __sramdata uint32_t ddr_speed_bin; // used for ddr3 only
|
||||
static __sramdata uint32_t ddr_capability_per_die; // one chip cs capability
|
||||
static __sramdata uint32_t ddr_freq;
|
||||
@@ -1023,9 +1061,19 @@ uint32 ddr_get_row(void)
|
||||
|
||||
i = *(volatile uint32*)SysSrv_DdrConf;
|
||||
row = ddr_cfg_2_rbc[i].row;
|
||||
if(pGRF_Reg->GRF_SOC_CON[2] & (1<<1))
|
||||
if(chip_rk3066b_flag == true)
|
||||
{
|
||||
row += 1;
|
||||
if(pGRF_Reg_RK3066B->GRF_SOC_CON[2] & (1<<1))
|
||||
{
|
||||
row += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pGRF_Reg->GRF_SOC_CON[2] & (1<<1))
|
||||
{
|
||||
row += 1;
|
||||
}
|
||||
}
|
||||
return row;
|
||||
}
|
||||
@@ -1360,18 +1408,101 @@ uint32_t __sramlocalfunc ddr_set_pll(uint32_t nMHz, uint32_t set)
|
||||
ddr_delayus(1);
|
||||
pCRU_Reg->CRU_PLL_CON[pll_id][3] = PLL_DE_RESET;
|
||||
dsb();
|
||||
while (delay > 0)
|
||||
while (delay > 0)
|
||||
{
|
||||
ddr_delayus(1);
|
||||
if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4))
|
||||
break;
|
||||
delay--;
|
||||
}
|
||||
|
||||
if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4))
|
||||
break;
|
||||
delay--;
|
||||
}
|
||||
pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16)
|
||||
| (0x0<<8) //clk_ddr_src = DDR PLL
|
||||
| 0; //clk_ddr_src:clk_ddrphy = 1:1
|
||||
|
||||
|
||||
pCRU_Reg->CRU_MODE_CON = (0x3<<((pll_id*4) + 16)) | (0x1<<(pll_id*4)); //PLL normal
|
||||
dsb();
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************
|
||||
RK3066B
|
||||
NR NO NF Fout freq Step finally use
|
||||
1 14 46 - 91 78MHz - 157MHz 1.7MHz 78MHz<= 150MHz
|
||||
1 8 46 - 91 137MHz - 275MHz 3MHz 150MHz<= 200MHz
|
||||
1 6 46 - 91 183MHz - 366MHz 4MHz 200MHz<= 300MHz
|
||||
1 4 46 - 91 275MHz - 550MHz 6MHz 300MHz<= 550MHz
|
||||
1 2 46 - 91 550MHz - 1100MHz 12MHz 550MHz<= 1100MHz
|
||||
1 1 46 - 91 1100MHz - 2200MHz 24MHz 1100MHz<= 2200MHz
|
||||
******************************************/
|
||||
uint32_t __sramlocalfunc ddr_set_pll_rk3600b(uint32_t nMHz, uint32_t set)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
int delay = 1000;
|
||||
uint32_t pll_id=1; //DPLL
|
||||
|
||||
if(nMHz == 24)
|
||||
{
|
||||
ret = 24;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(!set)
|
||||
{
|
||||
if(nMHz <= 150)
|
||||
{
|
||||
clkod = 14;
|
||||
}
|
||||
else if(nMHz <= 200)
|
||||
{
|
||||
clkod = 8;
|
||||
}
|
||||
else if(nMHz <= 300)
|
||||
{
|
||||
clkod = 6;
|
||||
}
|
||||
else if(nMHz <= 550)
|
||||
{
|
||||
clkod = 4;
|
||||
}
|
||||
else if(nMHz <= 1100)
|
||||
{
|
||||
clkod = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
clkod = 1;
|
||||
}
|
||||
clkr = 1;
|
||||
clkf=(nMHz*clkr*clkod)/24;
|
||||
ret = (24*clkf)/(clkr*clkod);
|
||||
}
|
||||
else
|
||||
{
|
||||
pCRU_Reg->CRU_MODE_CON = (0x3<<((pll_id*4) + 16)) | (0x0<<(pll_id*4)); //PLL slow-mode
|
||||
dsb();
|
||||
|
||||
pCRU_Reg->CRU_PLL_CON[pll_id][3] = PLL_RESET_RK3066B;
|
||||
pCRU_Reg->CRU_PLL_CON[pll_id][0] = NR_RK3066B(clkr) | NO_RK3066B(clkod);
|
||||
pCRU_Reg->CRU_PLL_CON[pll_id][1] = NF_RK3066B(clkf);
|
||||
// pCRU_Reg->CRU_PLL_CON[pll_id][2] = NB(clkf>>1);
|
||||
ddr_delayus(1);
|
||||
pCRU_Reg->CRU_PLL_CON[pll_id][3] = PLL_DE_RESET_RK3066B;
|
||||
dsb();
|
||||
while (delay > 0)
|
||||
{
|
||||
ddr_delayus(1);
|
||||
if (pGRF_Reg_RK3066B->GRF_SOC_STATUS0 & (0x1<<5))
|
||||
break;
|
||||
delay--;
|
||||
}
|
||||
|
||||
pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16)
|
||||
| (0x0<<8) //clk_ddr_src = DDR PLL
|
||||
| 0; //clk_ddr_src:clk_ddrphy = 1:1
|
||||
|
||||
pCRU_Reg->CRU_MODE_CON = (0x3<<((pll_id*4) + 16)) | (0x1<<(pll_id*4)); //PLL normal
|
||||
dsb();
|
||||
}
|
||||
@@ -2798,9 +2929,19 @@ __sramfunc void ddr_adjust_config(uint32_t dram_type)
|
||||
ddr_move_to_Config_state();
|
||||
|
||||
//extend capability for debug
|
||||
if(pGRF_Reg->GRF_SOC_CON[2] & (0x1<<1))
|
||||
if(chip_rk3066b_flag == true)
|
||||
{
|
||||
pGRF_Reg->GRF_SOC_CON[2] = rank_to_row15_en;
|
||||
if(pGRF_Reg_RK3066B->GRF_SOC_CON[2] & (0x1<<1))
|
||||
{
|
||||
pGRF_Reg_RK3066B->GRF_SOC_CON[2] = rank_to_row15_en;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pGRF_Reg->GRF_SOC_CON[2] & (0x1<<1))
|
||||
{
|
||||
pGRF_Reg->GRF_SOC_CON[2] = rank_to_row15_en;
|
||||
}
|
||||
}
|
||||
|
||||
//set data training address
|
||||
@@ -2985,15 +3126,18 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz)
|
||||
|
||||
// freq = (Fin/NR)*NF/OD
|
||||
if((pCRU_Reg->CRU_MODE_CON&3) == 1) // CPLL Normal mode
|
||||
freq = 24 *((pCRU_Reg->CRU_PLL_CON[0][1]&0x1fff)+1) // NF = 2*(CLKF+1)
|
||||
freq = 24 *((pCRU_Reg->CRU_PLL_CON[0][1]&0xffff)+1) // NF = 2*(CLKF+1)
|
||||
/((((regvalue>>8)&0x3f)+1) // NR = CLKR+1
|
||||
*((regvalue&0xF)+1)); // OD = 2^CLKOD
|
||||
*((regvalue&0x3F)+1)); // OD = 2^CLKOD
|
||||
else
|
||||
freq = 24;
|
||||
|
||||
loops_per_us = LPJ_100MHZ*freq / 1000000;
|
||||
|
||||
ret=ddr_set_pll(nMHz,0);
|
||||
|
||||
if(chip_rk3066b_flag == true)
|
||||
ret=ddr_set_pll_rk3600b(nMHz,0);
|
||||
else
|
||||
ret=ddr_set_pll(nMHz,0);
|
||||
ddr_get_parameter(ret);
|
||||
|
||||
/** 1. Make sure there is no host access */
|
||||
@@ -3014,7 +3158,14 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz)
|
||||
n= pCRU_Reg->CRU_PLL_CON[0][0];
|
||||
n= pPMU_Reg->PMU_WAKEUP_CFG[0];
|
||||
n= *(volatile uint32_t *)SysSrv_DdrConf;
|
||||
n= pGRF_Reg->GRF_SOC_STATUS0;
|
||||
if(chip_rk3066b_flag == true)
|
||||
{
|
||||
n= pGRF_Reg_RK3066B->GRF_SOC_STATUS0;
|
||||
}
|
||||
else
|
||||
{
|
||||
n= pGRF_Reg->GRF_SOC_STATUS0;
|
||||
}
|
||||
dsb();
|
||||
|
||||
/** 2. ddr enter self-refresh mode or precharge power-down mode */
|
||||
@@ -3022,7 +3173,10 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz)
|
||||
ddr_selfrefresh_enter(ret);
|
||||
|
||||
/** 3. change frequence */
|
||||
ddr_set_pll(ret,1);
|
||||
if(chip_rk3066b_flag == true)
|
||||
ddr_set_pll_rk3600b(ret,1);
|
||||
else
|
||||
ddr_set_pll(ret,1);
|
||||
ddr_freq = ret;
|
||||
|
||||
/** 5. Issues a Mode Exit command */
|
||||
@@ -3092,9 +3246,17 @@ void __sramfunc ddr_resume(void)
|
||||
while (delay > 0)
|
||||
{
|
||||
ddr_delayus(1);
|
||||
if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4))
|
||||
break;
|
||||
delay--;
|
||||
if(chip_rk3066b_flag == true)
|
||||
{
|
||||
if (pGRF_Reg_RK3066B->GRF_SOC_STATUS0 & (0x1<<5))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4))
|
||||
break;
|
||||
}
|
||||
delay--;
|
||||
}
|
||||
|
||||
pCRU_Reg->CRU_MODE_CON = (0x3<<((1*4) + 16)) | (0x1<<(1*4)); //PLL normal
|
||||
@@ -3127,9 +3289,19 @@ uint32 ddr_get_cap(void)
|
||||
break;
|
||||
}
|
||||
row = ddr_cfg_2_rbc[i].row;
|
||||
if(pGRF_Reg->GRF_SOC_CON[2] & (1<<1))
|
||||
if(*(volatile uint32_t *)(ROM_CHIP_ID_ADDR+0x0c) == 0x56313030)
|
||||
{
|
||||
row += 1;
|
||||
if(pGRF_Reg_RK3066B->GRF_SOC_CON[2] & (1<<1))
|
||||
{
|
||||
row += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(pGRF_Reg->GRF_SOC_CON[2] & (1<<1))
|
||||
{
|
||||
row += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (1 << (row+(ddr_cfg_2_rbc[i].col)+(ddr_cfg_2_rbc[i].bank)+2))*cs;
|
||||
@@ -3225,7 +3397,15 @@ int ddr_init(uint32_t dram_speed_bin, uint32_t freq)
|
||||
uint32_t cs,die=1;
|
||||
uint32_t gsr,dqstr;
|
||||
|
||||
ddr_print("version 1.00 20120822 \n");
|
||||
ddr_print("version 1.00 20120903 \n");
|
||||
|
||||
if(*(volatile uint32_t *)(ROM_CHIP_ID_ADDR+0x0c) == 0x56313030)
|
||||
{
|
||||
chip_rk3066b_flag=true;
|
||||
ddr_print("RK3066B \n");
|
||||
}
|
||||
else
|
||||
chip_rk3066b_flag=false;
|
||||
|
||||
mem_type = pPHY_Reg->DCR.b.DDRMD;
|
||||
ddr_speed_bin = dram_speed_bin;
|
||||
|
||||
@@ -88,21 +88,22 @@ out:
|
||||
|
||||
uint32_t ddr_set_rate(uint32_t nMHz)
|
||||
{
|
||||
_ddr_change_freq(nMHz);
|
||||
return 0;
|
||||
nMHz = _ddr_change_freq(nMHz);
|
||||
return nMHz;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
static uint32_t ddr_resume_freq=DDR_FREQ;
|
||||
static uint32_t ddr_suspend_freq=120;
|
||||
static void ddr_early_suspend(struct early_suspend *h)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
//Enable auto self refresh 0x01*32 DDR clk cycle
|
||||
ddr_set_auto_self_refresh(true);
|
||||
|
||||
value = _ddr_change_freq(120);
|
||||
|
||||
|
||||
ddr_resume_freq=clk_get_rate(ddr.ddr_pll)/1000000;
|
||||
value = ddr_set_rate(ddr_suspend_freq);
|
||||
ddr_print("init success!!! freq=%dMHz\n", value);
|
||||
|
||||
return;
|
||||
@@ -115,8 +116,7 @@ static void ddr_late_resume(struct early_suspend *h)
|
||||
//Disable auto self refresh
|
||||
ddr_set_auto_self_refresh(false);
|
||||
|
||||
value = _ddr_change_freq(DDR_FREQ);
|
||||
|
||||
value = ddr_set_rate(ddr_resume_freq);
|
||||
ddr_print("init success!!! freq=%dMHz\n", value);
|
||||
|
||||
return;
|
||||
@@ -173,13 +173,9 @@ static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
|
||||
p=strsep(&cookie_pot,"M");
|
||||
value = simple_strtol(p,NULL,10);
|
||||
printk("change!!! freq=%dMHz\n", value);
|
||||
cpu1_online=cpu_online(1);
|
||||
if(cpu1_online)
|
||||
cpu_down(1);
|
||||
value=ddr_change_freq(value);
|
||||
if(cpu1_online)
|
||||
cpu_up(1);
|
||||
value=ddr_set_rate(value);
|
||||
printk("success!!! freq=%dMHz\n", value);
|
||||
msleep(32);
|
||||
printk("\n");
|
||||
}
|
||||
else
|
||||
@@ -216,16 +212,9 @@ static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
|
||||
}while(value < value1);
|
||||
|
||||
printk("change!!! freq=%dMHz\n", value);
|
||||
|
||||
cpu1_online=cpu_online(1);
|
||||
if(cpu1_online)
|
||||
cpu_down(1);
|
||||
msleep(32);
|
||||
value=ddr_change_freq(value);
|
||||
if(cpu1_online)
|
||||
cpu_up(1);
|
||||
value=ddr_set_rate(value);
|
||||
printk("success!!! freq=%dMHz\n", value);
|
||||
|
||||
msleep(32);
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -269,14 +258,9 @@ static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
|
||||
}
|
||||
|
||||
printk("change!!! freq=%dMHz\n", value);
|
||||
cpu1_online=cpu_online(1);
|
||||
if(cpu1_online)
|
||||
cpu_down(1);
|
||||
msleep(32);
|
||||
value=ddr_change_freq(value);
|
||||
if(cpu1_online)
|
||||
cpu_up(1);
|
||||
value=ddr_set_rate(value);
|
||||
printk("success!!! freq=%dMHz\n", value);
|
||||
msleep(32);
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -287,7 +271,9 @@ static ssize_t ddr_proc_write(struct file *file, const char __user *buffer,
|
||||
printk("-->'b&&B' auto change ddr freq test (specific),Example: echo 'a:200M-400M-1000T' > ddr_test\n");
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'h':
|
||||
case 'H':
|
||||
default:
|
||||
printk("Help for ddr_ts .\n-->The Cmd list: \n");
|
||||
printk("-->'a&&A' auto change ddr freq test (random),Example: echo 'a:200M-400M-100T' > ddr_test\n");
|
||||
|
||||
Reference in New Issue
Block a user