From patchwork Thu Feb 8 23:59:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Agner X-Patchwork-Id: 871160 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=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="nYOAPm21"; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=agner.ch header.i=@agner.ch header.b="rAg+hRLL"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.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 3zcwD82tYdz9ryQ for ; Fri, 9 Feb 2018 10:59:52 +1100 (AEDT) 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=x7D22SGqEK0BiHbcJPjHlrO6ynAiKQejCDAeq9TDKWs=; b=nYOAPm21okJhpjmpo8lq98eSOK sbsk9DJggCo8nbZqCvklo5fjdaQFD0xCHGSBsOszo/hOJRIIfacrn2VrX9BksHvEZ6iF0I7wZOWre bCWyuQ3+elfLSbKA0R1xDd6Xj9EY+M9pd3WaD4UtRdoFYLciOypRkvxnK+Ejc5S0D3lvH+oQaV1nB PB3oCrdHmTKIsIEVpPqwzpL92+ZpoONajzbxOftkysB5uUGS7n33g4p12OuIDx1a5m3uY/DL/5DhD CgwTXRQI6fsoYx2Dhv25Yquwbv9TY7rVy5h2As0ogJbIFb6lVdl0iqs8X1K/EpaJ1NbjiW1Y8rKzK E6yB+LwA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.89 #1 (Red Hat Linux)) id 1ejw6V-0007N6-BR; Thu, 08 Feb 2018 23:59:47 +0000 Received: from mail.kmu-office.ch ([2a02:418:6a02::a2]) by bombadil.infradead.org with esmtps (Exim 4.89 #1 (Red Hat Linux)) id 1ejw6K-0007D2-2C for linux-mtd@lists.infradead.org; Thu, 08 Feb 2018 23:59:38 +0000 Received: from trochilidae.lan (unknown [IPv6:2001:1620:c6e::587]) by mail.kmu-office.ch (Postfix) with ESMTPSA id 176255C139A; Fri, 9 Feb 2018 00:51:59 +0100 (CET) From: Stefan Agner To: miquel.raynal@free-electrons.com, boris.brezillon@free-electrons.com Subject: [RFC PATCH v3 1/3] mtd: nand: vf610_nfc: remove unused function Date: Fri, 9 Feb 2018 00:59:19 +0100 Message-Id: <20180208235921.31840-2-stefan@agner.ch> X-Mailer: git-send-email 2.16.1 In-Reply-To: <20180208235921.31840-1-stefan@agner.ch> References: <20180208235921.31840-1-stefan@agner.ch> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=agner.ch; s=dkim; t=1518133919; bh=TwclumtO8GSZifvDBh7Pwh0W0Py2MfxqL90SEtoo9Us=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=rAg+hRLLd/iH1S7SW1ehuq4lidhITMc7Ma+hwir8l0sPIcMhYusXcpjKcCPyUNGyEzLSIRGYHh/2+6914ApAtXD+qnKbd2uUNKHCURW0xlMxZRv4z2eTj8LI78GC8DHiE0HyT/I7DNCS8xe6CPfAlh6qjZoQ8Faxi/hBqZ0/G9M= X-Spam-Note: CRM114 invocation failed X-Spam-Score: -2.0 (--) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-2.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid 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: marcel.ziswiler@toradex.com, richard@nod.at, bpringlemeir@gmail.com, stefan@agner.ch, marek.vasut@gmail.com, linux-mtd@lists.infradead.org, cyrille.pitchen@wedev4u.fr, computersforpeace@gmail.com, dwmw2@infradead.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org The function count_written_bits has been replaced by the generic nand_check_erased_ecc_chunk() function with commit 48c25cf44118 ("mtd: nand: vf610_nfc: use nand_check_erased_ecc_chunk() helper"). Remove the unused function. Signed-off-by: Stefan Agner --- drivers/mtd/nand/vf610_nfc.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index 80d31a58e558..2fa61cbdbaf7 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -511,21 +511,6 @@ static void vf610_nfc_select_chip(struct mtd_info *mtd, int chip) vf610_nfc_write(nfc, NFC_ROW_ADDR, tmp); } -/* Count the number of 0's in buff up to max_bits */ -static inline int count_written_bits(uint8_t *buff, int size, int max_bits) -{ - uint32_t *buff32 = (uint32_t *)buff; - int k, written_bits = 0; - - for (k = 0; k < (size / 4); k++) { - written_bits += hweight32(~buff32[k]); - if (unlikely(written_bits > max_bits)) - break; - } - - return written_bits; -} - static inline int vf610_nfc_correct_data(struct mtd_info *mtd, uint8_t *dat, uint8_t *oob, int page) { From patchwork Thu Feb 8 23:59:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Agner X-Patchwork-Id: 871162 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=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="dj+4HXye"; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=agner.ch header.i=@agner.ch header.b="Z89NeWDK"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.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 3zcwDj6DmQz9s4q for ; Fri, 9 Feb 2018 11:00:21 +1100 (AEDT) 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=Rawei6qnc3u3hFADtSGbcNVh99R1whg6XoUMY7j5d1c=; b=dj+4HXye5PriMpL2rnbYPdka4v grfS4j4m1aE9nxPFpkzEQUt8QsrTnBm33DJ6cHnr4Mabj9OMALwbtQlMEdP5jt9XzX3XjqtkTE4cX bnXZjvA7XpNBwwIhjq3q6NAy0Ak6AsXwssBCpCui/e5aPPape+3Biw1c+XSfDL4i22xfXPILja8OR tBqousyjbjyMlVkhNOcCo5x8O/I5DrDAwjJ+Hw7wxzBSTCBd7pnOCxpReaQFxonD0G3pPhjt00wZr 9FEB3m9uk2Tl4BjPeuTAO/qDK3RJ4valSz4eby30Na/J4SAeNPNn0OuzQgWgztuXr6g1wOV1uxMiz sVzvxhWw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.89 #1 (Red Hat Linux)) id 1ejw6x-0000SE-Ld; Fri, 09 Feb 2018 00:00:15 +0000 Received: from mail.kmu-office.ch ([2a02:418:6a02::a2]) by bombadil.infradead.org with esmtps (Exim 4.89 #1 (Red Hat Linux)) id 1ejw6K-0007D3-2E for linux-mtd@lists.infradead.org; Thu, 08 Feb 2018 23:59:39 +0000 Received: from trochilidae.lan (unknown [IPv6:2001:1620:c6e::587]) by mail.kmu-office.ch (Postfix) with ESMTPSA id 551425C139B; Fri, 9 Feb 2018 00:51:59 +0100 (CET) From: Stefan Agner To: miquel.raynal@free-electrons.com, boris.brezillon@free-electrons.com Subject: [RFC PATCH v3 2/3] mtd: nand: vf610_nfc: make use of ->exec_op() Date: Fri, 9 Feb 2018 00:59:20 +0100 Message-Id: <20180208235921.31840-3-stefan@agner.ch> X-Mailer: git-send-email 2.16.1 In-Reply-To: <20180208235921.31840-1-stefan@agner.ch> References: <20180208235921.31840-1-stefan@agner.ch> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=agner.ch; s=dkim; t=1518133919; bh=RhN+pRC+iIvNJQk4CD/MWF5np1vt7zvhR3LjEDoIoE4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=Z89NeWDKBGK+cPRP8YIX9qNinhATxAPxJXIWJrp9t5tDcRmqTyDYoIK073aBKXUQikZfrtPFubD/Me5/Jn7aWmaK+qVprMkPjTaowzgQcX1RSb0CO1bzNLlQnr+CoNyBsItgslnK4y2lOHQn1+RlglUPBt3IYdjhIG3321stKDw= X-Spam-Note: CRM114 invocation failed X-Spam-Score: -2.0 (--) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-2.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid 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: marcel.ziswiler@toradex.com, richard@nod.at, bpringlemeir@gmail.com, stefan@agner.ch, marek.vasut@gmail.com, linux-mtd@lists.infradead.org, cyrille.pitchen@wedev4u.fr, computersforpeace@gmail.com, dwmw2@infradead.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org This reworks the driver to make use of ->exec_op() callback. The command sequencer of the VF610 NFC aligns well with the new ops interface. The ops are translated to a NFC command code while filling the necessary registers. Instead of using the special status and read id command codes (which require the status/id form special registers) the driver now uses the main data buffer for all commands. This simplifies the driver as no special casing is needed. For control data (status byte, id bytes and parameter page) the driver needs to reverse byte order for little endian CPUs since the controller seems to store the bytes in big endian order in the data buffer. The current state seems to pass MTD tests on a Colibri VF61. Signed-off-by: Stefan Agner --- drivers/mtd/nand/vf610_nfc.c | 279 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 267 insertions(+), 12 deletions(-) diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index 2fa61cbdbaf7..eae95877422d 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -74,6 +74,21 @@ #define RESET_CMD_CODE 0x4040 #define STATUS_READ_CMD_CODE 0x4068 +/* NFC_CMD2[CODE] controller cycle bit masks */ +#define COMMAND_CMD_BYTE1 BIT(14) +#define COMMAND_CAR_BYTE1 BIT(13) +#define COMMAND_CAR_BYTE2 BIT(12) +#define COMMAND_RAR_BYTE1 BIT(11) +#define COMMAND_RAR_BYTE2 BIT(10) +#define COMMAND_RAR_BYTE3 BIT(9) +#define COMMAND_WRITE_DATA BIT(8) +#define COMMAND_CMD_BYTE2 BIT(7) +#define COMMAND_RB_HANDSHAKE BIT(6) +#define COMMAND_READ_DATA BIT(5) +#define COMMAND_CMD_BYTE3 BIT(4) +#define COMMAND_READ_STATUS BIT(3) +#define COMMAND_READ_ID BIT(2) + /* NFC ECC mode define */ #define ECC_BYPASS 0 #define ECC_45_BYTE 6 @@ -97,10 +112,14 @@ /* NFC_COL_ADDR Field */ #define COL_ADDR_MASK 0x0000FFFF #define COL_ADDR_SHIFT 0 +#define COL_ADDR(pos, val) ((val & 0xFF) << (8 * (pos))) + /* NFC_ROW_ADDR Field */ #define ROW_ADDR_MASK 0x00FFFFFF #define ROW_ADDR_SHIFT 0 +#define ROW_ADDR(pos, val) ((val & 0xFF) << (8 * (pos))) + #define ROW_ADDR_CHIP_SEL_RB_MASK 0xF0000000 #define ROW_ADDR_CHIP_SEL_RB_SHIFT 28 #define ROW_ADDR_CHIP_SEL_MASK 0x0F000000 @@ -173,6 +192,11 @@ static inline struct vf610_nfc *mtd_to_nfc(struct mtd_info *mtd) return container_of(mtd_to_nand(mtd), struct vf610_nfc, chip); } +static inline struct vf610_nfc *chip_to_nfc(struct nand_chip *chip) +{ + return container_of(chip, struct vf610_nfc, chip); +} + static inline u32 vf610_nfc_read(struct vf610_nfc *nfc, uint reg) { return readl(nfc->regs + reg); @@ -489,6 +513,184 @@ static int vf610_nfc_dev_ready(struct mtd_info *mtd) return 1; } +static inline void vf610_nfc_run(struct vf610_nfc *nfc, u32 col, u32 row, u32 cmd1, u32 cmd2, u32 trfr_sz) +{ + vf610_nfc_set_field(nfc, NFC_COL_ADDR, COL_ADDR_MASK, + COL_ADDR_SHIFT, col); + + vf610_nfc_set_field(nfc, NFC_ROW_ADDR, ROW_ADDR_MASK, + ROW_ADDR_SHIFT, row); + + vf610_nfc_write(nfc, NFC_SECTOR_SIZE, trfr_sz); + vf610_nfc_write(nfc, NFC_FLASH_CMD1, cmd1); + vf610_nfc_write(nfc, NFC_FLASH_CMD2, cmd2); + + dev_dbg(nfc->dev, "col 0x%08x, row 0x%08x, cmd1 0x%08x, cmd2 0x%08x, trfr_sz %d\n", + col, row, cmd1, cmd2, trfr_sz); + + vf610_nfc_done(nfc); +} + +static inline const struct nand_op_instr *vf610_get_next_instr( + const struct nand_subop *subop, int *op_id) +{ + if (*op_id + 1 >= subop->ninstrs) + return NULL; + + (*op_id)++; + + return &subop->instrs[*op_id]; +} + +static int vf610_nfc_cmd(struct nand_chip *chip, + const struct nand_subop *subop) +{ + const struct nand_op_instr *instr; + struct vf610_nfc *nfc = chip_to_nfc(chip); + struct mtd_info *mtd = nand_to_mtd(chip); + int op_id = -1, addr = 0, trfr_sz = 0; + u32 col = 0, row = 0, cmd1 = 0, cmd2 = 0, code = 0; + + /* Some ops are optional, but they need to be in order */ + instr = vf610_get_next_instr(subop, &op_id); + if (!instr) + return -EINVAL; + + if (instr && instr->type == NAND_OP_CMD_INSTR) { + dev_dbg(nfc->dev, "OP_CMD: code 0x%02x\n", instr->ctx.cmd.opcode); + cmd2 |= instr->ctx.cmd.opcode << CMD_BYTE1_SHIFT; + code |= COMMAND_CMD_BYTE1; + + instr = vf610_get_next_instr(subop, &op_id); + } + + if (instr && instr->type == NAND_OP_ADDR_INSTR) { + + if (instr->ctx.addr.naddrs > 1) { + col = COL_ADDR(0, instr->ctx.addr.addrs[addr++]); + code |= COMMAND_CAR_BYTE1; + + if (mtd->writesize > 512) { + col |= COL_ADDR(1, instr->ctx.addr.addrs[addr++]); + code |= COMMAND_CAR_BYTE2; + } + } + + row = ROW_ADDR(0, instr->ctx.addr.addrs[addr++]); + code |= COMMAND_RAR_BYTE1; + if (addr < instr->ctx.addr.naddrs) { + row |= ROW_ADDR(1, instr->ctx.addr.addrs[addr++]); + code |= COMMAND_RAR_BYTE2; + } + if (addr < instr->ctx.addr.naddrs) { + row |= ROW_ADDR(2, instr->ctx.addr.addrs[addr++]); + code |= COMMAND_RAR_BYTE3; + } + + dev_dbg(nfc->dev, "OP_ADDR: col %d, row %d\n", col, row); + + instr = vf610_get_next_instr(subop, &op_id); + } + + if (instr && instr->type == NAND_OP_DATA_OUT_INSTR) { + int len = nand_subop_get_data_len(subop, op_id); + int offset = nand_subop_get_data_start_off(subop, op_id); + + dev_dbg(nfc->dev, "OP_DATA_OUT: len %d, offset %d\n", len, offset); + + vf610_nfc_memcpy(nfc->regs + NFC_MAIN_AREA(0) + offset, + instr->ctx.data.buf.in + offset, + len); + code |= COMMAND_WRITE_DATA; + trfr_sz += len; + + instr = vf610_get_next_instr(subop, &op_id); + } + + if (instr && instr->type == NAND_OP_CMD_INSTR) { + cmd1 |= instr->ctx.cmd.opcode << CMD_BYTE2_SHIFT; + code |= COMMAND_CMD_BYTE2; + + instr = vf610_get_next_instr(subop, &op_id); + } + + if (instr && instr->type == NAND_OP_WAITRDY_INSTR) { + //dev_dbg(nfc->dev, "WAITRDY [max %d ms]\n", + // instr->ctx.waitrdy.timeout_ms); + code |= COMMAND_RB_HANDSHAKE; + + instr = vf610_get_next_instr(subop, &op_id); + } + + if (instr && instr->type == NAND_OP_DATA_IN_INSTR) { + int len = nand_subop_get_data_len(subop, op_id); + code |= COMMAND_READ_DATA; + trfr_sz += len; + } + + cmd2 |= code << CMD_CODE_SHIFT; + + vf610_nfc_ecc_mode(nfc, ECC_BYPASS); + vf610_nfc_run(nfc, col, row, cmd1, cmd2, trfr_sz); + + if (instr && instr->type == NAND_OP_DATA_IN_INSTR) { + int len = nand_subop_get_data_len(subop, op_id); + int offset = nand_subop_get_data_start_off(subop, op_id); + bool fix_byte_order = false; + +#ifdef __LITTLE_ENDIAN + fix_byte_order = true; +#endif + dev_dbg(nfc->dev, "OP_DATA_IN: 8-bit: %d, len %d, offset %d\n", + instr->ctx.data.force_8bit , len, offset); + + /* + * HACK: force_8bit indicates reading of the parameter, status + * or id data. The controllers seems to store data in big endian + * byte order to the buffers. Reverse on little endian machines. + */ + if (instr->ctx.data.force_8bit && fix_byte_order) { + u8 *buf = instr->ctx.data.buf.in; + + while (len--) { + int c = offset ^ 0x3; + + *buf = *((u8 *)(nfc->regs + NFC_MAIN_AREA(0) + c)); + buf++; offset++; + } + } else { + vf610_nfc_memcpy(instr->ctx.data.buf.in + offset, + nfc->regs + NFC_MAIN_AREA(0) + offset, + len); + } + } + + return 0; +} + +static const struct nand_op_parser vf610_nfc_op_parser = NAND_OP_PARSER( + NAND_OP_PARSER_PATTERN( + vf610_nfc_cmd, + NAND_OP_PARSER_PAT_CMD_ELEM(true), + NAND_OP_PARSER_PAT_ADDR_ELEM(true, 5), + NAND_OP_PARSER_PAT_DATA_OUT_ELEM(true, PAGE_2K + OOB_MAX), + NAND_OP_PARSER_PAT_CMD_ELEM(true), + NAND_OP_PARSER_PAT_WAITRDY_ELEM(true), + NAND_OP_PARSER_PAT_DATA_IN_ELEM(true, PAGE_2K + OOB_MAX)), + ); + +static int vf610_nfc_exec_op(struct nand_chip *chip, + const struct nand_operation *op, + bool check_only) +{ + struct vf610_nfc *nfc = chip_to_nfc(chip); + + dev_dbg(nfc->dev, "exec_op, opcode 0x%02x\n", op->instrs[0].ctx.cmd.opcode); + + return nand_op_parser_exec_op(chip, &vf610_nfc_op_parser, op, check_only); +} + + /* * This function supports Vybrid only (MPC5125 would have full RB and four CS) */ @@ -527,8 +729,7 @@ static inline int vf610_nfc_correct_data(struct mtd_info *mtd, uint8_t *dat, return ecc_count; /* Read OOB without ECC unit enabled */ - vf610_nfc_command(mtd, NAND_CMD_READOOB, 0, page); - vf610_nfc_read_buf(mtd, oob, mtd->oobsize); + nand_read_oob_op(&nfc->chip, page, 0, oob, mtd->oobsize); /* * On an erased page, bit count (including OOB) should be zero or @@ -542,12 +743,42 @@ static inline int vf610_nfc_correct_data(struct mtd_info *mtd, uint8_t *dat, static int vf610_nfc_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - int eccsize = chip->ecc.size; + struct vf610_nfc *nfc = mtd_to_nfc(mtd); + int trfr_sz = mtd->writesize + mtd->oobsize; + u32 col = 0, row = 0, cmd1 = 0, cmd2 = 0, code = 0; int stat; - nand_read_page_op(chip, page, 0, buf, eccsize); + cmd2 |= NAND_CMD_READ0 << CMD_BYTE1_SHIFT; + code |= COMMAND_CMD_BYTE1; + + code |= COMMAND_CAR_BYTE1; + code |= COMMAND_CAR_BYTE2; + + row = ROW_ADDR(0, page & 0xff); + code |= COMMAND_RAR_BYTE1; + row |= ROW_ADDR(1, page >> 8); + code |= COMMAND_RAR_BYTE2; + + if (chip->options & NAND_ROW_ADDR_3) { + row |= ROW_ADDR(2, page >> 16); + code |= COMMAND_RAR_BYTE3; + } + + cmd1 |= NAND_CMD_READSTART << CMD_BYTE2_SHIFT; + code |= COMMAND_CMD_BYTE2; + + code |= COMMAND_RB_HANDSHAKE; + code |= COMMAND_READ_DATA; + cmd2 |= code << CMD_CODE_SHIFT; + + vf610_nfc_ecc_mode(nfc, nfc->ecc_mode); + vf610_nfc_run(nfc, col, row, cmd1, cmd2, trfr_sz); + + vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0), mtd->writesize); if (oob_required) - vf610_nfc_read_buf(mtd, chip->oob_poi, mtd->oobsize); + vf610_nfc_memcpy(chip->oob_poi, + nfc->regs + NFC_MAIN_AREA(0) + mtd->writesize, + mtd->oobsize); stat = vf610_nfc_correct_data(mtd, buf, chip->oob_poi, page); @@ -564,16 +795,39 @@ static int vf610_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required, int page) { struct vf610_nfc *nfc = mtd_to_nfc(mtd); + int trfr_sz = mtd->writesize + mtd->oobsize; + u32 col = 0, row = 0, cmd1 = 0, cmd2 = 0, code = 0; + int ret = 0; + + cmd2 |= NAND_CMD_SEQIN << CMD_BYTE1_SHIFT; + code |= COMMAND_CMD_BYTE1; + + code |= COMMAND_CAR_BYTE1; + code |= COMMAND_CAR_BYTE2; + + row = ROW_ADDR(0, page & 0xff); + code |= COMMAND_RAR_BYTE1; + row |= ROW_ADDR(1, page >> 8); + code |= COMMAND_RAR_BYTE2; + if (chip->options & NAND_ROW_ADDR_3) { + row |= ROW_ADDR(2, page >> 16); + code |= COMMAND_RAR_BYTE3; + } - nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); - if (oob_required) - vf610_nfc_write_buf(mtd, chip->oob_poi, mtd->oobsize); + cmd1 |= NAND_CMD_PAGEPROG << CMD_BYTE2_SHIFT; + code |= COMMAND_CMD_BYTE2; + + code |= COMMAND_WRITE_DATA; + + vf610_nfc_memcpy(nfc->regs + NFC_MAIN_AREA(0), buf, mtd->writesize); + + code |= COMMAND_RB_HANDSHAKE; + cmd2 |= code << CMD_CODE_SHIFT; - /* Always write whole page including OOB due to HW ECC */ - nfc->use_hw_ecc = true; - nfc->write_sz = mtd->writesize + mtd->oobsize; + vf610_nfc_ecc_mode(nfc, nfc->ecc_mode); + vf610_nfc_run(nfc, col, row, cmd1, cmd2, trfr_sz); - return nand_prog_page_end_op(chip); + return ret; } static const struct of_device_id vf610_nfc_dt_ids[] = { @@ -686,6 +940,7 @@ static int vf610_nfc_probe(struct platform_device *pdev) chip->read_word = vf610_nfc_read_word; chip->read_buf = vf610_nfc_read_buf; chip->write_buf = vf610_nfc_write_buf; + chip->exec_op = vf610_nfc_exec_op; chip->select_chip = vf610_nfc_select_chip; chip->onfi_set_features = nand_onfi_get_set_features_notsupp; chip->onfi_get_features = nand_onfi_get_set_features_notsupp; From patchwork Thu Feb 8 23:59:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Agner X-Patchwork-Id: 871161 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=65.50.211.133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="LEKoPEup"; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=agner.ch header.i=@agner.ch header.b="bbNOVJc8"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.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 3zcwDP3FV1z9ryQ for ; Fri, 9 Feb 2018 11:00:05 +1100 (AEDT) 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=yoGMvYMyPaWt0e7qa5ryAwx0cJgwNwEqKe62b9nmK8Q=; b=LEKoPEupMYsXtU30+nWpEqla4U AYiHltcnTdhwsaeugDCBDgAZ+ESjK+A71eSQEJQFXb75jDoIKbtJJqyLZ9TxcmKc2tllgiX8Ha+7+ JCOJlsELYnB6x74dbP4oQ0MLSfLntfKYlhhD7n70OJWgujZllkjQf8cI8WF4Z1Xl/jhy6XD4TgEv7 Uf+reRgqWRotojOAfssjG4v/oz2qAvMLzFSawskHVd+MWqQuCxUEoi/i/6RLdXLjiEONDgnu9yM4K BXY7mjH60mUXCojTo7i9QQV04x30IRzU8jYnKzpU8fWk5Q86feITo0BjTp0evHb5byQfi+UyFNg2R cq6vU7Ew==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.89 #1 (Red Hat Linux)) id 1ejw6h-0007c1-6j; Thu, 08 Feb 2018 23:59:59 +0000 Received: from mail.kmu-office.ch ([2a02:418:6a02::a2]) by bombadil.infradead.org with esmtps (Exim 4.89 #1 (Red Hat Linux)) id 1ejw6K-0007D5-2C for linux-mtd@lists.infradead.org; Thu, 08 Feb 2018 23:59:39 +0000 Received: from trochilidae.lan (unknown [IPv6:2001:1620:c6e::587]) by mail.kmu-office.ch (Postfix) with ESMTPSA id 9B4275C13B3; Fri, 9 Feb 2018 00:51:59 +0100 (CET) From: Stefan Agner To: miquel.raynal@free-electrons.com, boris.brezillon@free-electrons.com Subject: [RFC PATCH v3 3/3] mtd: nand: vf610_nfc: remove old hooks Date: Fri, 9 Feb 2018 00:59:21 +0100 Message-Id: <20180208235921.31840-4-stefan@agner.ch> X-Mailer: git-send-email 2.16.1 In-Reply-To: <20180208235921.31840-1-stefan@agner.ch> References: <20180208235921.31840-1-stefan@agner.ch> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=agner.ch; s=dkim; t=1518133919; bh=Qyk42seb6t7Fjp329G3OI3Fk1KHfGmpcH2ZBfvjvqmw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=bbNOVJc8VgpVl/AuglVWbyAD3LqO54OzNg09GJ9qqxWiv2K6cxixM4zl14v0AJ2gvF6DoEwcPxlh5qFrNt4ABu9M9YnwiEjpzkaUgtPHvpK3kV0rIL5mptKJbTIyUUEgruW5XN545jwkBI/O/SCafIwcH9F6ktosylu+uZf7H3g= X-Spam-Note: CRM114 invocation failed X-Spam-Score: -2.0 (--) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-2.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid 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: marcel.ziswiler@toradex.com, richard@nod.at, bpringlemeir@gmail.com, stefan@agner.ch, marek.vasut@gmail.com, linux-mtd@lists.infradead.org, cyrille.pitchen@wedev4u.fr, computersforpeace@gmail.com, dwmw2@infradead.org MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Now that the driver is using ->exec_op(), remove the old hooks. Signed-off-by: Stefan Agner --- drivers/mtd/nand/vf610_nfc.c | 255 ------------------------------------------- 1 file changed, 255 deletions(-) diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index eae95877422d..ee80a3005adb 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -59,21 +59,6 @@ #define OOB_64 0x0040 #define OOB_MAX 0x0100 -/* - * NFC_CMD2[CODE] values. See section: - * - 31.4.7 Flash Command Code Description, Vybrid manual - * - 23.8.6 Flash Command Sequencer, MPC5125 manual - * - * Briefly these are bitmasks of controller cycles. - */ -#define READ_PAGE_CMD_CODE 0x7EE0 -#define READ_ONFI_PARAM_CMD_CODE 0x4860 -#define PROGRAM_PAGE_CMD_CODE 0x7FC0 -#define ERASE_CMD_CODE 0x4EC0 -#define READ_ID_CMD_CODE 0x4804 -#define RESET_CMD_CODE 0x4040 -#define STATUS_READ_CMD_CODE 0x4068 - /* NFC_CMD2[CODE] controller cycle bit masks */ #define COMMAND_CMD_BYTE1 BIT(14) #define COMMAND_CAR_BYTE1 BIT(13) @@ -161,13 +146,6 @@ #define ECC_STATUS_MASK 0x80 #define ECC_STATUS_ERR_COUNT 0x3F -enum vf610_nfc_alt_buf { - ALT_BUF_DATA = 0, - ALT_BUF_ID = 1, - ALT_BUF_STAT = 2, - ALT_BUF_ONFI = 3, -}; - enum vf610_nfc_variant { NFC_VFC610 = 1, }; @@ -177,13 +155,9 @@ struct vf610_nfc { struct device *dev; void __iomem *regs; struct completion cmd_done; - uint buf_offset; - int write_sz; /* Status and ID are in alternate locations. */ - enum vf610_nfc_alt_buf alt_buf; enum vf610_nfc_variant variant; struct clk *clk; - bool use_hw_ecc; u32 ecc_mode; }; @@ -267,53 +241,6 @@ static void vf610_nfc_done(struct vf610_nfc *nfc) vf610_nfc_clear_status(nfc); } -static u8 vf610_nfc_get_id(struct vf610_nfc *nfc, int col) -{ - u32 flash_id; - - if (col < 4) { - flash_id = vf610_nfc_read(nfc, NFC_FLASH_STATUS1); - flash_id >>= (3 - col) * 8; - } else { - flash_id = vf610_nfc_read(nfc, NFC_FLASH_STATUS2); - flash_id >>= 24; - } - - return flash_id & 0xff; -} - -static u8 vf610_nfc_get_status(struct vf610_nfc *nfc) -{ - return vf610_nfc_read(nfc, NFC_FLASH_STATUS2) & STATUS_BYTE1_MASK; -} - -static void vf610_nfc_send_command(struct vf610_nfc *nfc, u32 cmd_byte1, - u32 cmd_code) -{ - u32 tmp; - - vf610_nfc_clear_status(nfc); - - tmp = vf610_nfc_read(nfc, NFC_FLASH_CMD2); - tmp &= ~(CMD_BYTE1_MASK | CMD_CODE_MASK | BUFNO_MASK); - tmp |= cmd_byte1 << CMD_BYTE1_SHIFT; - tmp |= cmd_code << CMD_CODE_SHIFT; - vf610_nfc_write(nfc, NFC_FLASH_CMD2, tmp); -} - -static void vf610_nfc_send_commands(struct vf610_nfc *nfc, u32 cmd_byte1, - u32 cmd_byte2, u32 cmd_code) -{ - u32 tmp; - - vf610_nfc_send_command(nfc, cmd_byte1, cmd_code); - - tmp = vf610_nfc_read(nfc, NFC_FLASH_CMD1); - tmp &= ~CMD_BYTE2_MASK; - tmp |= cmd_byte2 << CMD_BYTE2_SHIFT; - vf610_nfc_write(nfc, NFC_FLASH_CMD1, tmp); -} - static irqreturn_t vf610_nfc_irq(int irq, void *data) { struct mtd_info *mtd = data; @@ -325,19 +252,6 @@ static irqreturn_t vf610_nfc_irq(int irq, void *data) return IRQ_HANDLED; } -static void vf610_nfc_addr_cycle(struct vf610_nfc *nfc, int column, int page) -{ - if (column != -1) { - if (nfc->chip.options & NAND_BUSWIDTH_16) - column = column / 2; - vf610_nfc_set_field(nfc, NFC_COL_ADDR, COL_ADDR_MASK, - COL_ADDR_SHIFT, column); - } - if (page != -1) - vf610_nfc_set_field(nfc, NFC_ROW_ADDR, ROW_ADDR_MASK, - ROW_ADDR_SHIFT, page); -} - static inline void vf610_nfc_ecc_mode(struct vf610_nfc *nfc, int ecc_mode) { vf610_nfc_set_field(nfc, NFC_FLASH_CONFIG, @@ -350,169 +264,6 @@ static inline void vf610_nfc_transfer_size(struct vf610_nfc *nfc, int size) vf610_nfc_write(nfc, NFC_SECTOR_SIZE, size); } -static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, - int column, int page) -{ - struct vf610_nfc *nfc = mtd_to_nfc(mtd); - int trfr_sz = nfc->chip.options & NAND_BUSWIDTH_16 ? 1 : 0; - - nfc->buf_offset = max(column, 0); - nfc->alt_buf = ALT_BUF_DATA; - - switch (command) { - case NAND_CMD_SEQIN: - /* Use valid column/page from preread... */ - vf610_nfc_addr_cycle(nfc, column, page); - nfc->buf_offset = 0; - - /* - * SEQIN => data => PAGEPROG sequence is done by the controller - * hence we do not need to issue the command here... - */ - return; - case NAND_CMD_PAGEPROG: - trfr_sz += nfc->write_sz; - vf610_nfc_transfer_size(nfc, trfr_sz); - vf610_nfc_send_commands(nfc, NAND_CMD_SEQIN, - command, PROGRAM_PAGE_CMD_CODE); - if (nfc->use_hw_ecc) - vf610_nfc_ecc_mode(nfc, nfc->ecc_mode); - else - vf610_nfc_ecc_mode(nfc, ECC_BYPASS); - break; - - case NAND_CMD_RESET: - vf610_nfc_transfer_size(nfc, 0); - vf610_nfc_send_command(nfc, command, RESET_CMD_CODE); - break; - - case NAND_CMD_READOOB: - trfr_sz += mtd->oobsize; - column = mtd->writesize; - vf610_nfc_transfer_size(nfc, trfr_sz); - vf610_nfc_send_commands(nfc, NAND_CMD_READ0, - NAND_CMD_READSTART, READ_PAGE_CMD_CODE); - vf610_nfc_addr_cycle(nfc, column, page); - vf610_nfc_ecc_mode(nfc, ECC_BYPASS); - break; - - case NAND_CMD_READ0: - trfr_sz += mtd->writesize + mtd->oobsize; - vf610_nfc_transfer_size(nfc, trfr_sz); - vf610_nfc_send_commands(nfc, NAND_CMD_READ0, - NAND_CMD_READSTART, READ_PAGE_CMD_CODE); - vf610_nfc_addr_cycle(nfc, column, page); - vf610_nfc_ecc_mode(nfc, nfc->ecc_mode); - break; - - case NAND_CMD_PARAM: - nfc->alt_buf = ALT_BUF_ONFI; - trfr_sz = 3 * sizeof(struct nand_onfi_params); - vf610_nfc_transfer_size(nfc, trfr_sz); - vf610_nfc_send_command(nfc, command, READ_ONFI_PARAM_CMD_CODE); - vf610_nfc_addr_cycle(nfc, -1, column); - vf610_nfc_ecc_mode(nfc, ECC_BYPASS); - break; - - case NAND_CMD_ERASE1: - vf610_nfc_transfer_size(nfc, 0); - vf610_nfc_send_commands(nfc, command, - NAND_CMD_ERASE2, ERASE_CMD_CODE); - vf610_nfc_addr_cycle(nfc, column, page); - break; - - case NAND_CMD_READID: - nfc->alt_buf = ALT_BUF_ID; - nfc->buf_offset = 0; - vf610_nfc_transfer_size(nfc, 0); - vf610_nfc_send_command(nfc, command, READ_ID_CMD_CODE); - vf610_nfc_addr_cycle(nfc, -1, column); - break; - - case NAND_CMD_STATUS: - nfc->alt_buf = ALT_BUF_STAT; - vf610_nfc_transfer_size(nfc, 0); - vf610_nfc_send_command(nfc, command, STATUS_READ_CMD_CODE); - break; - default: - return; - } - - vf610_nfc_done(nfc); - - nfc->use_hw_ecc = false; - nfc->write_sz = 0; -} - -static void vf610_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len) -{ - struct vf610_nfc *nfc = mtd_to_nfc(mtd); - uint c = nfc->buf_offset; - - /* Alternate buffers are only supported through read_byte */ - WARN_ON(nfc->alt_buf); - - vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, len); - - nfc->buf_offset += len; -} - -static void vf610_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, - int len) -{ - struct vf610_nfc *nfc = mtd_to_nfc(mtd); - uint c = nfc->buf_offset; - uint l; - - l = min_t(uint, len, mtd->writesize + mtd->oobsize - c); - vf610_nfc_memcpy(nfc->regs + NFC_MAIN_AREA(0) + c, buf, l); - - nfc->write_sz += l; - nfc->buf_offset += l; -} - -static uint8_t vf610_nfc_read_byte(struct mtd_info *mtd) -{ - struct vf610_nfc *nfc = mtd_to_nfc(mtd); - u8 tmp; - uint c = nfc->buf_offset; - - switch (nfc->alt_buf) { - case ALT_BUF_ID: - tmp = vf610_nfc_get_id(nfc, c); - break; - case ALT_BUF_STAT: - tmp = vf610_nfc_get_status(nfc); - break; -#ifdef __LITTLE_ENDIAN - case ALT_BUF_ONFI: - /* Reverse byte since the controller uses big endianness */ - c = nfc->buf_offset ^ 0x3; - /* fall-through */ -#endif - default: - tmp = *((u8 *)(nfc->regs + NFC_MAIN_AREA(0) + c)); - break; - } - nfc->buf_offset++; - return tmp; -} - -static u16 vf610_nfc_read_word(struct mtd_info *mtd) -{ - u16 tmp; - - vf610_nfc_read_buf(mtd, (u_char *)&tmp, sizeof(tmp)); - return tmp; -} - -/* If not provided, upper layers apply a fixed delay. */ -static int vf610_nfc_dev_ready(struct mtd_info *mtd) -{ - /* NFC handles R/B internally; always ready. */ - return 1; -} - static inline void vf610_nfc_run(struct vf610_nfc *nfc, u32 col, u32 row, u32 cmd1, u32 cmd2, u32 trfr_sz) { vf610_nfc_set_field(nfc, NFC_COL_ADDR, COL_ADDR_MASK, @@ -934,12 +685,6 @@ static int vf610_nfc_probe(struct platform_device *pdev) goto err_clk; } - chip->dev_ready = vf610_nfc_dev_ready; - chip->cmdfunc = vf610_nfc_command; - chip->read_byte = vf610_nfc_read_byte; - chip->read_word = vf610_nfc_read_word; - chip->read_buf = vf610_nfc_read_buf; - chip->write_buf = vf610_nfc_write_buf; chip->exec_op = vf610_nfc_exec_op; chip->select_chip = vf610_nfc_select_chip; chip->onfi_set_features = nand_onfi_get_set_features_notsupp;