From patchwork Tue Mar 21 10:03:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Petazzoni X-Patchwork-Id: 741476 X-Patchwork-Delegate: boris.brezillon@free-electrons.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3vnT3P4z6Gz9s2x for ; Tue, 21 Mar 2017 21:05:53 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="SX7J2e3c"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=WsCKIAeIlfmglmFu5a8gHZ/GDc40q3qauYHtzp3SmQk=; b=SX7J2e3cYEi/LVfM2TwLXv0Gkf I+QBTEf8+xf4Q00PcRDBZF+/NDVmbLOUUDMHKxz5bScRlcrIFH+nwiUrmCl4oEHMa2+5hP9HtpjIZ H9HgGHYqpS6ODobMtenq2gmErDa9Svmpf5fqKD7K8vez6KJPB7a21LnJmka3uCCF1ofdBH+Gs2eDp vPvFIhEgcPQivEbE5CjsbVZ9PXlofZpEfUADZFEn+y3i8Ud3/7cCjzeBgUo5RxNExcw4U6svBRm7A BWkoL2QgNjc+wedFqKnRdwS/nUKoSUjE7OK44gyArvwHUlAkwbBOJyt1zo+ENSxuB3GJYMfaTdDkg +tOqXDVQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cqGfi-0002es-Uj; Tue, 21 Mar 2017 10:05:46 +0000 Received: from mail.free-electrons.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cqGej-0000NU-TM for linux-mtd@lists.infradead.org; Tue, 21 Mar 2017 10:04:50 +0000 Received: by mail.free-electrons.com (Postfix, from userid 110) id 021482081F; Tue, 21 Mar 2017 11:04:24 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.free-electrons.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost (LStLambert-657-1-97-87.w90-63.abo.wanadoo.fr [90.63.216.87]) by mail.free-electrons.com (Postfix) with ESMTPSA id D1777207ED; Tue, 21 Mar 2017 11:04:23 +0100 (CET) From: Thomas Petazzoni To: Boris Brezillon , Richard Weinberger , David Woodhouse , Brian Norris , Marek Vasut , Cyrille Pitchen Subject: [PATCH 03/13] mtd: nand: fsmc: add support to use NAND timings Date: Tue, 21 Mar 2017 11:03:55 +0100 Message-Id: <1490090645-8576-4-git-send-email-thomas.petazzoni@free-electrons.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490090645-8576-1-git-send-email-thomas.petazzoni@free-electrons.com> References: <1490090645-8576-1-git-send-email-thomas.petazzoni@free-electrons.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170321_030446_248859_5DF8503A X-CRM114-Status: GOOD ( 17.90 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record -0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Petazzoni , Linus Walleij , Stefan Roese , linux-mtd@lists.infradead.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Until now, the fsmc_nand driver was either using controller timings specified in the Device Tree (through FSMC specific DT properties) or alternatively default/fallback timings. This commit implements support to use the timings advertised by the NAND chip itself, and passed by the NAND core to the ->setup_data_interface() callback. Many thanks to Boris Brezillon for coming up with the logic to convert the NAND chip timings into the timings expected by the FSMC controller. Also, since the timings are now not only coming from the DT, the message warning that default timings will be used is removed. Signed-off-by: Thomas Petazzoni Reviewed-by: Linus Walleij --- drivers/mtd/nand/fsmc_nand.c | 78 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 4a98433..d2e85c6 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c @@ -364,6 +364,62 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) writeb_relaxed(cmd, this->IO_ADDR_W); } +static int fsmc_calc_timings(struct fsmc_nand_data *host, + const struct nand_sdr_timings *sdrt, + struct fsmc_nand_timings *tims) +{ + unsigned long hclk = clk_get_rate(host->clk); + unsigned long hclkn = NSEC_PER_SEC / hclk; + uint32_t thiz, thold, twait, tset; + + if (sdrt->tRC_min < 30000) + return -EOPNOTSUPP; + + tims->tar = DIV_ROUND_UP(sdrt->tAR_min / 1000, hclkn) - 1; + if (tims->tar > FSMC_TAR_MASK) + tims->tar = FSMC_TAR_MASK; + tims->tclr = DIV_ROUND_UP(sdrt->tCLR_min / 1000, hclkn) - 1; + if (tims->tclr > FSMC_TCLR_MASK) + tims->tclr = FSMC_TCLR_MASK; + + thiz = sdrt->tCS_min - sdrt->tWP_min; + tims->thiz = DIV_ROUND_UP(thiz / 1000, hclkn); + + thold = sdrt->tDH_min; + if (thold < sdrt->tCH_min) + thold = sdrt->tCH_min; + if (thold < sdrt->tCLH_min) + thold = sdrt->tCLH_min; + if (thold < sdrt->tWH_min) + thold = sdrt->tWH_min; + if (thold < sdrt->tALH_min) + thold = sdrt->tALH_min; + if (thold < sdrt->tREH_min) + thold = sdrt->tREH_min; + tims->thold = DIV_ROUND_UP(thold / 1000, hclkn); + if (tims->thold == 0) + tims->thold = 1; + else if (tims->thold > FSMC_THOLD_MASK) + tims->thold = FSMC_THOLD_MASK; + + twait = max(sdrt->tRP_min, sdrt->tWP_min); + tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1; + if (tims->twait == 0) + tims->twait = 1; + else if (tims->twait > FSMC_TWAIT_MASK) + tims->twait = FSMC_TWAIT_MASK; + + tset = max(sdrt->tCS_min - sdrt->tWP_min, + sdrt->tCEA_max - sdrt->tREA_max); + tims->tset = DIV_ROUND_UP(tset / 1000, hclkn) - 1; + if (tims->tset == 0) + tims->tset = 1; + else if (tims->tset > FSMC_TSET_MASK) + tims->tset = FSMC_TSET_MASK; + + return 0; +} + /* * fsmc_nand_setup - FSMC (Flexible Static Memory Controller) init routine * @@ -387,14 +443,26 @@ static int fsmc_setup_data_interface(struct mtd_info *mtd, .twait = FSMC_TWAIT_6, .tset = FSMC_TSET_0, }; + struct fsmc_nand_timings nand_timings; unsigned int bank = host->bank; void __iomem *regs = host->regs_va; int ret; - if (host->dev_timings) + if (host->dev_timings) { tims = host->dev_timings; - else - tims = &default_timings; + } else { + const struct nand_sdr_timings *sdrt; + + sdrt = nand_get_sdr_timings(conf); + if (IS_ERR(sdrt)) { + tims = &default_timings; + } else { + ret = fsmc_calc_timings(host, sdrt, &nand_timings); + if (ret) + return ret; + tims = &nand_timings; + } + } if (check_only) return 0; @@ -874,10 +942,8 @@ static int fsmc_nand_probe_config_dt(struct platform_device *pdev, return -ENOMEM; ret = of_property_read_u8_array(np, "timings", (u8 *)pdata->nand_timings, sizeof(*pdata->nand_timings)); - if (ret) { - dev_info(&pdev->dev, "No timings in dts specified, using default timings!\n"); + if (ret) pdata->nand_timings = NULL; - } /* Set default NAND bank to 0 */ pdata->bank = 0;