From patchwork Sat Mar 16 16:46:02 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Mosberger-Tang X-Patchwork-Id: 228227 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:4978:20e::2]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 30BC92C00AC for ; Sun, 17 Mar 2013 03:47:33 +1100 (EST) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UGuFG-0006SD-Jn; Sat, 16 Mar 2013 16:46:10 +0000 Received: from mail-qa0-f51.google.com ([209.85.216.51]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UGuFB-0006Rr-Vi for linux-mtd@lists.infradead.org; Sat, 16 Mar 2013 16:46:06 +0000 Received: by mail-qa0-f51.google.com with SMTP id cr7so889512qab.3 for ; Sat, 16 Mar 2013 09:46:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:x-received:date:message-id:subject:from:to :content-type; bh=QLqxydqUosYAZx+p/DWVDJEJSmkfBXU30x5UKp1wtKg=; b=UH55q8doOYo3IIbPaCzkKPKhLAaUsGwLzl1Yi7IfbANXQtJvQQklVIDiiw3RBOKQVG DlmgubzCL4MyjTN4Cbhm+f8AB6xyqBhd7C+ZitHNekDHGaEZ0nYTK6/j0Tc4kYCOigi+ G12Dm7csKsrEWRwtbLBE912oFYcEC8eQEcQhI1w0ZFsZp/7FWBU8FW+CatwHskjbKlZc dJpT4VOD0gsMkPLDT4dyhjZblRTGSx33adOpO83wFaeAzH2XOZRnPhgitb2+EHNYi4Tu EGdq47rw94tJ9nwzznopuj1+l1A+VrxUUA7V2/iqu/VoWiLjHLNrYtSuzlTIZGUemKp3 KD6w== MIME-Version: 1.0 X-Received: by 10.49.30.70 with SMTP id q6mr12884246qeh.28.1363452362929; Sat, 16 Mar 2013 09:46:02 -0700 (PDT) Received: by 10.49.63.66 with HTTP; Sat, 16 Mar 2013 09:46:02 -0700 (PDT) Date: Sat, 16 Mar 2013 10:46:02 -0600 Message-ID: Subject: ONFI patch From: David Mosberger-Tang To: linux-mtd@lists.infradead.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130316_124606_118018_914003D1 X-CRM114-Status: GOOD ( 16.92 ) X-Spam-Score: -2.7 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (dmosberger[at]gmail.com) -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.216.51 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 0.0 HTML_MESSAGE BODY: HTML included in message -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 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 X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org I would like to propose a patch along the attached to make some of the ONFI support routines work on 16-bit devices. It does the following: - Always call nand_flash_detect_onfi(), even for known chips. Without this, onfi_version stays at 0 and nand_onfi_get_features and nand_onfi_set_features will always fail with EINVAL. - For the READID, GET_FEATURES, and SET_FEATURES commands, the column address is always 1 byte, regardless of bus-width. - nand_onfi_set_features(), nand_onfi_get_features(), and nand_flash_detect_onfi() need to use 8-bit transfers, regardless of bus-width. I see that the linux-mtd tree has a NAND_BUSWIDTH_AUTO features, but I don't see how that's supposed to help for, say, nand_onfi-set_features() or nand_onfi_get_features() as nand_set_defaults() will eventually set the 16-bit transfer routines for 16-bit devices. The patch is relative to linux-mtd GIT tree. Thanks, --david diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 42c6392..31decd1 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -507,6 +507,32 @@ void nand_wait_ready(struct mtd_info *mtd) } EXPORT_SYMBOL_GPL(nand_wait_ready); +static int +set_column (struct mtd_info *mtd, struct nand_chip *chip, + unsigned int command, int column, + unsigned int column_width, int ctrl) +{ + switch (command) { + case NAND_CMD_READID: + case NAND_CMD_GET_FEATURES: + case NAND_CMD_SET_FEATURES: + chip->cmd_ctrl(mtd, column, ctrl); + ctrl &= ~NAND_CTRL_CHANGE; + break; + + default: + /* Adjust columns for 16 bit buswidth */ + if (chip->options & NAND_BUSWIDTH_16) + column >>= 1; + chip->cmd_ctrl(mtd, column, ctrl); + ctrl &= ~NAND_CTRL_CHANGE; + if (column_width > 8) + chip->cmd_ctrl(mtd, column >> 8, ctrl); + break; + } + return ctrl; +} + /** * nand_command - [DEFAULT] Send command to NAND device * @mtd: MTD device structure @@ -546,13 +572,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, /* Address cycle, when necessary */ ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE; /* Serially input address */ - if (column != -1) { - /* Adjust columns for 16 bit buswidth */ - if (chip->options & NAND_BUSWIDTH_16) - column >>= 1; - chip->cmd_ctrl(mtd, column, ctrl); - ctrl &= ~NAND_CTRL_CHANGE; - } + if (column != -1) + ctrl = set_column(mtd, chip, command, column, 8, ctrl); if (page_addr != -1) { chip->cmd_ctrl(mtd, page_addr, ctrl); ctrl &= ~NAND_CTRL_CHANGE; @@ -638,14 +659,9 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE; /* Serially input address */ - if (column != -1) { - /* Adjust columns for 16 bit buswidth */ - if (chip->options & NAND_BUSWIDTH_16) - column >>= 1; - chip->cmd_ctrl(mtd, column, ctrl); - ctrl &= ~NAND_CTRL_CHANGE; - chip->cmd_ctrl(mtd, column >> 8, ctrl); - } + if (column != -1) + ctrl = set_column (mtd, chip, command, column, 16, + ctrl); if (page_addr != -1) { chip->cmd_ctrl(mtd, page_addr, ctrl); chip->cmd_ctrl(mtd, page_addr >> 8, @@ -2737,7 +2753,7 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip, return -EINVAL; chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1); - chip->write_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN); + nand_write_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN); status = chip->waitfunc(mtd, chip); if (status & NAND_STATUS_FAIL) return -EIO; @@ -2761,7 +2777,7 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip, memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN); chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1); - chip->read_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN); + nand_read_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN); return 0; } @@ -2882,7 +2898,8 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1); for (i = 0; i < 3; i++) { - chip->read_buf(mtd, (uint8_t *)p, sizeof(*p)); + /* Must read with 8-bit transfers even on 16-bit devices: */ + nand_read_buf(mtd, (uint8_t *)p, sizeof (*p)); if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) == le16_to_cpu(p->crc)) { pr_info("ONFI param page %d valid\n", i); @@ -3227,11 +3244,9 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, break; chip->onfi_version = 0; - if (!type->name || !type->pagesize) { - /* Check is chip is ONFI compliant */ - if (nand_flash_detect_onfi(mtd, chip, &busw)) - goto ident_done; - } + /* Check is chip is ONFI compliant */ + if (nand_flash_detect_onfi(mtd, chip, &busw)) + goto ident_done; if (!type->name) return ERR_PTR(-ENODEV);