一、说明
内存控制器非常难配置,故而不能出错。我严格按照文档上的步骤配置,其中的参数自行体会。
二、配置流程
首先配置内存交错,然后初始化每个DMC。
223 void mem_ctrl_init(int reset)
224 {
225 struct exynos4_dmc *dmc1 = (struct exynos4_dmc *)samsung_get_base_dmc_ctrl();
226 struct exynos4_dmc *dmc2 = (struct exynos4_dmc *)(samsung_get_base_dmc_ctrl() + DMC_OFFSET);
227 /**
228 ¦* 配置内存交错
229 ¦*/
230 writel(APB_SFR_INTERLEAVE_CONF_VAL, &dmc1->ivcontrol);
231 writel(APB_SFR_INTERLEAVE_CONF_VAL, &dmc2->ivcontrol);
232
233 /*
234 ¦* 初始化内存控制器
235 ¦*/
236 dmc_init(dmc1);
237 dmc_init(dmc2);
238 }
配置步骤在代码中,对比手册阅读
static void dmc_init(struct exynos4_dmc *dmc)
{
/**
* Setup 2:
* enable PhyControl1.term_write_en, PhyControl1.term_read_en
*/
writel(mem.control1, &dmc->phycontrol1); //有差异
/**
* Stup 3:
* disable PhyZQControl.ctrl_zq_mode_noterm
* enable PhyZQControl.ctrl_zq_start
*/
writel(mem.zqcontrol, &dmc->phyzqcontrol);
/**
* Setup 4:
* set PhyControl0.ctrl_start_point, PhyControl0.ctrl_inc
* set PhyControl0.ctrl_dll_on to 1 ——activate PHY DLL
*/
phy_control_reset(0, dmc);
/**
* Setup 5:
* set PhyControl1.ctr_shiftc, PhyControl1.ctrl_offsetc
*/
writel(mem.control1, &dmc->phycontrol1);
/**
* Setup 6:
* set PhyControl0.ctrl_start to 1
*/
writel((mem.control0 | CTRL_START | CTRL_DLL_ON), &dmc->phycontrol0);
/**
* Setup 7:
* set ConControl, close auto refresh
*/
writel(mem.concontrol, &dmc->concontrol);
/**
* Setup 8:
* set MemControl, close power down modes, close pzq_en
*/
writel(mem.memcontrol, &dmc->memcontrol); //差异
/**
* Setup 9:
* set Memory info
*/
writel(mem.memconfig0, &dmc->memconfig0);
writel(mem.memconfig1, &dmc->memconfig1);
/**
* Setup 10:
* set PrechConfig
*/
writel(mem.prechconfig, &dmc->prechconfig);
/**
* Setup 11:
* set TimingAref, TimingRow, TimingData and TimingPower
*/
writel(mem.timingref, &dmc->timingref);
writel(mem.timingrow, &dmc->timingrow);
writel(mem.timingdata, &dmc->timingdata);
writel(mem.timingpower, &dmc->timingpower);
/**
* Setup 13:
* wait PhyStatus0.ctrl_clock and PhyStatus0.ctrl_flock to 1
*/
while(!(dmc->phystatus & 2));
/**
* Setup 15,16:
* set PhyContron1.fp_resync to 1
*/
phy_control_reset(1, dmc);
/**
* Setup 19:
* NOP command
* hold CKE to logic high level
* chip 0
*/
writel(DIRECT_CMD_NOP, &dmc->directcmd);
/**
* Setup 21:
* send EMRS2 command
* send EMRS3 command
* send EMRS command
* send MRS command
* chip 0
*/
dmc_config_mrs(dmc, 0);
/**
*Setup 26:
send ZQINIT command
chip 0
*/
writel(DIRECT_CMD_ZQ, &dmc->directcmd);
/**
* Setup 19:
* NOP command
* hold CKE to logic high level
* chip 1
*/
writel((DIRECT_CMD_NOP | DIRECT_CMD_CHIP1_SHIFT), &dmc->directcmd);
/**
* Setup 21:
* send EMRS2 command
* send EMRS3 command
* send EMRS command
* send MRS command
* chip 1
*/
dmc_config_mrs(dmc, 1);
/**
*Setup 26:
send ZQINIT command
chip 1
*/
writel((DIRECT_CMD_ZQ | DIRECT_CMD_CHIP1_SHIFT), &dmc->directcmd);
/**
* Setup 28:
* set ConControl auto refresh
*/
writel((mem.concontrol | AREF_EN), &dmc->concontrol);
/**
* Setup 29:
* set MemControl
*/
writel((mem.memcontrol | MEMCONTROL_OR), &dmc->memcontrol);
}
三、配置参数
/********************************************************************************
*
* 内存控制器的配置
*
********************************************************************************/
/* DMC */
#define DIRECT_CMD_CHIP1_SHIFT (1 << 20)
#define MEM_TIMINGS_MSR_COUNT 4
#define CTRL_START (1 << 0)
#define CTRL_DLL_ON (1 << 1)
#define AREF_EN (1 << 5)
#define DRV_TYPE (1 << 6)
struct mem_timings {
unsigned direct_cmd_msr[MEM_TIMINGS_MSR_COUNT];
unsigned timingref;
unsigned timingrow;
unsigned timingdata;
unsigned timingpower;
unsigned zqcontrol;
unsigned control0;
unsigned control1;
unsigned control2;
unsigned concontrol;
unsigned prechconfig;
unsigned memcontrol;
unsigned memconfig0;
unsigned memconfig1;
unsigned dll_resync;
unsigned dll_on;
};
/* MIU */
/* MIU Config Register Offsets*/
#ifdef CONFIG_ITOP4412
#define APB_SFR_INTERLEAVE_CONF_VAL 0x80000007
#endif
#ifdef CONFIG_MIU_1BIT_INTERLEAVED
#define APB_SFR_INTERLEAVE_CONF_VAL 0x0000000c
#endif
#ifdef CONFIG_MIU_2BIT_INTERLEAVED
#define APB_SFR_INTERLEAVE_CONF_VAL 0x2000150c
#endif
#define FORCE_DLL_RESYNC 3
#define DLL_CONTROL_ON 1
#define DIRECT_CMD_NOP 0x07000000
#define DIRECT_CMD1 0x00020000
#define DIRECT_CMD2 0x00030000
#define DIRECT_CMD3 0x00010002
#define DIRECT_CMD4 0x00000328
#define DIRECT_CMD_ZQ 0x0a000000
#define CTRL_ZQ_MODE_NOTERM (0x1 << 0)
#define CTRL_ZQ_START (0x1 << 1)
#define CTRL_ZQ_DIV (0x0 << 4)
#define CTRL_ZQ_MODE_DDS (0x7 << 8)
#define CTRL_ZQ_MODE_TERM (0x2 << 11)
#define CTRL_ZQ_FORCE_IMPN (0x5 << 14)
#define CTRL_ZQ_FORCE_IMPP (0x6 << 17)
#define CTRL_DCC (0xE38 << 20)
#define ZQ_CONTROL_VAL (CTRL_ZQ_MODE_NOTERM | CTRL_ZQ_START\
| CTRL_ZQ_DIV | CTRL_ZQ_MODE_DDS\
| CTRL_ZQ_MODE_TERM | CTRL_ZQ_FORCE_IMPN\
| CTRL_ZQ_FORCE_IMPP | CTRL_DCC)
#define ASYNC (0 << 0)
#define CLK_RATIO (1 << 1)
#define DIV_PIPE (1 << 3)
#define AWR_ON (1 << 4)
#define AREF_DISABLE (0 << 5)
#define DRV_TYPE_DISABLE (0 << 6)
#define CHIP0_NOT_EMPTY (0 << 8)
#define CHIP1_NOT_EMPTY (0 << 9)
#define DQ_SWAP_DISABLE (0 << 10)
#define QOS_FAST_DISABLE (0 << 11)
#define RD_FETCH (0x3 << 12)
#define TIMEOUT_LEVEL0 (0xFFF << 16)
#define CONCONTROL_VAL (ASYNC | CLK_RATIO | DIV_PIPE | AWR_ON\
| AREF_DISABLE | DRV_TYPE_DISABLE\
| CHIP0_NOT_EMPTY | CHIP1_NOT_EMPTY\
| DQ_SWAP_DISABLE | QOS_FAST_DISABLE\
| RD_FETCH | TIMEOUT_LEVEL0)
#define MEMCONTROL_OR (1 | 2 | (1 << 4) | (1 << 24))
#define CLK_STOP_DISABLE (0 << 1)
#define DPWRDN_DISABLE (0 << 2)
#define DPWRDN_TYPE (0 << 3)
#define TP_DISABLE (0 << 4)
#define DSREF_DIABLE (0 << 5)
#define ADD_LAT_PALL (1 << 6)
#define MEM_TYPE_DDR3 (6 << 8)
#define MEM_WIDTH_32 (2 << 12)
#define NUM_CHIP_2 (1 << 16)
#define BL_8 (3 << 20)
#define MEMCONTROL_VAL (CLK_STOP_DISABLE | DPWRDN_DISABLE\
| DPWRDN_TYPE | TP_DISABLE | DSREF_DIABLE\
| ADD_LAT_PALL | MEM_TYPE_DDR3 | MEM_WIDTH_32\
| NUM_CHIP_2 | BL_8)
#define CHIP_BANK_8 (0x3 << 0)
#define CHIP_COL_10 (0x3 << 8)
#define CHIP_MAP_INTERLEAVED (0x1 << 12)
#ifdef CONFIG_MIU_LINEAR
#define CHIP_ROW (0x2 << 4)
#define CHIP0_BASE (0x40 << 24)
#define CHIP1_BASE (0x60 << 24)
#define CHIP_MASK (0xe0 << 16)
#else
#define CHIP_ROW (0x3 << 4)
#define CHIP0_BASE (0x40 << 24)
#define CHIP1_BASE (0x80 << 24)
#define CHIP_MASK (0x80 << 16)
#endif
#define MEMCONFIG0_VAL (CHIP_BANK_8 | CHIP_ROW | CHIP_COL_10\
| CHIP_MAP_INTERLEAVED | CHIP_MASK | CHIP0_BASE)
#define MEMCONFIG1_VAL (CHIP_BANK_8 | CHIP_ROW | CHIP_COL_10\
| CHIP_MAP_INTERLEAVED | CHIP_MASK | CHIP1_BASE)
#define TP_CNT (0x64 << 24)
#define PRECHCONFIG TP_CNT
#define CTRL_OFF (0 << 0)
#define CTRL_DLL_OFF (0 << 1)
#define CTRL_HALF (0 << 2)
#define CTRL_DFDQS (1 << 3)
#define DQS_DELAY (0 << 4)
#define CTRL_START_POINT (0x10 << 8)
#define CTRL_INC (0x10 << 16)
#define CTRL_FORCE (0x71 << 24)
#define CONTROL0_VAL (CTRL_OFF | CTRL_DLL_OFF | CTRL_HALF\
| CTRL_DFDQS | DQS_DELAY | CTRL_START_POINT\
| CTRL_INC | CTRL_FORCE)
#define CTRL_SHIFTC (6 << 0)
#define CTRL_REF (8 << 4)
#define CTRL_SHGATE (1 << 29)
#define TERM_READ_EN (1 << 30)
#define TERM_WRITE_EN (1 << 31)
#define CONTROL1_VAL (CTRL_SHIFTC | CTRL_REF | CTRL_SHGATE\
| TERM_READ_EN | TERM_WRITE_EN)
#define CONTROL2_VAL 0x00000000
#ifdef DRAM_CLK_200
#define TIMINGREF_VAL 0x000000BB
#define TIMINGROW_VAL 0x4046654f
#define TIMINGDATA_VAL 0x46400506
#define TIMINGPOWER_VAL 0x52000A3C
#endif
#ifdef DRAM_CLK_330
#define TIMINGREF_VAL 0x000000BC
#define TIMINGROW_VAL 0x3545548d
#define TIMINGDATA_VAL 0x45430506
#define TIMINGPOWER_VAL 0x4439033c
#endif
#ifdef DRAM_CLK_400
#define TIMINGREF_VAL 0x000000BC
#define TIMINGROW_VAL 0x45430506
#define TIMINGDATA_VAL 0x56500506
#define TIMINGPOWER_VAL 0x5444033d
#endif
#endif
修改include/configs/itop4412.h,选择合适的时钟#define CONFIG_CLK_1000_200_200
四、验证结果
读写验证:在对应的内存区域随机选择内存地址,直接读写,看能否正常读写。
内存映射:在地址0x40000000处写入数据,在0x80000000读取数据,看其值是否一样。
内存间歇:在0x80000000附近读写内存,看内存是否连续。
内存长度:在0xC0000000附近读写内存,看内存实际容量。