ARM: AM43xx: EPOS_EVM: Add support for LPDDR2

AM4372 EPOS EVM has 1GB LPDDR2(Part no: MT42L256M32D2LG-25 WT:A)
Adding LPDDR2 init sequence and register details for the same.
Below is the brief description of LPDDR2 init sequence:
-> Configure VTP
-> Configure DDR IO settings
-> Disable initialization and refreshes until EMIF registers are programmed.
-> Program Timing registers
-> Program PHY control and Temp alert and ZQ config registers.
-> Enable initialization and refreshes and configure SDRAM CONFIG register
-> Wait till initialization is complete and the configure MR registers.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
This commit is contained in:
Lokesh Vutla 2013-12-10 15:02:22 +05:30 committed by Tom Rini
parent 965de8b91b
commit d3daba10f1
8 changed files with 256 additions and 3 deletions

View file

@ -36,6 +36,71 @@ static struct ddr_data_regs *ddr_data_reg[2] = {
static struct ddr_cmdtctrl *ioctrl_reg = {
(struct ddr_cmdtctrl *)DDR_CONTROL_BASE_ADDR};
static inline u32 get_mr(int nr, u32 cs, u32 mr_addr)
{
u32 mr;
mr_addr |= cs << EMIF_REG_CS_SHIFT;
writel(mr_addr, &emif_reg[nr]->emif_lpddr2_mode_reg_cfg);
mr = readl(&emif_reg[nr]->emif_lpddr2_mode_reg_data);
debug("get_mr: EMIF1 cs %d mr %08x val 0x%x\n", cs, mr_addr, mr);
if (((mr & 0x0000ff00) >> 8) == (mr & 0xff) &&
((mr & 0x00ff0000) >> 16) == (mr & 0xff) &&
((mr & 0xff000000) >> 24) == (mr & 0xff))
return mr & 0xff;
else
return mr;
}
static inline void set_mr(int nr, u32 cs, u32 mr_addr, u32 mr_val)
{
mr_addr |= cs << EMIF_REG_CS_SHIFT;
writel(mr_addr, &emif_reg[nr]->emif_lpddr2_mode_reg_cfg);
writel(mr_val, &emif_reg[nr]->emif_lpddr2_mode_reg_data);
}
static void configure_mr(int nr, u32 cs)
{
u32 mr_addr;
while (get_mr(nr, cs, LPDDR2_MR0) & LPDDR2_MR0_DAI_MASK)
;
set_mr(nr, cs, LPDDR2_MR10, 0x56);
set_mr(nr, cs, LPDDR2_MR1, 0x43);
set_mr(nr, cs, LPDDR2_MR2, 0x2);
mr_addr = LPDDR2_MR2 | EMIF_REG_REFRESH_EN_MASK;
set_mr(nr, cs, mr_addr, 0x2);
}
/*
* Configure EMIF4D5 registers and MR registers
*/
void config_sdram_emif4d5(const struct emif_regs *regs, int nr)
{
writel(0x0, &emif_reg[nr]->emif_pwr_mgmt_ctrl);
writel(0x0, &emif_reg[nr]->emif_pwr_mgmt_ctrl_shdw);
writel(0x1, &emif_reg[nr]->emif_iodft_tlgc);
writel(regs->zq_config, &emif_reg[nr]->emif_zq_config);
writel(regs->temp_alert_config, &emif_reg[nr]->emif_temp_alert_config);
writel(regs->emif_rd_wr_lvl_rmp_win,
&emif_reg[nr]->emif_rd_wr_lvl_rmp_win);
writel(regs->emif_rd_wr_lvl_rmp_ctl,
&emif_reg[nr]->emif_rd_wr_lvl_rmp_ctl);
writel(regs->emif_rd_wr_lvl_ctl, &emif_reg[nr]->emif_rd_wr_lvl_ctl);
writel(regs->emif_rd_wr_exec_thresh,
&emif_reg[nr]->emif_rd_wr_exec_thresh);
writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl);
writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config);
configure_mr(nr, 0);
configure_mr(nr, 1);
}
/**
* Configure SDRAM
*/
@ -72,15 +137,67 @@ void set_sdram_timings(const struct emif_regs *regs, int nr)
writel(regs->sdram_tim3, &emif_reg[nr]->emif_sdram_tim_3_shdw);
}
void __weak emif_get_ext_phy_ctrl_const_regs(const u32 **regs, u32 *size)
{
}
/*
* Configure EXT PHY registers
*/
static void ext_phy_settings(const struct emif_regs *regs, int nr)
{
u32 *ext_phy_ctrl_base = 0;
u32 *emif_ext_phy_ctrl_base = 0;
const u32 *ext_phy_ctrl_const_regs;
u32 i = 0;
u32 size;
ext_phy_ctrl_base = (u32 *)&(regs->emif_ddr_ext_phy_ctrl_1);
emif_ext_phy_ctrl_base =
(u32 *)&(emif_reg[nr]->emif_ddr_ext_phy_ctrl_1);
/* Configure external phy control timing registers */
for (i = 0; i < EMIF_EXT_PHY_CTRL_TIMING_REG; i++) {
writel(*ext_phy_ctrl_base, emif_ext_phy_ctrl_base++);
/* Update shadow registers */
writel(*ext_phy_ctrl_base++, emif_ext_phy_ctrl_base++);
}
/*
* external phy 6-24 registers do not change with
* ddr frequency
*/
emif_get_ext_phy_ctrl_const_regs(&ext_phy_ctrl_const_regs, &size);
if (!size)
return;
for (i = 0; i < size; i++) {
writel(ext_phy_ctrl_const_regs[i], emif_ext_phy_ctrl_base++);
/* Update shadow registers */
writel(ext_phy_ctrl_const_regs[i], emif_ext_phy_ctrl_base++);
}
}
/**
* Configure DDR PHY
*/
void config_ddr_phy(const struct emif_regs *regs, int nr)
{
/*
* disable initialization and refreshes for now until we
* finish programming EMIF regs.
*/
setbits_le32(&emif_reg[nr]->emif_sdram_ref_ctrl,
EMIF_REG_INITREF_DIS_MASK);
writel(regs->emif_ddr_phy_ctlr_1,
&emif_reg[nr]->emif_ddr_phy_ctrl_1);
writel(regs->emif_ddr_phy_ctlr_1,
&emif_reg[nr]->emif_ddr_phy_ctrl_1_shdw);
if (get_emif_rev((u32)emif_reg[nr]) == EMIF_4D5)
ext_phy_settings(regs, nr);
}
/**

View file

@ -48,6 +48,11 @@ static struct vtp_reg *vtpreg[2] = {
#ifdef CONFIG_AM33XX
static struct ddr_ctrl *ddrctrl = (struct ddr_ctrl *)DDR_CTRL_ADDR;
#endif
#ifdef CONFIG_AM43XX
static struct ddr_ctrl *ddrctrl = (struct ddr_ctrl *)DDR_CTRL_ADDR;
static struct cm_device_inst *cm_device =
(struct cm_device_inst *)CM_DEVICE_INST;
#endif
#ifdef CONFIG_TI81XX
void config_dmm(const struct dmm_lisa_map_regs *regs)
@ -104,9 +109,24 @@ void config_ddr(unsigned int pll, const struct ctrl_ioregs *ioregs,
/* Set CKE to be controlled by EMIF/DDR PHY */
writel(DDR_CKE_CTRL_NORMAL, &ddrctrl->ddrckectrl);
#endif
#ifdef CONFIG_AM43XX
writel(readl(&cm_device->cm_dll_ctrl) & ~0x1, &cm_device->cm_dll_ctrl);
while ((readl(&cm_device->cm_dll_ctrl) && CM_DLL_READYST) == 0)
;
writel(0x0, &ddrctrl->ddrioctrl);
config_io_ctrl(ioregs);
/* Set CKE to be controlled by EMIF/DDR PHY */
writel(DDR_CKE_CTRL_NORMAL, &ddrctrl->ddrckectrl);
#endif
/* Program EMIF instance */
config_ddr_phy(regs, nr);
set_sdram_timings(regs, nr);
config_sdram(regs, nr);
if (get_emif_rev(EMIF1_BASE) == EMIF_4D5)
config_sdram_emif4d5(regs, nr);
else
config_sdram(regs, nr);
}
#endif

View file

@ -28,6 +28,9 @@
#define UART_CLK_RUNNING_MASK 0x1
#define UART_SMART_IDLE_EN (0x1 << 0x3)
#define CM_DLL_CTRL_NO_OVERRIDE 0x0
#define CM_DLL_READYST 0x4
extern void enable_dmm_clocks(void);
extern const struct dpll_params dpll_core_opp100;
extern struct dpll_params dpll_mpu_opp100;

View file

@ -401,6 +401,11 @@ struct cm_perpll {
unsigned int cpgmac0clkctrl; /* offset 0xB20 */
};
struct cm_device_inst {
unsigned int cm_clkout1_ctrl;
unsigned int cm_dll_ctrl;
};
struct cm_dpll {
unsigned int resv1;
unsigned int clktimer2clk; /* offset 0x04 */

View file

@ -18,7 +18,11 @@
#define VTP_CTRL_READY (0x1 << 5)
#define VTP_CTRL_ENABLE (0x1 << 6)
#define VTP_CTRL_START_EN (0x1)
#ifdef CONFIG_AM43XX
#define DDR_CKE_CTRL_NORMAL 0x3
#else
#define DDR_CKE_CTRL_NORMAL 0x1
#endif
#define PHY_EN_DYN_PWRDN (0x1 << 20)
/* Micron MT47H128M16RT-25E */
@ -124,6 +128,14 @@
#define K4B2G1646EBIH9_PHY_WR_DATA 0x76
#define K4B2G1646EBIH9_IOCTRL_VALUE 0x18B
#define LPDDR2_ADDRCTRL_IOCTRL_VALUE 0x294
#define LPDDR2_ADDRCTRL_WD0_IOCTRL_VALUE 0x00000000
#define LPDDR2_ADDRCTRL_WD1_IOCTRL_VALUE 0x00000000
#define LPDDR2_DATA0_IOCTRL_VALUE 0x20000294
#define LPDDR2_DATA1_IOCTRL_VALUE 0x20000294
#define LPDDR2_DATA2_IOCTRL_VALUE 0x20000294
#define LPDDR2_DATA3_IOCTRL_VALUE 0x20000294
/**
* Configure DMM
*/
@ -133,6 +145,7 @@ void config_dmm(const struct dmm_lisa_map_regs *regs);
* Configure SDRAM
*/
void config_sdram(const struct emif_regs *regs, int nr);
void config_sdram_emif4d5(const struct emif_regs *regs, int nr);
/**
* Set SDRAM timings
@ -278,12 +291,27 @@ struct ddr_cmdtctrl {
unsigned int resv2[12];
unsigned int dt0ioctl;
unsigned int dt1ioctl;
unsigned int dt2ioctrl;
unsigned int dt3ioctrl;
unsigned int resv3[4];
unsigned int emif_sdram_config_ext;
};
struct ctrl_ioregs {
unsigned int cm0ioctl;
unsigned int cm1ioctl;
unsigned int cm2ioctl;
unsigned int dt0ioctl;
unsigned int dt1ioctl;
unsigned int dt2ioctrl;
unsigned int dt3ioctrl;
unsigned int emif_sdram_config_ext;
};
/**
* Configure DDR io control registers
*/
void config_io_ctrl(unsigned long val);
void config_io_ctrl(const struct ctrl_ioregs *ioregs);
struct ddr_ctrl {
unsigned int ddrioctrl;
@ -291,8 +319,9 @@ struct ddr_ctrl {
unsigned int ddrckectrl;
};
void config_ddr(unsigned int pll, unsigned int ioctrl,
void config_ddr(unsigned int pll, const struct ctrl_ioregs *ioregs,
const struct ddr_data *data, const struct cmd_control *ctrl,
const struct emif_regs *regs, int nr);
void emif_get_ext_phy_ctrl_const_regs(const u32 **regs, u32 *size);
#endif /* _DDR_DEFS_H */

View file

@ -62,6 +62,7 @@
#define PRM_PER_USBPHYOCP2SCP0_CLKCTRL (CM_PER + 0x5b8)
#define PRM_PER_USBPHYOCP2SCP1_CLKCTRL (CM_PER + 0x5c0)
#define USBPHYOCPSCP_MODULE_EN (1 << 1)
#define CM_DEVICE_INST 0x44df4100
/* Control status register */
#define CTRL_CRYSTAL_FREQ_SRC_MASK (1 << 31)

View file

@ -14,11 +14,15 @@
#define _EMIF_H_
#include <asm/types.h>
#include <common.h>
#include <asm/io.h>
/* Base address */
#define EMIF1_BASE 0x4c000000
#define EMIF2_BASE 0x4d000000
#define EMIF_4D 0x4
#define EMIF_4D5 0x5
/* Registers shifts, masks and values */
/* EMIF_MOD_ID_REV */
@ -1148,6 +1152,14 @@ struct read_write_regs {
u32 write_reg;
};
static inline u32 get_emif_rev(u32 base)
{
struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
return (readl(&emif->emif_mod_id_rev) & EMIF_REG_MAJOR_REVISION_MASK)
>> EMIF_REG_MAJOR_REVISION_SHIFT;
}
/* assert macros */
#if defined(DEBUG)
#define emif_assert(c) ({ if (!(c)) for (;;); })

View file

@ -15,6 +15,8 @@
#include <asm/arch/clock.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/mux.h>
#include <asm/arch/ddr_defs.h>
#include <asm/emif.h>
#include "board.h"
DECLARE_GLOBAL_DATA_PTR;
@ -122,6 +124,69 @@ const struct dpll_params epos_evm_dpll_ddr = {
const struct dpll_params gp_evm_dpll_ddr = {
400, 23, 1, -1, 1, -1, -1};
const struct ctrl_ioregs ioregs_lpddr2 = {
.cm0ioctl = LPDDR2_ADDRCTRL_IOCTRL_VALUE,
.cm1ioctl = LPDDR2_ADDRCTRL_WD0_IOCTRL_VALUE,
.cm2ioctl = LPDDR2_ADDRCTRL_WD1_IOCTRL_VALUE,
.dt0ioctl = LPDDR2_DATA0_IOCTRL_VALUE,
.dt1ioctl = LPDDR2_DATA0_IOCTRL_VALUE,
.dt2ioctrl = LPDDR2_DATA0_IOCTRL_VALUE,
.dt3ioctrl = LPDDR2_DATA0_IOCTRL_VALUE,
.emif_sdram_config_ext = 0x1,
};
const struct emif_regs emif_regs_lpddr2 = {
.sdram_config = 0x808012BA,
.ref_ctrl = 0x0000040D,
.sdram_tim1 = 0xEA86B411,
.sdram_tim2 = 0x103A094A,
.sdram_tim3 = 0x0F6BA37F,
.read_idle_ctrl = 0x00050000,
.zq_config = 0x50074BE4,
.temp_alert_config = 0x0,
.emif_rd_wr_lvl_rmp_win = 0x0,
.emif_rd_wr_lvl_rmp_ctl = 0x0,
.emif_rd_wr_lvl_ctl = 0x0,
.emif_ddr_phy_ctlr_1 = 0x0E084006,
.emif_rd_wr_exec_thresh = 0x00000405,
.emif_ddr_ext_phy_ctrl_1 = 0x04010040,
.emif_ddr_ext_phy_ctrl_2 = 0x00500050,
.emif_ddr_ext_phy_ctrl_3 = 0x00500050,
.emif_ddr_ext_phy_ctrl_4 = 0x00500050,
.emif_ddr_ext_phy_ctrl_5 = 0x00500050
};
const u32 ext_phy_ctrl_const_base_lpddr2[] = {
0x00500050,
0x00350035,
0x00350035,
0x00350035,
0x00350035,
0x00350035,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x40001000,
0x08102040
};
void emif_get_ext_phy_ctrl_const_regs(const u32 **regs, u32 *size)
{
*regs = ext_phy_ctrl_const_base_lpddr2;
*size = ARRAY_SIZE(ext_phy_ctrl_const_base_lpddr2);
return;
}
const struct dpll_params *get_dpll_ddr_params(void)
{
struct am43xx_board_id header;
@ -217,6 +282,7 @@ void set_mux_conf_regs(void)
void sdram_init(void)
{
config_ddr(0, &ioregs_lpddr2, NULL, NULL, &emif_regs_lpddr2, 0);
}
#endif