From patchwork Wed Apr 23 10:16:50 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Huang Shijie X-Patchwork-Id: 4040061 Return-Path: X-Original-To: patchwork-linux-spi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 344999F319 for ; Wed, 23 Apr 2014 11:14:50 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3668A201F2 for ; Wed, 23 Apr 2014 11:14:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2899A201EC for ; Wed, 23 Apr 2014 11:14:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752113AbaDWLOk (ORCPT ); Wed, 23 Apr 2014 07:14:40 -0400 Received: from mail-bl2lp0212.outbound.protection.outlook.com ([207.46.163.212]:6447 "EHLO na01-bl2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751620AbaDWLOe (ORCPT ); Wed, 23 Apr 2014 07:14:34 -0400 Received: from DM2PR03CA008.namprd03.prod.outlook.com (10.141.52.156) by BLUPR03MB422.namprd03.prod.outlook.com (10.141.78.143) with Microsoft SMTP Server (TLS) id 15.0.921.12; Wed, 23 Apr 2014 11:14:10 +0000 Received: from BN1BFFO11FD048.protection.gbl (2a01:111:f400:7c10::1:124) by DM2PR03CA008.outlook.office365.com (2a01:111:e400:2414::28) with Microsoft SMTP Server (TLS) id 15.0.921.12 via Frontend Transport; Wed, 23 Apr 2014 11:14:10 +0000 Received: from az84smr01.freescale.net (192.88.158.246) by BN1BFFO11FD048.mail.protection.outlook.com (10.58.145.3) with Microsoft SMTP Server (TLS) id 15.0.929.8 via Frontend Transport; Wed, 23 Apr 2014 11:14:10 +0000 Received: from shlinux2.ap.freescale.net (shlinux2.ap.freescale.net [10.192.224.44]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id s3NBDxmV008408; Wed, 23 Apr 2014 04:14:06 -0700 From: Huang Shijie To: CC: , , , , , , , Huang Shijie Subject: [PATCH v1 2/7] mtd: spi-nor: add DDR quad read support Date: Wed, 23 Apr 2014 18:16:50 +0800 Message-ID: <1398248215-26768-3-git-send-email-b32955@freescale.com> X-Mailer: git-send-email 1.7.2.rc3 In-Reply-To: References: X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:192.88.158.246; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10009001)(6009001)(428001)(189002)(199002)(99396002)(50226001)(4396001)(80976001)(77982001)(77096999)(44976005)(19580405001)(19580395003)(50986999)(62966002)(85852003)(92726001)(47776003)(20776003)(79102001)(92566001)(80022001)(74502001)(74662001)(31966008)(575784001)(93916002)(89996001)(76176999)(87286001)(83322001)(6806004)(48376002)(76482001)(81342001)(81542001)(46102001)(33646001)(77156001)(36756003)(50466002)(87936001)(11926002)(88136002)(83072002)(42262001); DIR:OUT; SFP:1101; SCL:1; SRVR:BLUPR03MB422; H:az84smr01.freescale.net; FPR:8068E6FF.A0C65C1B.EFD75777.A184002.2044B; MLV:sfv; PTR:gate-az5.freescale.com; MX:1; A:1; LANG:en; MIME-Version: 1.0 X-Forefront-PRVS: 01901B3451 Received-SPF: None (: freescale.com does not designate permitted sender hosts) X-OriginatorOrg: freescale.com Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham 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 patch adds the DDR quad read support by the following: [1] add SPI_NOR_DDR_QUAD read mode. [2] add DDR Quad read opcodes: SPINOR_OP_READ_1_4_4_D / SPINOR_OP_READ4_1_4_4_D [3] add set_ddr_quad_mode() to initialize for the DDR quad read. Currently it only works for Spansion NOR. [3] set the dummy with 8 for DDR quad read. The m25p80.c can not support the DDR quad read, the SPI NOR controller can set the dummy value in its driver, such as fsl-quadspi.c. Test this patch for Spansion s25fl128s NOR flash. Signed-off-by: Huang Shijie --- drivers/mtd/spi-nor/spi-nor.c | 50 +++++++++++++++++++++++++++++++++++++++- include/linux/mtd/spi-nor.h | 8 +++++- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 1a12f81..e2f69db 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -74,6 +74,15 @@ static int read_cr(struct spi_nor *nor) static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor) { switch (nor->flash_read) { + case SPI_NOR_DDR_QUAD: + /* + * The m25p80.c can not support the DDR quad read. + * We set the dummy cycles to 8 by default. If the SPI NOR + * controller driver has already set it before call the + * spi_nor_scan(), we just keep it as it is. + */ + if (nor->read_dummy) + return nor->read_dummy; case SPI_NOR_FAST: case SPI_NOR_DUAL: case SPI_NOR_QUAD: @@ -402,6 +411,7 @@ struct flash_info { #define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */ #define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */ #define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ +#define SPI_NOR_DDR_QUAD_READ 0x80 /* Flash supports DDR Quad Read */ }; #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ @@ -846,6 +856,24 @@ static int spansion_quad_enable(struct spi_nor *nor) return 0; } +static int set_ddr_quad_mode(struct spi_nor *nor, u32 jedec_id) +{ + int status; + + switch (JEDEC_MFR(jedec_id)) { + case CFI_MFR_AMD: /* Spansion, actually */ + status = spansion_quad_enable(nor); + if (status) { + dev_err(nor->dev, + "Spansion DDR quad-read not enabled\n"); + return -EINVAL; + } + return status; + default: + return -EINVAL; + } +} + static int set_quad_mode(struct spi_nor *nor, u32 jedec_id) { int status; @@ -1016,8 +1044,15 @@ int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id, if (info->flags & SPI_NOR_NO_FR) nor->flash_read = SPI_NOR_NORMAL; - /* Quad/Dual-read mode takes precedence over fast/normal */ - if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) { + /* DDR Quad/Quad/Dual-read mode takes precedence over fast/normal */ + if (mode == SPI_NOR_DDR_QUAD && info->flags & SPI_NOR_DDR_QUAD_READ) { + ret = set_ddr_quad_mode(nor, info->jedec_id); + if (ret) { + dev_err(dev, "DDR quad mode not supported\n"); + return ret; + } + nor->flash_read = SPI_NOR_DDR_QUAD; + } else if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) { ret = set_quad_mode(nor, info->jedec_id); if (ret) { dev_err(dev, "quad mode not supported\n"); @@ -1030,6 +1065,14 @@ int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id, /* Default commands */ switch (nor->flash_read) { + case SPI_NOR_DDR_QUAD: + if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) { /* Spansion */ + nor->read_opcode = SPINOR_OP_READ_1_4_4_D; + } else { + dev_err(dev, "DDR Quad Read is not supported.\n"); + return -EINVAL; + } + break; case SPI_NOR_QUAD: nor->read_opcode = SPINOR_OP_READ_1_1_4; break; @@ -1057,6 +1100,9 @@ int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id, if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) { /* Dedicated 4-byte command set */ switch (nor->flash_read) { + case SPI_NOR_DDR_QUAD: + nor->read_opcode = SPINOR_OP_READ4_1_4_4_D; + break; case SPI_NOR_QUAD: nor->read_opcode = SPINOR_OP_READ4_1_1_4; break; diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 5324184..fea7769 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -12,10 +12,11 @@ /* * Note on opcode nomenclature: some opcodes have a format like - * SPINOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number + * SPINOR_OP_FUNCTION{4,}_x_y_z{_D}. The numbers x, y, and z stand for the number * of I/O lines used for the opcode, address, and data (respectively). The * FUNCTION has an optional suffix of '4', to represent an opcode which - * requires a 4-byte (32-bit) address. + * requires a 4-byte (32-bit) address. The suffix of 'D' stands for the + * DDR mode. */ /* Flash opcodes. */ @@ -26,6 +27,7 @@ #define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */ #define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual SPI) */ #define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad SPI) */ +#define SPINOR_OP_READ_1_4_4_D 0xed /* Read data bytes (DDR Quad SPI) */ #define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */ #define SPINOR_OP_BE_4K 0x20 /* Erase 4KiB block */ #define SPINOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ @@ -40,6 +42,7 @@ #define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */ #define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual SPI) */ #define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */ +#define SPINOR_OP_READ4_1_4_4_D 0xee /* Read data bytes (DDR Quad SPI) */ #define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */ #define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */ @@ -74,6 +77,7 @@ enum read_mode { SPI_NOR_FAST, SPI_NOR_DUAL, SPI_NOR_QUAD, + SPI_NOR_DDR_QUAD, }; /**