From patchwork Wed Dec 19 11:03:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 154249 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp4800136ljp; Wed, 19 Dec 2018 03:06:50 -0800 (PST) X-Google-Smtp-Source: AFSGD/XDJKc+7fGNJC2bMD/BqpdG/kCeE75o9Pj8Rj8WkzOwu7avD/xs9RyaSftt8Hfx4rTH4HdJ X-Received: by 2002:a17:906:2da2:: with SMTP id g2-v6mr12668157eji.189.1545217610173; Wed, 19 Dec 2018 03:06:50 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1545217610; cv=none; d=google.com; s=arc-20160816; b=IEgbDIz4Osef5W2cC8+2nU34wn2KR9ckBEYqj4sNTXJUep9YT8n413vQhEmcOGcE1c 8MQr+a/meM3m+C43IGHIFTyEXPKz5hv2J7j5Q9Q1BAJ7HO+X7jt/PMcw4banw1pdBGHy 9tnNnSFx8l54pXpGht5CM7T0xD3OPe57Gwamg0ugrGIq9gsFJYGxy+sa1ElVTSj/1BGY rCd8WGINF9eQ+4Dvd3ITTYDzChfYY4EcdXVrRQi2ShUxAO2se2IUKErX93IVBznKDDm9 Cj+fwcgTMGvuiBGP33VfSExRlk3cmZIBif4R2CeJcjzoz2WdujsVWYjXjb4OuBLAuM0w 9X+g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:dkim-signature:dkim-filter; bh=SyHgNhQn+iErSuv3YmmVa4uqdC5KYjqDhPB/2vIHeMA=; b=PZWZLVcaXqKCWJ8ERgye+D2MpGGqtultuIKizBBtCKja5Zorb3AxPFUQyCR1G0+sbE /jizXQvwiCShVhZ/ZJkPE8nmGW9ccvroOCqP1UNvJKXRHReIeSHSgUdaHPku8pI8PoU0 +XKQmrA/yK6AmEFctnP8fQblAOId3drW5J/RrIz7bhzYuQLN3LM9JCUFHbc2wX/pTF0Z Yw8tnV17qRnvd6dOZ0F3woK9run1vi7BB8KKRcvGYLrf/0hpiavrESIi4whkujqio24z yMkTrWwGIFj7tGbqk6a+dIzy1CdE3kG/z74eyh6RVk3OGt9STO+TWrLQAUIQnjnQEoDd eVFQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@nifty.com header.s=dec2015msa header.b=YlrpL4Oq; spf=pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de Return-Path: Received: from lists.denx.de (dione.denx.de. [81.169.180.215]) by mx.google.com with ESMTP id p37si4444134edc.272.2018.12.19.03.06.49; Wed, 19 Dec 2018 03:06:50 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) client-ip=81.169.180.215; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@nifty.com header.s=dec2015msa header.b=YlrpL4Oq; spf=pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by lists.denx.de (Postfix, from userid 105) id C1CDBC22026; Wed, 19 Dec 2018 11:04:27 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 86405C2201F; Wed, 19 Dec 2018 11:03:49 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id BCFBCC21EF2; Wed, 19 Dec 2018 11:03:47 +0000 (UTC) Received: from conuserg-09.nifty.com (conuserg-09.nifty.com [210.131.2.76]) by lists.denx.de (Postfix) with ESMTPS id C7213C21F8A for ; Wed, 19 Dec 2018 11:03:46 +0000 (UTC) Received: from pug.e01.socionext.com (p14092-ipngnfx01kyoto.kyoto.ocn.ne.jp [153.142.97.92]) (authenticated) by conuserg-09.nifty.com with ESMTP id wBJB3SMP001192; Wed, 19 Dec 2018 20:03:31 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-09.nifty.com wBJB3SMP001192 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.com; s=dec2015msa; t=1545217411; bh=hPo1VGk6rZSiFCXotbocQpvd6SsnuR9Vv3TDe1LKcEA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YlrpL4OqZsGstUAHgyVb89p6eTNNjfU97IWxCN7qWuzwfRClM70zdHwIy0RbppdV+ 21NqEAe/6nLodx4tGXpGvzP3Q5PuNPjeGKDnzhOTIHhZtLh7bn0CyD3surqSiLXylX X3RQK8oZ5YSZi1suhMUQ7WhLnfR+bf8KWJS/3cURap0mWG9Z9e/QndoJMRjtpUMDk9 QmC9DcDKHBBXTAAQB+Ikftz5Il1UK+rnKuK0KaLmEwJNGa7NebG/MPbW1hE7Fk6a3F 6GQcX2uGS6fpcNfLcAvprJrP7XrIVBHEmQ5K1PWAi8ddUZdHunCWgEQGZGoKAwdZqT tm7S3VPRQrU3A== X-Nifty-SrcIP: [153.142.97.92] From: Masahiro Yamada To: u-boot@lists.denx.de Date: Wed, 19 Dec 2018 20:03:18 +0900 Message-Id: <1545217401-27018-7-git-send-email-yamada.masahiro@socionext.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1545217401-27018-1-git-send-email-yamada.masahiro@socionext.com> References: <1545217401-27018-1-git-send-email-yamada.masahiro@socionext.com> Subject: [U-Boot] [PATCH 6/9] mtd: rawnand: denali: optimize timing parameters for data interface X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 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" Based on Linux commit 1dfac31a5a63ac04a9b5fbc3f5105a586560f191 This commit improves the ->setup_data_interface() hook. The denali_setup_data_interface() needs the frequency of clk_x and the ratio of clk_x / clk. The latter is currently hardcoded in the driver, like this: #define DENALI_CLK_X_MULT 6 The IP datasheet requires that clk_x / clk be 4, 5, or 6. I just chose 6 because it is the most defensive value, but it is not optimal. By getting the clock rate of both "clk" and "clk_x", the driver can compute the timing values more precisely. To not break the existing platforms, the fallback value, 50 MHz is provided. It is true for all upstreamed platforms. Signed-off-by: Masahiro Yamada --- drivers/mtd/nand/raw/denali.c | 47 ++++++++++++++++++++-------------------- drivers/mtd/nand/raw/denali.h | 1 + drivers/mtd/nand/raw/denali_dt.c | 2 ++ 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c index d1cac06..bbfa3b6 100644 --- a/drivers/mtd/nand/raw/denali.c +++ b/drivers/mtd/nand/raw/denali.c @@ -69,14 +69,6 @@ static int dma_mapping_error(void *dev, dma_addr_t addr) #define DENALI_INVALID_BANK -1 #define DENALI_NR_BANKS 4 -/* - * The bus interface clock, clk_x, is phase aligned with the core clock. The - * clk_x is an integral multiple N of the core clk. The value N is configured - * at IP delivery time, and its available value is 4, 5, or 6. We need to align - * to the largest value to make it work with any possible configuration. - */ -#define DENALI_CLK_X_MULT 6 - static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd) { return container_of(mtd_to_nand(mtd), struct denali_nand_info, nand); @@ -946,7 +938,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, { struct denali_nand_info *denali = mtd_to_denali(mtd); const struct nand_sdr_timings *timings; - unsigned long t_clk; + unsigned long t_x, mult_x; int acc_clks, re_2_we, re_2_re, we_2_re, addr_2_data; int rdwr_en_lo, rdwr_en_hi, rdwr_en_lo_hi, cs_setup; int addr_2_data_mask; @@ -957,15 +949,24 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, return PTR_ERR(timings); /* clk_x period in picoseconds */ - t_clk = DIV_ROUND_DOWN_ULL(1000000000000ULL, denali->clk_x_rate); - if (!t_clk) + t_x = DIV_ROUND_DOWN_ULL(1000000000000ULL, denali->clk_x_rate); + if (!t_x) + return -EINVAL; + + /* + * The bus interface clock, clk_x, is phase aligned with the core clock. + * The clk_x is an integral multiple N of the core clk. The value N is + * configured at IP delivery time, and its available value is 4, 5, 6. + */ + mult_x = DIV_ROUND_CLOSEST_ULL(denali->clk_x_rate, denali->clk_rate); + if (mult_x < 4 || mult_x > 6) return -EINVAL; if (chipnr == NAND_DATA_IFACE_CHECK_ONLY) return 0; /* tREA -> ACC_CLKS */ - acc_clks = DIV_ROUND_UP(timings->tREA_max, t_clk); + acc_clks = DIV_ROUND_UP(timings->tREA_max, t_x); acc_clks = min_t(int, acc_clks, ACC_CLKS__VALUE); tmp = ioread32(denali->reg + ACC_CLKS); @@ -974,7 +975,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, iowrite32(tmp, denali->reg + ACC_CLKS); /* tRWH -> RE_2_WE */ - re_2_we = DIV_ROUND_UP(timings->tRHW_min, t_clk); + re_2_we = DIV_ROUND_UP(timings->tRHW_min, t_x); re_2_we = min_t(int, re_2_we, RE_2_WE__VALUE); tmp = ioread32(denali->reg + RE_2_WE); @@ -983,7 +984,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, iowrite32(tmp, denali->reg + RE_2_WE); /* tRHZ -> RE_2_RE */ - re_2_re = DIV_ROUND_UP(timings->tRHZ_max, t_clk); + re_2_re = DIV_ROUND_UP(timings->tRHZ_max, t_x); re_2_re = min_t(int, re_2_re, RE_2_RE__VALUE); tmp = ioread32(denali->reg + RE_2_RE); @@ -997,8 +998,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, * With WE_2_RE properly set, the Denali controller automatically takes * care of the delay; the driver need not set NAND_WAIT_TCCS. */ - we_2_re = DIV_ROUND_UP(max(timings->tCCS_min, timings->tWHR_min), - t_clk); + we_2_re = DIV_ROUND_UP(max(timings->tCCS_min, timings->tWHR_min), t_x); we_2_re = min_t(int, we_2_re, TWHR2_AND_WE_2_RE__WE_2_RE); tmp = ioread32(denali->reg + TWHR2_AND_WE_2_RE); @@ -1013,7 +1013,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, if (denali->revision < 0x0501) addr_2_data_mask >>= 1; - addr_2_data = DIV_ROUND_UP(timings->tADL_min, t_clk); + addr_2_data = DIV_ROUND_UP(timings->tADL_min, t_x); addr_2_data = min_t(int, addr_2_data, addr_2_data_mask); tmp = ioread32(denali->reg + TCWAW_AND_ADDR_2_DATA); @@ -1023,7 +1023,7 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, /* tREH, tWH -> RDWR_EN_HI_CNT */ rdwr_en_hi = DIV_ROUND_UP(max(timings->tREH_min, timings->tWH_min), - t_clk); + t_x); rdwr_en_hi = min_t(int, rdwr_en_hi, RDWR_EN_HI_CNT__VALUE); tmp = ioread32(denali->reg + RDWR_EN_HI_CNT); @@ -1032,11 +1032,10 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, iowrite32(tmp, denali->reg + RDWR_EN_HI_CNT); /* tRP, tWP -> RDWR_EN_LO_CNT */ - rdwr_en_lo = DIV_ROUND_UP(max(timings->tRP_min, timings->tWP_min), - t_clk); + rdwr_en_lo = DIV_ROUND_UP(max(timings->tRP_min, timings->tWP_min), t_x); rdwr_en_lo_hi = DIV_ROUND_UP(max(timings->tRC_min, timings->tWC_min), - t_clk); - rdwr_en_lo_hi = max(rdwr_en_lo_hi, DENALI_CLK_X_MULT); + t_x); + rdwr_en_lo_hi = max_t(int, rdwr_en_lo_hi, mult_x); rdwr_en_lo = max(rdwr_en_lo, rdwr_en_lo_hi - rdwr_en_hi); rdwr_en_lo = min_t(int, rdwr_en_lo, RDWR_EN_LO_CNT__VALUE); @@ -1046,8 +1045,8 @@ static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, iowrite32(tmp, denali->reg + RDWR_EN_LO_CNT); /* tCS, tCEA -> CS_SETUP_CNT */ - cs_setup = max3((int)DIV_ROUND_UP(timings->tCS_min, t_clk) - rdwr_en_lo, - (int)DIV_ROUND_UP(timings->tCEA_max, t_clk) - acc_clks, + cs_setup = max3((int)DIV_ROUND_UP(timings->tCS_min, t_x) - rdwr_en_lo, + (int)DIV_ROUND_UP(timings->tCEA_max, t_x) - acc_clks, 0); cs_setup = min_t(int, cs_setup, CS_SETUP_CNT__VALUE); diff --git a/drivers/mtd/nand/raw/denali.h b/drivers/mtd/nand/raw/denali.h index 9b797be..019deda 100644 --- a/drivers/mtd/nand/raw/denali.h +++ b/drivers/mtd/nand/raw/denali.h @@ -292,6 +292,7 @@ struct udevice; struct denali_nand_info { struct nand_chip nand; + unsigned long clk_rate; /* core clock rate */ unsigned long clk_x_rate; /* bus interface clock rate */ int active_bank; /* currently selected bank */ struct udevice *dev; diff --git a/drivers/mtd/nand/raw/denali_dt.c b/drivers/mtd/nand/raw/denali_dt.c index f9eadb4..d384b97 100644 --- a/drivers/mtd/nand/raw/denali_dt.c +++ b/drivers/mtd/nand/raw/denali_dt.c @@ -118,6 +118,7 @@ static int denali_dt_probe(struct udevice *dev) } if (clk_x.dev) { + denali->clk_rate = clk_get_rate(&clk); denali->clk_x_rate = clk_get_rate(&clk_x); } else { /* @@ -126,6 +127,7 @@ static int denali_dt_probe(struct udevice *dev) */ dev_notice(dev, "necessary clock is missing. default clock rates are used.\n"); + denali->clk_rate = 50000000; denali->clk_x_rate = 200000000; }