diff mbox series

[U-Boot,v4,3/8] drivers/ddr/fsl: Add 3DS RDIMM support

Message ID 1517247880-14471-3-git-send-email-york.sun@nxp.com
State Accepted
Delegated to: York Sun
Headers show
Series [U-Boot,v4,1/8] drivers/ddr/fsl: Fix DDR4 RDIMM support | expand

Commit Message

York Sun Jan. 29, 2018, 5:44 p.m. UTC
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 <york.sun@nxp.com>

---

Changes in v4:
New patch to add 3DS support.

Changes in v3: None
Changes in v2: None

 drivers/ddr/fsl/ctrl_regs.c             | 43 ++++++++++++++++++++++++++-------
 drivers/ddr/fsl/ddr4_dimm_params.c      | 26 ++++++++++++++++++--
 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, 90 insertions(+), 16 deletions(-)
diff mbox series

Patch

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..0d3d137 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;
 }
@@ -132,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) {
@@ -163,6 +171,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 +180,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 +321,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;