All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/3] Fix iMX6 DDR configuration issues and update toradex apalis-imx6
@ 2022-04-04  8:51 Francesco Dolcini
  2022-04-04  8:51 ` [RFC PATCH 1/3] mx6: ddr: Restore ralat/walat in write level calibration Francesco Dolcini
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Francesco Dolcini @ 2022-04-04  8:51 UTC (permalink / raw)
  To: Stefano Babic, Fabio Estevam, uboot-imx, Marek Vasut, Tim Harvey
  Cc: Francesco Dolcini, u-boot

Dear all,
we do recently have debugged some spurious boot failures and crashes, about 2%
of times on specific "bad" modules", on the toradex apalis imx6 [0].

We found a couple of issues in the generic imx6 ddr configuration code and we
updated the apalis-imx6 memory timing to fix those. With the following patches
applied we were able to run a complete validation cycle (weeks of testing for
multiple SKUs) over the whole industrial temperature range (-40
to +85) without any issues.

I'm sending this patch as RFC since we plan to run some additional validation
testing SKUs from different batches before asking for this to be merged.

[0] https://lore.kernel.org/all/20211202161428.GA104937@francesco-nb.int.toradex.com/

Francesco Dolcini (3):
  mx6: ddr: Restore ralat/walat in write level calibration
  mx6: ddr: Wait before issuing the first MRS cmd
  board: apalis_imx6: DDR init using mx6_dram_cfg()

 arch/arm/mach-imx/mx6/ddr.c             |  10 +-
 board/toradex/apalis_imx6/apalis_imx6.c | 439 ++++++++++--------------
 2 files changed, 193 insertions(+), 256 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH 1/3] mx6: ddr: Restore ralat/walat in write level calibration
  2022-04-04  8:51 [RFC PATCH 0/3] Fix iMX6 DDR configuration issues and update toradex apalis-imx6 Francesco Dolcini
@ 2022-04-04  8:51 ` Francesco Dolcini
  2022-04-04 13:40   ` Marek Vasut
  2022-04-04  8:51 ` [RFC PATCH 2/3] mx6: ddr: Wait before issuing the first MRS cmd Francesco Dolcini
  2022-04-04  8:51 ` [RFC PATCH 3/3] board: apalis_imx6: DDR init using mx6_dram_cfg() Francesco Dolcini
  2 siblings, 1 reply; 10+ messages in thread
From: Francesco Dolcini @ 2022-04-04  8:51 UTC (permalink / raw)
  To: Stefano Babic, Fabio Estevam, uboot-imx, Marek Vasut, Tim Harvey
  Cc: Francesco Dolcini, u-boot

The current DDR write level calibration routine always overwrite
the ralat/walat fields to their maximum value, just save
the existing values at the beginning of the calibration routine
and restore it at the end.

In case the delay is estimated by the user to be more than one cycle the
walat should be configured according to that, this is not
automatically done.  From the i.MX6 RM:

   The user should read the results of the associated delay-line at
   MPWLDECTRL#[WL_DL_ABS_OFFSET#] and in case the user estimates that the
   reasonable delay may be above 1 cycle then the user should indicate it at
   MPWLDECTRL#[WL_CYC_DEL#]. Moreover the user should indicate it in
   MDMISC[WALAT] field. For example, if the result of the write leveling calibration
   is 100/256 parts of a cycle, but the user estimates that the delay is above 2 cycles
   then MPWLDECTRL#[WL_CYC_DEL#] should be configured to 2, so the total
   delay will be 2 and 100/256 parts of a cycle

Probably it would just possible to not overwrite the mdmisc register in
the first place, since this is not present in the write_level_calib() example
in NXP AN4467 [1] nor in the i.MX6 RM (44.11.6.1 Hardware Write Leveling
Calibration).

Fixes: d339f16911c7 ("arm: imx6: Add DDR3 calibration code for MX6 Q/D/DL")
Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
---
 arch/arm/mach-imx/mx6/ddr.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/mx6/ddr.c b/arch/arm/mach-imx/mx6/ddr.c
index f872bfdab315..08e2f0f130a6 100644
--- a/arch/arm/mach-imx/mx6/ddr.c
+++ b/arch/arm/mach-imx/mx6/ddr.c
@@ -108,7 +108,7 @@ int mmdc_do_write_level_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 {
 	struct mmdc_p_regs *mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR;
 	struct mmdc_p_regs *mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR;
-	u32 esdmisc_val, zq_val;
+	u32 esdmisc_val, zq_val, mdmisc_val;
 	u32 errors = 0;
 	u32 ldectrl[4] = {0};
 	u32 ddr_mr1 = 0x4;
@@ -131,6 +131,9 @@ int mmdc_do_write_level_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	/* disable Adopt power down timer */
 	setbits_le32(&mmdc0->mapsr, 0x1);
 
+	/* Save old RALAT and WALAT values */
+	mdmisc_val = readl(&mmdc0->mdmisc);
+
 	debug("Starting write leveling calibration.\n");
 
 	/*
@@ -217,6 +220,9 @@ int mmdc_do_write_level_calibration(struct mx6_ddr_sysinfo const *sysinfo)
 	writel(esdmisc_val, &mmdc0->mdref);
 	writel(zq_val, &mmdc0->mpzqhwctrl);
 
+	/* restore walat/ralat */
+	writel(mdmisc_val, &mmdc0->mdmisc);
+
 	debug("\tMMDC_MPWLDECTRL0 after write level cal: 0x%08x\n",
 	      readl(&mmdc0->mpwldectrl0));
 	debug("\tMMDC_MPWLDECTRL1 after write level cal: 0x%08x\n",
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 2/3] mx6: ddr: Wait before issuing the first MRS cmd
  2022-04-04  8:51 [RFC PATCH 0/3] Fix iMX6 DDR configuration issues and update toradex apalis-imx6 Francesco Dolcini
  2022-04-04  8:51 ` [RFC PATCH 1/3] mx6: ddr: Restore ralat/walat in write level calibration Francesco Dolcini
@ 2022-04-04  8:51 ` Francesco Dolcini
  2022-04-04 13:39   ` Marek Vasut
  2022-04-04  8:51 ` [RFC PATCH 3/3] board: apalis_imx6: DDR init using mx6_dram_cfg() Francesco Dolcini
  2 siblings, 1 reply; 10+ messages in thread
From: Francesco Dolcini @ 2022-04-04  8:51 UTC (permalink / raw)
  To: Stefano Babic, Fabio Estevam, uboot-imx, Marek Vasut, Tim Harvey
  Cc: Francesco Dolcini, u-boot

Wait 1ms before issuing the first MRS command to write DDR3 Mode
registers.

There is a requirement to wait minimum of Reset CKE Exit time, tXPR,
with tXPR = max(tXS, 5tCK) and to wait 500 useconds after reset is
de-asserted. It seems that for some reason this is not enforced by the
MMDC controller, despite MMDCx_MDOR RST_to_CKE and tXPR being correctly
configured.

Without this change we experienced random memory initialization failures
with about 2% boot failure rate on specific problematic boards, after
this change we were able to do more than 10.000 power-cycle without a
single failure.

Fixes: fe0f7f7842e1 ("mx6: add mmdc configuration for MX6Q/MX6DL")
Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
---
 arch/arm/mach-imx/mx6/ddr.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/mach-imx/mx6/ddr.c b/arch/arm/mach-imx/mx6/ddr.c
index 08e2f0f130a6..7b3d620094c4 100644
--- a/arch/arm/mach-imx/mx6/ddr.c
+++ b/arch/arm/mach-imx/mx6/ddr.c
@@ -1526,6 +1526,8 @@ void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,
 			((sysinfo->ncs == 2) ? 1 : 0) << 30; /* SDE_1 for CS1 */
 
 	/* Step 8: Write Mode Registers to Init DDR3 devices */
+	mdelay(1); /* Wait before issuing the first MRS command
+		      (tXPR / 500us CKE delay after reset deassertion) */
 	for (cs = 0; cs < sysinfo->ncs; cs++) {
 		/* MR2 */
 		val = (sysinfo->rtt_wr & 3) << 9 | (ddr3_cfg->SRT & 1) << 7 |
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFC PATCH 3/3] board: apalis_imx6: DDR init using mx6_dram_cfg()
  2022-04-04  8:51 [RFC PATCH 0/3] Fix iMX6 DDR configuration issues and update toradex apalis-imx6 Francesco Dolcini
  2022-04-04  8:51 ` [RFC PATCH 1/3] mx6: ddr: Restore ralat/walat in write level calibration Francesco Dolcini
  2022-04-04  8:51 ` [RFC PATCH 2/3] mx6: ddr: Wait before issuing the first MRS cmd Francesco Dolcini
@ 2022-04-04  8:51 ` Francesco Dolcini
  2 siblings, 0 replies; 10+ messages in thread
From: Francesco Dolcini @ 2022-04-04  8:51 UTC (permalink / raw)
  To: Stefano Babic, Fabio Estevam, uboot-imx, Marek Vasut, Tim Harvey
  Cc: Francesco Dolcini, u-boot

Do DDR initialization using the procedural mx6_dram_cfg() instead of
programming the MMDC using a raw list of register/value pairs, this
solves some rare boot failures on specific "bad" modules.

Calibration values, DDR geometry are unchanged, memory timings are
updated according to the relevant memory datasheet.

For IT temperature range SKUs CL is decreased from 8 to 7 and tFAW
value is increased, for commercial temperature range SKUs some minor
changes on ODT parameters.

Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
---
 board/toradex/apalis_imx6/apalis_imx6.c | 439 ++++++++++--------------
 1 file changed, 184 insertions(+), 255 deletions(-)

diff --git a/board/toradex/apalis_imx6/apalis_imx6.c b/board/toradex/apalis_imx6/apalis_imx6.c
index 25a4cd9f38bb..0438f0701435 100644
--- a/board/toradex/apalis_imx6/apalis_imx6.c
+++ b/board/toradex/apalis_imx6/apalis_imx6.c
@@ -806,244 +806,6 @@ void ldo_mode_set(int ldo_bypass)
 #include "asm/arch/iomux.h"
 #include "asm/arch/crm_regs.h"
 
-static int mx6_com_dcd_table[] = {
-/* ddr-setup.cfg */
-MX6_IOM_DRAM_SDQS0, 0x00000030,
-MX6_IOM_DRAM_SDQS1, 0x00000030,
-MX6_IOM_DRAM_SDQS2, 0x00000030,
-MX6_IOM_DRAM_SDQS3, 0x00000030,
-MX6_IOM_DRAM_SDQS4, 0x00000030,
-MX6_IOM_DRAM_SDQS5, 0x00000030,
-MX6_IOM_DRAM_SDQS6, 0x00000030,
-MX6_IOM_DRAM_SDQS7, 0x00000030,
-
-MX6_IOM_GRP_B0DS, 0x00000030,
-MX6_IOM_GRP_B1DS, 0x00000030,
-MX6_IOM_GRP_B2DS, 0x00000030,
-MX6_IOM_GRP_B3DS, 0x00000030,
-MX6_IOM_GRP_B4DS, 0x00000030,
-MX6_IOM_GRP_B5DS, 0x00000030,
-MX6_IOM_GRP_B6DS, 0x00000030,
-MX6_IOM_GRP_B7DS, 0x00000030,
-MX6_IOM_GRP_ADDDS, 0x00000030,
-/* 40 Ohm drive strength for cs0/1,sdba2,cke0/1,sdwe */
-MX6_IOM_GRP_CTLDS, 0x00000030,
-
-MX6_IOM_DRAM_DQM0, 0x00020030,
-MX6_IOM_DRAM_DQM1, 0x00020030,
-MX6_IOM_DRAM_DQM2, 0x00020030,
-MX6_IOM_DRAM_DQM3, 0x00020030,
-MX6_IOM_DRAM_DQM4, 0x00020030,
-MX6_IOM_DRAM_DQM5, 0x00020030,
-MX6_IOM_DRAM_DQM6, 0x00020030,
-MX6_IOM_DRAM_DQM7, 0x00020030,
-
-MX6_IOM_DRAM_CAS, 0x00020030,
-MX6_IOM_DRAM_RAS, 0x00020030,
-MX6_IOM_DRAM_SDCLK_0, 0x00020030,
-MX6_IOM_DRAM_SDCLK_1, 0x00020030,
-
-MX6_IOM_DRAM_RESET, 0x00020030,
-MX6_IOM_DRAM_SDCKE0, 0x00003000,
-MX6_IOM_DRAM_SDCKE1, 0x00003000,
-
-MX6_IOM_DRAM_SDODT0, 0x00003030,
-MX6_IOM_DRAM_SDODT1, 0x00003030,
-
-/* (differential input) */
-MX6_IOM_DDRMODE_CTL, 0x00020000,
-/* (differential input) */
-MX6_IOM_GRP_DDRMODE, 0x00020000,
-/* disable ddr pullups */
-MX6_IOM_GRP_DDRPKE, 0x00000000,
-MX6_IOM_DRAM_SDBA2, 0x00000000,
-/* 40 Ohm drive strength for cs0/1,sdba2,cke0/1,sdwe */
-MX6_IOM_GRP_DDR_TYPE, 0x000C0000,
-
-/* Read data DQ Byte0-3 delay */
-MX6_MMDC_P0_MPRDDQBY0DL, 0x33333333,
-MX6_MMDC_P0_MPRDDQBY1DL, 0x33333333,
-MX6_MMDC_P0_MPRDDQBY2DL, 0x33333333,
-MX6_MMDC_P0_MPRDDQBY3DL, 0x33333333,
-MX6_MMDC_P1_MPRDDQBY0DL, 0x33333333,
-MX6_MMDC_P1_MPRDDQBY1DL, 0x33333333,
-MX6_MMDC_P1_MPRDDQBY2DL, 0x33333333,
-MX6_MMDC_P1_MPRDDQBY3DL, 0x33333333,
-
-/*
- * MDMISC	mirroring	interleaved (row/bank/col)
- */
-MX6_MMDC_P0_MDMISC, 0x00081740,
-
-/*
- * MDSCR	con_req
- */
-MX6_MMDC_P0_MDSCR, 0x00008000,
-
-/* 1066mhz_4x128mx16.cfg */
-
-MX6_MMDC_P0_MDPDC, 0x00020036,
-MX6_MMDC_P0_MDCFG0, 0x555A7954,
-MX6_MMDC_P0_MDCFG1, 0xDB328F64,
-MX6_MMDC_P0_MDCFG2, 0x01FF00DB,
-MX6_MMDC_P0_MDRWD, 0x000026D2,
-MX6_MMDC_P0_MDOR, 0x005A1023,
-MX6_MMDC_P0_MDOTC, 0x09555050,
-MX6_MMDC_P0_MDPDC, 0x00025576,
-MX6_MMDC_P0_MDASP, 0x00000027,
-MX6_MMDC_P0_MDCTL, 0x831A0000,
-MX6_MMDC_P0_MDSCR, 0x04088032,
-MX6_MMDC_P0_MDSCR, 0x00008033,
-MX6_MMDC_P0_MDSCR, 0x00428031,
-MX6_MMDC_P0_MDSCR, 0x19308030,
-MX6_MMDC_P0_MDSCR, 0x04008040,
-MX6_MMDC_P0_MPZQHWCTRL, 0xA1390003,
-MX6_MMDC_P1_MPZQHWCTRL, 0xA1390003,
-MX6_MMDC_P0_MDREF, 0x00005800,
-MX6_MMDC_P0_MPODTCTRL, 0x00000000,
-MX6_MMDC_P1_MPODTCTRL, 0x00000000,
-
-MX6_MMDC_P0_MPDGCTRL0, 0x432A0338,
-MX6_MMDC_P0_MPDGCTRL1, 0x03260324,
-MX6_MMDC_P1_MPDGCTRL0, 0x43340344,
-MX6_MMDC_P1_MPDGCTRL1, 0x031E027C,
-
-MX6_MMDC_P0_MPRDDLCTL, 0x33272D2E,
-MX6_MMDC_P1_MPRDDLCTL, 0x2F312B37,
-
-MX6_MMDC_P0_MPWRDLCTL, 0x3A35433C,
-MX6_MMDC_P1_MPWRDLCTL, 0x4336453F,
-
-MX6_MMDC_P0_MPWLDECTRL0, 0x0009000E,
-MX6_MMDC_P0_MPWLDECTRL1, 0x0018000B,
-MX6_MMDC_P1_MPWLDECTRL0, 0x00060015,
-MX6_MMDC_P1_MPWLDECTRL1, 0x0006000E,
-
-MX6_MMDC_P0_MPMUR0, 0x00000800,
-MX6_MMDC_P1_MPMUR0, 0x00000800,
-MX6_MMDC_P0_MDSCR, 0x00000000,
-MX6_MMDC_P0_MAPSR, 0x00011006,
-};
-
-static int mx6_it_dcd_table[] = {
-/* ddr-setup.cfg */
-MX6_IOM_DRAM_SDQS0, 0x00000030,
-MX6_IOM_DRAM_SDQS1, 0x00000030,
-MX6_IOM_DRAM_SDQS2, 0x00000030,
-MX6_IOM_DRAM_SDQS3, 0x00000030,
-MX6_IOM_DRAM_SDQS4, 0x00000030,
-MX6_IOM_DRAM_SDQS5, 0x00000030,
-MX6_IOM_DRAM_SDQS6, 0x00000030,
-MX6_IOM_DRAM_SDQS7, 0x00000030,
-
-MX6_IOM_GRP_B0DS, 0x00000030,
-MX6_IOM_GRP_B1DS, 0x00000030,
-MX6_IOM_GRP_B2DS, 0x00000030,
-MX6_IOM_GRP_B3DS, 0x00000030,
-MX6_IOM_GRP_B4DS, 0x00000030,
-MX6_IOM_GRP_B5DS, 0x00000030,
-MX6_IOM_GRP_B6DS, 0x00000030,
-MX6_IOM_GRP_B7DS, 0x00000030,
-MX6_IOM_GRP_ADDDS, 0x00000030,
-/* 40 Ohm drive strength for cs0/1,sdba2,cke0/1,sdwe */
-MX6_IOM_GRP_CTLDS, 0x00000030,
-
-MX6_IOM_DRAM_DQM0, 0x00020030,
-MX6_IOM_DRAM_DQM1, 0x00020030,
-MX6_IOM_DRAM_DQM2, 0x00020030,
-MX6_IOM_DRAM_DQM3, 0x00020030,
-MX6_IOM_DRAM_DQM4, 0x00020030,
-MX6_IOM_DRAM_DQM5, 0x00020030,
-MX6_IOM_DRAM_DQM6, 0x00020030,
-MX6_IOM_DRAM_DQM7, 0x00020030,
-
-MX6_IOM_DRAM_CAS, 0x00020030,
-MX6_IOM_DRAM_RAS, 0x00020030,
-MX6_IOM_DRAM_SDCLK_0, 0x00020030,
-MX6_IOM_DRAM_SDCLK_1, 0x00020030,
-
-MX6_IOM_DRAM_RESET, 0x00020030,
-MX6_IOM_DRAM_SDCKE0, 0x00003000,
-MX6_IOM_DRAM_SDCKE1, 0x00003000,
-
-MX6_IOM_DRAM_SDODT0, 0x00003030,
-MX6_IOM_DRAM_SDODT1, 0x00003030,
-
-/* (differential input) */
-MX6_IOM_DDRMODE_CTL, 0x00020000,
-/* (differential input) */
-MX6_IOM_GRP_DDRMODE, 0x00020000,
-/* disable ddr pullups */
-MX6_IOM_GRP_DDRPKE, 0x00000000,
-MX6_IOM_DRAM_SDBA2, 0x00000000,
-/* 40 Ohm drive strength for cs0/1,sdba2,cke0/1,sdwe */
-MX6_IOM_GRP_DDR_TYPE, 0x000C0000,
-
-/* Read data DQ Byte0-3 delay */
-MX6_MMDC_P0_MPRDDQBY0DL, 0x33333333,
-MX6_MMDC_P0_MPRDDQBY1DL, 0x33333333,
-MX6_MMDC_P0_MPRDDQBY2DL, 0x33333333,
-MX6_MMDC_P0_MPRDDQBY3DL, 0x33333333,
-MX6_MMDC_P1_MPRDDQBY0DL, 0x33333333,
-MX6_MMDC_P1_MPRDDQBY1DL, 0x33333333,
-MX6_MMDC_P1_MPRDDQBY2DL, 0x33333333,
-MX6_MMDC_P1_MPRDDQBY3DL, 0x33333333,
-
-/*
- * MDMISC	mirroring	interleaved (row/bank/col)
- */
-MX6_MMDC_P0_MDMISC, 0x00081740,
-
-/*
- * MDSCR	con_req
- */
-MX6_MMDC_P0_MDSCR, 0x00008000,
-
-/* 1066mhz_4x256mx16.cfg */
-
-MX6_MMDC_P0_MDPDC, 0x00020036,
-MX6_MMDC_P0_MDCFG0, 0x898E78f5,
-MX6_MMDC_P0_MDCFG1, 0xff328f64,
-MX6_MMDC_P0_MDCFG2, 0x01FF00DB,
-MX6_MMDC_P0_MDRWD, 0x000026D2,
-MX6_MMDC_P0_MDOR, 0x008E1023,
-MX6_MMDC_P0_MDOTC, 0x09444040,
-MX6_MMDC_P0_MDPDC, 0x00025576,
-MX6_MMDC_P0_MDASP, 0x00000047,
-MX6_MMDC_P0_MDCTL, 0x841A0000,
-MX6_MMDC_P0_MDSCR, 0x02888032,
-MX6_MMDC_P0_MDSCR, 0x00008033,
-MX6_MMDC_P0_MDSCR, 0x00048031,
-MX6_MMDC_P0_MDSCR, 0x19408030,
-MX6_MMDC_P0_MDSCR, 0x04008040,
-MX6_MMDC_P0_MPZQHWCTRL, 0xA1390003,
-MX6_MMDC_P1_MPZQHWCTRL, 0xA1390003,
-MX6_MMDC_P0_MDREF, 0x00007800,
-MX6_MMDC_P0_MPODTCTRL, 0x00022227,
-MX6_MMDC_P1_MPODTCTRL, 0x00022227,
-
-MX6_MMDC_P0_MPDGCTRL0, 0x03300338,
-MX6_MMDC_P0_MPDGCTRL1, 0x03240324,
-MX6_MMDC_P1_MPDGCTRL0, 0x03440350,
-MX6_MMDC_P1_MPDGCTRL1, 0x032C0308,
-
-MX6_MMDC_P0_MPRDDLCTL, 0x40363C3E,
-MX6_MMDC_P1_MPRDDLCTL, 0x3C3E3C46,
-
-MX6_MMDC_P0_MPWRDLCTL, 0x403E463E,
-MX6_MMDC_P1_MPWRDLCTL, 0x4A384C46,
-
-MX6_MMDC_P0_MPWLDECTRL0, 0x0009000E,
-MX6_MMDC_P0_MPWLDECTRL1, 0x0018000B,
-MX6_MMDC_P1_MPWLDECTRL0, 0x00060015,
-MX6_MMDC_P1_MPWLDECTRL1, 0x0006000E,
-
-MX6_MMDC_P0_MPMUR0, 0x00000800,
-MX6_MMDC_P1_MPMUR0, 0x00000800,
-MX6_MMDC_P0_MDSCR, 0x00000000,
-MX6_MMDC_P0_MAPSR, 0x00011006,
-};
-
 static void ccgr_init(void)
 {
 	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
@@ -1068,51 +830,218 @@ static void ccgr_init(void)
 	writel(0x000000FB, &ccm->ccosr);
 }
 
-static void ddr_init(int *table, int size)
-{
-	int i;
 
-	for (i = 0; i < size / 2 ; i++)
-		writel(table[2 * i + 1], table[2 * i]);
-}
+#define PAD_CTL_INPUT_DDR BIT(17)
+
+struct mx6dq_iomux_ddr_regs mx6_ddr_ioregs = {
+	/* Differential input, 40 ohm DSE */
+	.dram_sdclk_0 = PAD_CTL_DSE_40ohm | PAD_CTL_INPUT_DDR,
+	.dram_sdclk_1 = PAD_CTL_DSE_40ohm | PAD_CTL_INPUT_DDR,
+	.dram_cas = PAD_CTL_DSE_40ohm | PAD_CTL_INPUT_DDR,
+	.dram_ras = PAD_CTL_DSE_40ohm | PAD_CTL_INPUT_DDR,
+	.dram_reset = PAD_CTL_DSE_40ohm | PAD_CTL_INPUT_DDR,
+
+	/* SDKE[0:1]: BIT(12) and BIT(13) are reserved and set at reset */
+	.dram_sdcke0 = 0x00003000,
+	.dram_sdcke1 = 0x00003000,
+
+	.dram_sdba2 = 0x00000000,
+
+	/* ODT[0:1]: 40 ohm DSE, BIT(12) and BIT(13) are reserved and set at reset */
+	.dram_sdodt0 = PAD_CTL_DSE_40ohm | 0x00003000,
+	.dram_sdodt1 = PAD_CTL_DSE_40ohm | 0x00003000,
+
+	/* SDQS[0:7]: 40 ohm DSE, Pull/Keeper Disabled, ODT Disabled */
+	.dram_sdqs0 = PAD_CTL_DSE_40ohm,
+	.dram_sdqs1 = PAD_CTL_DSE_40ohm,
+	.dram_sdqs2 = PAD_CTL_DSE_40ohm,
+	.dram_sdqs3 = PAD_CTL_DSE_40ohm,
+	.dram_sdqs4 = PAD_CTL_DSE_40ohm,
+	.dram_sdqs5 = PAD_CTL_DSE_40ohm,
+	.dram_sdqs6 = PAD_CTL_DSE_40ohm,
+	.dram_sdqs7 = PAD_CTL_DSE_40ohm,
+
+	/* DQM[0:7]: Differential input, 40 ohm DSE, Pull/Keeper Disabled, ODT Disabled */
+	.dram_dqm0 = PAD_CTL_DSE_40ohm | PAD_CTL_INPUT_DDR,
+	.dram_dqm1 = PAD_CTL_DSE_40ohm | PAD_CTL_INPUT_DDR,
+	.dram_dqm2 = PAD_CTL_DSE_40ohm | PAD_CTL_INPUT_DDR,
+	.dram_dqm3 = PAD_CTL_DSE_40ohm | PAD_CTL_INPUT_DDR,
+	.dram_dqm4 = PAD_CTL_DSE_40ohm | PAD_CTL_INPUT_DDR,
+	.dram_dqm5 = PAD_CTL_DSE_40ohm | PAD_CTL_INPUT_DDR,
+	.dram_dqm6 = PAD_CTL_DSE_40ohm | PAD_CTL_INPUT_DDR,
+	.dram_dqm7 = PAD_CTL_DSE_40ohm | PAD_CTL_INPUT_DDR,
+};
+
+struct mx6dq_iomux_grp_regs mx6_grp_ioregs = {
+	/* DDR3 */
+	.grp_ddr_type = 0x000C0000,
+
+	/* SDQS[0:7]: Differential input */
+	.grp_ddrmode_ctl = PAD_CTL_INPUT_DDR,
+
+	/* DATA[0:63]: Pull/Keeper disabled */
+	.grp_ddrpke = 0,
+
+	/* ADDR[0:16], SDBA[0:1]: 40 ohm DSE */
+	.grp_addds = PAD_CTL_DSE_40ohm,
+
+	/* CS0/CS1/SDBA2/CKE0/CKE1/SDWE: 40 ohm DSE */
+	.grp_ctlds = PAD_CTL_DSE_40ohm,
+
+	/* DATA[0:63]: Differential input */
+	.grp_ddrmode = PAD_CTL_INPUT_DDR,
+
+	/* DATA[0:63]: 40 ohm DSE */
+	.grp_b0ds = PAD_CTL_DSE_40ohm,
+	.grp_b1ds = PAD_CTL_DSE_40ohm,
+	.grp_b2ds = PAD_CTL_DSE_40ohm,
+	.grp_b3ds = PAD_CTL_DSE_40ohm,
+	.grp_b4ds = PAD_CTL_DSE_40ohm,
+	.grp_b5ds = PAD_CTL_DSE_40ohm,
+	.grp_b6ds = PAD_CTL_DSE_40ohm,
+	.grp_b7ds = PAD_CTL_DSE_40ohm,
+};
+
+struct mx6_ddr_sysinfo sysinfo = {
+	.dsize = 2,         /* width of data bus: 2=64 */
+	.cs_density = 32,   /* full range so that get_mem_size() works, 32Gb per CS */
+	.ncs = 1,
+	.cs1_mirror = 0,
+	.rtt_wr = 2,        /* Dynamic ODT, RZQ/2 */
+	.rtt_nom = 2,       /* RZQ/2 */
+	.walat = 0,         /* Write additional latency */
+	.ralat = 5,         /* Read additional latency */
+	.mif3_mode = 3,     /* Command prediction working mode */
+	.bi_on = 1,         /* Bank interleaving enabled */
+	.sde_to_rst = 0x10, /* 14 cycles, 200us (JEDEC default) */
+	.rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */
+	.pd_fast_exit = 1,  /* enable precharge power-down fast exit */
+	.ddr_type = DDR_TYPE_DDR3,
+	.refsel = 1,        /* Refresh cycles at 32KHz */
+	.refr = 3,          /* 4 refresh commands per refresh cycle */
+};
+
+static const struct mx6_mmdc_calibration mx6_mmdc_calib = {
+	.p0_mpwldectrl0 = 0x0009000E,
+	.p0_mpwldectrl1 = 0x0018000B,
+	.p1_mpwldectrl0 = 0x00060015,
+	.p1_mpwldectrl1 = 0x0006000E,
+	.p0_mpdgctrl0 = 0x432A0338,
+	.p0_mpdgctrl1 = 0x03260324,
+	.p1_mpdgctrl0 = 0x43340344,
+	.p1_mpdgctrl1 = 0x031E027C,
+	.p0_mprddlctl = 0x33272D2E,
+	.p1_mprddlctl = 0x2F312B37,
+	.p0_mpwrdlctl = 0x3A35433C,
+	.p1_mpwrdlctl = 0x4336453F,
+};
+
+static const struct mx6_ddr3_cfg ddr3_cfg = {
+	.mem_speed = 1066,
+	.density = 2,
+	.width = 16,
+	.banks = 8,
+	.rowaddr = 14,
+	.coladdr = 10,
+	.pagesz = 2,
+	.trcd = 1312,
+	.trcmin = 4812,
+	.trasmin = 3500,
+	.SRT = 0,
+};
+
+struct mx6_ddr_sysinfo sysinfo_it = {
+	.dsize = 2,         /* width of data bus: 2=64 */
+	.cs_density = 32,   /* full range so that get_mem_size() works, 32Gb per CS */
+	.ncs = 1,
+	.cs1_mirror = 0,
+	.rtt_wr = 1,        /* Dynamic ODT, RZQ/4 */
+	.rtt_nom = 1,       /* RZQ/4 */
+	.walat = 0,         /* Write additional latency */
+	.ralat = 5,         /* Read additional latency */
+	.mif3_mode = 3,     /* Command prediction working mode */
+	.bi_on = 1,         /* Bank interleaving enabled */
+	.sde_to_rst = 0x10, /* 14 cycles, 200us (JEDEC default) */
+	.rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */
+	.pd_fast_exit = 1,  /* enable precharge power-down fast exit */
+	.ddr_type = DDR_TYPE_DDR3,
+	.refsel = 1,        /* Refresh cycles at 32KHz */
+	.refr = 7,          /* 8 refresh commands per refresh cycle */
+};
+
+static const struct mx6_mmdc_calibration mx6_mmdc_calib_it = {
+	.p0_mpwldectrl0 = 0x0009000E,
+	.p0_mpwldectrl1 = 0x0018000B,
+	.p1_mpwldectrl0 = 0x00060015,
+	.p1_mpwldectrl1 = 0x0006000E,
+	.p0_mpdgctrl0 = 0x03300338,
+	.p0_mpdgctrl1 = 0x03240324,
+	.p1_mpdgctrl0 = 0x03440350,
+	.p1_mpdgctrl1 = 0x032C0308,
+	.p0_mprddlctl = 0x40363C3E,
+	.p1_mprddlctl = 0x3C3E3C46,
+	.p0_mpwrdlctl = 0x403E463E,
+	.p1_mpwrdlctl = 0x4A384C46,
+};
+
+static const struct mx6_ddr3_cfg ddr3_cfg_it = {
+	.mem_speed = 1066,
+	.density = 4,
+	.width = 16,
+	.banks = 8,
+	.rowaddr = 15,
+	.coladdr = 10,
+	.pagesz = 2,
+	.trcd = 1312,
+	.trcmin = 4812,
+	.trasmin = 3500,
+	.SRT = 1,
+};
+
 
 /* Perform DDR DRAM calibration */
-static void spl_dram_perform_cal(void)
+static void spl_dram_perform_cal(const struct mx6_ddr_sysinfo *ddr_sysinfo)
 {
 #ifdef CONFIG_MX6_DDRCAL
 	int err;
-	struct mx6_ddr_sysinfo ddr_sysinfo = {
-		.dsize = 2,
-	};
 
-	err = mmdc_do_write_level_calibration(&ddr_sysinfo);
+	err = mmdc_do_write_level_calibration(ddr_sysinfo);
 	if (err)
 		printf("error %d from write level calibration\n", err);
-	err = mmdc_do_dqs_calibration(&ddr_sysinfo);
+	err = mmdc_do_dqs_calibration(ddr_sysinfo);
 	if (err)
 		printf("error %d from dqs calibration\n", err);
 #endif
 }
 
+/* MMDC initialization */
 static void spl_dram_init(void)
 {
-	int minc, maxc;
+	bool temp_grade_it;
 
-	switch (get_cpu_temp_grade(&minc, &maxc)) {
+	switch (get_cpu_temp_grade(NULL, NULL)) {
 	case TEMP_COMMERCIAL:
 	case TEMP_EXTCOMMERCIAL:
 		puts("Commercial temperature grade DDR3 timings.\n");
-		ddr_init(mx6_com_dcd_table, ARRAY_SIZE(mx6_com_dcd_table));
+		temp_grade_it = false;
 		break;
 	case TEMP_INDUSTRIAL:
 	case TEMP_AUTOMOTIVE:
 	default:
 		puts("Industrial temperature grade DDR3 timings.\n");
-		ddr_init(mx6_it_dcd_table, ARRAY_SIZE(mx6_it_dcd_table));
+		temp_grade_it = true;
 		break;
 	};
+
+	mx6dq_dram_iocfg(64, &mx6_ddr_ioregs, &mx6_grp_ioregs);
+
+	if (temp_grade_it)
+		mx6_dram_cfg(&sysinfo_it, &mx6_mmdc_calib_it, &ddr3_cfg_it);
+	else
+		mx6_dram_cfg(&sysinfo, &mx6_mmdc_calib, &ddr3_cfg);
+
 	udelay(100);
-	spl_dram_perform_cal();
+	spl_dram_perform_cal(&sysinfo);
 }
 
 void board_init_f(ulong dummy)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH 2/3] mx6: ddr: Wait before issuing the first MRS cmd
  2022-04-04  8:51 ` [RFC PATCH 2/3] mx6: ddr: Wait before issuing the first MRS cmd Francesco Dolcini
@ 2022-04-04 13:39   ` Marek Vasut
  2022-04-04 14:53     ` Francesco Dolcini
  0 siblings, 1 reply; 10+ messages in thread
From: Marek Vasut @ 2022-04-04 13:39 UTC (permalink / raw)
  To: Francesco Dolcini, Stefano Babic, Fabio Estevam, uboot-imx, Tim Harvey
  Cc: u-boot

On 4/4/22 10:51, Francesco Dolcini wrote:
> Wait 1ms before issuing the first MRS command to write DDR3 Mode
> registers.
> 
> There is a requirement to wait minimum of Reset CKE Exit time, tXPR,
> with tXPR = max(tXS, 5tCK) and to wait 500 useconds after reset is
> de-asserted. It seems that for some reason this is not enforced by the
> MMDC controller, despite MMDCx_MDOR RST_to_CKE and tXPR being correctly
> configured.
> 
> Without this change we experienced random memory initialization failures
> with about 2% boot failure rate on specific problematic boards, after
> this change we were able to do more than 10.000 power-cycle without a
> single failure.
> 
> Fixes: fe0f7f7842e1 ("mx6: add mmdc configuration for MX6Q/MX6DL")
> Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
> ---
>   arch/arm/mach-imx/mx6/ddr.c | 2 ++
>   1 file changed, 2 insertions(+)
> 
> diff --git a/arch/arm/mach-imx/mx6/ddr.c b/arch/arm/mach-imx/mx6/ddr.c
> index 08e2f0f130a6..7b3d620094c4 100644
> --- a/arch/arm/mach-imx/mx6/ddr.c
> +++ b/arch/arm/mach-imx/mx6/ddr.c
> @@ -1526,6 +1526,8 @@ void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,
>   			((sysinfo->ncs == 2) ? 1 : 0) << 30; /* SDE_1 for CS1 */
>   
>   	/* Step 8: Write Mode Registers to Init DDR3 devices */
> +	mdelay(1); /* Wait before issuing the first MRS command
> +		      (tXPR / 500us CKE delay after reset deassertion) */

Should we infer this delay from tXPR instead ?

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH 1/3] mx6: ddr: Restore ralat/walat in write level calibration
  2022-04-04  8:51 ` [RFC PATCH 1/3] mx6: ddr: Restore ralat/walat in write level calibration Francesco Dolcini
@ 2022-04-04 13:40   ` Marek Vasut
  0 siblings, 0 replies; 10+ messages in thread
From: Marek Vasut @ 2022-04-04 13:40 UTC (permalink / raw)
  To: Francesco Dolcini, Stefano Babic, Fabio Estevam, uboot-imx, Tim Harvey
  Cc: u-boot

On 4/4/22 10:51, Francesco Dolcini wrote:
> The current DDR write level calibration routine always overwrite
> the ralat/walat fields to their maximum value, just save
> the existing values at the beginning of the calibration routine
> and restore it at the end.
> 
> In case the delay is estimated by the user to be more than one cycle the
> walat should be configured according to that, this is not
> automatically done.  From the i.MX6 RM:
> 
>     The user should read the results of the associated delay-line at
>     MPWLDECTRL#[WL_DL_ABS_OFFSET#] and in case the user estimates that the
>     reasonable delay may be above 1 cycle then the user should indicate it at
>     MPWLDECTRL#[WL_CYC_DEL#]. Moreover the user should indicate it in
>     MDMISC[WALAT] field. For example, if the result of the write leveling calibration
>     is 100/256 parts of a cycle, but the user estimates that the delay is above 2 cycles
>     then MPWLDECTRL#[WL_CYC_DEL#] should be configured to 2, so the total
>     delay will be 2 and 100/256 parts of a cycle
> 
> Probably it would just possible to not overwrite the mdmisc register in
> the first place, since this is not present in the write_level_calib() example
> in NXP AN4467 [1] nor in the i.MX6 RM (44.11.6.1 Hardware Write Leveling
> Calibration).
> 
> Fixes: d339f16911c7 ("arm: imx6: Add DDR3 calibration code for MX6 Q/D/DL")
> Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
> ---
>   arch/arm/mach-imx/mx6/ddr.c | 8 +++++++-
>   1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/mach-imx/mx6/ddr.c b/arch/arm/mach-imx/mx6/ddr.c
> index f872bfdab315..08e2f0f130a6 100644
> --- a/arch/arm/mach-imx/mx6/ddr.c
> +++ b/arch/arm/mach-imx/mx6/ddr.c
> @@ -108,7 +108,7 @@ int mmdc_do_write_level_calibration(struct mx6_ddr_sysinfo const *sysinfo)
>   {
>   	struct mmdc_p_regs *mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR;
>   	struct mmdc_p_regs *mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR;
> -	u32 esdmisc_val, zq_val;
> +	u32 esdmisc_val, zq_val, mdmisc_val;
>   	u32 errors = 0;
>   	u32 ldectrl[4] = {0};
>   	u32 ddr_mr1 = 0x4;
> @@ -131,6 +131,9 @@ int mmdc_do_write_level_calibration(struct mx6_ddr_sysinfo const *sysinfo)
>   	/* disable Adopt power down timer */
>   	setbits_le32(&mmdc0->mapsr, 0x1);
>   
> +	/* Save old RALAT and WALAT values */
> +	mdmisc_val = readl(&mmdc0->mdmisc);
> +
>   	debug("Starting write leveling calibration.\n");
>   
>   	/*
> @@ -217,6 +220,9 @@ int mmdc_do_write_level_calibration(struct mx6_ddr_sysinfo const *sysinfo)
>   	writel(esdmisc_val, &mmdc0->mdref);
>   	writel(zq_val, &mmdc0->mpzqhwctrl);
>   
> +	/* restore walat/ralat */
> +	writel(mdmisc_val, &mmdc0->mdmisc);
> +
>   	debug("\tMMDC_MPWLDECTRL0 after write level cal: 0x%08x\n",
>   	      readl(&mmdc0->mpwldectrl0));
>   	debug("\tMMDC_MPWLDECTRL1 after write level cal: 0x%08x\n",

Reviewed-by: Marek Vasut <marex@denx.de>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH 2/3] mx6: ddr: Wait before issuing the first MRS cmd
  2022-04-04 13:39   ` Marek Vasut
@ 2022-04-04 14:53     ` Francesco Dolcini
  2022-04-04 19:56       ` Marek Vasut
  0 siblings, 1 reply; 10+ messages in thread
From: Francesco Dolcini @ 2022-04-04 14:53 UTC (permalink / raw)
  To: Marek Vasut
  Cc: Francesco Dolcini, Stefano Babic, Fabio Estevam, uboot-imx,
	Tim Harvey, u-boot

Hello Marek,
thanks for your review.

On Mon, Apr 04, 2022 at 03:39:35PM +0200, Marek Vasut wrote:
> On 4/4/22 10:51, Francesco Dolcini wrote:
> > Wait 1ms before issuing the first MRS command to write DDR3 Mode
> > registers.
> > 
> > There is a requirement to wait minimum of Reset CKE Exit time, tXPR,
> > with tXPR = max(tXS, 5tCK) and to wait 500 useconds after reset is
> > de-asserted. It seems that for some reason this is not enforced by the
> > MMDC controller, despite MMDCx_MDOR RST_to_CKE and tXPR being correctly
> > configured.
> > 
> > Without this change we experienced random memory initialization failures
> > with about 2% boot failure rate on specific problematic boards, after
> > this change we were able to do more than 10.000 power-cycle without a
> > single failure.
> > 
> > Fixes: fe0f7f7842e1 ("mx6: add mmdc configuration for MX6Q/MX6DL")
> > Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
> > ---
> >   arch/arm/mach-imx/mx6/ddr.c | 2 ++
> >   1 file changed, 2 insertions(+)
> > 
> > diff --git a/arch/arm/mach-imx/mx6/ddr.c b/arch/arm/mach-imx/mx6/ddr.c
> > index 08e2f0f130a6..7b3d620094c4 100644
> > --- a/arch/arm/mach-imx/mx6/ddr.c
> > +++ b/arch/arm/mach-imx/mx6/ddr.c
> > @@ -1526,6 +1526,8 @@ void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,
> >   			((sysinfo->ncs == 2) ? 1 : 0) << 30; /* SDE_1 for CS1 */
> >   	/* Step 8: Write Mode Registers to Init DDR3 devices */
> > +	mdelay(1); /* Wait before issuing the first MRS command
> > +		      (tXPR / 500us CKE delay after reset deassertion) */
> 
> Should we infer this delay from tXPR instead ?

I could just delay(tXPR + 500us) and do the exact worst case delay.

However I wonder if it is worth doing it, the 1ms delay works in
practice, it is big enough to be correct in any case, but small enough
not to be a concern on the boot time.

Please note that I do not know which timing is violated here
(tXPR, the 500us after reset de-assertion or both of them).

Francesco


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH 2/3] mx6: ddr: Wait before issuing the first MRS cmd
  2022-04-04 14:53     ` Francesco Dolcini
@ 2022-04-04 19:56       ` Marek Vasut
  2022-04-05  9:09         ` Francesco Dolcini
  0 siblings, 1 reply; 10+ messages in thread
From: Marek Vasut @ 2022-04-04 19:56 UTC (permalink / raw)
  To: Francesco Dolcini
  Cc: Stefano Babic, Fabio Estevam, uboot-imx, Tim Harvey, u-boot

On 4/4/22 16:53, Francesco Dolcini wrote:
> Hello Marek,
> thanks for your review.
> 
> On Mon, Apr 04, 2022 at 03:39:35PM +0200, Marek Vasut wrote:
>> On 4/4/22 10:51, Francesco Dolcini wrote:
>>> Wait 1ms before issuing the first MRS command to write DDR3 Mode
>>> registers.
>>>
>>> There is a requirement to wait minimum of Reset CKE Exit time, tXPR,
>>> with tXPR = max(tXS, 5tCK) and to wait 500 useconds after reset is
>>> de-asserted. It seems that for some reason this is not enforced by the
>>> MMDC controller, despite MMDCx_MDOR RST_to_CKE and tXPR being correctly
>>> configured.
>>>
>>> Without this change we experienced random memory initialization failures
>>> with about 2% boot failure rate on specific problematic boards, after
>>> this change we were able to do more than 10.000 power-cycle without a
>>> single failure.
>>>
>>> Fixes: fe0f7f7842e1 ("mx6: add mmdc configuration for MX6Q/MX6DL")
>>> Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
>>> ---
>>>    arch/arm/mach-imx/mx6/ddr.c | 2 ++
>>>    1 file changed, 2 insertions(+)
>>>
>>> diff --git a/arch/arm/mach-imx/mx6/ddr.c b/arch/arm/mach-imx/mx6/ddr.c
>>> index 08e2f0f130a6..7b3d620094c4 100644
>>> --- a/arch/arm/mach-imx/mx6/ddr.c
>>> +++ b/arch/arm/mach-imx/mx6/ddr.c
>>> @@ -1526,6 +1526,8 @@ void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,
>>>    			((sysinfo->ncs == 2) ? 1 : 0) << 30; /* SDE_1 for CS1 */
>>>    	/* Step 8: Write Mode Registers to Init DDR3 devices */
>>> +	mdelay(1); /* Wait before issuing the first MRS command
>>> +		      (tXPR / 500us CKE delay after reset deassertion) */
>>
>> Should we infer this delay from tXPR instead ?
> 
> I could just delay(tXPR + 500us) and do the exact worst case delay.
> 
> However I wonder if it is worth doing it, the 1ms delay works in
> practice, it is big enough to be correct in any case, but small enough
> not to be a concern on the boot time.
> 
> Please note that I do not know which timing is violated here
> (tXPR, the 500us after reset de-assertion or both of them).

Can the tXPR ever be larger than 500us ?

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH 2/3] mx6: ddr: Wait before issuing the first MRS cmd
  2022-04-04 19:56       ` Marek Vasut
@ 2022-04-05  9:09         ` Francesco Dolcini
  2022-04-05  9:28           ` Marek Vasut
  0 siblings, 1 reply; 10+ messages in thread
From: Francesco Dolcini @ 2022-04-05  9:09 UTC (permalink / raw)
  To: Marek Vasut
  Cc: Francesco Dolcini, Stefano Babic, Fabio Estevam, uboot-imx,
	Tim Harvey, u-boot

On Mon, Apr 04, 2022 at 09:56:50PM +0200, Marek Vasut wrote:
> On 4/4/22 16:53, Francesco Dolcini wrote:
> > On Mon, Apr 04, 2022 at 03:39:35PM +0200, Marek Vasut wrote:
> > > > --- a/arch/arm/mach-imx/mx6/ddr.c
> > > > +++ b/arch/arm/mach-imx/mx6/ddr.c
> > > > @@ -1526,6 +1526,8 @@ void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,
> > > >    			((sysinfo->ncs == 2) ? 1 : 0) << 30; /* SDE_1 for CS1 */
> > > >    	/* Step 8: Write Mode Registers to Init DDR3 devices */
> > > > +	mdelay(1); /* Wait before issuing the first MRS command
> > > > +		      (tXPR / 500us CKE delay after reset deassertion) */
> > > 
> > > Should we infer this delay from tXPR instead ?
> > 
> > I could just delay(tXPR + 500us) and do the exact worst case delay.
> > 
> > However I wonder if it is worth doing it, the 1ms delay works in
> > practice, it is big enough to be correct in any case, but small enough
> > not to be a concern on the boot time.
> > 
> > Please note that I do not know which timing is violated here
> > (tXPR, the 500us after reset de-assertion or both of them).
> 
> Can the tXPR ever be larger than 500us ?

No, it can't. Max value for 8GB density is 360ns, min value 120ns
for 1GB density (see JEDEC standard, but also mx6/ddr.c).

Would be fine for you to improve the commit message and code comment
to make this discussion we just had transparent, while keeping the 1ms
delay?

Francesco


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC PATCH 2/3] mx6: ddr: Wait before issuing the first MRS cmd
  2022-04-05  9:09         ` Francesco Dolcini
@ 2022-04-05  9:28           ` Marek Vasut
  0 siblings, 0 replies; 10+ messages in thread
From: Marek Vasut @ 2022-04-05  9:28 UTC (permalink / raw)
  To: Francesco Dolcini
  Cc: Stefano Babic, Fabio Estevam, uboot-imx, Tim Harvey, u-boot

On 4/5/22 11:09, Francesco Dolcini wrote:
> On Mon, Apr 04, 2022 at 09:56:50PM +0200, Marek Vasut wrote:
>> On 4/4/22 16:53, Francesco Dolcini wrote:
>>> On Mon, Apr 04, 2022 at 03:39:35PM +0200, Marek Vasut wrote:
>>>>> --- a/arch/arm/mach-imx/mx6/ddr.c
>>>>> +++ b/arch/arm/mach-imx/mx6/ddr.c
>>>>> @@ -1526,6 +1526,8 @@ void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,
>>>>>     			((sysinfo->ncs == 2) ? 1 : 0) << 30; /* SDE_1 for CS1 */
>>>>>     	/* Step 8: Write Mode Registers to Init DDR3 devices */
>>>>> +	mdelay(1); /* Wait before issuing the first MRS command
>>>>> +		      (tXPR / 500us CKE delay after reset deassertion) */
>>>>
>>>> Should we infer this delay from tXPR instead ?
>>>
>>> I could just delay(tXPR + 500us) and do the exact worst case delay.
>>>
>>> However I wonder if it is worth doing it, the 1ms delay works in
>>> practice, it is big enough to be correct in any case, but small enough
>>> not to be a concern on the boot time.
>>>
>>> Please note that I do not know which timing is violated here
>>> (tXPR, the 500us after reset de-assertion or both of them).
>>
>> Can the tXPR ever be larger than 500us ?
> 
> No, it can't. Max value for 8GB density is 360ns, min value 120ns
> for 1GB density (see JEDEC standard, but also mx6/ddr.c).
> 
> Would be fine for you to improve the commit message and code comment
> to make this discussion we just had transparent, while keeping the 1ms
> delay?

Yeah, 1ms is fine. If you do V2, add my:

Reviewed-by: Marek Vasut <marex@denx.de>

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2022-04-05  9:28 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-04  8:51 [RFC PATCH 0/3] Fix iMX6 DDR configuration issues and update toradex apalis-imx6 Francesco Dolcini
2022-04-04  8:51 ` [RFC PATCH 1/3] mx6: ddr: Restore ralat/walat in write level calibration Francesco Dolcini
2022-04-04 13:40   ` Marek Vasut
2022-04-04  8:51 ` [RFC PATCH 2/3] mx6: ddr: Wait before issuing the first MRS cmd Francesco Dolcini
2022-04-04 13:39   ` Marek Vasut
2022-04-04 14:53     ` Francesco Dolcini
2022-04-04 19:56       ` Marek Vasut
2022-04-05  9:09         ` Francesco Dolcini
2022-04-05  9:28           ` Marek Vasut
2022-04-04  8:51 ` [RFC PATCH 3/3] board: apalis_imx6: DDR init using mx6_dram_cfg() Francesco Dolcini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.