diff options
| author | Lokesh Vutla <lokeshvutla@ti.com> | 2013-12-10 15:02:22 +0530 | 
|---|---|---|
| committer | Tom Rini <trini@ti.com> | 2013-12-18 21:14:44 -0500 | 
| commit | d3daba10f159cca7e9d24c6f154926a9b92c75e3 (patch) | |
| tree | 34dee6df0d4914e66bc0bc9a3c652b20fc0e7eb7 /arch/arm | |
| parent | 965de8b91bddd1f5967240d1d44005719b09dd5e (diff) | |
| download | olio-uboot-2014.01-d3daba10f159cca7e9d24c6f154926a9b92c75e3.tar.xz olio-uboot-2014.01-d3daba10f159cca7e9d24c6f154926a9b92c75e3.zip | |
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>
Diffstat (limited to 'arch/arm')
| -rw-r--r-- | arch/arm/cpu/armv7/am33xx/ddr.c | 117 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/am33xx/emif4.c | 22 | ||||
| -rw-r--r-- | arch/arm/include/asm/arch-am33xx/clocks_am33xx.h | 3 | ||||
| -rw-r--r-- | arch/arm/include/asm/arch-am33xx/cpu.h | 5 | ||||
| -rw-r--r-- | arch/arm/include/asm/arch-am33xx/ddr_defs.h | 33 | ||||
| -rw-r--r-- | arch/arm/include/asm/arch-am33xx/hardware_am43xx.h | 1 | ||||
| -rw-r--r-- | arch/arm/include/asm/emif.h | 12 | 
7 files changed, 190 insertions, 3 deletions
| diff --git a/arch/arm/cpu/armv7/am33xx/ddr.c b/arch/arm/cpu/armv7/am33xx/ddr.c index 255f333b6..1abbb07c9 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 adda650fe..d28fceb75 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 02ed5957e..4c9352a2e 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 3ee37dc4e..9febfa271 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 2278358ab..6af4b84e5 100644 --- a/arch/arm/include/asm/arch-am33xx/ddr_defs.h +++ b/arch/arm/include/asm/arch-am33xx/ddr_defs.h @@ -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 */ diff --git a/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h b/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h index 468521bf3..15399dcc7 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 << 1) +#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 d9d521a51..e68c113e2 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 */ @@ -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 (;;); }) |