From patchwork Wed Nov 27 15:23:05 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Denis Carikli X-Patchwork-Id: 294596 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from casper.infradead.org (unknown [IPv6:2001:770:15f::2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 865102C009F for ; Thu, 28 Nov 2013 02:24:02 +1100 (EST) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Vlgxz-0004iU-Kq; Wed, 27 Nov 2013 15:23:51 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Vlgxy-0006tc-02; Wed, 27 Nov 2013 15:23:50 +0000 Received: from [2a01:e0c:1:1599:215:17ff:fe31:fb8] (helo=smtp2-g21.free.fr) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Vlgxu-0006sY-4I for linux-mtd@lists.infradead.org; Wed, 27 Nov 2013 15:23:48 +0000 Received: from denis-N73SV.local.eukrea.com (unknown [88.170.243.169]) by smtp2-g21.free.fr (Postfix) with ESMTP id C56C74B0265; Wed, 27 Nov 2013 16:23:15 +0100 (CET) From: Denis Carikli To: David Woodhouse Subject: [PATCHv2][] mtd: nand: mxc_nand: Add onfi & 4k flashs support. Date: Wed, 27 Nov 2013 16:23:05 +0100 Message-Id: <1385565786-29705-1-git-send-email-denis@eukrea.com> X-Mailer: git-send-email 1.7.9.5 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20131127_102347_022860_28E018FB X-CRM114-Status: GOOD ( 17.29 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.7 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 0.8 RDNS_NONE Delivered to internal network by a host with no rDNS Cc: Denis Carikli , Sascha Hauer , linux-mtd@lists.infradead.org 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 * CMD_PARAM and read_param were added to get the ONFI structure. * Fixed OOB size for flash with 224 OOB on i.MX51/3 Tested on an i.MX53 with: NAND device: Manufacturer ID: 0x2c, Chip ID: 0x38 (Micron MT29F8G08ABABAWP) NAND device: 1024MiB, SLC, page size: 4096, OOB size: 224 This patch was ported from that barebox commit: 632c457 nand_imx: update to support onfi & 4k flashs Cc: David Woodhouse Cc: linux-mtd@lists.infradead.org Cc: Sascha Hauer Signed-off-by: Denis Carikli Signed-off-by: Eric BĂ©nard --- ChangeLog v1->v2: - Better commit message title. --- drivers/mtd/nand/mxc_nand.c | 68 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 9dfdb06..68c107c 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -145,6 +145,7 @@ struct mxc_nand_devtype_data { void (*send_addr)(struct mxc_nand_host *, uint16_t, int); void (*send_page)(struct mtd_info *, unsigned int); void (*send_read_id)(struct mxc_nand_host *); + void (*send_read_param)(struct mxc_nand_host *); uint16_t (*get_dev_status)(struct mxc_nand_host *); int (*check_int)(struct mxc_nand_host *); void (*irq_control)(struct mxc_nand_host *, int); @@ -529,6 +530,44 @@ static void send_page_v1(struct mtd_info *mtd, unsigned int ops) } } +static void send_read_param_v3(struct mxc_nand_host *host) +{ + /* Read ID into main buffer */ + writel(NFC_OUTPUT, NFC_V3_LAUNCH); + + wait_op_done(host, true); + + memcpy32_fromio(host->data_buf, host->main_area0, 1024); +} + +static void send_read_param_v1_v2(struct mxc_nand_host *host) +{ + struct nand_chip *this = &host->nand; + + /* NANDFC buffer 0 is used for device ID output */ + writew(0x0, NFC_V1_V2_BUF_ADDR); + + writew(NFC_OUTPUT, NFC_V1_V2_CONFIG2); + + /* Wait for operation to complete */ + wait_op_done(host, true); + + if (this->options & NAND_BUSWIDTH_16) { + u16 *mainbuf = host->main_area0; + + /* + * Pack the every-other-byte result for 16-bit ID reads + * into every-byte as the generic code expects and various + * chips implement. + */ + + mainbuf[0] = (mainbuf[0] & 0xff) | ((mainbuf[1] & 0xff) << 8); + mainbuf[1] = (mainbuf[2] & 0xff) | ((mainbuf[3] & 0xff) << 8); + mainbuf[2] = (mainbuf[4] & 0xff) | ((mainbuf[5] & 0xff) << 8); + } + memcpy32_fromio(host->data_buf, host->main_area0, 1024); +} + static void send_read_id_v3(struct mxc_nand_host *host) { struct nand_chip *this = &host->nand; @@ -748,6 +787,10 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) n = min(n, len); + /* handle the read param special case */ + if ((mtd->writesize == 0) && (len != 0)) + n = len; + memcpy(buf, host->data_buf + col, n); host->buf_start += n; @@ -841,9 +884,12 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) * MXC NANDFC can only perform full page+spare or * spare-only read/write. When the upper layers * perform a read/write buf operation, the saved column - * address is used to index into the full page. + * address is used to index into the full page. + * + * The colum address must be sent to the flash in + * order to get the ONFI header (0x20) */ - host->devtype_data->send_addr(host, 0, page_addr == -1); + host->devtype_data->send_addr(host, column, page_addr == -1); if (mtd->writesize > 512) /* another col addr cycle for 2k page */ host->devtype_data->send_addr(host, 0, false); @@ -997,9 +1043,11 @@ static void preset_v3(struct mtd_info *mtd) writel(0, NFC_V3_IPC); + /* if the flash has a 224 oob, the NFC must be configured to 218 */ config2 = NFC_V3_CONFIG2_ONE_CYCLE | NFC_V3_CONFIG2_2CMD_PHASES | - NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) | + NFC_V3_CONFIG2_SPAS(((mtd->oobsize > 218) ? + 218 : mtd->oobsize) >> 1) | NFC_V3_CONFIG2_ST_CMD(0x70) | NFC_V3_CONFIG2_INT_MSK | NFC_V3_CONFIG2_NUM_ADDR_PHASE0; @@ -1120,6 +1168,13 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, host->devtype_data->send_cmd(host, command, true); mxc_do_addr_cycle(mtd, column, page_addr); host->devtype_data->send_read_id(host); + host->buf_start = 0; + break; + + case NAND_CMD_PARAM: + host->devtype_data->send_cmd(host, command, true); + mxc_do_addr_cycle(mtd, column, page_addr); + host->devtype_data->send_read_param(host); host->buf_start = column; break; @@ -1217,6 +1272,7 @@ static const struct mxc_nand_devtype_data imx25_nand_devtype_data = { .send_addr = send_addr_v1_v2, .send_page = send_page_v2, .send_read_id = send_read_id_v1_v2, + .send_read_param = send_read_param_v3, .get_dev_status = get_dev_status_v1_v2, .check_int = check_int_v1_v2, .irq_control = irq_control_v1_v2, @@ -1243,13 +1299,14 @@ static const struct mxc_nand_devtype_data imx51_nand_devtype_data = { .send_addr = send_addr_v3, .send_page = send_page_v3, .send_read_id = send_read_id_v3, + .send_read_param = send_read_param_v3, .get_dev_status = get_dev_status_v3, .check_int = check_int_v3, .irq_control = irq_control_v3, .get_ecc_status = get_ecc_status_v3, .ecclayout_512 = &nandv2_hw_eccoob_smallpage, .ecclayout_2k = &nandv2_hw_eccoob_largepage, - .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */ + .ecclayout_4k = &nandv2_hw_eccoob_4k, .select_chip = mxc_nand_select_chip_v1_v3, .correct_data = mxc_nand_correct_data_v2_v3, .irqpending_quirk = 0, @@ -1270,13 +1327,14 @@ static const struct mxc_nand_devtype_data imx53_nand_devtype_data = { .send_addr = send_addr_v3, .send_page = send_page_v3, .send_read_id = send_read_id_v3, + .send_read_param = send_read_param_v3, .get_dev_status = get_dev_status_v3, .check_int = check_int_v3, .irq_control = irq_control_v3, .get_ecc_status = get_ecc_status_v3, .ecclayout_512 = &nandv2_hw_eccoob_smallpage, .ecclayout_2k = &nandv2_hw_eccoob_largepage, - .ecclayout_4k = &nandv2_hw_eccoob_smallpage, /* XXX: needs fix */ + .ecclayout_4k = &nandv2_hw_eccoob_4k, .select_chip = mxc_nand_select_chip_v1_v3, .correct_data = mxc_nand_correct_data_v2_v3, .irqpending_quirk = 0,