From patchwork Tue Jun 21 18:41:34 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Nelson X-Patchwork-Id: 638820 X-Patchwork-Delegate: sbabic@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 3rYxXp23mPz9t0n for ; Wed, 22 Jun 2016 04:47:06 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 6EABCA7678; Tue, 21 Jun 2016 20:47:00 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ukh8r-A-kbK7; Tue, 21 Jun 2016 20:47:00 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 593EBA765B; Tue, 21 Jun 2016 20:46:59 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 62CE0A756F for ; Tue, 21 Jun 2016 20:46:51 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 55lRAdsR9LvE for ; Tue, 21 Jun 2016 20:46:51 +0200 (CEST) X-Greylist: delayed 300 seconds by postgrey-1.34 at theia; Tue, 21 Jun 2016 20:46:46 CEST X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from fed1rmfepo103.cox.net (fed1rmfepo103.cox.net [68.230.241.145]) by theia.denx.de (Postfix) with ESMTP id 52053A7524 for ; Tue, 21 Jun 2016 20:46:46 +0200 (CEST) Received: from fed1rmimpo210.cox.net ([68.230.241.161]) by fed1rmfepo103.cox.net (InterMail vM.8.01.05.28 201-2260-151-171-20160122) with ESMTP id <20160621184147.SRQE27913.fed1rmfepo103.cox.net@fed1rmimpo210.cox.net> for ; Tue, 21 Jun 2016 14:41:47 -0400 Received: from localhost.localdomain ([98.167.220.73]) by fed1rmimpo210.cox.net with cox id 9Whk1t0051bd1YJ01WhmGv; Tue, 21 Jun 2016 14:41:47 -0400 X-CT-Class: Clean X-CT-Score: 0.00 X-CT-RefID: str=0001.0A020201.57698A6B.01A7, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0 X-CT-Spam: 0 X-Authority-Analysis: v=2.1 cv=P+Oa/n0u c=1 sm=1 tr=0 a=IKzc1XMGcUxYR4OhBl0X0A==:117 a=IKzc1XMGcUxYR4OhBl0X0A==:17 a=L9H7d07YOLsA:10 a=9cW_t1CCXrUA:10 a=s5jvgZ67dGcA:10 a=9_1hYV8uAAAA:8 a=VkOKp2ych-CA9aP1QTEA:9 a=FKwbt-OhbrkoYuZlCyy7:22 X-CM-Score: 0.00 Authentication-Results: cox.net; auth=pass (CRAM-MD5) smtp.auth=eric.a.nelson@cox.net From: Eric Nelson To: u-boot@lists.denx.de Date: Tue, 21 Jun 2016 11:41:34 -0700 Message-Id: <1466534502-17233-5-git-send-email-eric@nelint.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1466534502-17233-1-git-send-email-eric@nelint.com> References: <1466534502-17233-1-git-send-email-eric@nelint.com> Cc: marex@denx.de, otavio@ossystems.com.br, gary.bisson@boundarydevices.com, joe.hershberger@ni.com, fabio.estevam@nxp.com Subject: [U-Boot] [RFC PATCH 04/12] imx: mx6: ddr: pass sysinfo to calibration routines X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Before calling the dynamic DDR calibration routines, board files must call mx6_dram_cfg, so they already have a struct mx6_ddr_sysinfo available for use in determining the bus width. Use it for determining the DRAM bus width instead of a mix of dynamic determination in mmdc_do_dqs_calibration() and assumed 64-bit support in mmdc_do_write_level_calibration(). This allows the use of the DDR calibration routines on CPU variants like i.MX6SL that only have a single MMDC port. Signed-off-by: Eric Nelson --- arch/arm/cpu/armv7/mx6/ddr.c | 119 +++++++++++++++++++------------- arch/arm/include/asm/arch-mx6/mx6-ddr.h | 6 +- 2 files changed, 75 insertions(+), 50 deletions(-) diff --git a/arch/arm/cpu/armv7/mx6/ddr.c b/arch/arm/cpu/armv7/mx6/ddr.c index eb2d000..f9fb552 100644 --- a/arch/arm/cpu/armv7/mx6/ddr.c +++ b/arch/arm/cpu/armv7/mx6/ddr.c @@ -86,14 +86,16 @@ static void modify_dg_result(u32 *reg_st0, u32 *reg_st1, u32 *reg_ctrl) writel(val_ctrl, reg_ctrl); } -int mmdc_do_write_level_calibration(struct mx6_mmdc_calibration *calib) +int mmdc_do_write_level_calibration(struct mx6_ddr_sysinfo const *sysinfo, + struct mx6_mmdc_calibration *calib) { 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 errors = 0; - u32 ldectrl[4]; + u32 ldectrl[4] = {0}; u32 ddr_mr1 = 0x4; + u32 rwalat_max; /* * Stash old values in case calibration fails, @@ -101,8 +103,10 @@ int mmdc_do_write_level_calibration(struct mx6_mmdc_calibration *calib) */ ldectrl[0] = readl(&mmdc0->mpwldectrl0); ldectrl[1] = readl(&mmdc0->mpwldectrl1); - ldectrl[2] = readl(&mmdc1->mpwldectrl0); - ldectrl[3] = readl(&mmdc1->mpwldectrl1); + if (sysinfo->dsize == 2) { + ldectrl[2] = readl(&mmdc1->mpwldectrl0); + ldectrl[3] = readl(&mmdc1->mpwldectrl1); + } /* disable DDR logic power down timer */ clrbits_le32(&mmdc0->mdpdc, 0xff00); @@ -122,10 +126,11 @@ int mmdc_do_write_level_calibration(struct mx6_mmdc_calibration *calib) writel(zq_val & ~0x3, &mmdc0->mpzqhwctrl); /* 3. increase walat and ralat to maximum */ - setbits_le32(&mmdc0->mdmisc, - (1 << 6) | (1 << 7) | (1 << 8) | (1 << 16) | (1 << 17)); - setbits_le32(&mmdc1->mdmisc, - (1 << 6) | (1 << 7) | (1 << 8) | (1 << 16) | (1 << 17)); + rwalat_max = (1 << 6) | (1 << 7) | (1 << 8) | (1 << 16) | (1 << 17); + setbits_le32(&mmdc0->mdmisc, rwalat_max); + if (sysinfo->dsize == 2) + setbits_le32(&mmdc1->mdmisc, rwalat_max); + /* * 4 & 5. Configure the external DDR device to enter write-leveling * mode through Load Mode Register command. @@ -152,21 +157,25 @@ int mmdc_do_write_level_calibration(struct mx6_mmdc_calibration *calib) */ if (readl(&mmdc0->mpwlgcr) & 0x00000F00) errors |= 1; - if (readl(&mmdc1->mpwlgcr) & 0x00000F00) - errors |= 2; + if (sysinfo->dsize == 2) + if (readl(&mmdc1->mpwlgcr) & 0x00000F00) + errors |= 2; debug("Ending write leveling calibration. Error mask: 0x%x\n", errors); /* check to see if cal failed */ if ((readl(&mmdc0->mpwldectrl0) == 0x001F001F) && (readl(&mmdc0->mpwldectrl1) == 0x001F001F) && - (readl(&mmdc1->mpwldectrl0) == 0x001F001F) && - (readl(&mmdc1->mpwldectrl1) == 0x001F001F)) { + ((sysinfo->dsize < 2) || + ((readl(&mmdc1->mpwldectrl0) == 0x001F001F) && + (readl(&mmdc1->mpwldectrl1) == 0x001F001F)))) { debug("Cal seems to have soft-failed due to memory not supporting write leveling on all channels. Restoring original write leveling values.\n"); writel(ldectrl[0], &mmdc0->mpwldectrl0); writel(ldectrl[1], &mmdc0->mpwldectrl1); - writel(ldectrl[2], &mmdc1->mpwldectrl0); - writel(ldectrl[3], &mmdc1->mpwldectrl1); + if (sysinfo->dsize == 2) { + writel(ldectrl[2], &mmdc1->mpwldectrl0); + writel(ldectrl[3], &mmdc1->mpwldectrl1); + } errors |= 4; } @@ -189,22 +198,28 @@ int mmdc_do_write_level_calibration(struct mx6_mmdc_calibration *calib) readl(&mmdc0->mpwldectrl0)); debug("\tMMDC_MPWLDECTRL1 after write level cal: 0x%08X\n", readl(&mmdc0->mpwldectrl1)); - debug("\tMMDC_MPWLDECTRL0 after write level cal: 0x%08X\n", - readl(&mmdc1->mpwldectrl0)); - debug("\tMMDC_MPWLDECTRL1 after write level cal: 0x%08X\n", - readl(&mmdc1->mpwldectrl1)); + if (sysinfo->dsize == 2) { + debug("\tMMDC_MPWLDECTRL0 after write level cal: 0x%08X\n", + readl(&mmdc1->mpwldectrl0)); + debug("\tMMDC_MPWLDECTRL1 after write level cal: 0x%08X\n", + readl(&mmdc1->mpwldectrl1)); + } /* We must force a readback of these values, to get them to stick */ if (calib) { calib->p0_mpwldectrl0 = readl(&mmdc0->mpwldectrl0); calib->p0_mpwldectrl1 = readl(&mmdc0->mpwldectrl1); - calib->p1_mpwldectrl0 = readl(&mmdc1->mpwldectrl0); - calib->p1_mpwldectrl1 = readl(&mmdc1->mpwldectrl1); + if (sysinfo->dsize == 2) { + calib->p1_mpwldectrl0 = readl(&mmdc1->mpwldectrl0); + calib->p1_mpwldectrl1 = readl(&mmdc1->mpwldectrl1); + } } else { readl(&mmdc0->mpwldectrl0); readl(&mmdc0->mpwldectrl1); - readl(&mmdc1->mpwldectrl0); - readl(&mmdc1->mpwldectrl1); + if (sysinfo->dsize == 2) { + readl(&mmdc1->mpwldectrl0); + readl(&mmdc1->mpwldectrl1); + } } /* enable DDR logic power down timer: */ @@ -219,7 +234,8 @@ int mmdc_do_write_level_calibration(struct mx6_mmdc_calibration *calib) return errors; } -int mmdc_do_dqs_calibration(struct mx6_mmdc_calibration *calib) +int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo, + struct mx6_mmdc_calibration *calib) { 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; @@ -230,7 +246,6 @@ int mmdc_do_dqs_calibration(struct mx6_mmdc_calibration *calib) bool cs0_enable_initial; bool cs1_enable_initial; u32 esdmisc_val; - u32 bus_size; u32 temp_ref; u32 pddword = 0x00ffff00; /* best so far, place into MPPDCMPR1 */ u32 errors = 0; @@ -299,10 +314,6 @@ int mmdc_do_dqs_calibration(struct mx6_mmdc_calibration *calib) cs0_enable = readl(&mmdc0->mdctl) & 0x80000000; cs1_enable = readl(&mmdc0->mdctl) & 0x40000000; - /* Check to see what the data bus size is */ - bus_size = (readl(&mmdc0->mdctl) & 0x30000) >> 16; - debug("Data bus size: %d (%d bits)\n", bus_size, 1 << (bus_size + 4)); - precharge_all(cs0_enable, cs1_enable); /* Write the pre-defined value into MPPDCMPR1 */ @@ -321,11 +332,11 @@ int mmdc_do_dqs_calibration(struct mx6_mmdc_calibration *calib) * Both PHYs for x64 configuration, if x32, do only PHY0. */ writel(initdelay, &mmdc0->mprddlctl); - if (bus_size == 0x2) + if (sysinfo->dsize == 0x2) writel(initdelay, &mmdc1->mprddlctl); /* Force a measurment, for previous delay setup to take effect. */ - force_delay_measurement(bus_size); + force_delay_measurement(sysinfo->dsize); /* * *************************** @@ -369,7 +380,7 @@ int mmdc_do_dqs_calibration(struct mx6_mmdc_calibration *calib) if (readl(&mmdc0->mpdgctrl0) & 0x00001000) errors |= 1; - if ((bus_size == 0x2) && (readl(&mmdc1->mpdgctrl0) & 0x00001000)) + if ((sysinfo->dsize == 0x2) && (readl(&mmdc1->mpdgctrl0) & 0x00001000)) errors |= 2; /* @@ -381,7 +392,7 @@ int mmdc_do_dqs_calibration(struct mx6_mmdc_calibration *calib) &mmdc0->mpdgctrl0); modify_dg_result(&mmdc0->mpdghwst2, &mmdc0->mpdghwst3, &mmdc0->mpdgctrl1); - if (bus_size == 0x2) { + if (sysinfo->dsize == 0x2) { modify_dg_result(&mmdc1->mpdghwst0, &mmdc1->mpdghwst1, &mmdc1->mpdgctrl0); modify_dg_result(&mmdc1->mpdghwst2, &mmdc1->mpdghwst3, @@ -424,7 +435,8 @@ int mmdc_do_dqs_calibration(struct mx6_mmdc_calibration *calib) if (readl(&mmdc0->mprddlhwctl) & 0x0000000f) errors |= 4; - if ((bus_size == 0x2) && (readl(&mmdc1->mprddlhwctl) & 0x0000000f)) + if ((sysinfo->dsize == 0x2) && + (readl(&mmdc1->mprddlhwctl) & 0x0000000f)) errors |= 8; debug("Ending Read Delay calibration. Error mask: 0x%x\n", errors); @@ -450,14 +462,14 @@ int mmdc_do_dqs_calibration(struct mx6_mmdc_calibration *calib) * Both PHYs for x64 configuration, if x32, do only PHY0. */ writel(initdelay, &mmdc0->mpwrdlctl); - if (bus_size == 0x2) + if (sysinfo->dsize == 0x2) writel(initdelay, &mmdc1->mpwrdlctl); /* * XXX This isn't in the manual. Force a measurement, * for previous delay setup to effect. */ - force_delay_measurement(bus_size); + force_delay_measurement(sysinfo->dsize); /* * 9. 10. Start the automatic write calibration process @@ -477,7 +489,8 @@ int mmdc_do_dqs_calibration(struct mx6_mmdc_calibration *calib) if (readl(&mmdc0->mpwrdlhwctl) & 0x0000000f) errors |= 16; - if ((bus_size == 0x2) && (readl(&mmdc1->mpwrdlhwctl) & 0x0000000f)) + if ((sysinfo->dsize == 0x2) && + (readl(&mmdc1->mpwrdlhwctl) & 0x0000000f)) errors |= 32; debug("Ending Write Delay calibration. Error mask: 0x%x\n", errors); @@ -529,14 +542,18 @@ int mmdc_do_dqs_calibration(struct mx6_mmdc_calibration *calib) debug("Read DQS gating calibration:\n"); debug("\tMPDGCTRL0 PHY0 = 0x%08X\n", readl(&mmdc0->mpdgctrl0)); debug("\tMPDGCTRL1 PHY0 = 0x%08X\n", readl(&mmdc0->mpdgctrl1)); - debug("\tMPDGCTRL0 PHY1 = 0x%08X\n", readl(&mmdc1->mpdgctrl0)); - debug("\tMPDGCTRL1 PHY1 = 0x%08X\n", readl(&mmdc1->mpdgctrl1)); + if (sysinfo->dsize == 2) { + debug("\tMPDGCTRL0 PHY1 = 0x%08X\n", readl(&mmdc1->mpdgctrl0)); + debug("\tMPDGCTRL1 PHY1 = 0x%08X\n", readl(&mmdc1->mpdgctrl1)); + } debug("Read calibration:\n"); debug("\tMPRDDLCTL PHY0 = 0x%08X\n", readl(&mmdc0->mprddlctl)); - debug("\tMPRDDLCTL PHY1 = 0x%08X\n", readl(&mmdc1->mprddlctl)); + if (sysinfo->dsize == 2) + debug("\tMPRDDLCTL PHY1 = 0x%08X\n", readl(&mmdc1->mprddlctl)); debug("Write calibration:\n"); debug("\tMPWRDLCTL PHY0 = 0x%08X\n", readl(&mmdc0->mpwrdlctl)); - debug("\tMPWRDLCTL PHY1 = 0x%08X\n", readl(&mmdc1->mpwrdlctl)); + if (sysinfo->dsize == 2) + debug("\tMPWRDLCTL PHY1 = 0x%08X\n", readl(&mmdc1->mpwrdlctl)); /* * Registers below are for debugging purposes. These print out @@ -548,22 +565,28 @@ int mmdc_do_dqs_calibration(struct mx6_mmdc_calibration *calib) debug("\tMPDGHWST1 PHY0 = 0x%08x\n", readl(&mmdc0->mpdghwst1)); debug("\tMPDGHWST2 PHY0 = 0x%08x\n", readl(&mmdc0->mpdghwst2)); debug("\tMPDGHWST3 PHY0 = 0x%08x\n", readl(&mmdc0->mpdghwst3)); - debug("\tMPDGHWST0 PHY1 = 0x%08x\n", readl(&mmdc1->mpdghwst0)); - debug("\tMPDGHWST1 PHY1 = 0x%08x\n", readl(&mmdc1->mpdghwst1)); - debug("\tMPDGHWST2 PHY1 = 0x%08x\n", readl(&mmdc1->mpdghwst2)); - debug("\tMPDGHWST3 PHY1 = 0x%08x\n", readl(&mmdc1->mpdghwst3)); + if (sysinfo->dsize == 2) { + debug("\tMPDGHWST0 PHY1 = 0x%08x\n", readl(&mmdc1->mpdghwst0)); + debug("\tMPDGHWST1 PHY1 = 0x%08x\n", readl(&mmdc1->mpdghwst1)); + debug("\tMPDGHWST2 PHY1 = 0x%08x\n", readl(&mmdc1->mpdghwst2)); + debug("\tMPDGHWST3 PHY1 = 0x%08x\n", readl(&mmdc1->mpdghwst3)); + } debug("Final do_dqs_calibration error mask: 0x%x\n", errors); if (calib) { calib->p0_mpdgctrl0 = readl(&mmdc0->mpdgctrl0); calib->p0_mpdgctrl1 = readl(&mmdc0->mpdgctrl1); - calib->p1_mpdgctrl0 = readl(&mmdc1->mpdgctrl0); - calib->p1_mpdgctrl1 = readl(&mmdc1->mpdgctrl1); + if (sysinfo->dsize == 2) { + calib->p1_mpdgctrl0 = readl(&mmdc1->mpdgctrl0); + calib->p1_mpdgctrl1 = readl(&mmdc1->mpdgctrl1); + } calib->p0_mprddlctl = readl(&mmdc0->mprddlctl); - calib->p1_mprddlctl = readl(&mmdc1->mprddlctl); + if (sysinfo->dsize == 2) + calib->p1_mprddlctl = readl(&mmdc1->mprddlctl); calib->p0_mpwrdlctl = readl(&mmdc0->mpwrdlctl); - calib->p1_mpwrdlctl = readl(&mmdc1->mpwrdlctl); + if (sysinfo->dsize == 2) + calib->p1_mpwrdlctl = readl(&mmdc1->mpwrdlctl); } return errors; } diff --git a/arch/arm/include/asm/arch-mx6/mx6-ddr.h b/arch/arm/include/asm/arch-mx6/mx6-ddr.h index 948862c..41adacf 100644 --- a/arch/arm/include/asm/arch-mx6/mx6-ddr.h +++ b/arch/arm/include/asm/arch-mx6/mx6-ddr.h @@ -457,8 +457,10 @@ void mx6sl_dram_iocfg(unsigned width, const struct mx6sl_iomux_grp_regs *); #if defined(CONFIG_MX6QDL) || defined(CONFIG_MX6Q) || defined(CONFIG_MX6D) -int mmdc_do_write_level_calibration(struct mx6_mmdc_calibration *calib); -int mmdc_do_dqs_calibration(struct mx6_mmdc_calibration *calib); +int mmdc_do_write_level_calibration(struct mx6_ddr_sysinfo const *sysinfo, + struct mx6_mmdc_calibration *calib); +int mmdc_do_dqs_calibration(struct mx6_ddr_sysinfo const *sysinfo, + struct mx6_mmdc_calibration *calib); #endif /* configure mx6 mmdc registers */