From patchwork Fri Jun 23 07:12:28 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: xiaolei li X-Patchwork-Id: 9805807 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 6437B600C5 for ; Fri, 23 Jun 2017 07:14:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 539A12870D for ; Fri, 23 Jun 2017 07:14:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 47D1C2872A; Fri, 23 Jun 2017 07:14:01 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id A52792870D for ; Fri, 23 Jun 2017 07:14:00 +0000 (UTC) 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:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version: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=n2s45k/sx0ne/7tefWl6GBppDMn8ctLcxxxtxkjNE3w=; b=NDiPZM+jhEwT/C Ts2ZRFwbViC6EwWIDXf68sRLCTT3SOBLgu9cZDwfbCiM1ikf8yPTrsnBqBvxEI5UD+vyPlhXlAVtS PYh5xE/hi1VpBxeS2IgVfSCPR6ooS5jNbfYndLur4QbtQtKmQq7h0O87KvrKjmnbbwbGgCcxh8pv6 Xi5ruQ+8Fiq1aWP61nms8Io6UWJOZKwuSzdIvo6HwiEoD2NikxgJ0smlWob+BbsdoLAxu2hIHfx2g XebvZ4BLE+9obxUaH/DRzRwCpGDMpz0JUMzQT0dQK6tvME1UjWnkSg7nj8nDZXRZAN8q+OlYeYsk/ 2js23JQ28UmK+X8s2rpw==; 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 1dOIn2-00068Z-2q; Fri, 23 Jun 2017 07:14:00 +0000 Received: from [210.61.82.183] (helo=mailgw01.mediatek.com) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1dOImD-00050F-Gs; Fri, 23 Jun 2017 07:13:14 +0000 Received: from mtkcas06.mediatek.inc [(172.21.101.30)] by mailgw01.mediatek.com (envelope-from ) (mhqrelay.mediatek.com ESMTP with TLS) with ESMTP id 1356485173; Fri, 23 Jun 2017 15:12:43 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs03n2.mediatek.inc (172.21.101.182) with Microsoft SMTP Server (TLS) id 15.0.1210.3; Fri, 23 Jun 2017 15:12:40 +0800 Received: from mtkslt306.mediatek.inc (10.21.14.136) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1210.3 via Frontend Transport; Fri, 23 Jun 2017 15:12:40 +0800 From: Xiaolei Li To: , Subject: [PATCH 5/5] mtd: nand: mtk: add ->setup_data_interface() hook Date: Fri, 23 Jun 2017 15:12:28 +0800 Message-ID: <1498201948-39088-6-git-send-email-xiaolei.li@mediatek.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1498201948-39088-1-git-send-email-xiaolei.li@mediatek.com> References: <1498201948-39088-1-git-send-email-xiaolei.li@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170623_001309_790056_3702C804 X-CRM114-Status: GOOD ( 15.31 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: srv_heupstream@mediatek.com, bayi.cheng@mediatek.com, jie.wu@mediatek.com, linux-mediatek@lists.infradead.org, matthias.bgg@gmail.com, linux-mtd@lists.infradead.org, xiaolei.li@mediatek.com, rogercc.lin@mediatek.com Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Currently, we use the fixed ACC timing 0x10804211. This is not the best setting for each case. Actually, MTK NAND controller can adapt ACC timings dynamically according to nfi clock frequence. Implement the ->setup_data_interface() hook to optimize driver performance. Signed-off-by: Xiaolei Li --- drivers/mtd/nand/mtk_nand.c | 90 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 15 deletions(-) diff --git a/drivers/mtd/nand/mtk_nand.c b/drivers/mtd/nand/mtk_nand.c index d51c58e..f7ae994 100644 --- a/drivers/mtd/nand/mtk_nand.c +++ b/drivers/mtd/nand/mtk_nand.c @@ -100,11 +100,15 @@ #define MTK_MAX_SECTOR (16) #define MTK_NAND_MAX_NSELS (2) #define MTK_NFC_MIN_SPARE (16) +#define ACCTIMING(tpoecs, tprecs, tc2r, tw2r, twh, twst, trlt) \ + ((tpoecs) << 28 | (tprecs) << 22 | (tc2r) << 16 | \ + (tw2r) << 12 | (twh) << 8 | (twst) << 4 | (trlt)) struct mtk_nfc_caps { const u8 *spare_size; u8 num_spare_size; u8 pageformat_spare_shift; + u8 nfi_clk_div; }; struct mtk_nfc_bad_mark_ctl { @@ -495,6 +499,74 @@ static void mtk_nfc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) mtk_nfc_write_byte(mtd, buf[i]); } +static int mtk_nfc_setup_data_interface(struct mtd_info *mtd, int csline, + const struct nand_data_interface *conf) +{ + struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd)); + const struct nand_sdr_timings *timings; + u32 rate, tpoecs, tprecs, tc2r, tw2r, twh, twst, trlt; + + timings = nand_get_sdr_timings(conf); + if (IS_ERR(timings)) + return -ENOTSUPP; + + if (csline == NAND_DATA_IFACE_CHECK_ONLY) + return 0; + + rate = clk_get_rate(nfc->clk.nfi_clk); + /* There is a frequency divider in some IPs */ + rate /= nfc->caps->nfi_clk_div; + + /* turn clock rate into KHZ */ + rate /= 1000; + + tpoecs = max(timings->tALH_min, timings->tCLH_min) / 1000; + tpoecs = DIV_ROUND_UP(tpoecs * rate, 1000000); + tpoecs &= 0xf; + + tprecs = max(timings->tCLS_min, timings->tALS_min) / 1000; + tprecs = DIV_ROUND_UP(tprecs * rate, 1000000); + tprecs &= 0x3f; + + /* sdr interface has no tCR which means CE# low to RE# low */ + tc2r = 0; + + tw2r = timings->tWHR_min / 1000; + tw2r = DIV_ROUND_UP(tw2r * rate, 1000000); + tw2r = DIV_ROUND_UP(tw2r - 1, 2); + tw2r &= 0xf; + + twh = max(timings->tREH_min, timings->tWH_min) / 1000; + twh = DIV_ROUND_UP(twh * rate, 1000000) - 1; + twh &= 0xf; + + twst = timings->tWP_min / 1000; + twst = DIV_ROUND_UP(twst * rate, 1000000) - 1; + twst &= 0xf; + + trlt = max(timings->tREA_max, timings->tRP_min) / 1000; + trlt = DIV_ROUND_UP(trlt * rate, 1000000) - 1; + trlt &= 0xf; + + /* + * ACCON: access timing control register + * ------------------------------------- + * 31:28: tpoecs, minimum required time for CS post pulling down after + * accessing the device + * 27:22: tprecs, minimum required time for CS pre pulling down before + * accessing the device + * 21:16: tc2r, minimum required time from NCEB low to NREB low + * 15:12: tw2r, minimum required time from NWEB high to NREB low. + * 11:08: twh, write enable hold time + * 07:04: twst, write wait states + * 03:00: trlt, read wait states + */ + trlt = ACCTIMING(tpoecs, tprecs, tc2r, tw2r, twh, twst, trlt); + nfi_writel(nfc, trlt, NFI_ACCCON); + + return 0; +} + static int mtk_nfc_sector_encode(struct nand_chip *chip, u8 *data) { struct mtk_nfc *nfc = nand_get_controller_data(chip); @@ -952,21 +1024,6 @@ static int mtk_nfc_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, static inline void mtk_nfc_hw_init(struct mtk_nfc *nfc) { /* - * ACCON: access timing control register - * ------------------------------------- - * 31:28: minimum required time for CS post pulling down after accessing - * the device - * 27:22: minimum required time for CS pre pulling down before accessing - * the device - * 21:16: minimum required time from NCEB low to NREB low - * 15:12: minimum required time from NWEB high to NREB low. - * 11:08: write enable hold time - * 07:04: write wait states - * 03:00: read wait states - */ - nfi_writel(nfc, 0x10804211, NFI_ACCCON); - - /* * CNRNB: nand ready/busy register * ------------------------------- * 7:4: timeout register for polling the NAND busy/ready signal @@ -1240,6 +1297,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc, nand->read_byte = mtk_nfc_read_byte; nand->read_buf = mtk_nfc_read_buf; nand->cmd_ctrl = mtk_nfc_cmd_ctrl; + nand->setup_data_interface = mtk_nfc_setup_data_interface; /* set default mode in case dt entry is missing */ nand->ecc.mode = NAND_ECC_HW; @@ -1330,12 +1388,14 @@ static int mtk_nfc_nand_chips_init(struct device *dev, struct mtk_nfc *nfc) .spare_size = spare_size_mt2701, .num_spare_size = 16, .pageformat_spare_shift = 4, + .nfi_clk_div = 1, }; static const struct mtk_nfc_caps mtk_nfc_caps_mt2712 = { .spare_size = spare_size_mt2712, .num_spare_size = 19, .pageformat_spare_shift = 16, + .nfi_clk_div = 2, }; static const struct of_device_id mtk_nfc_id_table[] = {