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 <lokeshvu...@ti.com> --- arch/arm/cpu/armv7/am33xx/Makefile | 8 +- arch/arm/cpu/armv7/am33xx/emif4d5.c | 183 ++++++++++++++++++++ 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 | 26 +++ arch/arm/include/asm/arch-am33xx/hardware_am43xx.h | 1 + arch/arm/include/asm/emif.h | 12 ++ board/ti/am43xx/board.c | 59 +++++++ 8 files changed, 295 insertions(+), 2 deletions(-) create mode 100644 arch/arm/cpu/armv7/am33xx/emif4d5.c diff --git a/arch/arm/cpu/armv7/am33xx/Makefile b/arch/arm/cpu/armv7/am33xx/Makefile index f6a297c..8414430 100644 --- a/arch/arm/cpu/armv7/am33xx/Makefile +++ b/arch/arm/cpu/armv7/am33xx/Makefile @@ -19,12 +19,16 @@ endif COBJS-$(CONFIG_TI816X) += clock_ti816x.o COBJS += sys_info.o COBJS += mem.o -COBJS += ddr.o -COBJS += emif4.o COBJS += board.o COBJS += mux.o COBJS-$(CONFIG_NAND_OMAP_GPMC) += elm.o +ifeq ($(CONFIG_AM43XX),) +COBJS += ddr.o +COBJS += emif4.o +endif +COBJS-$(CONFIG_AM43XX) += emif4d5.o + SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS) $(COBJS-y) $(SOBJS)) diff --git a/arch/arm/cpu/armv7/am33xx/emif4d5.c b/arch/arm/cpu/armv7/am33xx/emif4d5.c new file mode 100644 index 0000000..eea1fa3 --- /dev/null +++ b/arch/arm/cpu/armv7/am33xx/emif4d5.c @@ -0,0 +1,183 @@ +/* + * emif4d5.c + * + * AM43XX emif4d5 configuration file + * + * Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/ddr_defs.h> +#include <asm/arch/hardware.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> +#include <asm/io.h> +#include <asm/emif.h> + +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; +static struct ddr_cmdtctrl *ioctrl_reg = + (struct ddr_cmdtctrl *)DDR_CONTROL_BASE_ADDR; +static struct vtp_reg *vtpreg = (struct vtp_reg *)VTP0_CTRL_ADDR; + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + /* dram_init must store complete ramsize in gd->ram_size */ + gd->ram_size = get_ram_size( + (void *)CONFIG_SYS_SDRAM_BASE, + CONFIG_MAX_RAM_BANK_SIZE); + return 0; +} + +static void config_vtp(void) +{ + writel(readl(&vtpreg->vtp0ctrlreg) | VTP_CTRL_ENABLE, + &vtpreg->vtp0ctrlreg); + writel(readl(&vtpreg->vtp0ctrlreg) & (~VTP_CTRL_START_EN), + &vtpreg->vtp0ctrlreg); + writel(readl(&vtpreg->vtp0ctrlreg) | VTP_CTRL_START_EN, + &vtpreg->vtp0ctrlreg); + + while ((readl(&vtpreg->vtp0ctrlreg) & VTP_CTRL_READY) != + VTP_CTRL_READY) + ; +} + +static void ext_phy_settings(const struct emif_regs *regs, + const u32 *ext_phy_ctrl_const_regs) +{ + u32 *ext_phy_ctrl_base = 0; + u32 *emif_ext_phy_ctrl_base = 0; + u32 i = 0; + + struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE; + + ext_phy_ctrl_base = (u32 *)&(regs->emif_ddr_ext_phy_ctrl_1); + emif_ext_phy_ctrl_base = (u32 *)&(emif->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++); + } + + for (i = 0; i < EMIF_EXT_PHY_CTRL_CONST_REG; 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++); + } +} + +static inline u32 get_mr(u32 base, u32 cs, u32 mr_addr) +{ + u32 mr; + struct emif_reg_struct *emif = (struct emif_reg_struct *)base; + + mr_addr |= cs << EMIF_REG_CS_SHIFT; + writel(mr_addr, &emif->emif_lpddr2_mode_reg_cfg); + + mr = readl(&emif->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(u32 base, u32 cs, u32 mr_addr, u32 mr_val) +{ + struct emif_reg_struct *emif = (struct emif_reg_struct *)base; + + mr_addr |= cs << EMIF_REG_CS_SHIFT; + writel(mr_addr, &emif->emif_lpddr2_mode_reg_cfg); + writel(mr_val, &emif->emif_lpddr2_mode_reg_data); +} + +static void configure_mr(u32 base, u32 cs) +{ + u32 mr_addr; + + while (get_mr(base, cs, LPDDR2_MR0) & LPDDR2_MR0_DAI_MASK) + ; + set_mr(base, cs, LPDDR2_MR10, 0x56); + + set_mr(base, cs, LPDDR2_MR1, 0x43); + set_mr(base, cs, LPDDR2_MR2, 0x2); + + mr_addr = LPDDR2_MR2 | EMIF_REG_REFRESH_EN_MASK; + set_mr(base, cs, mr_addr, 0x2); +} + +void do_sdram_init(const struct ctrl_ioregs *ioregs, + const struct emif_regs *regs, + const u32 *ext_phy_ctrl_const_regs) +{ + struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE; + + config_vtp(); + + writel(readl(&cm_device->cm_dll_ctrl) & ~0x1, &cm_device->cm_dll_ctrl); + while ((readl(&cm_device->cm_dll_ctrl) && CM_DLL_READYST) == 0) + ; + + /* io settings */ + writel(ioregs->cm0ioctl, &ioctrl_reg->cm0ioctl); + writel(ioregs->cm1ioctl, &ioctrl_reg->cm1ioctl); + writel(ioregs->cm2ioctl, &ioctrl_reg->cm2ioctl); + writel(ioregs->dt0ioctl, &ioctrl_reg->dt0ioctl); + writel(ioregs->dt1ioctl, &ioctrl_reg->dt1ioctl); + writel(ioregs->dt2ioctrl, &ioctrl_reg->dt2ioctrl); + writel(ioregs->dt3ioctrl, &ioctrl_reg->dt3ioctrl); + writel(ioregs->emif_sdram_config_ext, + &ioctrl_reg->emif_sdram_config_ext); + writel(0x0, &ddrctrl->ddrioctrl); + + /* Set CKE to be controlled by EMIF/DDR PHY */ + writel(readl(&ddrctrl->ddrckectrl) | 0x3, &ddrctrl->ddrckectrl); + + /* + * disable initialization and refreshes for now until we + * finish programming EMIF regs. + */ + setbits_le32(&emif->emif_sdram_ref_ctrl, EMIF_REG_INITREF_DIS_MASK); + + writel(regs->sdram_tim1, &emif->emif_sdram_tim_1); + writel(regs->sdram_tim1, &emif->emif_sdram_tim_1_shdw); + writel(regs->sdram_tim2, &emif->emif_sdram_tim_2); + writel(regs->sdram_tim2, &emif->emif_sdram_tim_2_shdw); + writel(regs->sdram_tim3, &emif->emif_sdram_tim_3); + writel(regs->sdram_tim3, &emif->emif_sdram_tim_3_shdw); + + writel(0x0, &emif->emif_pwr_mgmt_ctrl); + writel(0x0, &emif->emif_pwr_mgmt_ctrl_shdw); + writel(0x1, &emif->emif_iodft_tlgc); + writel(regs->zq_config, &emif->emif_zq_config); + + writel(regs->temp_alert_config, &emif->emif_temp_alert_config); + writel(regs->emif_rd_wr_lvl_rmp_win, &emif->emif_rd_wr_lvl_rmp_win); + writel(regs->emif_rd_wr_lvl_rmp_ctl, &emif->emif_rd_wr_lvl_rmp_ctl); + writel(regs->emif_rd_wr_lvl_ctl, &emif->emif_rd_wr_lvl_ctl); + writel(regs->emif_ddr_phy_ctlr_1, &emif->emif_ddr_phy_ctrl_1); + writel(regs->emif_ddr_phy_ctlr_1, &emif->emif_ddr_phy_ctrl_1_shdw); + writel(regs->emif_rd_wr_exec_thresh, &emif->emif_rd_wr_exec_thresh); + + ext_phy_settings(regs, ext_phy_ctrl_const_regs); + + clrbits_le32(&emif->emif_sdram_ref_ctrl, EMIF_REG_INITREF_DIS_MASK); + + writel(regs->sdram_config, &emif->emif_sdram_config); + writel(regs->ref_ctrl, &emif->emif_sdram_ref_ctrl); + + configure_mr(EMIF1_BASE, 0); + configure_mr(EMIF1_BASE, 1); +} 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 f463b27..23af125 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..1880415 100644 --- a/arch/arm/include/asm/arch-am33xx/ddr_defs.h +++ b/arch/arm/include/asm/arch-am33xx/ddr_defs.h @@ -126,6 +126,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 */ @@ -291,6 +299,21 @@ 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; }; /** @@ -308,4 +331,7 @@ void config_ddr(unsigned int pll, unsigned int ioctrl, const struct ddr_data *data, const struct cmd_control *ctrl, const struct emif_regs *regs, int nr); +void do_sdram_init(const struct ctrl_ioregs *ioregs, + const struct emif_regs *emif_regs, + const u32 *ext_phy_ctrl_const_regs); #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 4dbc789..d82f050 100644 --- a/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h +++ b/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h @@ -63,5 +63,6 @@ #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 #endif /* __AM43XX_HARDWARE_AM43XX_H */ diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h index 1b94a99..5edc3a4 100644 --- a/arch/arm/include/asm/emif.h +++ b/arch/arm/include/asm/emif.h @@ -690,6 +690,18 @@ struct emif_reg_struct { u32 emif_ddr_ext_phy_ctrl_23_shdw; u32 emif_ddr_ext_phy_ctrl_24; u32 emif_ddr_ext_phy_ctrl_24_shdw; + u32 emif_ddr_ext_phy_ctrl_25; + u32 emif_ddr_ext_phy_ctrl_25_shdw; + u32 emif_ddr_ext_phy_ctrl_26; + u32 emif_ddr_ext_phy_ctrl_26_shdw; + u32 emif_ddr_ext_phy_ctrl_27; + u32 emif_ddr_ext_phy_ctrl_27_shdw; + u32 emif_ddr_ext_phy_ctrl_28; + u32 emif_ddr_ext_phy_ctrl_28_shdw; + u32 emif_ddr_ext_phy_ctrl_29; + u32 emif_ddr_ext_phy_ctrl_29_shdw; + u32 emif_ddr_ext_phy_ctrl_30; + u32 emif_ddr_ext_phy_ctrl_30_shdw; }; struct dmm_lisa_map_regs { diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c index a700d1f..83d184d 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; @@ -83,6 +85,61 @@ const struct dpll_params gp_evm_dpll_core = { const struct dpll_params gp_evm_dpll_per = { 960, 23, 5, -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[EMIF_EXT_PHY_CTRL_CONST_REG] = { + 0x00500050, + 0x00350035, + 0x00350035, + 0x00350035, + 0x00350035, + 0x00350035, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x40001000, + 0x08102040 +}; + const struct dpll_params *get_dpll_ddr_params(void) { if (board_is_eposevm()) @@ -134,6 +191,8 @@ void set_mux_conf_regs(void) void sdram_init(void) { + do_sdram_init(&ioregs_lpddr2, &emif_regs_lpddr2, + ext_phy_ctrl_const_base_lpddr2); } #endif -- 1.7.9.5 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot