drivers/ddr/fsl: Add calculation of register control words
authorYork Sun <york.sun@nxp.com>
Mon, 29 Jan 2018 18:24:08 +0000 (10:24 -0800)
committerYork Sun <york.sun@nxp.com>
Tue, 30 Jan 2018 17:14:07 +0000 (09:14 -0800)
DDR4 RDIMM has some information in SPD to be used to calculate the
control words for register chip. The rest can be found from JEDEC
spec DDR4RCD02.

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/options.c
include/ddr_spd.h
include/fsl_ddr_dimm_params.h

index bcab9046adcaacc0c7f7aa440306bfeff8ca3b2a..8b8727116dadb47fd060e3004febbd92cf1d3984 100644 (file)
@@ -724,10 +724,14 @@ static void set_timing_cfg_2(const unsigned int ctrl_num,
 }
 
 /* DDR SDRAM Register Control Word */
-static void set_ddr_sdram_rcw(fsl_ddr_cfg_regs_t *ddr,
-                              const memctl_options_t *popts,
-                              const common_timing_params_t *common_dimm)
+static void set_ddr_sdram_rcw(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 ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
+       unsigned int rc0a, rc0f;
+
        if (common_dimm->all_dimms_registered &&
            !common_dimm->all_dimms_unbuffered) {
                if (popts->rcw_override) {
@@ -735,6 +739,16 @@ static void set_ddr_sdram_rcw(fsl_ddr_cfg_regs_t *ddr,
                        ddr->ddr_sdram_rcw_2 = popts->rcw_2;
                        ddr->ddr_sdram_rcw_3 = popts->rcw_3;
                } else {
+                       rc0a = ddr_freq > 3200 ? 0x7 :
+                              (ddr_freq > 2933 ? 0x6 :
+                               (ddr_freq > 2666 ? 0x5 :
+                                (ddr_freq > 2400 ? 0x4 :
+                                 (ddr_freq > 2133 ? 0x3 :
+                                  (ddr_freq > 1866 ? 0x2 :
+                                   (ddr_freq > 1600 ? 1 : 0))))));
+                       rc0f = ddr_freq > 3200 ? 0x3 :
+                              (ddr_freq > 2400 ? 0x2 :
+                               (ddr_freq > 2133 ? 0x1 : 0));
                        ddr->ddr_sdram_rcw_1 =
                                common_dimm->rcw[0] << 28 | \
                                common_dimm->rcw[1] << 24 | \
@@ -747,12 +761,14 @@ static void set_ddr_sdram_rcw(fsl_ddr_cfg_regs_t *ddr,
                        ddr->ddr_sdram_rcw_2 =
                                common_dimm->rcw[8] << 28 | \
                                common_dimm->rcw[9] << 24 | \
-                               common_dimm->rcw[10] << 20 | \
+                               rc0a << 20 | \
                                common_dimm->rcw[11] << 16 | \
                                common_dimm->rcw[12] << 12 | \
                                common_dimm->rcw[13] << 8 | \
                                common_dimm->rcw[14] << 4 | \
-                               common_dimm->rcw[15];
+                               rc0f;
+                       ddr->ddr_sdram_rcw_3 =
+                               ((ddr_freq - 1260 + 19) / 20) << 8;
                }
                debug("FSLDDR: ddr_sdram_rcw_1 = 0x%08x\n",
                      ddr->ddr_sdram_rcw_1);
@@ -2561,6 +2577,8 @@ compute_fsl_memctl_config_regs(const unsigned int ctrl_num,
        set_ddr_sdram_mode_9(ddr, popts, common_dimm, unq_mrs_en);
        set_ddr_sdram_mode_10(ctrl_num, ddr, popts, common_dimm, unq_mrs_en);
 #endif
+       set_ddr_sdram_rcw(ctrl_num, ddr, popts, common_dimm);
+
        set_ddr_sdram_interval(ctrl_num, ddr, popts, common_dimm);
        set_ddr_data_init(ddr);
        set_ddr_sdram_clk_cntl(ddr, popts);
@@ -2582,8 +2600,6 @@ compute_fsl_memctl_config_regs(const unsigned int ctrl_num,
 
        set_ddr_sr_cntr(ddr, sr_it);
 
-       set_ddr_sdram_rcw(ddr, popts, common_dimm);
-
 #ifdef CONFIG_SYS_FSL_DDR_EMU
        /* disble DDR training for emulator */
        ddr->debug[2] = 0x00000400;
index 1f1d9b897a49eb66db703cade8bb92dbf6329a2a..5c8fc8804d476ba691c9d0a2420682698f21a080 100644 (file)
@@ -139,6 +139,7 @@ unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num,
        };
        int spd_error = 0;
        u8 *ptr;
+       u8 val;
 
        if (spd->mem_type) {
                if (spd->mem_type != SPD_MEMTYPE_DDR4) {
@@ -191,6 +192,26 @@ unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num,
                pdimm->registered_dimm = 1;
                if (spd->mod_section.registered.reg_map & 0x1)
                        pdimm->mirrored_dimm = 1;
+               val = spd->mod_section.registered.ca_stren;
+               pdimm->rcw[3] = val >> 4;
+               pdimm->rcw[4] = ((val & 0x3) << 2) | ((val & 0xc) >> 2);
+               val = spd->mod_section.registered.clk_stren;
+               pdimm->rcw[5] = ((val & 0x3) << 2) | ((val & 0xc) >> 2);
+               /* Not all in SPD. For convience only. Boards may overwrite. */
+               pdimm->rcw[6] = 0xf;
+               /*
+                * A17 only used for 16Gb and above devices.
+                * C[2:0] only used for 3DS.
+                */
+               pdimm->rcw[8] = pdimm->die_density >= 0x6 ? 0x0 : 0x8 |
+                               (pdimm->package_3ds > 0x3 ? 0x0 :
+                                (pdimm->package_3ds > 0x1 ? 0x1 :
+                                 (pdimm->package_3ds > 0 ? 0x2 : 0x3)));
+               if (pdimm->package_3ds || pdimm->n_ranks != 4)
+                       pdimm->rcw[13] = 0xc;
+               else
+                       pdimm->rcw[13] = 0xd;   /* Fix encoded by board */
+
                break;
 
        case DDR4_SPD_MODULETYPE_UDIMM:
index 5158ea2089951320f2d1e3c33cf698fb246b7701..85ec48c28e38814bbaaf171088118996bc9e8051 100644 (file)
@@ -750,7 +750,9 @@ unsigned int populate_memctl_options(const common_timing_params_t *common_dimm,
        defined(CONFIG_SYS_FSL_DDR4)
        const struct dynamic_odt *pdodt = odt_unknown;
 #endif
+#if (CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4)
        ulong ddr_freq;
+#endif
 
        /*
         * Extract hwconfig from environment since we have not properly setup
@@ -1295,6 +1297,7 @@ done:
 
        popts->package_3ds = pdimm->package_3ds;
 
+#if (CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4)
        ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
        if (popts->registered_dimm_en) {
                popts->rcw_override = 1;
@@ -1308,6 +1311,7 @@ done:
                else
                        popts->rcw_2 = 0x00300000;
        }
+#endif
 
        fsl_ddr_board_options(popts, pdimm, ctrl_num);
 
index d71cd9ab3c0b02386ff8af78b414187b488ebdd3..20dc9ea1a6da11996ce47871e45db8198745b104 100644 (file)
@@ -382,9 +382,11 @@ struct ddr4_spd_eeprom_s {
                        /* 135 Register Revision Number */
                        uint8_t reg_rev;
                        /* 136 Address mapping from register to DRAM */
-                       uint8_t reg_map;
-                       /* 137~253 Reserved */
-                       uint8_t res_137[254-137];
+                       u8 reg_map;
+                       u8 ca_stren;
+                       u8 clk_stren;
+                       /* 139~253 Reserved */
+                       u8 res_137[254 - 139];
                        /* 254~255 CRC */
                        uint8_t crc[2];
                } registered;
index c6c819ea0a9ed8737a7bcf5f6bc5245a4534ef52..1f78ea2d86b787211237556ec446e2b417eb61f2 100644 (file)
@@ -106,7 +106,7 @@ typedef struct dimm_params_s {
        int tqhs_ps;    /* byte 45, spd->tqhs */
 #endif
 
-       /* DDR3 RDIMM */
+       /* DDR3 & DDR4 RDIMM */
        unsigned char rcw[16];  /* Register Control Word 0-15 */
 #ifdef CONFIG_SYS_FSL_DDR4
        unsigned int dq_mapping[18];