From patchwork Fri Apr 20 08:19:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Lefebvre X-Patchwork-Id: 901781 X-Patchwork-Delegate: boris.brezillon@free-electrons.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=essensium.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="JQEiE5NI"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=infradead.org header.i=@infradead.org header.b="P0oxFfCY"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=essensium-com.20150623.gappssmtp.com header.i=@essensium-com.20150623.gappssmtp.com header.b="R2+Fmher"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 40S8WV6dhHz9s1w for ; Fri, 20 Apr 2018 18:43:02 +1000 (AEST) 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=tynM8OJqdHS58I/hkGHX1j8Mz1cosXGHGpOFD4EALAI=; b=JQEiE5NIY0KFzKTZmlIeUAnMe2 gifDPlVaRK5dIDjtm7F8NPtcH9Pn1TBh92ytOF3LgkRek8MtP2mOJAegyenFEgwxngEN00EH95/Lf b9u7Ux/xqh+p9rJzEkXxyyVjhWcfRpK8b7msX9kerdcQTr5OhzMgzyQ5syGGjxXXJkaK2XkPAPDMD R3Al0ezBPeqjQ0+1Envy9iSSvhKD3dRv/kMTc8KlUtwI23WlkQI1NkIujZgSooals2HLw06sc161c d6Rh3UEcBVGweySYQ+wuElSLL783pPvrBkeWtGKXRLznOklQ2Gkab6KXsamN7sfkc/vxUijQSmYkg cb5L2e1w==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1f9Rd7-00023e-F9; Fri, 20 Apr 2018 08:42:53 +0000 Received: from merlin.infradead.org ([2001:8b0:10b:1231::1]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1f9RNE-0007sA-Pd for linux-mtd@bombadil.infradead.org; Fri, 20 Apr 2018 08:26:29 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=MmQh88UNlXPi/jfuc9deTzYpxooZvRs1aQOPb5HIspc=; b=P0oxFfCYcuEuNqnJeb2DeJ90T OisPGc7o2W3dGWuGnhEFKEhkSy7KhmmO7VgFuvc+WJLJB0sSmpZgUf/giSTsOAEvQYVXHiyX5dKxq x7Bmui3Kw/g4gQP6USElvVKoQY9Hye69HBtiAfBqg6wETGYUhqoBL1o7bZugJyg/udSPiS4eeIOQv W8w4Pi/P1+ItGpxGs4hlf1f/ZM2pEKbB+G+GxLHRhO7Pt7Zngu50UB/UP+uFpwDs5mBkDZ8hsG5wW RGG/MA4JVL6Jld6clZ58P8gmyuJ879Di+GeP0UKnoAAogTGWVeGkcSV5rdlSiizqYR47mmB6P7T3G VOm7/FrIg==; Received: from mail-wr0-x241.google.com ([2a00:1450:400c:c0c::241]) by merlin.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1f9RNA-0001zQ-U5 for linux-mtd@lists.infradead.org; Fri, 20 Apr 2018 08:26:26 +0000 Received: by mail-wr0-x241.google.com with SMTP id v15-v6so2563441wrm.10 for ; Fri, 20 Apr 2018 01:26:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=essensium-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=MmQh88UNlXPi/jfuc9deTzYpxooZvRs1aQOPb5HIspc=; b=R2+Fmherrzakq7PTN7iigoBhIVfYcxj2bBrbXpEco0bqCCIpLFtbGmdNWZjcOVfsGF B4cejDpl1qYOM9/o98NXxTaEZPqQJAiuzd9Xxknk0dj+ubwNHTCDPMxdC8P8bQMTwuJT Z7PpZIXRZmdxvUHZibyQsTnsssOuQtZCUgsuE6zOF0aEzRl87W3fiQsHCwidpaHkiCqY 9iY7dvrgkvlIVIbc+15SZraoZlCPf0+comGsBJpfrB+EkRdNrnN1DIsMIzeDgATcWxLE Ky2VoD4AAdhNLHmlAPHrj/JRCCkyBfLv+KjDiYln4UFSw4hMhF804mV6pQqRMc1PccAx 4AKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=MmQh88UNlXPi/jfuc9deTzYpxooZvRs1aQOPb5HIspc=; b=b+vthcnSij3GjZvf4qHJLfqyls9Yujqg6x/7uqa2G6Oz4XYyW1xnj9B+Yr4CjzlRz3 2mifedUHuICDfSecePRWLSleXifiIzrGkpYJU7weuOfDnn3j3TZ7Km1uUYbYvGswoC9w WT3E+21dozmcTsqVbnyid+mUEZfcbCUFd08pj2NN4RDptU+drsWxOWABYHjOaKP/nBms iHdQTSrQ3Uvn5ybrZo4KToFP1rxLu3I+hZJyPxVDL3GHAtkVKObJagD1K/GCOw+3pjwr DpKwU0ppO22/wwaSW8apP+NV6jTZjpay9yY65+wv14ZeBodxMmpO6gR00Xvuti4LsMJv /QHQ== X-Gm-Message-State: ALQs6tA2F02Zkh5G8o5d9DrxcUvDMQQUq8JEPETV1B3b7s9BQr6Hgqj3 OOYjJ+RmpG+OLVlQ9Gaop9QLtuvi X-Google-Smtp-Source: AIpwx4/8y3dei6Jnojp/tQ4q8tZ0Q5o3MaUUlCLKMXunPICBec4dl+EHuHYA62QZoMe9DEsI3hKOog== X-Received: by 2002:adf:e549:: with SMTP id z9-v6mr1044172wrm.186.1524212769399; Fri, 20 Apr 2018 01:26:09 -0700 (PDT) Received: from Darth.local.ess-mail.com (178-118-196-9.access.telenet.be. [178.118.196.9]) by smtp.gmail.com with ESMTPSA id e64sm1834235wmg.22.2018.04.20.01.26.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 20 Apr 2018 01:26:08 -0700 (PDT) From: Sam Lefebvre To: linux-mtd@lists.infradead.org Subject: [PATCH 10/18] mtd: rawnand: factor nand_command_lp() into nand_command() Date: Fri, 20 Apr 2018 10:19:38 +0200 Message-Id: <20180420081946.16088-11-sam.lefebvre@essensium.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20180420081946.16088-1-sam.lefebvre@essensium.com> References: <20180420081946.16088-1-sam.lefebvre@essensium.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180420_042625_119205_02AF7A32 X-CRM114-Status: GOOD ( 31.71 ) X-Spam-Score: 1.0 (+) X-Spam-Report: SpamAssassin version 3.4.1 on merlin.infradead.org summary: Content analysis details: (1.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2a00:1450:400c:c0c:0:0:0:241 listed in] [list.dnswl.org] 1.0 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.0 T_DKIMWL_WL_MED DKIMwl.org - Whitelisted Medium sender 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: Han Xu , Sam Lefebvre , "Arnout Vandecappelle \(Essensium/Mind\)" MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: "Arnout Vandecappelle (Essensium/Mind)" The nand_command() and nand_command_lp() functions are very similar. Factor them into a single function, and use conditions on writesize to identify the differences. is_lp checks are added everywhere to make sure the behaviour is exactly the same as before. Most likely, the checks in CACHEDPROG, RNDIN and RNDOUT are not needed since these commands are only valid for LP devices. But since I'm not sure of that, I'm leaving it as is. The only side effect of this patch is that the large-page behaviour is activated a little bit earlier: as soon as writesize is set. However, only SEQIN, READOOB, READ0, CACHEDPROG, RNDIN and RNDOUT behave differently between small and large page. Of these, only RNDOUT is used in nand_detect(). RNDOUT is used by nand_change_read_column_op() which is called by nand_flash_detect_ext_param_page(). Before this patch, the switch to nand_command_lp was already made just before calling that function so the behaviour doesn't change. Signed-off-by: Arnout Vandecappelle (Essensium/Mind) --- Note that I don't have access to a small-page device, so only tested on large-page devices. Also only tested on i.MX6Q (gpmi-nand). I only verified the lack of change in behaviour during nand_detect by reading the code, so it's possible that I missed something. Testing on various devices (ONFI, JEDEC, non-ONFI/JEDEC) is needed to be really sure that nothing breaks. Note that this patch can be removed from the series without affecting the rest. --- drivers/mtd/nand/raw/nand_base.c | 236 ++++++++++++--------------------------- 1 file changed, 70 insertions(+), 166 deletions(-) diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index bcc0344b1f27..320efbe41bd6 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -747,121 +747,6 @@ int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms) }; EXPORT_SYMBOL_GPL(nand_soft_waitrdy); -/** - * nand_command - [DEFAULT] Send command to NAND device - * @mtd: MTD device structure - * @command: the command to be sent - * @column: the column address for this command, -1 if none - * @page_addr: the page address for this command, -1 if none - * - * Send command to NAND device. This function is used for small page devices - * (512 Bytes per page). - */ -static void nand_command(struct mtd_info *mtd, unsigned int command, - int column, int page_addr) -{ - register struct nand_chip *chip = mtd_to_nand(mtd); - int ctrl = NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE; - - /* Write out the command to the device */ - if (command == NAND_CMD_SEQIN) { - int readcmd; - - if (column >= mtd->writesize) { - /* OOB area */ - column -= mtd->writesize; - readcmd = NAND_CMD_READOOB; - } else if (column < 256) { - /* First 256 bytes --> READ0 */ - readcmd = NAND_CMD_READ0; - } else { - column -= 256; - readcmd = NAND_CMD_READ1; - } - chip->cmd_ctrl(mtd, readcmd, ctrl); - ctrl &= ~NAND_CTRL_CHANGE; - } - if (command != NAND_CMD_NONE) - chip->cmd_ctrl(mtd, command, ctrl); - - /* Address cycle, when necessary */ - ctrl = NAND_NCE | NAND_ALE | NAND_CTRL_CHANGE; - /* Serially input address */ - if (column != -1) { - /* Adjust columns for 16 bit buswidth */ - if (chip->options & NAND_BUSWIDTH_16 && - !nand_opcode_8bits(command)) - column >>= 1; - chip->cmd_ctrl(mtd, column, ctrl); - ctrl &= ~NAND_CTRL_CHANGE; - } - if (page_addr != -1) { - chip->cmd_ctrl(mtd, page_addr, ctrl); - ctrl &= ~NAND_CTRL_CHANGE; - chip->cmd_ctrl(mtd, page_addr >> 8, ctrl); - if (chip->options & NAND_ROW_ADDR_3) - chip->cmd_ctrl(mtd, page_addr >> 16, ctrl); - } - chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); - - /* - * Program and erase have their own busy handlers status and sequential - * in needs no delay - */ - switch (command) { - - case NAND_CMD_NONE: - case NAND_CMD_PAGEPROG: - case NAND_CMD_ERASE1: - case NAND_CMD_ERASE2: - case NAND_CMD_SEQIN: - case NAND_CMD_STATUS: - case NAND_CMD_READID: - case NAND_CMD_SET_FEATURES: - return; - - case NAND_CMD_RESET: - if (chip->dev_ready) - break; - udelay(chip->chip_delay); - chip->cmd_ctrl(mtd, NAND_CMD_STATUS, - NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); - chip->cmd_ctrl(mtd, NAND_CMD_NONE, - NAND_NCE | NAND_CTRL_CHANGE); - /* EZ-NAND can take upto 250ms as per ONFi v4.0 */ - nand_wait_status_ready(mtd, 250); - return; - - /* This applies to read commands */ - case NAND_CMD_READ0: - /* - * READ0 is sometimes used to exit GET STATUS mode. When this - * is the case no address cycles are requested, and we can use - * this information to detect that we should not wait for the - * device to be ready. - */ - if (column == -1 && page_addr == -1) - return; - - default: - /* - * If we don't have access to the busy pin, we apply the given - * command delay - */ - if (!chip->dev_ready) { - udelay(chip->chip_delay); - return; - } - } - /* - * Apply this short delay always to ensure that we do wait tWB in - * any case on any machine. - */ - ndelay(100); - - nand_wait_ready(mtd); -} - static void nand_ccs_delay(struct nand_chip *chip) { /* @@ -882,26 +767,48 @@ static void nand_ccs_delay(struct nand_chip *chip) } /** - * nand_command_lp - [DEFAULT] Send command to NAND large page device + * nand_command - [DEFAULT] Send command to NAND device * @mtd: MTD device structure * @command: the command to be sent * @column: the column address for this command, -1 if none * @page_addr: the page address for this command, -1 if none * - * Send command to NAND device. This is the version for the new large page - * devices. We don't have the separate regions as we have in the small page - * devices. We must emulate NAND_CMD_READOOB to keep the code compatible. + * Send command to NAND device. */ -static void nand_command_lp(struct mtd_info *mtd, unsigned int command, +static void nand_command(struct mtd_info *mtd, unsigned int command, int column, int page_addr) { register struct nand_chip *chip = mtd_to_nand(mtd); int ctrl = NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE; + /* Large page devices (> 512 bytes) behave slightly differently. */ + bool is_lp = mtd->writesize > 512; - /* Emulate NAND_CMD_READOOB */ - if (command == NAND_CMD_READOOB) { - column += mtd->writesize; - command = NAND_CMD_READ0; + if (is_lp) { + /* Large page devices don't have the separate regions as we + * have in the small page devices. We must emulate + * NAND_CMD_READOOB to keep the code compatible. + */ + if (command == NAND_CMD_READOOB) { + column += mtd->writesize; + command = NAND_CMD_READ0; + } + } else if (command == NAND_CMD_SEQIN) { + /* Write out the command to the device */ + int readcmd; + + if (column >= mtd->writesize) { + /* OOB area */ + column -= mtd->writesize; + readcmd = NAND_CMD_READOOB; + } else if (column < 256) { + /* First 256 bytes --> READ0 */ + readcmd = NAND_CMD_READ0; + } else { + column -= 256; + readcmd = NAND_CMD_READ1; + } + chip->cmd_ctrl(mtd, readcmd, ctrl); + ctrl &= ~NAND_CTRL_CHANGE; } /* Command latch cycle */ @@ -920,7 +827,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, ctrl &= ~NAND_CTRL_CHANGE; /* Only output a single addr cycle for 8bits opcodes. */ - if (!nand_opcode_8bits(command)) + if (is_lp && !nand_opcode_8bits(command)) chip->cmd_ctrl(mtd, column >> 8, ctrl); } if (page_addr != -1) { @@ -939,7 +846,6 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, switch (command) { case NAND_CMD_NONE: - case NAND_CMD_CACHEDPROG: case NAND_CMD_PAGEPROG: case NAND_CMD_ERASE1: case NAND_CMD_ERASE2: @@ -949,9 +855,17 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, case NAND_CMD_SET_FEATURES: return; + case NAND_CMD_CACHEDPROG: + if (is_lp) + return; + break; + case NAND_CMD_RNDIN: - nand_ccs_delay(chip); - return; + if (is_lp) { + nand_ccs_delay(chip); + return; + } + break; case NAND_CMD_RESET: if (chip->dev_ready) @@ -966,40 +880,44 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, return; case NAND_CMD_RNDOUT: - /* No ready / busy check necessary */ - chip->cmd_ctrl(mtd, NAND_CMD_RNDOUTSTART, - NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); - chip->cmd_ctrl(mtd, NAND_CMD_NONE, - NAND_NCE | NAND_CTRL_CHANGE); - - nand_ccs_delay(chip); - return; + if (is_lp) { + /* No ready / busy check necessary */ + chip->cmd_ctrl(mtd, NAND_CMD_RNDOUTSTART, + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); + chip->cmd_ctrl(mtd, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); + + nand_ccs_delay(chip); + return; + } + break; case NAND_CMD_READ0: /* * READ0 is sometimes used to exit GET STATUS mode. When this * is the case no address cycles are requested, and we can use - * this information to detect that READSTART should not be - * issued. + * this information to detect that that we should not wait for + * the device to be ready and READSTART should not be issued. */ if (column == -1 && page_addr == -1) return; - chip->cmd_ctrl(mtd, NAND_CMD_READSTART, - NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); - chip->cmd_ctrl(mtd, NAND_CMD_NONE, - NAND_NCE | NAND_CTRL_CHANGE); - - /* This applies to read commands */ - default: - /* - * If we don't have access to the busy pin, we apply the given - * command delay. - */ - if (!chip->dev_ready) { - udelay(chip->chip_delay); - return; + if (is_lp) { + chip->cmd_ctrl(mtd, NAND_CMD_READSTART, + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); + chip->cmd_ctrl(mtd, NAND_CMD_NONE, + NAND_NCE | NAND_CTRL_CHANGE); } + /* Read commands must wait */ + break; + } + /* + * If we don't have access to the busy pin, we apply the given command + * delay. + */ + if (!chip->dev_ready) { + udelay(chip->chip_delay); + return; } /* @@ -5180,16 +5098,6 @@ static int nand_flash_detect_onfi(struct nand_chip *chip) chip->ecc_step_ds = 512; } else if (chip->parameters.onfi.version >= 21 && (le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) { - - /* - * The nand_flash_detect_ext_param_page() uses the - * Change Read Column command which maybe not supported - * by the chip->cmdfunc. So try to update the chip->cmdfunc - * now. We do not replace user supplied command function. - */ - if (mtd->writesize > 512 && chip->cmdfunc == nand_command) - chip->cmdfunc = nand_command_lp; - /* The Extended Parameter Page is supported since ONFI 2.1. */ if (nand_flash_detect_ext_param_page(chip, p)) pr_warn("Failed to detect ONFI extended param page\n"); @@ -5686,10 +5594,6 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) chip->badblockbits = 8; chip->erase = single_erase; - /* Do not replace user supplied command function! */ - if (mtd->writesize > 512 && chip->cmdfunc == nand_command) - chip->cmdfunc = nand_command_lp; - pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n", maf_id, dev_id); pr_info("%s %s\n", nand_manufacturer_name(manufacturer),