From c0c32af0b2f037e3e167c7ac82e7110ebae48fb5 Mon Sep 17 00:00:00 2001 From: York Sun Date: Mon, 29 Jan 2018 09:44:35 -0800 Subject: [PATCH] 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 +++- include/common_timing_params.h | 1 + include/fsl_ddr_dimm_params.h | 6 ++++- include/fsl_ddr_sdram.h | 4 ++- 8 files changed, 89 insertions(+), 16 deletions(-) diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c index 33adfb1..bcab904 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 6e26ba8..1f1d9b8 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 660060d..78ca03b 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 850c8f6..6599901 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 a7eaed1..5158ea2 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; diff --git a/include/common_timing_params.h b/include/common_timing_params.h index b97147d..0700107 100644 --- a/include/common_timing_params.h +++ b/include/common_timing_params.h @@ -26,6 +26,7 @@ typedef struct { unsigned int trrds_ps; unsigned int trrdl_ps; unsigned int tccdl_ps; + unsigned int trfc_slr_ps; #else unsigned int twtr_ps; /* maximum = 63750 ps */ unsigned int trfc_ps; /* maximum = 255 ns + 256 ns + .75 ns diff --git a/include/fsl_ddr_dimm_params.h b/include/fsl_ddr_dimm_params.h index 12a1944..c6c819e 100644 --- a/include/fsl_ddr_dimm_params.h +++ b/include/fsl_ddr_dimm_params.h @@ -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 */ @@ -18,12 +19,14 @@ typedef struct dimm_params_s { char mpart[19]; /* guaranteed null terminated */ unsigned int n_ranks; + unsigned int die_density; unsigned long long rank_density; unsigned long long capacity; unsigned int data_width; unsigned int primary_sdram_width; unsigned int ec_sdram_width; unsigned int registered_dimm; + unsigned int package_3ds; /* number of dies in 3DS DIMM */ unsigned int device_width; /* x4, x8, x16 components */ /* SDRAM device parameters */ @@ -79,6 +82,7 @@ typedef struct dimm_params_s { int trrds_ps; int trrdl_ps; int tccdl_ps; + int trfc_slr_ps; #else int twr_ps; /* maximum = 63750 ps */ int trfc_ps; /* max = 255 ns + 256 ns + .75 ns diff --git a/include/fsl_ddr_sdram.h b/include/fsl_ddr_sdram.h index de7ef9b..d4275e6 100644 --- a/include/fsl_ddr_sdram.h +++ b/include/fsl_ddr_sdram.h @@ -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 */ @@ -366,6 +367,7 @@ typedef struct memctl_options_s { unsigned int quad_rank_present; unsigned int ap_en; /* address parity enable for RDIMM/DDR4-UDIMM */ unsigned int x4_en; /* enable x4 devices */ + unsigned int package_3ds; /* Global Timing Parameters */ unsigned int cas_latency_override;