[U-Boot] [PATCH V3 12/14] ARM: AM43xx: EPOS_EVM: Add support for LPDDR2

Lokesh Vutla lokeshvutla at ti.com
Tue Dec 10 10:32:22 CET 2013


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 at ti.com>
---
Changes since V2:
-> Seperated ioregs changes into a new patch.
 arch/arm/cpu/armv7/am33xx/ddr.c                    |  117 ++++++++++++++++++++
 arch/arm/cpu/armv7/am33xx/emif4.c                  |   22 +++-
 arch/arm/include/asm/arch-am33xx/clocks_am33xx.h   |    3 +
 arch/arm/include/asm/arch-am33xx/cpu.h             |    5 +
 arch/arm/include/asm/arch-am33xx/ddr_defs.h        |   33 +++++-
 arch/arm/include/asm/arch-am33xx/hardware_am43xx.h |    1 +
 arch/arm/include/asm/emif.h                        |   12 ++
 board/ti/am43xx/board.c                            |   66 +++++++++++
 8 files changed, 256 insertions(+), 3 deletions(-)

diff --git a/arch/arm/cpu/armv7/am33xx/ddr.c b/arch/arm/cpu/armv7/am33xx/ddr.c
index f4eac5f..243ec39 100644
--- a/arch/arm/cpu/armv7/am33xx/ddr.c
+++ b/arch/arm/cpu/armv7/am33xx/ddr.c
@@ -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);
 }
 
 /**
diff --git a/arch/arm/cpu/armv7/am33xx/emif4.c b/arch/arm/cpu/armv7/am33xx/emif4.c
index adda650..d28fceb 100644
--- a/arch/arm/cpu/armv7/am33xx/emif4.c
+++ b/arch/arm/cpu/armv7/am33xx/emif4.c
@@ -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
diff --git a/arch/arm/include/asm/arch-am33xx/clocks_am33xx.h b/arch/arm/include/asm/arch-am33xx/clocks_am33xx.h
index 02ed595..4c9352a 100644
--- a/arch/arm/include/asm/arch-am33xx/clocks_am33xx.h
+++ b/arch/arm/include/asm/arch-am33xx/clocks_am33xx.h
@@ -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;
diff --git a/arch/arm/include/asm/arch-am33xx/cpu.h b/arch/arm/include/asm/arch-am33xx/cpu.h
index 3ee37dc..9febfa2 100644
--- a/arch/arm/include/asm/arch-am33xx/cpu.h
+++ b/arch/arm/include/asm/arch-am33xx/cpu.h
@@ -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 */
diff --git a/arch/arm/include/asm/arch-am33xx/ddr_defs.h b/arch/arm/include/asm/arch-am33xx/ddr_defs.h
index fe48b5f..c98ab7f 100644
--- a/arch/arm/include/asm/arch-am33xx/ddr_defs.h
+++ b/arch/arm/include/asm/arch-am33xx/ddr_defs.h
@@ -19,7 +19,11 @@
 #define VTP_CTRL_ENABLE		(0x1 << 6)
 #define VTP_CTRL_START_EN	(0x1)
 #define PHY_DLL_LOCK_DIFF	0x0
+#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 */
@@ -126,6 +130,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
  */
@@ -135,6 +147,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
@@ -291,12 +304,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;
@@ -304,8 +332,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 */
diff --git a/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h b/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h
index ada1b4c..b9a701d 100644
--- a/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h
+++ b/arch/arm/include/asm/arch-am33xx/hardware_am43xx.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 << 2)
+#define CM_DEVICE_INST			0x44df4100
 
 /* Control status register */
 #define CTRL_CRYSTAL_FREQ_SRC_MASK		(1 << 31)
diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h
index 1b94a99..ce6b229 100644
--- a/arch/arm/include/asm/emif.h
+++ b/arch/arm/include/asm/emif.h
@@ -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 */
@@ -1139,6 +1143,14 @@ struct lpddr2_mr_regs {
 	s8 mr16;
 };
 
+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 (;;); })
diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c
index 5c92ac7..5a013e3 100644
--- a/board/ti/am43xx/board.c
+++ b/board/ti/am43xx/board.c
@@ -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
 
-- 
1.7.9.5



More information about the U-Boot mailing list