From patchwork Wed Feb 3 13:26:54 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cyrille Pitchen X-Patchwork-Id: 8203211 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 3D2FA9F38B for ; Wed, 3 Feb 2016 13:34:44 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 36B72201F2 for ; Wed, 3 Feb 2016 13:34:43 +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 3D8942027D for ; Wed, 3 Feb 2016 13:34:42 +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 1aQxYF-0005Qz-GJ; Wed, 03 Feb 2016 13:32:55 +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 1aQxWp-0008Qs-0g; Wed, 03 Feb 2016 13:32:03 +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; Wed, 3 Feb 2016 14:30:25 +0100 From: Cyrille Pitchen To: , Subject: [PATCH v3 09/14] mtd: spi-nor: configure the number of dummy clock cycles on Micron memories Date: Wed, 3 Feb 2016 14:26:54 +0100 Message-ID: <5ccaf4d6729c2569728cdf0038af6a3ad799647a.1454505161.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-20160203_053127_818217_6545DC7F X-CRM114-Status: GOOD ( 15.58 ) X-Spam-Score: -4.6 (----) 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, beanhuo@micron.com 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.6 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 The spi-nor framework currently expects all Fast Read operations to use 8 dummy clock cycles. Especially some drivers like m25p80 can only support multiple of 8 dummy clock cycles. On Micron memories, the number of dummy clock cycles to be used by Fast Read commands can be safely set to 8 by updating the Volatile Configuration Register (VCR). Also the XIP bit is set at the same time when updating the VCR so the Continuous Read mode is disabled: this prevents us from entering it by mistake. Signed-off-by: Cyrille Pitchen --- drivers/mtd/spi-nor/spi-nor.c | 72 ++++++++++++++++++++++++++++++++++++++----- include/linux/mtd/spi-nor.h | 2 ++ 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index ef520048edae..2b1a26588ae6 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1314,6 +1314,53 @@ static int winbond_set_single_mode(struct spi_nor *nor) return 0; } +static int micron_set_dummy_cycles(struct spi_nor *nor, u8 read_dummy) +{ + u8 vcr, val, mask; + int ret; + + /* Set bit3 (XIP) to disable the Continuous Read mode */ + mask = GENMASK(7, 4) | BIT(3); + val = ((read_dummy << 4) | BIT(3)) & mask; + + /* Read the Volatile Configuration Register (VCR). */ + ret = nor->read_reg(nor, SPINOR_OP_RD_VCR, &vcr, 1); + if (ret < 0) { + dev_err(nor->dev, "error while reading VCR register\n"); + return ret; + } + + /* Check whether we need to update the number of dummy cycles. */ + if ((vcr & mask) == val) { + nor->read_dummy = read_dummy; + return 0; + } + + /* Update the number of dummy into the VCR. */ + write_enable(nor); + vcr = (vcr & ~mask) | val; + ret = nor->write_reg(nor, SPINOR_OP_WR_VCR, &vcr, 1); + if (ret < 0) { + dev_err(nor->dev, "error while writing VCR register\n"); + return ret; + } + + ret = spi_nor_wait_till_ready(nor); + if (ret) + return ret; + + /* Read VCR and check it. */ + ret = nor->read_reg(nor, SPINOR_OP_RD_VCR, &vcr, 1); + if (ret < 0 || (vcr & mask) != val) { + dev_err(nor->dev, "Micron VCR dummy cycles not updated\n"); + return -EINVAL; + } + + /* Save the number of dummy cycles to use with Fast Read commands */ + nor->read_dummy = read_dummy; + return 0; +} + static int micron_set_protocol(struct spi_nor *nor, u8 mask, u8 val, enum spi_nor_protocol proto) { @@ -1398,12 +1445,15 @@ static int micron_set_quad_mode(struct spi_nor *nor) /* * Whatever the Quad mode is enabled or not, the * Fast Read Quad Output 1-1-4 (0x6b) op code is supported. + * Force the number of dummy cycles to 8 and disable the Continuous Read + * mode to prevent some drivers from using it by mistake (m25p80). + * We can change these settings safely as we write into a volatile + * register. */ 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; + return micron_set_dummy_cycles(nor, 8); } static int micron_set_dual_mode(struct spi_nor *nor) @@ -1428,12 +1478,15 @@ static int micron_set_dual_mode(struct spi_nor *nor) /* * Whatever the Dual mode is enabled or not, the * Fast Read Dual Output 1-1-2 (0x3b) op code is supported. + * Force the number of dummy cycles to 8 and disable the Continuous Read + * mode to prevent some drivers from using it by mistake (m25p80). + * We can change these settings safely as we write into a volatile + * register. */ 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; + return micron_set_dummy_cycles(nor, 8); } static int micron_set_single_mode(struct spi_nor *nor) @@ -1456,7 +1509,13 @@ 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. */ + /* + * Force the number of dummy cycles to 8 for Fast Read, 0 for Read + * and disable the Continuous Read mode to prevent some drivers from + * using it by mistake (m25p80). + * We can change these settings safely as we write into a volatile + * register. + */ switch (nor->read_opcode) { case SPINOR_OP_READ: case SPINOR_OP_READ4: @@ -1467,8 +1526,7 @@ static int micron_set_single_mode(struct spi_nor *nor) read_dummy = 8; break; } - nor->read_dummy = read_dummy; - return 0; + return micron_set_dummy_cycles(nor, read_dummy); } static int spansion_set_quad_mode(struct spi_nor *nor) diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index d0a6f343a063..2dc0f8b429ca 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -86,6 +86,8 @@ /* Used for Micron flashes only. */ #define SPINOR_OP_MIO_RDID 0xaf /* Multiple I/O Read JEDEC ID */ +#define SPINOR_OP_RD_VCR 0x85 /* Read VCR register */ +#define SPINOR_OP_WR_VCR 0x81 /* Write VCR register */ #define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */ #define SPINOR_OP_WD_EVCR 0x61 /* Write EVCR register */