From 426230a65f2dd62c3b6c1509e9775d5500db20d3 Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 29 Jan 2018 09:44:33 -0800 Subject: drivers/ddr/fsl: Fix DDR4 RDIMM support 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 --- drivers/ddr/fsl/ctrl_regs.c | 51 +++++++++++++++++++++++--------------- drivers/ddr/fsl/ddr4_dimm_params.c | 2 ++ drivers/ddr/fsl/interactive.c | 9 +++++-- 3 files changed, 40 insertions(+), 22 deletions(-) (limited to 'drivers/ddr') diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c index c0ee858a02..33adfb1f06 100644 --- a/drivers/ddr/fsl/ctrl_regs.c +++ b/drivers/ddr/fsl/ctrl_regs.c @@ -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); diff --git a/drivers/ddr/fsl/ddr4_dimm_params.c b/drivers/ddr/fsl/ddr4_dimm_params.c index 42834ca7b2..6e26ba88a5 100644 --- a/drivers/ddr/fsl/ddr4_dimm_params.c +++ b/drivers/ddr/fsl/ddr4_dimm_params.c @@ -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: diff --git a/drivers/ddr/fsl/interactive.c b/drivers/ddr/fsl/interactive.c index c99bd2fb6d..660060d7eb 100644 --- a/drivers/ddr/fsl/interactive.c +++ b/drivers/ddr/fsl/interactive.c @@ -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), -- cgit v1.2.1 From d46ec0bbaf1a38711b493266f49bb26ac9157d8a Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 29 Jan 2018 09:44:34 -0800 Subject: drivers/ddr/fsl: Fix workaround for A009803 Wrong field was masked in this workaround due to wrong endianness. The impacted SoCs have big-endian. Signed-off-by: York Sun --- drivers/ddr/fsl/fsl_ddr_gen4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ddr') diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c index b3a27ec5a8..7df9178415 100644 --- a/drivers/ddr/fsl/fsl_ddr_gen4.c +++ b/drivers/ddr/fsl/fsl_ddr_gen4.c @@ -210,7 +210,7 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, if (regs->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) { if (regs->ddr_sdram_cfg & SDRAM_CFG_RD_EN) { /* for RDIMM */ ddr_out32(&ddr->ddr_sdram_rcw_2, - regs->ddr_sdram_rcw_2 & ~0x0f000000); + regs->ddr_sdram_rcw_2 & ~0xf0); } ddr_out32(&ddr->err_disable, regs->err_disable | DDR_ERR_DISABLE_APED); -- cgit v1.2.1 From c0c32af0b2f037e3e167c7ac82e7110ebae48fb5 Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 29 Jan 2018 09:44:35 -0800 Subject: drivers/ddr/fsl: Add 3DS RDIMM support On top of RDIMM support, add new register calculation to support 3DS RDIMMs. Only symmetrical 3DS is supported at this time. Signed-off-by: York Sun --- drivers/ddr/fsl/ctrl_regs.c | 43 ++++++++++++++++++++++++++------- drivers/ddr/fsl/ddr4_dimm_params.c | 25 +++++++++++++++++-- drivers/ddr/fsl/interactive.c | 13 +++++++++- drivers/ddr/fsl/lc_common_dimm_params.c | 8 +++++- drivers/ddr/fsl/options.c | 5 +++- 5 files changed, 80 insertions(+), 14 deletions(-) (limited to 'drivers/ddr') diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c index 33adfb1f06..bcab9046ad 100644 --- a/drivers/ddr/fsl/ctrl_regs.c +++ b/drivers/ddr/fsl/ctrl_regs.c @@ -1,5 +1,6 @@ /* - * Copyright 2008-2014 Freescale Semiconductor, Inc. + * Copyright 2008-2016 Freescale Semiconductor, Inc. + * Copyright 2017-2018 NXP Semiconductor * * SPDX-License-Identifier: GPL-2.0+ */ @@ -492,7 +493,7 @@ static void set_timing_cfg_3(const unsigned int ctrl_num, | ((ext_pretoact & 0x1) << 28) | ((ext_acttopre & 0x3) << 24) | ((ext_acttorw & 0x1) << 22) - | ((ext_refrec & 0x1F) << 16) + | ((ext_refrec & 0x3F) << 16) | ((ext_caslat & 0x3) << 12) | ((ext_add_lat & 0x1) << 10) | ((ext_wrrec & 0x1) << 8) @@ -885,7 +886,7 @@ static void set_ddr_sdram_cfg_2(const unsigned int ctrl_num, } } sr_ie = popts->self_refresh_interrupt_en; - num_pr = 1; /* Make this configurable */ + num_pr = popts->package_3ds + 1; /* * 8572 manual says @@ -1193,7 +1194,7 @@ static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr, * need 0x500 to park. */ - debug("FSLDDR: ddr_sdram_mode_9) = 0x%08x\n", ddr->ddr_sdram_mode_9); + debug("FSLDDR: ddr_sdram_mode_9 = 0x%08x\n", ddr->ddr_sdram_mode_9); if (unq_mrs_en) { /* unique mode registers are supported */ for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { if (!rtt_park && @@ -1270,7 +1271,7 @@ static void set_ddr_sdram_mode_10(const unsigned int ctrl_num, | ((esdmode6 & 0xffff) << 16) | ((esdmode7 & 0xffff) << 0) ); - debug("FSLDDR: ddr_sdram_mode_10) = 0x%08x\n", ddr->ddr_sdram_mode_10); + debug("FSLDDR: ddr_sdram_mode_10 = 0x%08x\n", ddr->ddr_sdram_mode_10); if (unq_mrs_en) { /* unique mode registers are supported */ for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { switch (i) { @@ -1992,7 +1993,7 @@ static void set_timing_cfg_7(const unsigned int ctrl_num, 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; + par_lat = (ddr->ddr_sdram_rcw_2 & 0xf) + 1; debug("PAR_LAT = %u for mclk_ps = %d\n", par_lat, mclk_ps); } @@ -2079,9 +2080,23 @@ static void set_timing_cfg_8(const unsigned int ctrl_num, debug("FSLDDR: timing_cfg_8 = 0x%08x\n", ddr->timing_cfg_8); } -static void set_timing_cfg_9(fsl_ddr_cfg_regs_t *ddr) +static void set_timing_cfg_9(const unsigned int ctrl_num, + fsl_ddr_cfg_regs_t *ddr, + const memctl_options_t *popts, + const common_timing_params_t *common_dimm) { - ddr->timing_cfg_9 = 0; + unsigned int refrec_cid_mclk = 0; + unsigned int acttoact_cid_mclk = 0; + + if (popts->package_3ds) { + refrec_cid_mclk = + picos_to_mclk(ctrl_num, common_dimm->trfc_slr_ps); + acttoact_cid_mclk = 4U; /* tRRDS_slr */ + } + + ddr->timing_cfg_9 = (refrec_cid_mclk & 0x3ff) << 16 | + (acttoact_cid_mclk & 0xf) << 8; + debug("FSLDDR: timing_cfg_9 = 0x%08x\n", ddr->timing_cfg_9); } @@ -2142,6 +2157,16 @@ static void set_ddr_sdram_cfg_3(fsl_ddr_cfg_regs_t *ddr, /* Disable MRS on parity error for RDIMMs */ ddr->ddr_sdram_cfg_3 |= popts->registered_dimm_en ? 1 : 0; + if (popts->package_3ds) { /* only 2,4,8 are supported */ + if ((popts->package_3ds + 1) & 0x1) { + printf("Error: Unsupported 3DS DIMM with %d die\n", + popts->package_3ds + 1); + } else { + ddr->ddr_sdram_cfg_3 |= ((popts->package_3ds + 1) >> 1) + << 4; + } + } + debug("FSLDDR: ddr_sdram_cfg_3 = 0x%08x\n", ddr->ddr_sdram_cfg_3); } #endif /* CONFIG_SYS_FSL_DDR4 */ @@ -2548,7 +2573,7 @@ compute_fsl_memctl_config_regs(const unsigned int ctrl_num, set_timing_cfg_6(ddr); 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_timing_cfg_9(ctrl_num, ddr, popts, common_dimm); set_ddr_dq_mapping(ddr, dimm_params); #endif diff --git a/drivers/ddr/fsl/ddr4_dimm_params.c b/drivers/ddr/fsl/ddr4_dimm_params.c index 6e26ba88a5..1f1d9b897a 100644 --- a/drivers/ddr/fsl/ddr4_dimm_params.c +++ b/drivers/ddr/fsl/ddr4_dimm_params.c @@ -1,5 +1,8 @@ /* - * Copyright 2014 Freescale Semiconductor, Inc. + * Copyright 2014-2016 Freescale Semiconductor, Inc. + * Copyright 2017-2018 NXP Semiconductor + * + * SPDX-License-Identifier: GPL-2.0+ * * calculate the organization and timing parameter * from ddr3 spd, please refer to the spec @@ -98,6 +101,10 @@ compute_ranksize(const struct ddr4_spd_eeprom_s *spd) if ((spd->organization & 0x7) < 4) nbit_sdram_width = (spd->organization & 0x7) + 2; package_3ds = (spd->package_type & 0x3) == 0x2; + if ((spd->package_type & 0x80) && !package_3ds) { /* other than 3DS */ + printf("Warning: not supported SDRAM package type\n"); + return 0; + } if (package_3ds) die_count = (spd->package_type >> 4) & 0x7; @@ -105,7 +112,7 @@ compute_ranksize(const struct ddr4_spd_eeprom_s *spd) nbit_primary_bus_width - nbit_sdram_width + die_count); - debug("DDR: DDR III rank density = 0x%16llx\n", bsize); + debug("DDR: DDR rank density = 0x%16llx\n", bsize); return bsize; } @@ -163,6 +170,7 @@ unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num, pdimm->n_ranks = ((spd->organization >> 3) & 0x7) + 1; pdimm->rank_density = compute_ranksize(spd); pdimm->capacity = pdimm->n_ranks * pdimm->rank_density; + pdimm->die_density = spd->density_banks & 0xf; pdimm->primary_sdram_width = 1 << (3 + (spd->bus_width & 0x7)); if ((spd->bus_width >> 3) & 0x3) pdimm->ec_sdram_width = 8; @@ -171,6 +179,8 @@ unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num, pdimm->data_width = pdimm->primary_sdram_width + pdimm->ec_sdram_width; pdimm->device_width = 1 << ((spd->organization & 0x7) + 2); + pdimm->package_3ds = (spd->package_type & 0x3) == 0x2 ? + (spd->package_type >> 4) & 0x7 : 0; /* These are the types defined by the JEDEC SPD spec */ pdimm->mirrored_dimm = 0; @@ -310,6 +320,17 @@ unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num, /* min CAS to CAS Delay Time (tCCD_Lmin), same bank group */ pdimm->tccdl_ps = spd_to_ps(spd->tccdl_min, spd->fine_tccdl_min); + if (pdimm->package_3ds) { + if (pdimm->die_density <= 0x4) { + pdimm->trfc_slr_ps = 260000; + } else if (pdimm->die_density <= 0x5) { + pdimm->trfc_slr_ps = 350000; + } else { + printf("WARN: Unsupported logical rank density 0x%x\n", + pdimm->die_density); + } + } + /* * Average periodic refresh interval * tREFI = 7.8 us at normal temperature range diff --git a/drivers/ddr/fsl/interactive.c b/drivers/ddr/fsl/interactive.c index 660060d7eb..78ca03bcb2 100644 --- a/drivers/ddr/fsl/interactive.c +++ b/drivers/ddr/fsl/interactive.c @@ -1,5 +1,6 @@ /* - * Copyright 2010-2014 Freescale Semiconductor, Inc. + * Copyright 2010-2016 Freescale Semiconductor, Inc. + * Copyright 2017-2018 NXP Semiconductor * * SPDX-License-Identifier: GPL-2.0+ */ @@ -168,6 +169,7 @@ static void lowest_common_dimm_parameters_edit(fsl_ddr_info_t *pinfo, COMMON_TIMING(trrds_ps), COMMON_TIMING(trrdl_ps), COMMON_TIMING(tccdl_ps), + COMMON_TIMING(trfc_slr_ps), #else COMMON_TIMING(twtr_ps), COMMON_TIMING(trfc_ps), @@ -223,6 +225,7 @@ static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo, DIMM_PARM(data_width), DIMM_PARM(primary_sdram_width), DIMM_PARM(ec_sdram_width), + DIMM_PARM(package_3ds), DIMM_PARM(registered_dimm), DIMM_PARM(mirrored_dimm), DIMM_PARM(device_width), @@ -233,6 +236,7 @@ static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo, #ifdef CONFIG_SYS_FSL_DDR4 DIMM_PARM(bank_addr_bits), DIMM_PARM(bank_group_bits), + DIMM_PARM_HEX(die_density), #else DIMM_PARM(n_banks_per_sdram_device), #endif @@ -260,6 +264,7 @@ static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo, DIMM_PARM(trrds_ps), DIMM_PARM(trrdl_ps), DIMM_PARM(tccdl_ps), + DIMM_PARM(trfc_slr_ps), #else DIMM_PARM(twr_ps), DIMM_PARM(twtr_ps), @@ -320,6 +325,7 @@ static void print_dimm_parameters(const dimm_params_t *pdimm) DIMM_PARM(data_width), DIMM_PARM(primary_sdram_width), DIMM_PARM(ec_sdram_width), + DIMM_PARM(package_3ds), DIMM_PARM(registered_dimm), DIMM_PARM(mirrored_dimm), DIMM_PARM(device_width), @@ -330,6 +336,7 @@ static void print_dimm_parameters(const dimm_params_t *pdimm) #ifdef CONFIG_SYS_FSL_DDR4 DIMM_PARM(bank_addr_bits), DIMM_PARM(bank_group_bits), + DIMM_PARM_HEX(die_density), #else DIMM_PARM(n_banks_per_sdram_device), #endif @@ -359,6 +366,7 @@ static void print_dimm_parameters(const dimm_params_t *pdimm) DIMM_PARM(trrds_ps), DIMM_PARM(trrdl_ps), DIMM_PARM(tccdl_ps), + DIMM_PARM(trfc_slr_ps), #else DIMM_PARM(twr_ps), DIMM_PARM(twtr_ps), @@ -437,6 +445,7 @@ static void print_lowest_common_dimm_parameters( COMMON_TIMING(trrds_ps), COMMON_TIMING(trrdl_ps), COMMON_TIMING(tccdl_ps), + COMMON_TIMING(trfc_slr_ps), #else COMMON_TIMING(twtr_ps), COMMON_TIMING(trfc_ps), @@ -561,6 +570,7 @@ static void fsl_ddr_options_edit(fsl_ddr_info_t *pinfo, CTRL_OPTIONS(mirrored_dimm), CTRL_OPTIONS(ap_en), CTRL_OPTIONS(x4_en), + CTRL_OPTIONS(package_3ds), CTRL_OPTIONS(bstopre), CTRL_OPTIONS(wrlvl_override), CTRL_OPTIONS(wrlvl_sample), @@ -855,6 +865,7 @@ static void print_memctl_options(const memctl_options_t *popts) CTRL_OPTIONS(mirrored_dimm), CTRL_OPTIONS(ap_en), CTRL_OPTIONS(x4_en), + CTRL_OPTIONS(package_3ds), CTRL_OPTIONS(bstopre), CTRL_OPTIONS(wrlvl_override), CTRL_OPTIONS(wrlvl_sample), diff --git a/drivers/ddr/fsl/lc_common_dimm_params.c b/drivers/ddr/fsl/lc_common_dimm_params.c index 850c8f6c43..6599901893 100644 --- a/drivers/ddr/fsl/lc_common_dimm_params.c +++ b/drivers/ddr/fsl/lc_common_dimm_params.c @@ -1,5 +1,6 @@ /* - * Copyright 2008-2014 Freescale Semiconductor, Inc. + * Copyright 2008-2016 Freescale Semiconductor, Inc. + * Copyright 2017-2018 NXP Semiconductor * * SPDX-License-Identifier: GPL-2.0 */ @@ -234,6 +235,7 @@ compute_lowest_common_dimm_parameters(const unsigned int ctrl_num, unsigned int trrds_ps = 0; unsigned int trrdl_ps = 0; unsigned int tccdl_ps = 0; + unsigned int trfc_slr_ps = 0; #else unsigned int twr_ps = 0; unsigned int twtr_ps = 0; @@ -313,6 +315,8 @@ compute_lowest_common_dimm_parameters(const unsigned int ctrl_num, (unsigned int)dimm_params[i].trrdl_ps); tccdl_ps = max(tccdl_ps, (unsigned int)dimm_params[i].tccdl_ps); + trfc_slr_ps = max(trfc_slr_ps, + (unsigned int)dimm_params[i].trfc_slr_ps); #else twr_ps = max(twr_ps, (unsigned int)dimm_params[i].twr_ps); twtr_ps = max(twtr_ps, (unsigned int)dimm_params[i].twtr_ps); @@ -365,6 +369,7 @@ compute_lowest_common_dimm_parameters(const unsigned int ctrl_num, outpdimm->trrds_ps = trrds_ps; outpdimm->trrdl_ps = trrdl_ps; outpdimm->tccdl_ps = tccdl_ps; + outpdimm->trfc_slr_ps = trfc_slr_ps; #else outpdimm->twtr_ps = twtr_ps; outpdimm->trfc_ps = trfc_ps; @@ -567,6 +572,7 @@ compute_lowest_common_dimm_parameters(const unsigned int ctrl_num, debug("trrds_ps = %u\n", trrds_ps); debug("trrdl_ps = %u\n", trrdl_ps); debug("tccdl_ps = %u\n", tccdl_ps); + debug("trfc_slr_ps = %u\n", trfc_slr_ps); #else debug("twtr_ps = %u\n", outpdimm->twtr_ps); debug("trfc_ps = %u\n", outpdimm->trfc_ps); diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c index a7eaed1bd7..5158ea2089 100644 --- a/drivers/ddr/fsl/options.c +++ b/drivers/ddr/fsl/options.c @@ -1,5 +1,6 @@ /* - * Copyright 2008, 2010-2014 Freescale Semiconductor, Inc. + * Copyright 2008, 2010-2016 Freescale Semiconductor, Inc. + * Copyright 2017-2018 NXP Semiconductor * * SPDX-License-Identifier: GPL-2.0+ */ @@ -1292,6 +1293,8 @@ done: if (pdimm[0].n_ranks == 4) popts->quad_rank_present = 1; + popts->package_3ds = pdimm->package_3ds; + ddr_freq = get_ddr_freq(ctrl_num) / 1000000; if (popts->registered_dimm_en) { popts->rcw_override = 1; -- cgit v1.2.1 From 564e9383e53b567114bd3403246c0759a6d69c50 Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 29 Jan 2018 10:24:08 -0800 Subject: drivers/ddr/fsl: Add calculation of register control words 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 --- drivers/ddr/fsl/ctrl_regs.c | 30 +++++++++++++++++++++++------- drivers/ddr/fsl/ddr4_dimm_params.c | 21 +++++++++++++++++++++ drivers/ddr/fsl/options.c | 4 ++++ 3 files changed, 48 insertions(+), 7 deletions(-) (limited to 'drivers/ddr') diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c index bcab9046ad..8b8727116d 100644 --- a/drivers/ddr/fsl/ctrl_regs.c +++ b/drivers/ddr/fsl/ctrl_regs.c @@ -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; diff --git a/drivers/ddr/fsl/ddr4_dimm_params.c b/drivers/ddr/fsl/ddr4_dimm_params.c index 1f1d9b897a..5c8fc8804d 100644 --- a/drivers/ddr/fsl/ddr4_dimm_params.c +++ b/drivers/ddr/fsl/ddr4_dimm_params.c @@ -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: diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c index 5158ea2089..85ec48c28e 100644 --- a/drivers/ddr/fsl/options.c +++ b/drivers/ddr/fsl/options.c @@ -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); -- cgit v1.2.1 From 944537c56e7bf51efef640408113d707cd0ad9f0 Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 29 Jan 2018 09:44:37 -0800 Subject: drivers/ddr/fsl: Modify binding registers to save time on data init DDR controllers always use binding register to determine the memory space to perform data initialization. In case of controller interleaving, the space is doubled, resulting twice long wait. It wasn't too bad until the memory capacity increases. To reduce the wait time, reduce the binding space to half and restore it after data initialization. Three-way interleaving is no longer used and is removed. Signed-off-by: York Sun --- drivers/ddr/fsl/fsl_ddr_gen4.c | 60 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 11 deletions(-) (limited to 'drivers/ddr') diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c index 7df9178415..c225c8e723 100644 --- a/drivers/ddr/fsl/fsl_ddr_gen4.c +++ b/drivers/ddr/fsl/fsl_ddr_gen4.c @@ -16,6 +16,8 @@ #include #endif +#define CTLR_INTLV_MASK 0x20000000 + #if defined(CONFIG_SYS_FSL_ERRATUM_A008511) | \ defined(CONFIG_SYS_FSL_ERRATUM_A009803) static void set_wait_for_bits_clear(void *ptr, u32 value, u32 bits) @@ -54,6 +56,7 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, u32 temp32; u32 total_gb_size_per_controller; int timeout; + int mod_bnds = 0; #ifdef CONFIG_SYS_FSL_ERRATUM_A008511 u32 mr6; @@ -91,6 +94,7 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, printf("%s unexpected ctrl_num = %u\n", __func__, ctrl_num); return; } + mod_bnds = regs->cs[0].config & CTLR_INTLV_MASK; if (step == 2) goto step2; @@ -102,25 +106,48 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, ddr_out32(&ddr->eor, regs->ddr_eor); ddr_out32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl); - for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { if (i == 0) { - ddr_out32(&ddr->cs0_bnds, regs->cs[i].bnds); - ddr_out32(&ddr->cs0_config, regs->cs[i].config); + if (mod_bnds) { + debug("modified bnds\n"); + ddr_out32(&ddr->cs0_bnds, + (regs->cs[i].bnds & 0xfffefffe) >> 1); + ddr_out32(&ddr->cs0_config, + (regs->cs[i].config & + ~CTLR_INTLV_MASK)); + } else { + ddr_out32(&ddr->cs0_bnds, regs->cs[i].bnds); + ddr_out32(&ddr->cs0_config, regs->cs[i].config); + } ddr_out32(&ddr->cs0_config_2, regs->cs[i].config_2); } else if (i == 1) { - ddr_out32(&ddr->cs1_bnds, regs->cs[i].bnds); + if (mod_bnds) { + ddr_out32(&ddr->cs1_bnds, + (regs->cs[i].bnds & 0xfffefffe) >> 1); + } else { + ddr_out32(&ddr->cs1_bnds, regs->cs[i].bnds); + } ddr_out32(&ddr->cs1_config, regs->cs[i].config); ddr_out32(&ddr->cs1_config_2, regs->cs[i].config_2); } else if (i == 2) { - ddr_out32(&ddr->cs2_bnds, regs->cs[i].bnds); + if (mod_bnds) { + ddr_out32(&ddr->cs2_bnds, + (regs->cs[i].bnds & 0xfffefffe) >> 1); + } else { + ddr_out32(&ddr->cs2_bnds, regs->cs[i].bnds); + } ddr_out32(&ddr->cs2_config, regs->cs[i].config); ddr_out32(&ddr->cs2_config_2, regs->cs[i].config_2); } else if (i == 3) { - ddr_out32(&ddr->cs3_bnds, regs->cs[i].bnds); + if (mod_bnds) { + ddr_out32(&ddr->cs3_bnds, + (regs->cs[i].bnds & 0xfffefffe) >> 1); + } else { + ddr_out32(&ddr->cs3_bnds, regs->cs[i].bnds); + } ddr_out32(&ddr->cs3_config, regs->cs[i].config); ddr_out32(&ddr->cs3_config_2, regs->cs[i].config_2); } @@ -417,13 +444,10 @@ step2: ((regs->cs[i].config >> 8) & 0x7) + 12 + ((regs->cs[i].config >> 4) & 0x3) + 0 + ((regs->cs[i].config >> 0) & 0x7) + 8 + + ((regs->ddr_sdram_cfg_3 >> 4) & 0x3) + 3 - ((regs->ddr_sdram_cfg >> 19) & 0x3) - 26); /* minus 26 (count of 64M) */ } - if (fsl_ddr_get_intl3r() & 0x80000000) /* 3-way interleaving */ - total_gb_size_per_controller *= 3; - else if (regs->cs[0].config & 0x20000000) /* 2-way interleaving */ - total_gb_size_per_controller <<= 1; /* * total memory / bus width = transactions needed * transactions needed / data rate = seconds @@ -449,6 +473,21 @@ step2: if (timeout <= 0) printf("Waiting for D_INIT timeout. Memory may not work.\n"); + if (mod_bnds) { + debug("Reset to original bnds\n"); + ddr_out32(&ddr->cs0_bnds, regs->cs[0].bnds); +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1) + ddr_out32(&ddr->cs1_bnds, regs->cs[1].bnds); +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2) + ddr_out32(&ddr->cs2_bnds, regs->cs[2].bnds); +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 3) + ddr_out32(&ddr->cs3_bnds, regs->cs[3].bnds); +#endif +#endif +#endif + ddr_out32(&ddr->cs0_config, regs->cs[0].config); + } + #ifdef CONFIG_SYS_FSL_ERRATUM_A009663 ddr_out32(&ddr->sdram_interval, regs->ddr_sdram_interval); #endif @@ -468,7 +507,6 @@ step2: #define BIST_CR 0x80010000 #define BIST_CR_EN 0x80000000 #define BIST_CR_STAT 0x00000001 -#define CTLR_INTLV_MASK 0x20000000 /* Perform build-in test on memory. Three-way interleaving is not yet * supported by this code. */ if (env_get_f("ddr_bist", buffer, CONFIG_SYS_CBSIZE) >= 0) { -- cgit v1.2.1 From 140ad2d8991ca31d0e84af5119c74fc6e2c5a2d4 Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 29 Jan 2018 09:44:38 -0800 Subject: drivers/ddr/fsl: Cleanup unused variable Variable "row_density" is no longer used. Drop it from DIMM structure. Signed-off-by: York Sun --- drivers/ddr/fsl/ddr1_dimm_params.c | 1 - drivers/ddr/fsl/ddr2_dimm_params.c | 1 - drivers/ddr/fsl/ddr3_dimm_params.c | 1 - drivers/ddr/fsl/ddr4_dimm_params.c | 1 - drivers/ddr/fsl/interactive.c | 1 - 5 files changed, 5 deletions(-) (limited to 'drivers/ddr') diff --git a/drivers/ddr/fsl/ddr1_dimm_params.c b/drivers/ddr/fsl/ddr1_dimm_params.c index 369b325ff2..c02725e611 100644 --- a/drivers/ddr/fsl/ddr1_dimm_params.c +++ b/drivers/ddr/fsl/ddr1_dimm_params.c @@ -270,7 +270,6 @@ unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num, pdimm->n_banks_per_sdram_device = spd->nbanks; pdimm->edc_config = spd->config; pdimm->burst_lengths_bitmask = spd->burstl; - pdimm->row_density = spd->bank_dens; /* * Calculate the Maximum Data Rate based on the Minimum Cycle time. diff --git a/drivers/ddr/fsl/ddr2_dimm_params.c b/drivers/ddr/fsl/ddr2_dimm_params.c index af752cc96c..062c849075 100644 --- a/drivers/ddr/fsl/ddr2_dimm_params.c +++ b/drivers/ddr/fsl/ddr2_dimm_params.c @@ -269,7 +269,6 @@ unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num, pdimm->n_banks_per_sdram_device = spd->nbanks; pdimm->edc_config = spd->config; pdimm->burst_lengths_bitmask = spd->burstl; - pdimm->row_density = spd->rank_dens; /* * Calculate the Maximum Data Rate based on the Minimum Cycle time. diff --git a/drivers/ddr/fsl/ddr3_dimm_params.c b/drivers/ddr/fsl/ddr3_dimm_params.c index 9944dbbf03..8a0587a646 100644 --- a/drivers/ddr/fsl/ddr3_dimm_params.c +++ b/drivers/ddr/fsl/ddr3_dimm_params.c @@ -186,7 +186,6 @@ unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num, * BL8 -bit3, BC4 -bit2 */ pdimm->burst_lengths_bitmask = 0x0c; - pdimm->row_density = __ilog2(pdimm->rank_density); /* MTB - medium timebase * The unit in the SPD spec is ns, diff --git a/drivers/ddr/fsl/ddr4_dimm_params.c b/drivers/ddr/fsl/ddr4_dimm_params.c index 5c8fc8804d..4867fbc932 100644 --- a/drivers/ddr/fsl/ddr4_dimm_params.c +++ b/drivers/ddr/fsl/ddr4_dimm_params.c @@ -264,7 +264,6 @@ unsigned int ddr_compute_dimm_parameters(const unsigned int ctrl_num, * BL8 -bit3, BC4 -bit2 */ pdimm->burst_lengths_bitmask = 0x0c; - pdimm->row_density = __ilog2(pdimm->rank_density); /* MTB - medium timebase * The MTB in the SPD spec is 125ps, diff --git a/drivers/ddr/fsl/interactive.c b/drivers/ddr/fsl/interactive.c index 78ca03bcb2..1fa35c3c42 100644 --- a/drivers/ddr/fsl/interactive.c +++ b/drivers/ddr/fsl/interactive.c @@ -241,7 +241,6 @@ static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo, DIMM_PARM(n_banks_per_sdram_device), #endif DIMM_PARM(burst_lengths_bitmask), - DIMM_PARM(row_density), DIMM_PARM(tckmin_x_ps), DIMM_PARM(tckmin_x_minus_1_ps), -- cgit v1.2.1