+#ifdef CONFIG_SYS_FSL_DDR4
+/* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
+static void set_ddr_sdram_mode(const unsigned int ctrl_num,
+ fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const common_timing_params_t *common_dimm,
+ unsigned int cas_latency,
+ unsigned int additive_latency,
+ const unsigned int unq_mrs_en)
+{
+ int i;
+ unsigned short esdmode; /* Extended SDRAM mode */
+ unsigned short sdmode; /* SDRAM mode */
+
+ /* Mode Register - MR1 */
+ unsigned int qoff = 0; /* Output buffer enable 0=yes, 1=no */
+ unsigned int tdqs_en = 0; /* TDQS Enable: 0=no, 1=yes */
+ unsigned int rtt;
+ unsigned int wrlvl_en = 0; /* Write level enable: 0=no, 1=yes */
+ unsigned int al = 0; /* Posted CAS# additive latency (AL) */
+ unsigned int dic = 0; /* Output driver impedance, 40ohm */
+ unsigned int dll_en = 1; /* DLL Enable 1=Enable (Normal),
+ 0=Disable (Test/Debug) */
+
+ /* Mode Register - MR0 */
+ unsigned int wr = 0; /* Write Recovery */
+ unsigned int dll_rst; /* DLL Reset */
+ unsigned int mode; /* Normal=0 or Test=1 */
+ unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */
+ /* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
+ unsigned int bt;
+ unsigned int bl; /* BL: Burst Length */
+
+ unsigned int wr_mclk;
+ /* DDR4 support WR 10, 12, 14, 16, 18, 20, 24 */
+ static const u8 wr_table[] = {
+ 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6};
+ /* DDR4 support CAS 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24 */
+ static const u8 cas_latency_table[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8,
+ 9, 9, 10, 10, 11, 11};
+
+ if (popts->rtt_override)
+ rtt = popts->rtt_override_value;
+ else
+ rtt = popts->cs_local_opts[0].odt_rtt_norm;
+
+ if (additive_latency == (cas_latency - 1))
+ al = 1;
+ if (additive_latency == (cas_latency - 2))
+ al = 2;
+
+ if (popts->quad_rank_present)
+ dic = 1; /* output driver impedance 240/7 ohm */
+
+ /*
+ * The esdmode value will also be used for writing
+ * MR1 during write leveling for DDR3, although the
+ * bits specifically related to the write leveling
+ * scheme will be handled automatically by the DDR
+ * controller. so we set the wrlvl_en = 0 here.
+ */
+ esdmode = (0
+ | ((qoff & 0x1) << 12)
+ | ((tdqs_en & 0x1) << 11)
+ | ((rtt & 0x7) << 8)
+ | ((wrlvl_en & 0x1) << 7)
+ | ((al & 0x3) << 3)
+ | ((dic & 0x3) << 1) /* DIC field is split */
+ | ((dll_en & 0x1) << 0)
+ );
+
+ /*
+ * DLL control for precharge PD
+ * 0=slow exit DLL off (tXPDLL)
+ * 1=fast exit DLL on (tXP)
+ */
+
+ wr_mclk = picos_to_mclk(ctrl_num, common_dimm->twr_ps);
+ if (wr_mclk <= 24) {
+ wr = wr_table[wr_mclk - 10];
+ } else {
+ printf("Error: unsupported write recovery for mode register wr_mclk = %d\n",
+ wr_mclk);
+ }
+
+ dll_rst = 0; /* dll no reset */
+ mode = 0; /* normal mode */
+
+ /* look up table to get the cas latency bits */
+ if (cas_latency >= 9 && cas_latency <= 24)
+ caslat = cas_latency_table[cas_latency - 9];
+ else
+ printf("Error: unsupported cas latency for mode register\n");
+
+ bt = 0; /* Nibble sequential */
+
+ switch (popts->burst_length) {
+ case DDR_BL8:
+ bl = 0;
+ break;
+ case DDR_OTF:
+ bl = 1;
+ break;
+ case DDR_BC4:
+ bl = 2;
+ break;
+ default:
+ printf("Error: invalid burst length of %u specified. ",
+ popts->burst_length);
+ puts("Defaulting to on-the-fly BC4 or BL8 beats.\n");
+ bl = 1;
+ break;
+ }
+
+ sdmode = (0
+ | ((wr & 0x7) << 9)
+ | ((dll_rst & 0x1) << 8)
+ | ((mode & 0x1) << 7)
+ | (((caslat >> 1) & 0x7) << 4)
+ | ((bt & 0x1) << 3)
+ | ((caslat & 1) << 2)
+ | ((bl & 0x3) << 0)
+ );
+
+ ddr->ddr_sdram_mode = (0
+ | ((esdmode & 0xFFFF) << 16)
+ | ((sdmode & 0xFFFF) << 0)
+ );
+
+ debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
+
+ if (unq_mrs_en) { /* unique mode registers are supported */
+ for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (popts->rtt_override)
+ rtt = popts->rtt_override_value;
+ else
+ rtt = popts->cs_local_opts[i].odt_rtt_norm;
+
+ esdmode &= 0xF8FF; /* clear bit 10,9,8 for rtt */
+ esdmode |= (rtt & 0x7) << 8;
+ switch (i) {
+ case 1:
+ ddr->ddr_sdram_mode_3 = (0
+ | ((esdmode & 0xFFFF) << 16)
+ | ((sdmode & 0xFFFF) << 0)
+ );
+ break;
+ case 2:
+ ddr->ddr_sdram_mode_5 = (0
+ | ((esdmode & 0xFFFF) << 16)
+ | ((sdmode & 0xFFFF) << 0)
+ );
+ break;
+ case 3:
+ ddr->ddr_sdram_mode_7 = (0
+ | ((esdmode & 0xFFFF) << 16)
+ | ((sdmode & 0xFFFF) << 0)
+ );
+ break;
+ }
+ }
+ debug("FSLDDR: ddr_sdram_mode_3 = 0x%08x\n",
+ ddr->ddr_sdram_mode_3);
+ debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
+ ddr->ddr_sdram_mode_5);
+ debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
+ ddr->ddr_sdram_mode_5);
+ }
+}
+
+#elif defined(CONFIG_SYS_FSL_DDR3)