drivers/ddr/fsl: Fix DDR4 RDIMM support
authorYork Sun <york.sun@nxp.com>
Mon, 29 Jan 2018 17:44:33 +0000 (09:44 -0800)
committerYork Sun <york.sun@nxp.com>
Tue, 30 Jan 2018 17:14:06 +0000 (09:14 -0800)
For DDR4, command/address delay in mode registers and parity latency
in timing config register are only needed for UDIMMs, but not RDIMMs.
Add additional register rcw_3 for DDR4 RDIMM. Fix mirrored bit for
dual rank RDIMMs. Set sdram_cfg_3[DIS_MRS_PAR] for RDIMMs. Fix
calculation of timing config registers. Use hexadecimal format for
printing RCW (register control word) registers.

Signed-off-by: York Sun <york.sun@nxp.com>
drivers/ddr/fsl/ctrl_regs.c
drivers/ddr/fsl/ddr4_dimm_params.c
drivers/ddr/fsl/interactive.c
include/fsl_ddr_sdram.h

index c0ee858a02eeabd83981e8364fcc2be9e8218893..33adfb1f06f50ed17e836f9881ba48504236a682 100644 (file)
@@ -732,6 +732,7 @@ static void set_ddr_sdram_rcw(fsl_ddr_cfg_regs_t *ddr,
                if (popts->rcw_override) {
                        ddr->ddr_sdram_rcw_1 = popts->rcw_1;
                        ddr->ddr_sdram_rcw_2 = popts->rcw_2;
+                       ddr->ddr_sdram_rcw_3 = popts->rcw_3;
                } else {
                        ddr->ddr_sdram_rcw_1 =
                                common_dimm->rcw[0] << 28 | \
@@ -752,8 +753,12 @@ static void set_ddr_sdram_rcw(fsl_ddr_cfg_regs_t *ddr,
                                common_dimm->rcw[14] << 4 | \
                                common_dimm->rcw[15];
                }
-               debug("FSLDDR: ddr_sdram_rcw_1 = 0x%08x\n", ddr->ddr_sdram_rcw_1);
-               debug("FSLDDR: ddr_sdram_rcw_2 = 0x%08x\n", ddr->ddr_sdram_rcw_2);
+               debug("FSLDDR: ddr_sdram_rcw_1 = 0x%08x\n",
+                     ddr->ddr_sdram_rcw_1);
+               debug("FSLDDR: ddr_sdram_rcw_2 = 0x%08x\n",
+                     ddr->ddr_sdram_rcw_2);
+               debug("FSLDDR: ddr_sdram_rcw_3 = 0x%08x\n",
+                     ddr->ddr_sdram_rcw_3);
        }
 }
 
@@ -1159,8 +1164,14 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr,
                esdmode5 = 0x00000400;  /* Data mask enabled */
        }
 
-       /* set command/address parity latency */
-       if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) {
+       /*
+        * For DDR3, set C/A latency if address parity is enabled.
+        * For DDR4, set C/A latency for UDIMM only. For RDIMM the delay is
+        * handled by register chip and RCW settings.
+        */
+       if ((ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) &&
+           ((CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) ||
+            !popts->registered_dimm_en)) {
                if (mclk_ps >= 935) {
                        /* for DDR4-1600/1866/2133 */
                        esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK;
@@ -1193,7 +1204,9 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr,
                                esdmode5 = 0x00000400;
                        }
 
-                       if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) {
+                       if ((ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) &&
+                           ((CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) ||
+                            !popts->registered_dimm_en)) {
                                if (mclk_ps >= 935) {
                                        /* for DDR4-1600/1866/2133 */
                                        esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK;
@@ -1965,6 +1978,7 @@ static void set_timing_cfg_6(fsl_ddr_cfg_regs_t *ddr)
 
 static void set_timing_cfg_7(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 txpr, tcksre, tcksrx;
@@ -1975,16 +1989,11 @@ static void set_timing_cfg_7(const unsigned int ctrl_num,
        tcksre = max(5U, picos_to_mclk(ctrl_num, 10000));
        tcksrx = max(5U, picos_to_mclk(ctrl_num, 10000));
 
-       if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) {
-               if (mclk_ps >= 935) {
-                       /* parity latency 4 clocks in case of 1600/1866/2133 */
-                       par_lat = 4;
-               } else if (mclk_ps >= 833) {
-                       /* parity latency 5 clocks for DDR4-2400 */
-                       par_lat = 5;
-               } else {
-                       printf("parity: mclk_ps = %d not supported\n", mclk_ps);
-               }
+       if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN &&
+           CONFIG_FSL_SDRAM_TYPE == SDRAM_TYPE_DDR4) {
+               /* for DDR4 only */
+               par_lat = (popts->rcw_2 & 0xf) + 1;
+               debug("PAR_LAT = %u for mclk_ps = %d\n", par_lat, mclk_ps);
        }
 
        cs_to_cmd = 0;
@@ -2024,11 +2033,11 @@ static void set_timing_cfg_8(const unsigned int ctrl_num,
                             const common_timing_params_t *common_dimm,
                             unsigned int cas_latency)
 {
-       unsigned int rwt_bg, wrt_bg, rrt_bg, wwt_bg;
+       int rwt_bg, wrt_bg, rrt_bg, wwt_bg;
        unsigned int acttoact_bg, wrtord_bg, pre_all_rec;
-       unsigned int tccdl = picos_to_mclk(ctrl_num, common_dimm->tccdl_ps);
-       unsigned int wr_lat = ((ddr->timing_cfg_2 & 0x00780000) >> 19) +
-                             ((ddr->timing_cfg_2 & 0x00040000) >> 14);
+       int tccdl = picos_to_mclk(ctrl_num, common_dimm->tccdl_ps);
+       int wr_lat = ((ddr->timing_cfg_2 & 0x00780000) >> 19) +
+                     ((ddr->timing_cfg_2 & 0x00040000) >> 14);
 
        rwt_bg = cas_latency + 2 + 4 - wr_lat;
        if (rwt_bg < tccdl)
@@ -2130,6 +2139,8 @@ static void set_ddr_sdram_cfg_3(fsl_ddr_cfg_regs_t *ddr,
        rd_pre = popts->quad_rank_present ? 1 : 0;
 
        ddr->ddr_sdram_cfg_3 = (rd_pre & 0x1) << 16;
+       /* Disable MRS on parity error for RDIMMs */
+       ddr->ddr_sdram_cfg_3 |= popts->registered_dimm_en ? 1 : 0;
 
        debug("FSLDDR: ddr_sdram_cfg_3 = 0x%08x\n", ddr->ddr_sdram_cfg_3);
 }
@@ -2535,7 +2546,7 @@ compute_fsl_memctl_config_regs(const unsigned int ctrl_num,
 #ifdef CONFIG_SYS_FSL_DDR4
        set_ddr_sdram_cfg_3(ddr, popts);
        set_timing_cfg_6(ddr);
-       set_timing_cfg_7(ctrl_num, ddr, common_dimm);
+       set_timing_cfg_7(ctrl_num, ddr, popts, common_dimm);
        set_timing_cfg_8(ctrl_num, ddr, popts, common_dimm, cas_latency);
        set_timing_cfg_9(ddr);
        set_ddr_dq_mapping(ddr, dimm_params);
index 42834ca7b21ed507f4b373bb4b714cff5cc46773..6e26ba88a5d47fb35661e2f03a3a24500e5e80b9 100644 (file)
@@ -179,6 +179,8 @@ unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num,
        case DDR4_SPD_MODULETYPE_RDIMM:
                /* Registered/buffered DIMMs */
                pdimm->registered_dimm = 1;
+               if (spd->mod_section.registered.reg_map & 0x1)
+                       pdimm->mirrored_dimm = 1;
                break;
 
        case DDR4_SPD_MODULETYPE_UDIMM:
index c99bd2fb6d014ffa306a42fc6f8c8c179a61bb18..660060d7eb6bf1f13c75be98d83d41a0ed8229b2 100644 (file)
@@ -558,6 +558,7 @@ static void fsl_ddr_options_edit(fsl_ddr_info_t *pinfo,
                 */
                CTRL_OPTIONS(twot_en),
                CTRL_OPTIONS(threet_en),
+               CTRL_OPTIONS(mirrored_dimm),
                CTRL_OPTIONS(ap_en),
                CTRL_OPTIONS(x4_en),
                CTRL_OPTIONS(bstopre),
@@ -568,6 +569,7 @@ static void fsl_ddr_options_edit(fsl_ddr_info_t *pinfo,
                CTRL_OPTIONS(rcw_override),
                CTRL_OPTIONS(rcw_1),
                CTRL_OPTIONS(rcw_2),
+               CTRL_OPTIONS(rcw_3),
                CTRL_OPTIONS(ddr_cdr1),
                CTRL_OPTIONS(ddr_cdr2),
                CTRL_OPTIONS(tfaw_window_four_activates_ps),
@@ -660,6 +662,7 @@ static void print_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
                CFG_REGS(ddr_sr_cntr),
                CFG_REGS(ddr_sdram_rcw_1),
                CFG_REGS(ddr_sdram_rcw_2),
+               CFG_REGS(ddr_sdram_rcw_3),
                CFG_REGS(ddr_cdr1),
                CFG_REGS(ddr_cdr2),
                CFG_REGS(dq_map_0),
@@ -750,6 +753,7 @@ static void fsl_ddr_regs_edit(fsl_ddr_info_t *pinfo,
                CFG_REGS(ddr_sr_cntr),
                CFG_REGS(ddr_sdram_rcw_1),
                CFG_REGS(ddr_sdram_rcw_2),
+               CFG_REGS(ddr_sdram_rcw_3),
                CFG_REGS(ddr_cdr1),
                CFG_REGS(ddr_cdr2),
                CFG_REGS(dq_map_0),
@@ -857,8 +861,9 @@ static void print_memctl_options(const memctl_options_t *popts)
                CTRL_OPTIONS(wrlvl_start),
                CTRL_OPTIONS_HEX(cswl_override),
                CTRL_OPTIONS(rcw_override),
-               CTRL_OPTIONS(rcw_1),
-               CTRL_OPTIONS(rcw_2),
+               CTRL_OPTIONS_HEX(rcw_1),
+               CTRL_OPTIONS_HEX(rcw_2),
+               CTRL_OPTIONS_HEX(rcw_3),
                CTRL_OPTIONS_HEX(ddr_cdr1),
                CTRL_OPTIONS_HEX(ddr_cdr2),
                CTRL_OPTIONS(tfaw_window_four_activates_ps),
index 6a1f04b81ac400485c9f401ebba050e78502e922..de7ef9b53ffa5089f8492c37681baee08eaf4e76 100644 (file)
@@ -408,6 +408,7 @@ typedef struct memctl_options_s {
        unsigned int rcw_override;
        unsigned int rcw_1;
        unsigned int rcw_2;
+       unsigned int rcw_3;
        /* control register 1 */
        unsigned int ddr_cdr1;
        unsigned int ddr_cdr2;