From patchwork Fri Jan 8 16:02:20 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cyrille Pitchen X-Patchwork-Id: 7987551 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id BD4C19F1CC for ; Fri, 8 Jan 2016 16:10:04 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B79892014A for ; Fri, 8 Jan 2016 16:10:03 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A8EA720107 for ; Fri, 8 Jan 2016 16:10:02 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1aHZaU-0004tb-7Z; Fri, 08 Jan 2016 16:08:26 +0000 Received: from eusmtp01.atmel.com ([212.144.249.243]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1aHZXx-000271-AX; Fri, 08 Jan 2016 16:06:47 +0000 Received: from tenerife.corp.atmel.com (10.161.101.13) by eusmtp01.atmel.com (10.161.101.31) with Microsoft SMTP Server id 14.3.235.1; Fri, 8 Jan 2016 17:05:19 +0100 From: Cyrille Pitchen To: , Subject: [PATCH linux-next v2 08/14] mtd: spi-nor: configure the number of dummy clock cycles by manufacturer Date: Fri, 8 Jan 2016 17:02:20 +0100 Message-ID: <7f2f8d9a2097393e64dbc0d324a7d5de74095651.1452268345.git.cyrille.pitchen@atmel.com> X-Mailer: git-send-email 1.8.2.2 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160108_080550_722868_6A2DD55A X-CRM114-Status: GOOD ( 15.84 ) X-Spam-Score: -4.2 (----) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: marex@denx.de, boris.brezillon@free-electrons.com, vigneshr@ti.com, pawel.moll@arm.com, devicetree@vger.kernel.org, ijc+devicetree@hellion.org.uk, nicolas.ferre@atmel.com, linux-kernel@vger.kernel.org, robh+dt@kernel.org, galak@codeaurora.org, mark.rutland@arm.com, Cyrille Pitchen , linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This is a transitional patch which let us set the number of dummy clock cycles by manufacturer. More patches will follow by manufacturer to actually configure the relevant number of dummy clock cycles following the dedicated procedure. For instance, some manufacturers like Spansion configure the number of dummy clock cycles to be used by Fast Read command through some non-volatile register. In such a case, we should avoid updating its value but instead read it then set the nor->read_dummy accordingly. On the other hand, some manufacturers like Micron use some volatile register. In this case, we'd rather update this register to use a number of dummy clock cycles, which is a multiple of 8. Indeed some drivers, like m25p80, only support writing bytes, hence multiples of 8 bits. Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 99 ++++++++++++++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 25 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 067425c7a0ff..353a0f6ac3fe 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -139,24 +139,6 @@ static int read_cr(struct spi_nor *nor) } /* - * Dummy Cycle calculation for different type of read. - * It can be used to support more commands with - * different dummy cycle requirements. - */ -static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor) -{ - switch (nor->flash_read) { - case SPI_NOR_FAST: - case SPI_NOR_DUAL: - case SPI_NOR_QUAD: - return 8; - case SPI_NOR_NORMAL: - return 0; - } - return 0; -} - -/* * Write status register 1 byte * Returns negative if error occurred. */ @@ -1225,6 +1207,7 @@ static int macronix_set_quad_mode(struct spi_nor *nor) * read (performance enhance) mode by mistake! */ nor->read_opcode = SPINOR_OP_READ_1_4_4; + nor->read_dummy = 8; return 0; } @@ -1246,6 +1229,7 @@ static int macronix_set_quad_mode(struct spi_nor *nor) } nor->read_proto = SNOR_PROTO_1_1_4; nor->read_opcode = SPINOR_OP_READ_1_1_4; + nor->read_dummy = 8; return 0; } @@ -1259,12 +1243,27 @@ static int macronix_set_dual_mode(struct spi_nor *nor) { nor->read_proto = SNOR_PROTO_1_1_2; nor->read_opcode = SPINOR_OP_READ_1_1_2; + nor->read_dummy = 8; return 0; } static int macronix_set_single_mode(struct spi_nor *nor) { + u8 read_dummy; + + switch (nor->read_opcode) { + case SPINOR_OP_READ: + case SPINOR_OP_READ4: + read_dummy = 0; + break; + + default: + read_dummy = 8; + break; + } + nor->read_proto = SNOR_PROTO_1_1_1; + nor->read_dummy = read_dummy; return 0; } @@ -1285,6 +1284,7 @@ static int winbond_set_quad_mode(struct spi_nor *nor) * Hence the Fast Read 1-1-1 (0x0b) op code is chosen. */ nor->read_opcode = SPINOR_OP_READ_FAST; + nor->read_dummy = 8; return 0; } @@ -1303,6 +1303,7 @@ static int winbond_set_quad_mode(struct spi_nor *nor) } nor->read_proto = SNOR_PROTO_1_1_4; nor->read_opcode = SPINOR_OP_READ_1_1_4; + nor->read_dummy = 8; return 0; } @@ -1316,12 +1317,27 @@ static int winbond_set_dual_mode(struct spi_nor *nor) { nor->read_proto = SNOR_PROTO_1_1_2; nor->read_opcode = SPINOR_OP_READ_1_1_2; + nor->read_dummy = 8; return 0; } static int winbond_set_single_mode(struct spi_nor *nor) { + u8 read_dummy; + + switch (nor->read_opcode) { + case SPINOR_OP_READ: + case SPINOR_OP_READ4: + read_dummy = 0; + break; + + default: + read_dummy = 8; + break; + } + nor->read_proto = SNOR_PROTO_1_1_1; + nor->read_dummy = read_dummy; return 0; } @@ -1413,6 +1429,7 @@ static int micron_set_quad_mode(struct spi_nor *nor) if (nor->read_proto != SNOR_PROTO_4_4_4) nor->read_proto = SNOR_PROTO_1_1_4; nor->read_opcode = SPINOR_OP_READ_1_1_4; + nor->read_dummy = 8; return 0; } @@ -1442,11 +1459,14 @@ static int micron_set_dual_mode(struct spi_nor *nor) if (nor->read_proto != SNOR_PROTO_2_2_2) nor->read_proto = SNOR_PROTO_1_1_2; nor->read_opcode = SPINOR_OP_READ_1_1_2; + nor->read_dummy = 8; return 0; } static int micron_set_single_mode(struct spi_nor *nor) { + u8 read_dummy; + /* Check whether either the Dual or Quad mode is enabled. */ if (unlikely(nor->read_proto != SNOR_PROTO_1_1_1)) { int ret; @@ -1463,6 +1483,18 @@ static int micron_set_single_mode(struct spi_nor *nor) nor->read_proto = SNOR_PROTO_1_1_1; } + /* Force the number of dummy cycles to 8 for Fast Read, 0 for Read. */ + switch (nor->read_opcode) { + case SPINOR_OP_READ: + case SPINOR_OP_READ4: + read_dummy = 0; + break; + + default: + read_dummy = 8; + break; + } + nor->read_dummy = read_dummy; return 0; } @@ -1477,6 +1509,7 @@ static int spansion_set_quad_mode(struct spi_nor *nor) } nor->read_proto = SNOR_PROTO_1_1_4; nor->read_opcode = SPINOR_OP_READ_1_1_4; + nor->read_dummy = 8; return 0; } @@ -1484,12 +1517,27 @@ static int spansion_set_dual_mode(struct spi_nor *nor) { nor->read_proto = SNOR_PROTO_1_1_2; nor->read_opcode = SPINOR_OP_READ_1_1_2; + nor->read_dummy = 8; return 0; } static int spansion_set_single_mode(struct spi_nor *nor) { + u8 read_dummy; + + switch (nor->read_opcode) { + case SPINOR_OP_READ: + case SPINOR_OP_READ4: + read_dummy = 0; + break; + + default: + read_dummy = 8; + break; + } + nor->read_proto = SNOR_PROTO_1_1_1; + nor->read_dummy = read_dummy; return 0; } @@ -1704,11 +1752,14 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) if (info->flags & SPI_NOR_NO_FR) nor->flash_read = SPI_NOR_NORMAL; - /* Default commands */ - if (nor->flash_read == SPI_NOR_NORMAL) + /* Default commands and number of dummy cycles */ + if (nor->flash_read == SPI_NOR_NORMAL) { nor->read_opcode = SPINOR_OP_READ; - else + nor->read_dummy = 0; + } else { nor->read_opcode = SPINOR_OP_READ_FAST; + nor->read_dummy = 8; + } nor->program_opcode = SPINOR_OP_PP; @@ -1723,8 +1774,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) * - SNOR_PROTO_2_2_2 is either: * + Micron Dual mode enabled * - * The opcodes and the protocols are updated depending on the - * manufacturer. + * The opcodes, the protocols and the number of dummy cycles are updated + * depending on the manufacturer. * The read opcode and protocol should be updated by the relevant * function when entering Quad or Dual mode. */ @@ -1788,8 +1839,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) return -EINVAL; } - nor->read_dummy = spi_nor_read_dummy_cycles(nor); - dev_info(dev, "%s (%lld Kbytes)\n", info->name, (long long)mtd->size >> 10);