summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorLokesh Vutla <lokeshvutla@ti.com>2013-12-10 15:02:22 +0530
committerTom Rini <trini@ti.com>2013-12-18 21:14:44 -0500
commitd3daba10f159cca7e9d24c6f154926a9b92c75e3 (patch)
tree34dee6df0d4914e66bc0bc9a3c652b20fc0e7eb7 /arch
parent965de8b91bddd1f5967240d1d44005719b09dd5e (diff)
downloadu-boot-imx-d3daba10f159cca7e9d24c6f154926a9b92c75e3.zip
u-boot-imx-d3daba10f159cca7e9d24c6f154926a9b92c75e3.tar.gz
u-boot-imx-d3daba10f159cca7e9d24c6f154926a9b92c75e3.tar.bz2
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')
-rw-r--r--arch/arm/cpu/armv7/am33xx/ddr.c117
-rw-r--r--arch/arm/cpu/armv7/am33xx/emif4.c22
-rw-r--r--arch/arm/include/asm/arch-am33xx/clocks_am33xx.h3
-rw-r--r--arch/arm/include/asm/arch-am33xx/cpu.h5
-rw-r--r--arch/arm/include/asm/arch-am33xx/ddr_defs.h33
-rw-r--r--arch/arm/include/asm/arch-am33xx/hardware_am43xx.h1
-rw-r--r--arch/arm/include/asm/emif.h12
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 255f333..1abbb07 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 2278358..6af4b84 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 468521b..15399dc 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 d9d521a..e68c113 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 (;;); })