mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-26 14:40:41 +00:00
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:
parent
965de8b91b
commit
d3daba10f1
8 changed files with 256 additions and 3 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 (;;); })
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue