From patchwork Fri Oct 12 08:48:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982910 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="ODud7vKK"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42WhMt0plDz9s1c for ; Fri, 12 Oct 2018 19:49:13 +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=obfhWdC8whw+JcaVZfL6s4n58YbwmnX2oBpLpPyw2AI=; b=ODud7vKKcwPf0ccw8443wSvWW4 qMrHhUWnQvKKLOKa5i+epfQQGRp9XprlPl/++5aLOKqqNPqGg76LpqVG6HipOorRc28hzKAsgTPhJ ZVK/5O6uk7xzdim/S9HT4BhMDtgKb6FR7GPVir6EwPUqWdH9462U3T52eDnNtTjIIkAY0HwsPEE3r aTl+dslcTvde/24RCgphYSQe4+JboLR0o1f8w/cxINBfz6DWU05QIMf4sFvfJr3uYm0a5ptWNNj2B eDqdvJhJxBt/SOEBEc5NNR/V4EmGMIPrPo884Su69dGzHnB028+jcbtGAzp9J1HhHyI3Zg5uarxvl iw43vBWA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt7w-0001l0-IY; Fri, 12 Oct 2018 08:48:56 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt7q-0001hH-HE for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:48:52 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 3214320DE2; Fri, 12 Oct 2018 10:48:38 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id C72F3207BF; Fri, 12 Oct 2018 10:48:27 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 01/18] mtd: spi-nor: Add a flash_info entry for Macronix mx25uw51245g Date: Fri, 12 Oct 2018 10:48:08 +0200 Message-Id: <20181012084825.23697-2-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_014850_708489_F2A85E66 X-CRM114-Status: GOOD ( 14.17 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org mx25uw51245g is a SPI NOR that supports the SFDPRD command but returns an empty SFDP page. This forces us to add a new entry in the flash_info table. Note that the NOR supports modes 1-1-1 and 8-8-8, but nothing in between, hence the absence of SPI_NOR_{DUAL,QUAD}_READ flags. Signed-off-by: Boris Brezillon --- drivers/mtd/spi-nor/spi-nor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 1a9b3e6a181d..03c5d86ea687 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1374,6 +1374,7 @@ static const struct flash_info spi_nor_ids[] = { { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) }, { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, + { "mx25uw51245g", INFO(0xc2813a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_4B_OPCODES) }, { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "mx66l1g45g", INFO(0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, From patchwork Fri Oct 12 08:48:09 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982912 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="Bu7UfUqp"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42WhPW29Wpz9s1c for ; Fri, 12 Oct 2018 19:50:39 +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=ZfsdGSwQ8gu4SNb0OhofU43YCJYDDPJvBVjqDz3BpZY=; b=Bu7UfUqpJQYIEG8PjSVvnFJUVX Evt6/dNaigqbmzbcpgxjx/0ehg3HHmDBfEExvLjeymcS9YSzPrbnk8B+3Bv1zLZCoOYuZNpiN2KiF LQoVqosYhFNPqNZXqrE1T9pPJ30R+KfFjwSiVLl9aec5JxsNpXGbjhcCaduuub5IZm1eSxYV3I0Ps OxZDLy9Q2aXyJFwD3Q3etwoTlqr78vSYSkDVJ+5Vr1j5qR/hnVaTm+KKxZCSk7u5cY/wWn8ACTrf5 VqMhf74+GDKKuqX8+BI6h+ZTUuVBMty9mfUr1z3dXB22fmyg7x1GUf1MhexBNjW5yuk6iaclMaz+K 8Dfsx2Fw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt9M-0003Qm-E2; Fri, 12 Oct 2018 08:50:24 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt7q-0001hM-HF for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:48:54 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 84884207BF; Fri, 12 Oct 2018 10:48:38 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id 20AA62083D; Fri, 12 Oct 2018 10:48:28 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 02/18] spi: Prepare things for octo mode support Date: Fri, 12 Oct 2018 10:48:09 +0200 Message-Id: <20181012084825.23697-3-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_014850_896454_98E8CD58 X-CRM114-Status: GOOD ( 15.89 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Add the necessary flags and checks in spi.h, spi.c and spi-mem.c to support octo mode. Signed-off-by: Boris Brezillon --- drivers/spi/spi-mem.c | 7 +++++++ drivers/spi/spi.c | 12 ++++++++++-- include/linux/spi/spi.h | 2 ++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index 4a84b07a3186..2379efcaf1c6 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -121,6 +121,13 @@ static int spi_check_buswidth_req(struct spi_mem *mem, u8 buswidth, bool tx) break; + case 8: + if ((tx && (mode & SPI_TX_OCTO)) || + (!tx && (mode & SPI_RX_OCTO))) + return 0; + + break; + default: break; } diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 9da0bc5a036c..bc6fc74ff4ec 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1573,6 +1573,9 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, case 4: spi->mode |= SPI_TX_QUAD; break; + case 8: + spi->mode |= SPI_TX_OCTO; + break; default: dev_warn(&ctlr->dev, "spi-tx-bus-width %d not supported\n", @@ -1591,6 +1594,9 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, case 4: spi->mode |= SPI_RX_QUAD; break; + case 8: + spi->mode |= SPI_RX_OCTO; + break; default: dev_warn(&ctlr->dev, "spi-rx-bus-width %d not supported\n", @@ -2779,14 +2785,16 @@ int spi_setup(struct spi_device *spi) /* if it is SPI_3WIRE mode, DUAL and QUAD should be forbidden */ if ((spi->mode & SPI_3WIRE) && (spi->mode & - (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD))) + (SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTO | SPI_RX_DUAL | + SPI_RX_QUAD | SPI_RX_OCTO))) return -EINVAL; /* help drivers fail *cleanly* when they need options * that aren't supported with their current controller */ bad_bits = spi->mode & ~spi->controller->mode_bits; ugly_bits = bad_bits & - (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD); + (SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTO | SPI_RX_DUAL | + SPI_RX_QUAD | SPI_RX_OCTO); if (ugly_bits) { dev_warn(&spi->dev, "setup: ignoring unsupported mode bits %x\n", diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index a64235e05321..cea4e49a9e53 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -163,6 +163,8 @@ struct spi_device { #define SPI_TX_QUAD 0x200 /* transmit with 4 wires */ #define SPI_RX_DUAL 0x400 /* receive with 2 wires */ #define SPI_RX_QUAD 0x800 /* receive with 4 wires */ +#define SPI_TX_OCTO 0x1000 /* transmit with 8 wires */ +#define SPI_RX_OCTO 0x2000 /* receive with 8 wires */ int irq; void *controller_state; void *controller_data; From patchwork Fri Oct 12 08:48:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982913 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="OOW+po4N"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42WhQl3N2mz9s1c for ; Fri, 12 Oct 2018 19:51:43 +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=vxhZh9s0zwahpOJMBLt73CpGjD8ROKb4d5ttWwaWlwA=; b=OOW+po4NFVuAL494qBD/Ndz+xx udqS0bpvjXB/x6dsk1mBQhNwwakwioYyySlN465AwRauywqPWn+KYopJp74gKJYnkim3UrZ0nNkBR KfIPCQ6CXsTfKtyxBH/jnDHXTStJwQM7IWuHhOgfJ7rD+vQiLzrAKc6f8BJmDsBYemos6G44asc1o R73EcZrZsXkoPaNRNNZdO+yKuAnuOxC6LmSZEuwZAfQBDyllAhnM3niJX0SBIwEnqBZLGeMIHUpRH sKOuyZgqhQX/ouIc9n8xgiJdCnutac8/pqCMvc8RYuEqCcTpeH97nl/1TbpdACFhO4HvkxctqEluo FEl2k00A==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAtAK-0004BZ-Ej; Fri, 12 Oct 2018 08:51:24 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt7q-0001j7-HI for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:48:55 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 0F07A20898; Fri, 12 Oct 2018 10:48:48 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id 6D16320898; Fri, 12 Oct 2018 10:48:28 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 03/18] spi: spi-mem: Prepare things for DTR mode support Date: Fri, 12 Oct 2018 10:48:10 +0200 Message-Id: <20181012084825.23697-4-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_014850_902313_6D26B7CB X-CRM114-Status: GOOD ( 16.02 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Add dtr fields to the spi_mem_op struct and make sure all DTR operations are rejected for now. We intentionally do not expose a new flag at the spi_device level, since spi memories seem to be the only users of this feature. Signed-off-by: Boris Brezillon --- drivers/spi/spi-mem.c | 3 +++ include/linux/spi/spi-mem.h | 48 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index 2379efcaf1c6..3da57219b539 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -154,6 +154,9 @@ static bool spi_mem_default_supports_op(struct spi_mem *mem, op->data.dir == SPI_MEM_DATA_OUT)) return false; + if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr) + return false; + return true; } EXPORT_SYMBOL_GPL(spi_mem_default_supports_op); diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h index 69ee30456864..cad116005034 100644 --- a/include/linux/spi/spi-mem.h +++ b/include/linux/spi/spi-mem.h @@ -19,6 +19,13 @@ .opcode = __opcode, \ } +#define SPI_MEM_OP_DTR_CMD(__opcode, __buswidth) \ + { \ + .buswidth = __buswidth, \ + .opcode = __opcode, \ + .dtr = true, \ + } + #define SPI_MEM_OP_ADDR(__nbytes, __val, __buswidth) \ { \ .nbytes = __nbytes, \ @@ -26,6 +33,14 @@ .buswidth = __buswidth, \ } +#define SPI_MEM_OP_DTR_ADDR(__nbytes, __val, __buswidth) \ + { \ + .nbytes = __nbytes, \ + .val = __val, \ + .buswidth = __buswidth, \ + .dtr = true, \ + } + #define SPI_MEM_OP_NO_ADDR { } #define SPI_MEM_OP_DUMMY(__nbytes, __buswidth) \ @@ -34,6 +49,13 @@ .buswidth = __buswidth, \ } +#define SPI_MEM_OP_DTR_DUMMY(__nbytes, __buswidth) \ + { \ + .nbytes = __nbytes, \ + .buswidth = __buswidth, \ + .dtr = true, \ + } + #define SPI_MEM_OP_NO_DUMMY { } #define SPI_MEM_OP_DATA_IN(__nbytes, __buf, __buswidth) \ @@ -44,6 +66,15 @@ .buswidth = __buswidth, \ } +#define SPI_MEM_OP_DTR_DATA_IN(__nbytes, __buf, __buswidth) \ + { \ + .dir = SPI_MEM_DATA_IN, \ + .nbytes = __nbytes, \ + .buf.in = __buf, \ + .buswidth = __buswidth, \ + .dtr = true, \ + } + #define SPI_MEM_OP_DATA_OUT(__nbytes, __buf, __buswidth) \ { \ .dir = SPI_MEM_DATA_OUT, \ @@ -52,6 +83,15 @@ .buswidth = __buswidth, \ } +#define SPI_MEM_OP_DTR_DATA_OUT(__nbytes, __buf, __buswidth) \ + { \ + .dir = SPI_MEM_DATA_OUT, \ + .nbytes = __nbytes, \ + .buf.out = __buf, \ + .buswidth = __buswidth, \ + .dtr = true, \ + } + #define SPI_MEM_OP_NO_DATA { } /** @@ -68,10 +108,12 @@ enum spi_mem_data_dir { /** * struct spi_mem_op - describes a SPI memory operation * @cmd.buswidth: number of IO lines used to transmit the command + * @cmd.dtr: set true to transfer opcode in double transfer rate mode * @cmd.opcode: operation opcode * @addr.nbytes: number of address bytes to send. Can be zero if the operation * does not need to send an address * @addr.buswidth: number of IO lines used to transmit the address cycles + * @addr.dtr: set true to transfer address bytes in double transfer rate mode * @addr.val: address value. This value is always sent MSB first on the bus. * Note that only @addr.nbytes are taken into account in this * address value, so users should make sure the value fits in the @@ -79,34 +121,40 @@ enum spi_mem_data_dir { * @dummy.nbytes: number of dummy bytes to send after an opcode or address. Can * be zero if the operation does not require dummy bytes * @dummy.buswidth: number of IO lanes used to transmit the dummy bytes + * @dummy.dtr: set true to transfer dummy bytes in double transfer rate mode * @data.buswidth: number of IO lanes used to send/receive the data * @data.dir: direction of the transfer * @data.nbytes: number of data bytes to send/receive. Can be zero if the * operation does not involve transferring data + * @data.dtr: set true to transfer data bytes in double transfer rate mode * @data.buf.in: input buffer (must be DMA-able) * @data.buf.out: output buffer (must be DMA-able) */ struct spi_mem_op { struct { u8 buswidth; + bool dtr; u8 opcode; } cmd; struct { u8 nbytes; u8 buswidth; + bool dtr; u64 val; } addr; struct { u8 nbytes; u8 buswidth; + bool dtr; } dummy; struct { u8 buswidth; enum spi_mem_data_dir dir; unsigned int nbytes; + bool dtr; union { void *in; const void *out; From patchwork Fri Oct 12 08:48:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982911 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="tbeBODqB"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42WhNK0wVyz9s1c for ; Fri, 12 Oct 2018 19:49:37 +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=BrBsH/jRnEedUGWt9T8d02HEuHpJIpCHxMJQ3EY/piM=; b=tbeBODqBaMV8rTwLEAbM8P7tQA Rm89ES/fFer0AyWxbNdtVcbM4dTVhRrxiVHz30P1E3CqM325M5xDrrRlDP2zZhAYayV6eTgHtHioX xXlfuVztzTAuAHuc9tcLFDsXtU5mEiXC43Kr8ToTXHmp44UCdU+U/2WfXB3FLORCFlt/b45DE6PtV GawrbW5eir0k3ZE30FiuKXt0+RILFKhGvg5OZyeOn2gzAWlF3cLuCYZ3RU5vFKAUn4iQZbVYkAy3W VcXPvd5l4QXNQu2JUIha3o/SCo/ehOkRcGEcz8EQlxWZ0xKirqsTusH4b+wjn0YSuwYgyyIkRYxbG /AfR3kZg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt8P-00021V-H9; Fri, 12 Oct 2018 08:49:25 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt7q-0001j6-HH for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:48:52 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 0D34920DEE; Fri, 12 Oct 2018 10:48:48 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id B7D50208B5; Fri, 12 Oct 2018 10:48:28 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 04/18] spi: spi-mem: Prepare things for dual bytes opcodes support Date: Fri, 12 Oct 2018 10:48:11 +0200 Message-Id: <20181012084825.23697-5-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_014850_874623_7D88F0D2 X-CRM114-Status: GOOD ( 16.83 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Some SPI NORs are using 2bytes opcodes when operated in OPI (Octo Peripheral Interface). Make opcode an u16 and add an nbytes field to specify the number of opcode bytes. Also add the SPI_MEM_OP_[DTR_]CMD_16B() to declare 2bytes opcodes and update spi_mem_default_supports_op() to reject operations with 2 bytes opcodes. Signed-off-by: Boris Brezillon --- drivers/spi/spi-mem.c | 5 ++++- include/linux/spi/spi-mem.h | 21 ++++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index 3da57219b539..10bb852cfaea 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -157,6 +157,9 @@ static bool spi_mem_default_supports_op(struct spi_mem *mem, if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr) return false; + if (op->cmd.nbytes != 1) + return false; + return true; } EXPORT_SYMBOL_GPL(spi_mem_default_supports_op); @@ -171,7 +174,7 @@ static bool spi_mem_buswidth_is_valid(u8 buswidth) static int spi_mem_check_op(const struct spi_mem_op *op) { - if (!op->cmd.buswidth) + if (!op->cmd.buswidth || op->cmd.nbytes < 1 || op->cmd.nbytes > 2) return -EINVAL; if ((op->addr.nbytes && !op->addr.buswidth) || diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h index cad116005034..af54a1c91f93 100644 --- a/include/linux/spi/spi-mem.h +++ b/include/linux/spi/spi-mem.h @@ -17,12 +17,29 @@ { \ .buswidth = __buswidth, \ .opcode = __opcode, \ + .nbytes = 1, \ } #define SPI_MEM_OP_DTR_CMD(__opcode, __buswidth) \ { \ .buswidth = __buswidth, \ .opcode = __opcode, \ + .nbytes = 1, \ + .dtr = true, \ + } + +#define SPI_MEM_OP_CMD_16B(__opcode, __buswidth) \ + { \ + .buswidth = __buswidth, \ + .opcode = __opcode, \ + .nbytes = 2, \ + } + +#define SPI_MEM_OP_DTR_CMD_16B(__opcode, __buswidth) \ + { \ + .buswidth = __buswidth, \ + .opcode = __opcode, \ + .nbytes = 2, \ .dtr = true, \ } @@ -107,6 +124,7 @@ enum spi_mem_data_dir { /** * struct spi_mem_op - describes a SPI memory operation + * @cmd.nbytes: number of opcode bytes (only 1 or 2 are valid) * @cmd.buswidth: number of IO lines used to transmit the command * @cmd.dtr: set true to transfer opcode in double transfer rate mode * @cmd.opcode: operation opcode @@ -132,9 +150,10 @@ enum spi_mem_data_dir { */ struct spi_mem_op { struct { + u8 nbytes; u8 buswidth; bool dtr; - u8 opcode; + u16 opcode; } cmd; struct { From patchwork Fri Oct 12 08:48:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982921 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="MOmEi2SQ"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42WhYB6gG2z9s3T for ; Fri, 12 Oct 2018 19:57:18 +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=Zd0xEQl5WaTVgMw0AA6SqaVzVpzaj983i/Exui2yaY0=; b=MOmEi2SQrbazIagvdTqEIZKm8B lCUpm93ZknZYf7UOHnAPxM6e5m3heknot64kNCdC9djEPbiWQzsQRRdxnv/FGzrw+Q+PJp06MvkMe 9PSzWG8LxFUe0tRbAysgCMJIKvVMQxvIXi+tQKAv5E1054yMqVHlAETNqliKO0aHTRfvcFVZLWwri r18MQEW6gJ+PJbJeBkBU97/qRZYS4pyUmIgVv+YknF3zv8ntrBp5acBZLqJKCn8FItuzVPUerE9MN 6LHoMiss1I0HEPlXdwkBHNbwjJSymfuU1i1hrWiPSwpoKdJ10yaspLIYsisDOnMZRWeqtRJkT5tIH 94ghKgGw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAtFp-00084o-1m; Fri, 12 Oct 2018 08:57:05 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt82-0001kM-Vy for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:49:53 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 4B8F820DE8; Fri, 12 Oct 2018 10:48:48 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id 0CE95208B7; Fri, 12 Oct 2018 10:48:29 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 05/18] spi: spi-mem: mxic: Add support for DTR and Octo mode Date: Fri, 12 Oct 2018 10:48:12 +0200 Message-Id: <20181012084825.23697-6-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_014903_414708_279575AA X-CRM114-Status: GOOD ( 17.34 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Signed-off-by: Boris Brezillon --- drivers/spi/spi-mxic.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c index ce59ea2ecfe2..70e6bc9a099e 100644 --- a/drivers/spi/spi-mxic.c +++ b/drivers/spi/spi-mxic.c @@ -281,10 +281,11 @@ static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf, static bool mxic_spi_mem_supports_op(struct spi_mem *mem, const struct spi_mem_op *op) { - if (op->data.buswidth > 4 || op->addr.buswidth > 4 || - op->dummy.buswidth > 4 || op->cmd.buswidth > 4) + if (op->data.buswidth > 8 || op->addr.buswidth > 8 || + op->dummy.buswidth > 8 || op->cmd.buswidth > 8) return false; + if (op->data.nbytes && op->dummy.nbytes && op->data.buswidth != op->dummy.buswidth) return false; @@ -302,6 +303,7 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem, int nio = 1, i, ret; u32 ss_ctrl; u8 addr[8]; + u8 cmd[2]; ret = mxic_spi_clk_setup(mem->spi); if (ret) @@ -311,6 +313,8 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem, if (ret) return ret; + if (mem->spi->mode & (SPI_RX_OCTO | SPI_TX_OCTO)) + nio = 8; if (mem->spi->mode & (SPI_TX_QUAD | SPI_RX_QUAD)) nio = 4; else if (mem->spi->mode & (SPI_TX_DUAL | SPI_RX_DUAL)) @@ -323,17 +327,21 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem, mxic->regs + HC_CFG); writel(HC_EN_BIT, mxic->regs + HC_EN); - ss_ctrl = OP_CMD_BYTES(1) | OP_CMD_BUSW(fls(op->cmd.buswidth) - 1); + ss_ctrl = OP_CMD_BYTES(op->cmd.nbytes) | + OP_CMD_BUSW(fls(op->cmd.buswidth) - 1) | + (op->cmd.dtr ? OP_CMD_DDR : 0); if (op->addr.nbytes) ss_ctrl |= OP_ADDR_BYTES(op->addr.nbytes) | - OP_ADDR_BUSW(fls(op->addr.buswidth) - 1); + OP_ADDR_BUSW(fls(op->addr.buswidth) - 1) | + (op->addr.dtr ? OP_ADDR_DDR : 0); if (op->dummy.nbytes) ss_ctrl |= OP_DUMMY_CYC(op->dummy.nbytes); if (op->data.nbytes) { - ss_ctrl |= OP_DATA_BUSW(fls(op->data.buswidth) - 1); + ss_ctrl |= OP_DATA_BUSW(fls(op->data.buswidth) - 1) | + (op->data.dtr ? OP_DATA_DDR : 0); if (op->data.dir == SPI_MEM_DATA_IN) ss_ctrl |= OP_READ; } @@ -343,7 +351,14 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem, writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_ASSERT, mxic->regs + HC_CFG); - ret = mxic_spi_data_xfer(mxic, &op->cmd.opcode, NULL, 1); + if (op->cmd.nbytes == 2) { + cmd[0] = op->cmd.opcode >> 8; + cmd[1] = op->cmd.opcode; + } else { + cmd[0] = op->cmd.opcode; + } + + ret = mxic_spi_data_xfer(mxic, cmd, NULL, op->cmd.nbytes); if (ret) goto out; From patchwork Fri Oct 12 08:48:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982925 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="W8utuv0u"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42WhcF5ntNz9s3C for ; Fri, 12 Oct 2018 19:59:57 +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=G8dYcoLGohA4zwbyxNXVFxk8RkkqTX5wI6D9il/lsZc=; b=W8utuv0uRLPzGidd+kW2Ariv/s YhqBZ8bK/P8hoLbKzUzu5PnBkcX69f9HkEdsWGiCV600aAf1kQyf0GK88t6sV0pVfD+w2SsZ2qJ8u NG0Z2BgwjaktDayRyPCMUxATMyIEJ6+OxRV8qxM1soUWhivVJPvJNrv6VOboqiOPIzsCYVyAf93IQ +ljR7kQCtjUCcR7ApmqgbIR5jlBlcX+41lREt+//j8Dy60S/+eOJ2x4zzhsXjVqTuCSmJiyx+jC41 ofh7EvA54u51CZ8lTLl5DtcuMjWuIFmnToQ3FmyER7fYeK6c2bUz2DgZ47susxb1zTF5Wau8Mdzb9 QltbQl7A==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAtIK-0000kJ-P2; Fri, 12 Oct 2018 08:59:40 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt82-0001kN-W3 for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:51:04 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 650D4208B7; Fri, 12 Oct 2018 10:48:48 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id 5B529208C2; Fri, 12 Oct 2018 10:48:29 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 06/18] mtd: spi-nor: Move m25p80 code in spi-nor.c Date: Fri, 12 Oct 2018 10:48:13 +0200 Message-Id: <20181012084825.23697-7-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_014903_551937_1FF5227B X-CRM114-Status: GOOD ( 36.31 ) X-Spam-Note: SpamAssassin invocation failed 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org The m25p80 driver is actually a generic wrapper around the spi-mem layer. Not only the driver name is misleading, but we'd expect such a common logic to be directly available in the core. Another reason for moving this code is that SPI NOR controller drivers should progressively be replaced by SPI controller drivers implementing the spi_mem_ops interface, and when the conversion is done, we should have a single spi-nor driver directly interfacing with the spi-mem layer. While moving the code we also fix a longstanding issue when non-DMA-able buffers are passed by the MTD layer. Signed-off-by: Boris Brezillon --- drivers/mtd/devices/Kconfig | 18 -- drivers/mtd/devices/Makefile | 1 - drivers/mtd/devices/m25p80.c | 324 --------------------- drivers/mtd/spi-nor/Kconfig | 3 +- drivers/mtd/spi-nor/spi-nor.c | 657 ++++++++++++++++++++++++++++++++++++++++-- include/linux/mtd/spi-nor.h | 10 +- 6 files changed, 646 insertions(+), 367 deletions(-) delete mode 100644 drivers/mtd/devices/m25p80.c diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index e514d57a0419..93122dd011b3 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -78,24 +78,6 @@ config MTD_DATAFLASH_OTP other key product data. The second half is programmed with a unique-to-each-chip bit pattern at the factory. -config MTD_M25P80 - tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)" - depends on SPI_MASTER && MTD_SPI_NOR - select SPI_MEM - help - This enables access to most modern SPI flash chips, used for - program and data storage. Series supported include Atmel AT26DF, - Spansion S25SL, SST 25VF, ST M25P, and Winbond W25X. Other chips - are supported as well. See the driver source for the current list, - or to add other chips. - - Note that the original DataFlash chips (AT45 series, not AT26DF), - need an entirely different driver. - - Set up your spi devices with the right board-specific platform data, - if you want to specify device partitioning or to use a device which - doesn't support the JEDEC ID instruction. - config MTD_MCHP23K256 tristate "Microchip 23K256 SRAM" depends on SPI_MASTER diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index 94895eab3066..991c8d12c016 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile @@ -12,7 +12,6 @@ obj-$(CONFIG_MTD_MTDRAM) += mtdram.o obj-$(CONFIG_MTD_LART) += lart.o obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o -obj-$(CONFIG_MTD_M25P80) += m25p80.o obj-$(CONFIG_MTD_MCHP23K256) += mchp23k256.o obj-$(CONFIG_MTD_SPEAR_SMI) += spear_smi.o obj-$(CONFIG_MTD_SST25L) += sst25l.o diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c deleted file mode 100644 index cb14cf985b95..000000000000 --- a/drivers/mtd/devices/m25p80.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * MTD SPI driver for ST M25Pxx (and similar) serial flash chips - * - * Author: Mike Lavender, mike@steroidmicros.com - * - * Copyright (c) 2005, Intec Automation Inc. - * - * Some parts are based on lart.c by Abraham Van Der Merwe - * - * Cleaned up and generalized based on mtd_dataflash.c - * - * This code is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -struct m25p { - struct spi_mem *spimem; - struct spi_nor spi_nor; -}; - -static int m25p80_read_reg(struct spi_nor *nor, u8 code, u8 *val, int len) -{ - struct m25p *flash = nor->priv; - struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(code, 1), - SPI_MEM_OP_NO_ADDR, - SPI_MEM_OP_NO_DUMMY, - SPI_MEM_OP_DATA_IN(len, val, 1)); - int ret; - - ret = spi_mem_exec_op(flash->spimem, &op); - if (ret < 0) - dev_err(&flash->spimem->spi->dev, "error %d reading %x\n", ret, - code); - - return ret; -} - -static int m25p80_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) -{ - struct m25p *flash = nor->priv; - struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 1), - SPI_MEM_OP_NO_ADDR, - SPI_MEM_OP_NO_DUMMY, - SPI_MEM_OP_DATA_OUT(len, buf, 1)); - - return spi_mem_exec_op(flash->spimem, &op); -} - -static ssize_t m25p80_write(struct spi_nor *nor, loff_t to, size_t len, - const u_char *buf) -{ - struct m25p *flash = nor->priv; - struct spi_mem_op op = - SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 1), - SPI_MEM_OP_ADDR(nor->addr_width, to, 1), - SPI_MEM_OP_NO_DUMMY, - SPI_MEM_OP_DATA_OUT(len, buf, 1)); - int ret; - - /* get transfer protocols. */ - op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto); - op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto); - op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto); - - if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second) - op.addr.nbytes = 0; - - ret = spi_mem_adjust_op_size(flash->spimem, &op); - if (ret) - return ret; - op.data.nbytes = len < op.data.nbytes ? len : op.data.nbytes; - - ret = spi_mem_exec_op(flash->spimem, &op); - if (ret) - return ret; - - return op.data.nbytes; -} - -/* - * Read an address range from the nor chip. The address range - * may be any size provided it is within the physical boundaries. - */ -static ssize_t m25p80_read(struct spi_nor *nor, loff_t from, size_t len, - u_char *buf) -{ - struct m25p *flash = nor->priv; - struct spi_mem_op op = - SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 1), - SPI_MEM_OP_ADDR(nor->addr_width, from, 1), - SPI_MEM_OP_DUMMY(nor->read_dummy, 1), - SPI_MEM_OP_DATA_IN(len, buf, 1)); - size_t remaining = len; - int ret; - - /* get transfer protocols. */ - op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto); - op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->read_proto); - op.dummy.buswidth = op.addr.buswidth; - op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto); - - /* convert the dummy cycles to the number of bytes */ - op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8; - - while (remaining) { - op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX; - ret = spi_mem_adjust_op_size(flash->spimem, &op); - if (ret) - return ret; - - ret = spi_mem_exec_op(flash->spimem, &op); - if (ret) - return ret; - - op.addr.val += op.data.nbytes; - remaining -= op.data.nbytes; - op.data.buf.in += op.data.nbytes; - } - - return len; -} - -/* - * board specific setup should have ensured the SPI clock used here - * matches what the READ command supports, at least until this driver - * understands FAST_READ (for clocks over 25 MHz). - */ -static int m25p_probe(struct spi_mem *spimem) -{ - struct spi_device *spi = spimem->spi; - struct flash_platform_data *data; - struct m25p *flash; - struct spi_nor *nor; - struct spi_nor_hwcaps hwcaps = { - .mask = SNOR_HWCAPS_READ | - SNOR_HWCAPS_READ_FAST | - SNOR_HWCAPS_PP, - }; - char *flash_name; - int ret; - - data = dev_get_platdata(&spimem->spi->dev); - - flash = devm_kzalloc(&spimem->spi->dev, sizeof(*flash), GFP_KERNEL); - if (!flash) - return -ENOMEM; - - nor = &flash->spi_nor; - - /* install the hooks */ - nor->read = m25p80_read; - nor->write = m25p80_write; - nor->write_reg = m25p80_write_reg; - nor->read_reg = m25p80_read_reg; - - nor->dev = &spimem->spi->dev; - spi_nor_set_flash_node(nor, spi->dev.of_node); - nor->priv = flash; - - spi_mem_set_drvdata(spimem, flash); - flash->spimem = spimem; - - if (spi->mode & SPI_RX_QUAD) { - hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4; - - if (spi->mode & SPI_TX_QUAD) - hwcaps.mask |= (SNOR_HWCAPS_READ_1_4_4 | - SNOR_HWCAPS_PP_1_1_4 | - SNOR_HWCAPS_PP_1_4_4); - } else if (spi->mode & SPI_RX_DUAL) { - hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2; - - if (spi->mode & SPI_TX_DUAL) - hwcaps.mask |= SNOR_HWCAPS_READ_1_2_2; - } - - if (data && data->name) - nor->mtd.name = data->name; - - if (!nor->mtd.name) - nor->mtd.name = spi_mem_get_name(spimem); - - /* For some (historical?) reason many platforms provide two different - * names in flash_platform_data: "name" and "type". Quite often name is - * set to "m25p80" and then "type" provides a real chip name. - * If that's the case, respect "type" and ignore a "name". - */ - if (data && data->type) - flash_name = data->type; - else if (!strcmp(spi->modalias, "spi-nor")) - flash_name = NULL; /* auto-detect */ - else - flash_name = spi->modalias; - - ret = spi_nor_scan(nor, flash_name, &hwcaps); - if (ret) - return ret; - - return mtd_device_register(&nor->mtd, data ? data->parts : NULL, - data ? data->nr_parts : 0); -} - - -static int m25p_remove(struct spi_mem *spimem) -{ - struct m25p *flash = spi_mem_get_drvdata(spimem); - - spi_nor_restore(&flash->spi_nor); - - /* Clean up MTD stuff. */ - return mtd_device_unregister(&flash->spi_nor.mtd); -} - -static void m25p_shutdown(struct spi_mem *spimem) -{ - struct m25p *flash = spi_mem_get_drvdata(spimem); - - spi_nor_restore(&flash->spi_nor); -} -/* - * Do NOT add to this array without reading the following: - * - * Historically, many flash devices are bound to this driver by their name. But - * since most of these flash are compatible to some extent, and their - * differences can often be differentiated by the JEDEC read-ID command, we - * encourage new users to add support to the spi-nor library, and simply bind - * against a generic string here (e.g., "jedec,spi-nor"). - * - * Many flash names are kept here in this list (as well as in spi-nor.c) to - * keep them available as module aliases for existing platforms. - */ -static const struct spi_device_id m25p_ids[] = { - /* - * Allow non-DT platform devices to bind to the "spi-nor" modalias, and - * hack around the fact that the SPI core does not provide uevent - * matching for .of_match_table - */ - {"spi-nor"}, - - /* - * Entries not used in DTs that should be safe to drop after replacing - * them with "spi-nor" in platform data. - */ - {"s25sl064a"}, {"w25x16"}, {"m25p10"}, {"m25px64"}, - - /* - * Entries that were used in DTs without "jedec,spi-nor" fallback and - * should be kept for backward compatibility. - */ - {"at25df321a"}, {"at25df641"}, {"at26df081a"}, - {"mx25l4005a"}, {"mx25l1606e"}, {"mx25l6405d"}, {"mx25l12805d"}, - {"mx25l25635e"},{"mx66l51235l"}, - {"n25q064"}, {"n25q128a11"}, {"n25q128a13"}, {"n25q512a"}, - {"s25fl256s1"}, {"s25fl512s"}, {"s25sl12801"}, {"s25fl008k"}, - {"s25fl064k"}, - {"sst25vf040b"},{"sst25vf016b"},{"sst25vf032b"},{"sst25wf040"}, - {"m25p40"}, {"m25p80"}, {"m25p16"}, {"m25p32"}, - {"m25p64"}, {"m25p128"}, - {"w25x80"}, {"w25x32"}, {"w25q32"}, {"w25q32dw"}, - {"w25q80bl"}, {"w25q128"}, {"w25q256"}, - - /* Flashes that can't be detected using JEDEC */ - {"m25p05-nonjedec"}, {"m25p10-nonjedec"}, {"m25p20-nonjedec"}, - {"m25p40-nonjedec"}, {"m25p80-nonjedec"}, {"m25p16-nonjedec"}, - {"m25p32-nonjedec"}, {"m25p64-nonjedec"}, {"m25p128-nonjedec"}, - - /* Everspin MRAMs (non-JEDEC) */ - { "mr25h128" }, /* 128 Kib, 40 MHz */ - { "mr25h256" }, /* 256 Kib, 40 MHz */ - { "mr25h10" }, /* 1 Mib, 40 MHz */ - { "mr25h40" }, /* 4 Mib, 40 MHz */ - - { }, -}; -MODULE_DEVICE_TABLE(spi, m25p_ids); - -static const struct of_device_id m25p_of_table[] = { - /* - * Generic compatibility for SPI NOR that can be identified by the - * JEDEC READ ID opcode (0x9F). Use this, if possible. - */ - { .compatible = "jedec,spi-nor" }, - {} -}; -MODULE_DEVICE_TABLE(of, m25p_of_table); - -static struct spi_mem_driver m25p80_driver = { - .spidrv = { - .driver = { - .name = "m25p80", - .of_match_table = m25p_of_table, - }, - .id_table = m25p_ids, - }, - .probe = m25p_probe, - .remove = m25p_remove, - .shutdown = m25p_shutdown, - - /* REVISIT: many of these chips have deep power-down modes, which - * should clearly be entered on suspend() to minimize power use. - * And also when they're otherwise idle... - */ -}; - -module_spi_mem_driver(m25p80_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Mike Lavender"); -MODULE_DESCRIPTION("MTD SPI driver for ST M25Pxx flash chips"); diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig index 6cc9c929ff57..a1b0019edafa 100644 --- a/drivers/mtd/spi-nor/Kconfig +++ b/drivers/mtd/spi-nor/Kconfig @@ -1,6 +1,7 @@ menuconfig MTD_SPI_NOR tristate "SPI-NOR device support" - depends on MTD + depends on MTD && SPI_MASTER + select SPI_MEM help This is the framework for the SPI NOR which can be used by the SPI device drivers and the SPI-NOR device driver. diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 03c5d86ea687..d9b9dd76b987 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -96,6 +97,173 @@ struct flash_info { #define JEDEC_MFR(info) ((info)->id[0]) +static int spi_nor_exec_op(struct spi_nor *nor, struct spi_mem_op *op, + u64 *addr, void *buf, unsigned int len) +{ + int ret; + bool usebouncebuf; + + if (!op || (len && !buf)) + return -EINVAL; + + if (op->addr.nbytes && addr) + op->addr.val = *addr; + + op->data.nbytes = len; + + if (object_is_on_stack(buf) || !virt_addr_valid(buf)) + usebouncebuf = true; + if (len && usebouncebuf) { + if (len > nor->bouncebuf_size) + return -ENOTSUPP; + + if (op->data.dir == SPI_MEM_DATA_IN) { + op->data.buf.in = nor->bouncebuf; + } else { + op->data.buf.out = nor->bouncebuf; + memcpy(nor->bouncebuf, buf, len); + } + } else { + op->data.buf.out = buf; + } + + ret = spi_mem_exec_op(nor->spimem, op); + if (ret) + return ret; + + if (usebouncebuf && len && op->data.dir == SPI_MEM_DATA_IN) + memcpy(buf, nor->bouncebuf, len); + + return 0; +} + +static int spi_nor_data_op(struct spi_nor *nor, struct spi_mem_op *op, + void *buf, unsigned int len) +{ + return spi_nor_exec_op(nor, op, NULL, buf, len); +} + +static int spi_nor_nodata_op(struct spi_nor *nor, struct spi_mem_op *op) +{ + return spi_nor_exec_op(nor, op, NULL, NULL, 0); +} + +static ssize_t spi_nor_spimem_read_data(struct spi_nor *nor, loff_t ofs, + size_t len, u8 *buf) +{ + struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 1), + SPI_MEM_OP_ADDR(nor->addr_width, ofs, + 1), + SPI_MEM_OP_DUMMY(nor->read_dummy, 1), + SPI_MEM_OP_DATA_IN(len, buf, 1)); + bool usebouncebuf = false; + size_t remaining = len; + int ret; + + if (object_is_on_stack(buf) || !virt_addr_valid(buf)) { + usebouncebuf = true; + op.data.buf.in = nor->bouncebuf; + } + + /* get transfer protocols. */ + op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto); + op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->read_proto); + op.dummy.buswidth = op.addr.buswidth; + op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto); + + /* convert the dummy cycles to the number of bytes */ + op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8; + + while (remaining) { + op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX; + if (!usebouncebuf) + op.data.buf.out = buf; + else if (op.data.nbytes > nor->bouncebuf_size) + op.data.nbytes = nor->bouncebuf_size; + + ret = spi_mem_adjust_op_size(nor->spimem, &op); + if (ret) + return ret; + + ret = spi_mem_exec_op(nor->spimem, &op); + if (ret) + return ret; + + if (usebouncebuf) + memcpy(buf, nor->bouncebuf, op.data.nbytes); + + op.addr.val += op.data.nbytes; + remaining -= op.data.nbytes; + buf += op.data.nbytes; + } + + return len; +} + +static ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t ofs, size_t len, + u8 *buf) +{ + if (nor->spimem) + return spi_nor_spimem_read_data(nor, ofs, len, buf); + + return nor->read(nor, ofs, len, buf); +} + +static ssize_t spi_nor_spimem_write_data(struct spi_nor *nor, loff_t ofs, + size_t len, const u8 *buf) +{ + struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 1), + SPI_MEM_OP_ADDR(nor->addr_width, ofs, + 1), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(len, NULL, 1)); + bool usebouncebuf = false; + int ret; + + if (object_is_on_stack(buf) || !virt_addr_valid(buf)) { + usebouncebuf = true; + op.data.buf.out = nor->bouncebuf; + } + + /* get transfer protocols. */ + op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto); + op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto); + op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto); + + if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second) + op.addr.nbytes = 0; + + op.data.nbytes = len < UINT_MAX ? len : UINT_MAX; + + if (!usebouncebuf) { + op.data.buf.out = buf; + } else { + if (op.data.nbytes > nor->bouncebuf_size) + op.data.nbytes = nor->bouncebuf_size; + + memcpy(nor->bouncebuf, buf, op.data.nbytes); + } + + ret = spi_mem_adjust_op_size(nor->spimem, &op); + if (ret) + return ret; + + ret = spi_mem_exec_op(nor->spimem, &op); + if (ret) + return ret; + + return op.data.nbytes; +} + +static ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t ofs, size_t len, + const u8 *buf) +{ + if (nor->spimem) + return spi_nor_spimem_write_data(nor, ofs, len, buf); + + return nor->write(nor, ofs, len, buf); +} + /* * Read the status register, returning its value in the location * Return the status register value. @@ -106,7 +274,18 @@ static int read_sr(struct spi_nor *nor) int ret; u8 val; - ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val, 1); + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_IN(0, NULL, 1)); + + ret = spi_nor_data_op(nor, &op, &val, 1); + } else { + ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val, 1); + } + if (ret < 0) { pr_err("error %d reading SR\n", (int) ret); return ret; @@ -125,7 +304,18 @@ static int read_fsr(struct spi_nor *nor) int ret; u8 val; - ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val, 1); + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(SPINOR_OP_RDFSR, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_IN(0, NULL, 1)); + + ret = spi_nor_data_op(nor, &op, &val, 1); + } else { + ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val, 1); + } + if (ret < 0) { pr_err("error %d reading FSR\n", ret); return ret; @@ -144,7 +334,18 @@ static int read_cr(struct spi_nor *nor) int ret; u8 val; - ret = nor->read_reg(nor, SPINOR_OP_RDCR, &val, 1); + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(SPINOR_OP_RDCR, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_IN(0, NULL, 1)); + + ret = spi_nor_data_op(nor, &op, &val, 1); + } else { + ret = nor->read_reg(nor, SPINOR_OP_RDCR, &val, 1); + } + if (ret < 0) { dev_err(nor->dev, "error %d reading CR\n", ret); return ret; @@ -159,16 +360,37 @@ static int read_cr(struct spi_nor *nor) */ static int write_sr(struct spi_nor *nor, u8 val) { + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_IN(1, NULL, 1)); + + return spi_nor_data_op(nor, &op, &val, 1); + } + nor->cmd_buf[0] = val; return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1); } + /* * Set write enable latch with Write Enable command. * Returns negative if error occurred. */ static int write_enable(struct spi_nor *nor) { + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(SPINOR_OP_WREN, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_NO_DATA); + + return spi_nor_nodata_op(nor, &op); + } + return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0); } @@ -177,6 +399,16 @@ static int write_enable(struct spi_nor *nor) */ static int write_disable(struct spi_nor *nor) { + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(SPINOR_OP_WRDI, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_NO_DATA); + + return spi_nor_nodata_op(nor, &op); + } + return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0); } @@ -272,15 +504,41 @@ static int set_4byte(struct spi_nor *nor, bool enable) * ->set_4byte() implementation. */ nor->cmd_buf[0] = enable << 7; + + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(SPINOR_OP_BRWR, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(1, NULL, 1)); + + return spi_nor_data_op(nor, &op, nor->cmd_buf, 1); + } + return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1); } +static int xread_sr(struct spi_nor *nor, u8 *sr) +{ + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(SPINOR_OP_XRDSR, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_IN(0, NULL, 1)); + + return spi_nor_data_op(nor, &op, sr, 1); + } + + return nor->read_reg(nor, SPINOR_OP_XRDSR, sr, 1); +} + static int s3an_sr_ready(struct spi_nor *nor) { int ret; u8 val; - ret = nor->read_reg(nor, SPINOR_OP_XRDSR, &val, 1); + ret = xread_sr(nor, &val); if (ret < 0) { dev_err(nor->dev, "error %d reading XRDSR\n", (int) ret); return ret; @@ -289,6 +547,22 @@ static int s3an_sr_ready(struct spi_nor *nor) return !!(val & XSR_RDY); } + +static int clear_sr(struct spi_nor *nor) +{ + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(SPINOR_OP_CLSR, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_NO_DATA); + + return spi_nor_nodata_op(nor, &op); + } + + return nor->write_reg(nor, SPINOR_OP_CLSR, NULL, 0); +} + static int spi_nor_sr_ready(struct spi_nor *nor) { int sr = read_sr(nor); @@ -301,13 +575,28 @@ static int spi_nor_sr_ready(struct spi_nor *nor) else dev_err(nor->dev, "Programming Error occurred\n"); - nor->write_reg(nor, SPINOR_OP_CLSR, NULL, 0); + clear_sr(nor); return -EIO; } return !(sr & SR_WIP); } +static int clear_fsr(struct spi_nor *nor) +{ + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(SPINOR_OP_CLFSR, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_NO_DATA); + + return spi_nor_nodata_op(nor, &op); + } + + return nor->write_reg(nor, SPINOR_OP_CLFSR, NULL, 0); +} + static int spi_nor_fsr_ready(struct spi_nor *nor) { int fsr = read_fsr(nor); @@ -324,7 +613,8 @@ static int spi_nor_fsr_ready(struct spi_nor *nor) dev_err(nor->dev, "Attempted to modify a protected sector.\n"); - nor->write_reg(nor, SPINOR_OP_CLFSR, NULL, 0); + clear_fsr(nor); + return -EIO; } @@ -392,6 +682,16 @@ static int erase_chip(struct spi_nor *nor) { dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd.size >> 10)); + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(SPINOR_OP_CHIP_ERASE, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_NO_DATA); + + return spi_nor_nodata_op(nor, &op); + } + return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0); } @@ -454,6 +754,17 @@ static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr) if (nor->erase) return nor->erase(nor, addr); + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(nor->erase_opcode, 1), + SPI_MEM_OP_ADDR(nor->addr_width, addr, + 1), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_NO_DATA); + + return spi_nor_nodata_op(nor, &op); + } + /* * Default implementation, if driver doesn't have a specialized HW * control @@ -1550,13 +1861,28 @@ static const struct flash_info spi_nor_ids[] = { { }, }; +static int read_id(struct spi_nor *nor, u8 *id) +{ + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_IN(0, NULL, 1)); + + return spi_nor_data_op(nor, &op, id, SPI_NOR_MAX_ID_LEN); + } + + return nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); +} + static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) { int tmp; u8 id[SPI_NOR_MAX_ID_LEN]; const struct flash_info *info; - tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); + tmp = read_id(nor, id); if (tmp < 0) { dev_dbg(nor->dev, "error %d reading JEDEC ID\n", tmp); return ERR_PTR(tmp); @@ -1592,7 +1918,7 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, if (nor->flags & SNOR_F_S3AN_ADDR_DEFAULT) addr = spi_nor_s3an_addr_convert(nor, addr); - ret = nor->read(nor, addr, len, buf); + ret = spi_nor_read_data(nor, addr, len, buf); if (ret == 0) { /* We shouldn't see 0-length reads */ ret = -EIO; @@ -1637,7 +1963,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, nor->program_opcode = SPINOR_OP_BP; /* write one byte. */ - ret = nor->write(nor, to, 1, buf); + ret = spi_nor_write_data(nor, to, 1, buf); if (ret < 0) goto sst_write_err; WARN(ret != 1, "While writing 1 byte written %i bytes\n", @@ -1653,7 +1979,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, nor->program_opcode = SPINOR_OP_AAI_WP; /* write two bytes. */ - ret = nor->write(nor, to, 2, buf + actual); + ret = spi_nor_write_data(nor, to, 2, buf + actual); if (ret < 0) goto sst_write_err; WARN(ret != 2, "While writing 2 bytes written %i bytes\n", @@ -1676,7 +2002,7 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, write_enable(nor); nor->program_opcode = SPINOR_OP_BP; - ret = nor->write(nor, to, 1, buf + actual); + ret = spi_nor_write_data(nor, to, 1, buf + actual); if (ret < 0) goto sst_write_err; WARN(ret != 1, "While writing 1 byte written %i bytes\n", @@ -1738,7 +2064,7 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, addr = spi_nor_s3an_addr_convert(nor, addr); write_enable(nor); - ret = nor->write(nor, addr, page_remain, buf + i); + ret = spi_nor_write_data(nor, addr, page_remain, buf + i); if (ret < 0) goto write_err; written = ret; @@ -1767,7 +2093,18 @@ static int write_sr_cr(struct spi_nor *nor, u8 *sr_cr) write_enable(nor); - ret = nor->write_reg(nor, SPINOR_OP_WRSR, sr_cr, 2); + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(0, NULL, 1)); + + ret = spi_nor_data_op(nor, &op, sr_cr, 2); + } else { + ret = nor->write_reg(nor, SPINOR_OP_WRSR, sr_cr, 2); + } + if (ret < 0) { dev_err(nor->dev, "error while writing configuration register\n"); @@ -1909,6 +2246,36 @@ static int spansion_read_cr_quad_enable(struct spi_nor *nor) return 0; } +static int write_sr2(struct spi_nor *nor, u8 sr2) +{ + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(SPINOR_OP_WRSR2, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(0, NULL, 1)); + + return spi_nor_data_op(nor, &op, &sr2, 1); + } + + return nor->write_reg(nor, SPINOR_OP_WRSR2, &sr2, 1); +} + +static int read_sr2(struct spi_nor *nor, u8 *sr2) +{ + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(SPINOR_OP_RDSR2, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_IN(0, NULL, 1)); + + return spi_nor_data_op(nor, &op, sr2, 1); + } + + return nor->read_reg(nor, SPINOR_OP_RDSR2, sr2, 1); +} + /** * sr2_bit7_quad_enable() - set QE bit in Status Register 2. * @nor: pointer to a 'struct spi_nor' @@ -1927,7 +2294,7 @@ static int sr2_bit7_quad_enable(struct spi_nor *nor) int ret; /* Check current Quad Enable bit value. */ - ret = nor->read_reg(nor, SPINOR_OP_RDSR2, &sr2, 1); + ret = read_sr2(nor, &sr2); if (ret) return ret; if (sr2 & SR2_QUAD_EN_BIT7) @@ -1938,7 +2305,7 @@ static int sr2_bit7_quad_enable(struct spi_nor *nor) write_enable(nor); - ret = nor->write_reg(nor, SPINOR_OP_WRSR2, &sr2, 1); + ret = write_sr2(nor, sr2); if (ret < 0) { dev_err(nor->dev, "error while writing status register 2\n"); return -EINVAL; @@ -1951,7 +2318,7 @@ static int sr2_bit7_quad_enable(struct spi_nor *nor) } /* Read back and check it. */ - ret = nor->read_reg(nor, SPINOR_OP_RDSR2, &sr2, 1); + ret = read_sr2(nor, &sr2); if (!(ret > 0 && (sr2 & SR2_QUAD_EN_BIT7))) { dev_err(nor->dev, "SR2 Quad bit not set\n"); return -EINVAL; @@ -1962,8 +2329,10 @@ static int sr2_bit7_quad_enable(struct spi_nor *nor) static int spi_nor_check(struct spi_nor *nor) { - if (!nor->dev || !nor->read || !nor->write || - !nor->read_reg || !nor->write_reg) { + if (!nor->dev || + (!nor->spimem && + (!nor->read || !nor->write || !nor->read_reg || + !nor->write_reg))) { pr_err("spi-nor: please fill all the necessary fields!\n"); return -EINVAL; } @@ -1976,7 +2345,7 @@ static int s3an_nor_scan(const struct flash_info *info, struct spi_nor *nor) int ret; u8 val; - ret = nor->read_reg(nor, SPINOR_OP_XRDSR, &val, 1); + ret = xread_sr(nor, &val); if (ret < 0) { dev_err(nor->dev, "error %d reading XRDSR\n", (int) ret); return ret; @@ -2120,7 +2489,7 @@ static int spi_nor_read_raw(struct spi_nor *nor, u32 addr, size_t len, u8 *buf) int ret; while (len) { - ret = nor->read(nor, addr, len, buf); + ret = spi_nor_read_data(nor, addr, len, buf); if (!ret || ret > len) return -EIO; if (ret < 0) @@ -3545,6 +3914,19 @@ EXPORT_SYMBOL_GPL(spi_nor_restore); static int macronix_set_4byte(struct spi_nor *nor, bool enable) { + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(enable ? + SPINOR_OP_EN4B : + SPINOR_OP_EX4B, + 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_NO_DATA); + + return spi_nor_nodata_op(nor, &op); + } + return nor->write_reg(nor, enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B, NULL, 0); } @@ -3560,6 +3942,22 @@ static int micron_set_4byte(struct spi_nor *nor, bool enable) return ret; } +static int write_ear(struct spi_nor *nor, u8 ear) +{ + if (nor->spimem) { + struct spi_mem_op op = SPI_MEM_OP( + SPI_MEM_OP_CMD(SPINOR_OP_WREAR, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(0, NULL, 1)); + + return spi_nor_data_op(nor, &op, &ear, 1); + } + + nor->cmd_buf[0] = ear; + return nor->write_reg(nor, SPINOR_OP_WREAR, nor->cmd_buf, 1); +} + static int winbond_set_4byte(struct spi_nor *nor, bool enable) { int ret; @@ -3575,8 +3973,7 @@ static int winbond_set_4byte(struct spi_nor *nor, bool enable) * We must clear the register to enable normal behavior. */ write_enable(nor); - nor->cmd_buf[0] = 0; - nor->write_reg(nor, SPINOR_OP_WREAR, nor->cmd_buf, 1); + write_ear(nor, 0); write_disable(nor); return ret; @@ -3839,6 +4236,222 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, } EXPORT_SYMBOL_GPL(spi_nor_scan); +static int spi_nor_probe(struct spi_mem *spimem) +{ + struct spi_device *spi = spimem->spi; + struct flash_platform_data *data; + struct spi_nor *nor; + struct spi_nor_hwcaps hwcaps = { + .mask = SNOR_HWCAPS_READ | + SNOR_HWCAPS_READ_FAST | + SNOR_HWCAPS_PP, + }; + char *flash_name; + int ret; + + data = dev_get_platdata(&spi->dev); + + nor = devm_kzalloc(&spi->dev, sizeof(*nor), GFP_KERNEL); + if (!nor) + return -ENOMEM; + + /* + * We need the bounce buffer early to read/write registers when going + * through the spi-mem layer (buffers have to be DMA-able). + * We'll reallocate a new buffer if nor->page_size turns out to be + * greater than PAGE_SIZE (which shouldn't happen before long since NOR + * pages are usually less than 1KB) after spi_nor_scan() returns. + * Note: we can't use devm_kmalloc() here because it returns an address + * that is not cache-line aligned and is thus not suitable for DMA + * operations. + */ + nor->bouncebuf_size = PAGE_SIZE; + nor->bouncebuf = kmalloc(nor->bouncebuf_size, GFP_KERNEL); + if (!nor->bouncebuf) + return -ENOMEM; + + nor->spimem = spimem; + nor->dev = &spi->dev; + spi_nor_set_flash_node(nor, spi->dev.of_node); + + spi_mem_set_drvdata(spimem, nor); + + if (spi->mode & SPI_RX_QUAD) { + hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4; + + if (spi->mode & SPI_TX_QUAD) + hwcaps.mask |= (SNOR_HWCAPS_READ_1_4_4 | + SNOR_HWCAPS_PP_1_1_4 | + SNOR_HWCAPS_PP_1_4_4); + } else if (spi->mode & SPI_RX_DUAL) { + hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2; + + if (spi->mode & SPI_TX_DUAL) + hwcaps.mask |= SNOR_HWCAPS_READ_1_2_2; + } + + if (data && data->name) + nor->mtd.name = data->name; + + if (!nor->mtd.name) + nor->mtd.name = spi_mem_get_name(spimem); + + /* + * For some (historical?) reason many platforms provide two different + * names in flash_platform_data: "name" and "type". Quite often name is + * set to "m25p80" and then "type" provides a real chip name. + * If that's the case, respect "type" and ignore a "name". + */ + if (data && data->type) + flash_name = data->type; + else if (!strcmp(spi->modalias, "spi-nor")) + flash_name = NULL; /* auto-detect */ + else + flash_name = spi->modalias; + + ret = spi_nor_scan(nor, flash_name, &hwcaps); + if (ret) + goto err_free_bouncebuf; + + /* + * None of the existing parts have > 512B pages, but let's play safe + * and add this logic so that if anyone ever adds support for such + * a NOR we don't end up with buffer overflows. + */ + if (nor->page_size > PAGE_SIZE) { + nor->bouncebuf_size = nor->page_size; + kfree(nor->bouncebuf); + nor->bouncebuf = kmalloc(nor->bouncebuf_size, GFP_KERNEL); + if (!nor->bouncebuf) { + ret = -ENOMEM; + goto err_free_bouncebuf; + } + } + + ret = mtd_device_register(&nor->mtd, data ? data->parts : NULL, + data ? data->nr_parts : 0); + if (ret) + goto err_free_bouncebuf; + + return 0; + +err_free_bouncebuf: + kfree(nor->bouncebuf); + + return ret; +} + + +static int spi_nor_remove(struct spi_mem *spimem) +{ + struct spi_nor *nor = spi_mem_get_drvdata(spimem); + int ret; + + spi_nor_restore(nor); + + /* Clean up MTD stuff. */ + ret = mtd_device_unregister(&nor->mtd); + if (ret) + return ret; + + kfree(nor->bouncebuf); + + return 0; +} + +static void spi_nor_shutdown(struct spi_mem *spimem) +{ + struct spi_nor *nor = spi_mem_get_drvdata(spimem); + + spi_nor_restore(nor); +} + +/* + * Do NOT add to this array without reading the following: + * + * Historically, many flash devices are bound to this driver by their name. But + * since most of these flash are compatible to some extent, and their + * differences can often be differentiated by the JEDEC read-ID command, we + * encourage new users to add support to the spi-nor library, and simply bind + * against a generic string here (e.g., "jedec,spi-nor"). + * + * Many flash names are kept here in this list (as well as in spi-nor.c) to + * keep them available as module aliases for existing platforms. + */ +static const struct spi_device_id spi_nor_dev_ids[] = { + /* + * Allow non-DT platform devices to bind to the "spi-nor" modalias, and + * hack around the fact that the SPI core does not provide uevent + * matching for .of_match_table + */ + {"spi-nor"}, + + /* + * Entries not used in DTs that should be safe to drop after replacing + * them with "spi-nor" in platform data. + */ + {"s25sl064a"}, {"w25x16"}, {"m25p10"}, {"m25px64"}, + + /* + * Entries that were used in DTs without "jedec,spi-nor" fallback and + * should be kept for backward compatibility. + */ + {"at25df321a"}, {"at25df641"}, {"at26df081a"}, + {"mx25l4005a"}, {"mx25l1606e"}, {"mx25l6405d"}, {"mx25l12805d"}, + {"mx25l25635e"},{"mx66l51235l"}, + {"n25q064"}, {"n25q128a11"}, {"n25q128a13"}, {"n25q512a"}, + {"s25fl256s1"}, {"s25fl512s"}, {"s25sl12801"}, {"s25fl008k"}, + {"s25fl064k"}, + {"sst25vf040b"},{"sst25vf016b"},{"sst25vf032b"},{"sst25wf040"}, + {"m25p40"}, {"m25p80"}, {"m25p16"}, {"m25p32"}, + {"m25p64"}, {"m25p128"}, + {"w25x80"}, {"w25x32"}, {"w25q32"}, {"w25q32dw"}, + {"w25q80bl"}, {"w25q128"}, {"w25q256"}, + + /* Flashes that can't be detected using JEDEC */ + {"m25p05-nonjedec"}, {"m25p10-nonjedec"}, {"m25p20-nonjedec"}, + {"m25p40-nonjedec"}, {"m25p80-nonjedec"}, {"m25p16-nonjedec"}, + {"m25p32-nonjedec"}, {"m25p64-nonjedec"}, {"m25p128-nonjedec"}, + + /* Everspin MRAMs (non-JEDEC) */ + { "mr25h128" }, /* 128 Kib, 40 MHz */ + { "mr25h256" }, /* 256 Kib, 40 MHz */ + { "mr25h10" }, /* 1 Mib, 40 MHz */ + { "mr25h40" }, /* 4 Mib, 40 MHz */ + + { }, +}; +MODULE_DEVICE_TABLE(spi, spi_nor_ids); + +static const struct of_device_id spi_nor_of_table[] = { + /* + * Generic compatibility for SPI NOR that can be identified by the + * JEDEC READ ID opcode (0x9F). Use this, if possible. + */ + { .compatible = "jedec,spi-nor" }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, spi_nor_of_table); + +/* + * REVISIT: many of these chips have deep power-down modes, which + * should clearly be entered on suspend() to minimize power use. + * And also when they're otherwise idle... + */ +static struct spi_mem_driver spi_nor_driver = { + .spidrv = { + .driver = { + .name = "spi-nor", + .of_match_table = spi_nor_of_table, + }, + .id_table = spi_nor_dev_ids, + }, + .probe = spi_nor_probe, + .remove = spi_nor_remove, + .shutdown = spi_nor_shutdown, +}; +module_spi_mem_driver(spi_nor_driver); + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Huang Shijie "); MODULE_AUTHOR("Mike Lavender"); diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 09cb85e02de1..7ab70651a0f8 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -13,6 +13,7 @@ #include #include #include +#include /* * Manufacturer IDs @@ -337,6 +338,10 @@ struct flash_info; * @mtd: point to a mtd_info structure * @lock: the lock for the read/write/erase/lock/unlock operations * @dev: point to a spi device, or a spi nor controller device. + * @spimem: point to the spi mem device + * @bouncebuf: bounce buffer used when the buffer passed by the MTD + * layer is not DMA-able + * @bouncebuf_size: size of the bounce buffer * @info: spi-nor part JDEC MFR id and other info * @page_size: the page size of the SPI NOR * @addr_width: number of address bytes @@ -353,7 +358,7 @@ struct flash_info; * @erase_map: the erase map of the SPI NOR * @prepare: [OPTIONAL] do some preparations for the * read/write/erase/lock/unlock operations - * @unprepare: [OPTIONAL] do some post work after the +* @unprepare: [OPTIONAL] do some post work after the * read/write/erase/lock/unlock operations * @read_reg: [DRIVER-SPECIFIC] read out the register * @write_reg: [DRIVER-SPECIFIC] write data to the register @@ -373,6 +378,9 @@ struct spi_nor { struct mtd_info mtd; struct mutex lock; struct device *dev; + struct spi_mem *spimem; + void *bouncebuf; + unsigned int bouncebuf_size; const struct flash_info *info; u32 page_size; u8 addr_width; From patchwork Fri Oct 12 08:48:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982922 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="mTNMFICf"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42WhYv400Jz9s3C for ; Fri, 12 Oct 2018 19:57:55 +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=06qMUFkHf+Se5MWuipVRowWbZ20yxLVbGOjxiLqIqfU=; b=mTNMFICfNVDRsR+NNMkYvkUWEs df8GTuSbIZ5coPOL9WrT6rLeiHQtpUXoLMt8EfhxumLniDv7kxOoZE17/gJaFheapLPuRobY/LNZm 7QLQ/zvSNhKWuGn8ZXq//iPnmT9SXDvOzwfl7vuhfgGzmYgvynM6Hop1lvhIfjjWKmLD8+tNVFnb8 BsVvxvjNAtKfkF7t3ZWkQlL+O6RGb6gpsAREMnTOrr18/5PyadXLzQke60SQoJXLPSIyaYMyCu2Yt TCkFzIkuj21OopTbvRYRCVtJA0U4C9lgebQQUz1SjSf15iT0E26BvpDPGdxwu+hi8MTiTl4V7UaJE cR1utsxg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAtGP-0008KN-Gl; Fri, 12 Oct 2018 08:57:41 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt82-0001kP-W2 for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:50:03 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id A5F09208C2; Fri, 12 Oct 2018 10:48:48 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id B1F74208F4; Fri, 12 Oct 2018 10:48:29 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 07/18] mtd: spi-nor: Rework hwcaps selection for the spi-mem case Date: Fri, 12 Oct 2018 10:48:14 +0200 Message-Id: <20181012084825.23697-8-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_014903_450030_05DCD075 X-CRM114-Status: GOOD ( 23.41 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org The spi-mem layer provides a spi_mem_supports_op() function to check whether a specific operation is supported by the controller or not. This is much more accurate than the hwcaps selection logic based on SPI_{RX,TX}_ flags. Rework the hwcaps selection logic to use spi_mem_supports_op() when nor->spimem != NULL. Signed-off-by: Boris Brezillon --- drivers/mtd/spi-nor/spi-nor.c | 157 ++++++++++++++++++++++++++++++++++-------- include/linux/mtd/spi-nor.h | 14 ++++ 2 files changed, 142 insertions(+), 29 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index d9b9dd76b987..46e5d5d4a423 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -2839,6 +2839,110 @@ static int spi_nor_hwcaps_pp2cmd(u32 hwcaps) ARRAY_SIZE(hwcaps_pp2cmd)); } +static int spi_nor_spimem_check_readop(struct spi_nor *nor, + const struct spi_nor_read_command *read) +{ + struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(read->opcode, 1), + SPI_MEM_OP_ADDR(3, 0, 1), + SPI_MEM_OP_DUMMY(0, 1), + SPI_MEM_OP_DATA_IN(0, NULL, 1)); + + op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(read->proto); + op.addr.buswidth = spi_nor_get_protocol_addr_nbits(read->proto); + op.data.buswidth = spi_nor_get_protocol_data_nbits(read->proto); + op.dummy.buswidth = op.addr.buswidth; + op.dummy.nbytes = (read->num_mode_clocks + read->num_wait_states) * + op.dummy.buswidth / 8; + + /* + * First test with 3 address bytes. The opcode itself might already + * be a 4B addressing opcode but we don't care, because SPI controller + * implementation should not check the opcode, but just the sequence. + */ + if (!spi_mem_supports_op(nor->spimem, &op)) + return -ENOTSUPP; + + /* Now test with 4 address bytes. */ + op.addr.nbytes = 4; + if (!spi_mem_supports_op(nor->spimem, &op)) + return -ENOTSUPP; + + return 0; +} + +static int spi_nor_spimem_check_progop(struct spi_nor *nor, + const struct spi_nor_pp_command *pp) +{ + struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(pp->opcode, 1), + SPI_MEM_OP_ADDR(3, 0, 1), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(0, NULL, 1)); + + op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(pp->proto); + op.addr.buswidth = spi_nor_get_protocol_addr_nbits(pp->proto); + op.data.buswidth = spi_nor_get_protocol_data_nbits(pp->proto); + + /* + * First test with 3 address bytes. The opcode itself might already + * be a 4B addressing opcode but we don't care, because SPI controller + * implementation should not check the opcode, but just the sequence. + */ + if (!spi_mem_supports_op(nor->spimem, &op)) + return -ENOTSUPP; + + /* Now test with 4 address bytes. */ + op.addr.nbytes = 4; + if (!spi_mem_supports_op(nor->spimem, &op)) + return -ENOTSUPP; + + return 0; +} + +static void +spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, + const struct spi_nor_flash_parameter *params, + u32 *hwcaps) +{ + unsigned int cap; + + /* DTR modes are not supported yet, mask them all. */ + *hwcaps &= ~SNOR_HWCAPS_DTR; + + /* X-X-X modes are not supported yet, mask them all. */ + *hwcaps &= ~SNOR_HWCAPS_X_X_X; + + /* Start with read commands. */ + for (cap = 0; cap < 32; cap++) { + int idx; + + if (!(*hwcaps & BIT(cap))) + continue; + + idx = spi_nor_hwcaps_read2cmd(BIT(cap)); + if (idx < 0) + continue; + + if (spi_nor_spimem_check_readop(nor, ¶ms->reads[idx])) + *hwcaps &= ~BIT(cap); + } + + /* Now check program commands. */ + for (cap = 0; cap < 32; cap++) { + int idx; + + if (!(*hwcaps & BIT(cap))) + continue; + + idx = spi_nor_hwcaps_pp2cmd(BIT(cap)); + if (idx < 0) + continue; + + if (spi_nor_spimem_check_progop(nor, + ¶ms->page_programs[idx])) + *hwcaps &= ~BIT(cap); + } +} + /** * spi_nor_set_erase_type() - set a SPI NOR erase type * @erase: pointer to a structure that describes a SPI NOR erase type @@ -3800,16 +3904,25 @@ static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info, */ shared_mask = hwcaps->mask & params->hwcaps.mask; - /* SPI n-n-n protocols are not supported yet. */ - ignored_mask = (SNOR_HWCAPS_READ_2_2_2 | - SNOR_HWCAPS_READ_4_4_4 | - SNOR_HWCAPS_READ_8_8_8 | - SNOR_HWCAPS_PP_4_4_4 | - SNOR_HWCAPS_PP_8_8_8); - if (shared_mask & ignored_mask) { - dev_dbg(nor->dev, - "SPI n-n-n protocols are not supported yet.\n"); - shared_mask &= ~ignored_mask; + if (nor->spimem) { + /* + * When called from spi_nor_probe(), all caps are set and we + * need to discard some of them based on what the SPI + * controller actually supports (using spi_mem_supports_op()). + */ + spi_nor_spimem_adjust_hwcaps(nor, params, &shared_mask); + } else { + /* + * SPI n-n-n protocols are not supported when the SPI + * controller directly implements the spi_nor interface. + * Yet another reason to switch to spi-mem. + */ + ignored_mask = SNOR_HWCAPS_X_X_X; + if (shared_mask & ignored_mask) { + dev_dbg(nor->dev, + "SPI n-n-n protocols are not supported.\n"); + shared_mask &= ~ignored_mask; + } } /* Select the (Fast) Read command. */ @@ -4241,11 +4354,11 @@ static int spi_nor_probe(struct spi_mem *spimem) struct spi_device *spi = spimem->spi; struct flash_platform_data *data; struct spi_nor *nor; - struct spi_nor_hwcaps hwcaps = { - .mask = SNOR_HWCAPS_READ | - SNOR_HWCAPS_READ_FAST | - SNOR_HWCAPS_PP, - }; + /* + * Enable all caps by default. The core will mask them after + * checking what's really supported using spi_mem_supports_op(). + */ + struct spi_nor_hwcaps hwcaps = { .mask = SNOR_HWCAPS_ALL }; char *flash_name; int ret; @@ -4276,20 +4389,6 @@ static int spi_nor_probe(struct spi_mem *spimem) spi_mem_set_drvdata(spimem, nor); - if (spi->mode & SPI_RX_QUAD) { - hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4; - - if (spi->mode & SPI_TX_QUAD) - hwcaps.mask |= (SNOR_HWCAPS_READ_1_4_4 | - SNOR_HWCAPS_PP_1_1_4 | - SNOR_HWCAPS_PP_1_4_4); - } else if (spi->mode & SPI_RX_DUAL) { - hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2; - - if (spi->mode & SPI_TX_DUAL) - hwcaps.mask |= SNOR_HWCAPS_READ_1_2_2; - } - if (data && data->name) nor->mtd.name = data->name; diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 7ab70651a0f8..93400b17fbd0 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -517,6 +517,20 @@ struct spi_nor_hwcaps { #define SNOR_HWCAPS_PP_1_8_8 BIT(21) #define SNOR_HWCAPS_PP_8_8_8 BIT(22) +#define SNOR_HWCAPS_X_X_X (SNOR_HWCAPS_READ_2_2_2 | \ + SNOR_HWCAPS_READ_4_4_4 | \ + SNOR_HWCAPS_READ_8_8_8 | \ + SNOR_HWCAPS_PP_4_4_4 | \ + SNOR_HWCAPS_PP_8_8_8) + +#define SNOR_HWCAPS_DTR (SNOR_HWCAPS_READ_1_1_1_DTR | \ + SNOR_HWCAPS_READ_1_2_2_DTR | \ + SNOR_HWCAPS_READ_1_4_4_DTR | \ + SNOR_HWCAPS_READ_1_8_8_DTR) + +#define SNOR_HWCAPS_ALL (SNOR_HWCAPS_READ_MASK | \ + SNOR_HWCAPS_PP_MASK) + /** * spi_nor_scan() - scan the SPI NOR * @nor: the spi_nor structure From patchwork Fri Oct 12 08:48:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982927 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="ZbIujT3z"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42Whfm3JSqz9s3Z for ; Fri, 12 Oct 2018 20:02:08 +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=ZP9JGzGToXhBoaqxJb3uahAUVabk0jfX6QLooXvJP/8=; b=ZbIujT3zHGoLYAH+MG3Xf9/70C GcR5bKXMSpvfBogaYQGv4FR9ECMq8ftVvVDlahWWCHEdRuB3nif7qty4NihlNcS18ozL5AiE+MBRN 7uK+D+pFzAMdwttxPymvRZwKWXqSejIX9GterRZP0fg4Hz+GJ2zgwqccP9oRlSzDbS24KYXArWF0B fGWh4oV9cttWLyo3M/EiAwaYnVCRXdPwO+w4jwRfEgRizJEvMNXGTMSj5eVYU47wF70+fzPMaxxvU L9N/ZWzYhwquIFMOL/jup0at9DO2dOTB3Z4H0wZjqQp2C+XT+pk70SHLana1IZfUgky34AvDrwnCX ssI409FA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAtKT-0002pG-TC; Fri, 12 Oct 2018 09:01:54 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt82-0001kQ-Vz for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:49:46 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id A8032208B5; Fri, 12 Oct 2018 10:48:48 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id 196A520DB5; Fri, 12 Oct 2018 10:48:30 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 08/18] mtd: spi-nor: Define the DPI, QPI and OPI hwcaps Date: Fri, 12 Oct 2018 10:48:15 +0200 Message-Id: <20181012084825.23697-9-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_014903_419228_EA79300F X-CRM114-Status: GOOD ( 18.58 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Entering Dual, Quad or Octo Peripheral mode implies sending all following operations using the 2-2-2, 4-4-4 or 8-8-8 protocol, so, differentiating read/program operations is useless in this case. Define the DPI, QPI and OPI hwcap flags to replace the {READ,PP}{2_2_2,4_4_4,8_8_8} ones. While doing that, we get rid of the READ_{2_2_2,4_4_4} SFDP parsing bits, because it doesn't make sense to support only READs in Dual/Quad mode. Signed-off-by: Boris Brezillon --- drivers/mtd/spi-nor/atmel-quadspi.c | 5 ++- drivers/mtd/spi-nor/spi-nor.c | 26 +++------------- include/linux/mtd/spi-nor.h | 61 +++++++++++++++++++++---------------- 3 files changed, 41 insertions(+), 51 deletions(-) diff --git a/drivers/mtd/spi-nor/atmel-quadspi.c b/drivers/mtd/spi-nor/atmel-quadspi.c index 820048726b4f..e0f291492fd7 100644 --- a/drivers/mtd/spi-nor/atmel-quadspi.c +++ b/drivers/mtd/spi-nor/atmel-quadspi.c @@ -609,14 +609,13 @@ static int atmel_qspi_probe(struct platform_device *pdev) SNOR_HWCAPS_READ_FAST | SNOR_HWCAPS_READ_1_1_2 | SNOR_HWCAPS_READ_1_2_2 | - SNOR_HWCAPS_READ_2_2_2 | SNOR_HWCAPS_READ_1_1_4 | SNOR_HWCAPS_READ_1_4_4 | - SNOR_HWCAPS_READ_4_4_4 | SNOR_HWCAPS_PP | SNOR_HWCAPS_PP_1_1_4 | SNOR_HWCAPS_PP_1_4_4 | - SNOR_HWCAPS_PP_4_4_4, + SNOR_HWCAPS_DPI | + SNOR_HWCAPS_QPI, }; struct device_node *child, *np = pdev->dev.of_node; struct atmel_qspi *aq; diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 46e5d5d4a423..7fad94588c55 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -2732,14 +2732,6 @@ static const struct sfdp_bfpt_read sfdp_bfpt_reads[] = { SNOR_PROTO_1_2_2, }, - /* Fast Read 2-2-2 */ - { - SNOR_HWCAPS_READ_2_2_2, - BFPT_DWORD(5), BIT(0), /* Supported bit */ - BFPT_DWORD(6), 16, /* Settings */ - SNOR_PROTO_2_2_2, - }, - /* Fast Read 1-1-4 */ { SNOR_HWCAPS_READ_1_1_4, @@ -2755,14 +2747,6 @@ static const struct sfdp_bfpt_read sfdp_bfpt_reads[] = { BFPT_DWORD(3), 0, /* Settings */ SNOR_PROTO_1_4_4, }, - - /* Fast Read 4-4-4 */ - { - SNOR_HWCAPS_READ_4_4_4, - BFPT_DWORD(5), BIT(4), /* Supported bit */ - BFPT_DWORD(7), 16, /* Settings */ - SNOR_PROTO_4_4_4, - }, }; struct sfdp_bfpt_erase { @@ -2807,15 +2791,15 @@ static int spi_nor_hwcaps_read2cmd(u32 hwcaps) { SNOR_HWCAPS_READ_1_1_1_DTR, SNOR_CMD_READ_1_1_1_DTR }, { SNOR_HWCAPS_READ_1_1_2, SNOR_CMD_READ_1_1_2 }, { SNOR_HWCAPS_READ_1_2_2, SNOR_CMD_READ_1_2_2 }, - { SNOR_HWCAPS_READ_2_2_2, SNOR_CMD_READ_2_2_2 }, + { SNOR_HWCAPS_DPI, SNOR_CMD_READ_2_2_2 }, { SNOR_HWCAPS_READ_1_2_2_DTR, SNOR_CMD_READ_1_2_2_DTR }, { SNOR_HWCAPS_READ_1_1_4, SNOR_CMD_READ_1_1_4 }, { SNOR_HWCAPS_READ_1_4_4, SNOR_CMD_READ_1_4_4 }, - { SNOR_HWCAPS_READ_4_4_4, SNOR_CMD_READ_4_4_4 }, + { SNOR_HWCAPS_QPI, SNOR_CMD_READ_4_4_4 }, { SNOR_HWCAPS_READ_1_4_4_DTR, SNOR_CMD_READ_1_4_4_DTR }, { SNOR_HWCAPS_READ_1_1_8, SNOR_CMD_READ_1_1_8 }, { SNOR_HWCAPS_READ_1_8_8, SNOR_CMD_READ_1_8_8 }, - { SNOR_HWCAPS_READ_8_8_8, SNOR_CMD_READ_8_8_8 }, + { SNOR_HWCAPS_OPI, SNOR_CMD_READ_8_8_8 }, { SNOR_HWCAPS_READ_1_8_8_DTR, SNOR_CMD_READ_1_8_8_DTR }, }; @@ -2829,10 +2813,10 @@ static int spi_nor_hwcaps_pp2cmd(u32 hwcaps) { SNOR_HWCAPS_PP, SNOR_CMD_PP }, { SNOR_HWCAPS_PP_1_1_4, SNOR_CMD_PP_1_1_4 }, { SNOR_HWCAPS_PP_1_4_4, SNOR_CMD_PP_1_4_4 }, - { SNOR_HWCAPS_PP_4_4_4, SNOR_CMD_PP_4_4_4 }, + { SNOR_HWCAPS_QPI, SNOR_CMD_PP_4_4_4 }, { SNOR_HWCAPS_PP_1_1_8, SNOR_CMD_PP_1_1_8 }, { SNOR_HWCAPS_PP_1_8_8, SNOR_CMD_PP_1_8_8 }, - { SNOR_HWCAPS_PP_8_8_8, SNOR_CMD_PP_8_8_8 }, + { SNOR_HWCAPS_OPI, SNOR_CMD_PP_8_8_8 }, }; return spi_nor_hwcaps2cmd(hwcaps, hwcaps_pp2cmd, diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 93400b17fbd0..f2154672f75a 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -472,28 +472,25 @@ struct spi_nor_hwcaps { * then Quad SPI protocols before Dual SPI protocols, Fast Read and lastly * (Slow) Read. */ -#define SNOR_HWCAPS_READ_MASK GENMASK(14, 0) +#define SNOR_HWCAPS_READ_MASK GENMASK(11, 0) #define SNOR_HWCAPS_READ BIT(0) #define SNOR_HWCAPS_READ_FAST BIT(1) #define SNOR_HWCAPS_READ_1_1_1_DTR BIT(2) -#define SNOR_HWCAPS_READ_DUAL GENMASK(6, 3) +#define SNOR_HWCAPS_READ_DUAL GENMASK(5, 3) #define SNOR_HWCAPS_READ_1_1_2 BIT(3) #define SNOR_HWCAPS_READ_1_2_2 BIT(4) -#define SNOR_HWCAPS_READ_2_2_2 BIT(5) -#define SNOR_HWCAPS_READ_1_2_2_DTR BIT(6) +#define SNOR_HWCAPS_READ_1_2_2_DTR BIT(5) -#define SNOR_HWCAPS_READ_QUAD GENMASK(10, 7) -#define SNOR_HWCAPS_READ_1_1_4 BIT(7) -#define SNOR_HWCAPS_READ_1_4_4 BIT(8) -#define SNOR_HWCAPS_READ_4_4_4 BIT(9) -#define SNOR_HWCAPS_READ_1_4_4_DTR BIT(10) +#define SNOR_HWCAPS_READ_QUAD GENMASK(8, 6) +#define SNOR_HWCAPS_READ_1_1_4 BIT(6) +#define SNOR_HWCAPS_READ_1_4_4 BIT(7) +#define SNOR_HWCAPS_READ_1_4_4_DTR BIT(8) -#define SNOR_HWCPAS_READ_OCTO GENMASK(14, 11) -#define SNOR_HWCAPS_READ_1_1_8 BIT(11) -#define SNOR_HWCAPS_READ_1_8_8 BIT(12) -#define SNOR_HWCAPS_READ_8_8_8 BIT(13) -#define SNOR_HWCAPS_READ_1_8_8_DTR BIT(14) +#define SNOR_HWCPAS_READ_OCTO GENMASK(11, 9) +#define SNOR_HWCAPS_READ_1_1_8 BIT(9) +#define SNOR_HWCAPS_READ_1_8_8 BIT(10) +#define SNOR_HWCAPS_READ_1_8_8_DTR BIT(11) /* * Page Program capabilities. @@ -504,24 +501,33 @@ struct spi_nor_hwcaps { * JEDEC/SFDP standard to define them. Also at this moment no SPI flash memory * implements such commands. */ -#define SNOR_HWCAPS_PP_MASK GENMASK(22, 16) +#define SNOR_HWCAPS_PP_MASK GENMASK(20, 16) #define SNOR_HWCAPS_PP BIT(16) -#define SNOR_HWCAPS_PP_QUAD GENMASK(19, 17) +#define SNOR_HWCAPS_PP_QUAD GENMASK(18, 17) #define SNOR_HWCAPS_PP_1_1_4 BIT(17) #define SNOR_HWCAPS_PP_1_4_4 BIT(18) -#define SNOR_HWCAPS_PP_4_4_4 BIT(19) -#define SNOR_HWCAPS_PP_OCTO GENMASK(22, 20) -#define SNOR_HWCAPS_PP_1_1_8 BIT(20) -#define SNOR_HWCAPS_PP_1_8_8 BIT(21) -#define SNOR_HWCAPS_PP_8_8_8 BIT(22) +#define SNOR_HWCAPS_PP_OCTO GENMASK(20, 19) +#define SNOR_HWCAPS_PP_1_1_8 BIT(19) +#define SNOR_HWCAPS_PP_1_8_8 BIT(20) -#define SNOR_HWCAPS_X_X_X (SNOR_HWCAPS_READ_2_2_2 | \ - SNOR_HWCAPS_READ_4_4_4 | \ - SNOR_HWCAPS_READ_8_8_8 | \ - SNOR_HWCAPS_PP_4_4_4 | \ - SNOR_HWCAPS_PP_8_8_8) +/* + * DPI, QPI and OPI stand for Dual/Quad/Octo Peripheral Interface. Those modes + * force everything to be sent on 2, 4 or 8 I/O lines, including the opcode + * which is normally sent in SPI mode. + * They should only be used if + * 1/ their SPI equivalent is not supported by the chip and/or controller + * 2/ the chip does not have the SNOR_F_BROKEN_RESET set + * The same stands for the DTR variant of those modes. + */ +#define SNOR_HWCAPS_DPI BIT(24) +#define SNOR_HWCAPS_QPI BIT(25) +#define SNOR_HWCAPS_OPI BIT(26) + +#define SNOR_HWCAPS_X_X_X (SNOR_HWCAPS_DPI | \ + SNOR_HWCAPS_QPI | \ + SNOR_HWCAPS_OPI) #define SNOR_HWCAPS_DTR (SNOR_HWCAPS_READ_1_1_1_DTR | \ SNOR_HWCAPS_READ_1_2_2_DTR | \ @@ -529,7 +535,8 @@ struct spi_nor_hwcaps { SNOR_HWCAPS_READ_1_8_8_DTR) #define SNOR_HWCAPS_ALL (SNOR_HWCAPS_READ_MASK | \ - SNOR_HWCAPS_PP_MASK) + SNOR_HWCAPS_PP_MASK | \ + SNOR_HWCAPS_X_X_X) /** * spi_nor_scan() - scan the SPI NOR From patchwork Fri Oct 12 08:48:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982920 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="smnxJbdD"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42WhXH1Bw2z9s3T for ; Fri, 12 Oct 2018 19:56:31 +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=2aFskyR19TQf+vOmTUGu+/ueG2ZDScHZBZJVsFPW+qk=; b=smnxJbdDkYj82AtzqclIXk1vE7 dSzbRK5wnWsD6UJhzHPTxVcgOH/G0aY48Mvzz0WEW32BKBRxfCzYqQKApEGArLWnCJk3e7y5cQ3AG Frim29rKiU7cECfmj0eskAwP96QqQ6x5lv4+mxfSR0jYT4BuYjeWHPB5yO27PaO1IXaIGwu9D+MuP kxHHHRmnTj+L1LugI4tV1lgnQsaVlUBoKbQxfAauEpZuar4h3FJMqzAzHsVX7TsVWGSCSAz3sJpCC 95PCEVz5ei4FGTdgjO468jxXJyDrvvcFXO9fn69hVUhRb7d9pyXcYBDrsndsYxgEPOBD+xBEU+Zd7 1f9Tin1A==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAtF5-0007fi-TM; Fri, 12 Oct 2018 08:56:19 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt82-0001ky-Vx for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:49:47 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 104CD208F4; Fri, 12 Oct 2018 10:48:49 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id 6A64720DBD; Fri, 12 Oct 2018 10:48:30 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 09/18] mtd: spi-nor: Add spi_nor_{read, write}_reg() helpers Date: Fri, 12 Oct 2018 10:48:16 +0200 Message-Id: <20181012084825.23697-10-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_014903_421995_089AE076 X-CRM114-Status: GOOD ( 13.20 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Add the spi_nor_{read,write}_reg() helpers (which are just thin wrappers around ->{read,write}_reg()) in order to prepare things for X-X-X modes support. The idea is to reject calls to ->{read,write}_reg() when the chip has entered such a mode, because SPI NOR controller drivers are not ready for that. Signed-off-by: Boris Brezillon --- drivers/mtd/spi-nor/spi-nor.c | 48 ++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 7fad94588c55..42f299a0b76f 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -148,6 +148,16 @@ static int spi_nor_nodata_op(struct spi_nor *nor, struct spi_mem_op *op) return spi_nor_exec_op(nor, op, NULL, NULL, 0); } +static int spi_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *val, int len) +{ + return nor->read_reg(nor, opcode, val, len); +} + +static int spi_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *val, int len) +{ + return nor->write_reg(nor, opcode, val, len); +} + static ssize_t spi_nor_spimem_read_data(struct spi_nor *nor, loff_t ofs, size_t len, u8 *buf) { @@ -283,7 +293,7 @@ static int read_sr(struct spi_nor *nor) ret = spi_nor_data_op(nor, &op, &val, 1); } else { - ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val, 1); + ret = spi_nor_read_reg(nor, SPINOR_OP_RDSR, &val, 1); } if (ret < 0) { @@ -313,7 +323,7 @@ static int read_fsr(struct spi_nor *nor) ret = spi_nor_data_op(nor, &op, &val, 1); } else { - ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val, 1); + ret = spi_nor_read_reg(nor, SPINOR_OP_RDFSR, &val, 1); } if (ret < 0) { @@ -343,7 +353,7 @@ static int read_cr(struct spi_nor *nor) ret = spi_nor_data_op(nor, &op, &val, 1); } else { - ret = nor->read_reg(nor, SPINOR_OP_RDCR, &val, 1); + ret = spi_nor_read_reg(nor, SPINOR_OP_RDCR, &val, 1); } if (ret < 0) { @@ -371,7 +381,7 @@ static int write_sr(struct spi_nor *nor, u8 val) } nor->cmd_buf[0] = val; - return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1); + return spi_nor_write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1); } @@ -391,7 +401,7 @@ static int write_enable(struct spi_nor *nor) return spi_nor_nodata_op(nor, &op); } - return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0); + return spi_nor_write_reg(nor, SPINOR_OP_WREN, NULL, 0); } /* @@ -409,7 +419,7 @@ static int write_disable(struct spi_nor *nor) return spi_nor_nodata_op(nor, &op); } - return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0); + return spi_nor_write_reg(nor, SPINOR_OP_WRDI, NULL, 0); } static struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd) @@ -515,7 +525,7 @@ static int set_4byte(struct spi_nor *nor, bool enable) return spi_nor_data_op(nor, &op, nor->cmd_buf, 1); } - return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1); + return spi_nor_write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1); } static int xread_sr(struct spi_nor *nor, u8 *sr) @@ -530,7 +540,7 @@ static int xread_sr(struct spi_nor *nor, u8 *sr) return spi_nor_data_op(nor, &op, sr, 1); } - return nor->read_reg(nor, SPINOR_OP_XRDSR, sr, 1); + return spi_nor_read_reg(nor, SPINOR_OP_XRDSR, sr, 1); } static int s3an_sr_ready(struct spi_nor *nor) @@ -560,7 +570,7 @@ static int clear_sr(struct spi_nor *nor) return spi_nor_nodata_op(nor, &op); } - return nor->write_reg(nor, SPINOR_OP_CLSR, NULL, 0); + return spi_nor_write_reg(nor, SPINOR_OP_CLSR, NULL, 0); } static int spi_nor_sr_ready(struct spi_nor *nor) @@ -594,7 +604,7 @@ static int clear_fsr(struct spi_nor *nor) return spi_nor_nodata_op(nor, &op); } - return nor->write_reg(nor, SPINOR_OP_CLFSR, NULL, 0); + return spi_nor_write_reg(nor, SPINOR_OP_CLFSR, NULL, 0); } static int spi_nor_fsr_ready(struct spi_nor *nor) @@ -692,7 +702,7 @@ static int erase_chip(struct spi_nor *nor) return spi_nor_nodata_op(nor, &op); } - return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0); + return spi_nor_write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0); } static int spi_nor_lock_and_prep(struct spi_nor *nor, enum spi_nor_ops ops) @@ -774,7 +784,7 @@ static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr) addr >>= 8; } - return nor->write_reg(nor, nor->erase_opcode, buf, nor->addr_width); + return spi_nor_write_reg(nor, nor->erase_opcode, buf, nor->addr_width); } /** @@ -1873,7 +1883,7 @@ static int read_id(struct spi_nor *nor, u8 *id) return spi_nor_data_op(nor, &op, id, SPI_NOR_MAX_ID_LEN); } - return nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); + return spi_nor_read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); } static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) @@ -2102,7 +2112,7 @@ static int write_sr_cr(struct spi_nor *nor, u8 *sr_cr) ret = spi_nor_data_op(nor, &op, sr_cr, 2); } else { - ret = nor->write_reg(nor, SPINOR_OP_WRSR, sr_cr, 2); + ret = spi_nor_write_reg(nor, SPINOR_OP_WRSR, sr_cr, 2); } if (ret < 0) { @@ -2258,7 +2268,7 @@ static int write_sr2(struct spi_nor *nor, u8 sr2) return spi_nor_data_op(nor, &op, &sr2, 1); } - return nor->write_reg(nor, SPINOR_OP_WRSR2, &sr2, 1); + return spi_nor_write_reg(nor, SPINOR_OP_WRSR2, &sr2, 1); } static int read_sr2(struct spi_nor *nor, u8 *sr2) @@ -2273,7 +2283,7 @@ static int read_sr2(struct spi_nor *nor, u8 *sr2) return spi_nor_data_op(nor, &op, sr2, 1); } - return nor->read_reg(nor, SPINOR_OP_RDSR2, sr2, 1); + return spi_nor_read_reg(nor, SPINOR_OP_RDSR2, sr2, 1); } /** @@ -4024,8 +4034,8 @@ static int macronix_set_4byte(struct spi_nor *nor, bool enable) return spi_nor_nodata_op(nor, &op); } - return nor->write_reg(nor, enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B, - NULL, 0); + return spi_nor_write_reg(nor, enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B, + NULL, 0); } static int micron_set_4byte(struct spi_nor *nor, bool enable) @@ -4052,7 +4062,7 @@ static int write_ear(struct spi_nor *nor, u8 ear) } nor->cmd_buf[0] = ear; - return nor->write_reg(nor, SPINOR_OP_WREAR, nor->cmd_buf, 1); + return spi_nor_write_reg(nor, SPINOR_OP_WREAR, nor->cmd_buf, 1); } static int winbond_set_4byte(struct spi_nor *nor, bool enable) From patchwork Fri Oct 12 08:48:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982915 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="C4BgNHql"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42WhSD47gFz9s3T for ; Fri, 12 Oct 2018 19:53:00 +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=u7aJcQun7s0X38M3jYFdqP1M83NxYSLugKSwquuoIw0=; b=C4BgNHqlQY/xAls1ZbLGcCnhYm grIb7U8R/5pFGraniV2rhVuWxVtjz05PfJOnh2q+f24pvrvZ0qNsD7PaF67TgJ3shTw+EAfyE4okM rSzjRRZmaCNGU0JqDLKo2/AcVr2E9XfrOagN7o631gAoheLCXRJGEwoPkaQN1leFd6pHfc9bO4nL1 G1CUaD0HHzx2SntSagTyPE6gtHjz7Rs43kpZjeEgS+bFWda9qDdygzD6JQM//3tyMw9q9KPRoyTQ1 OOmAK0RIE3zctvfFDKK2OLC+phPLSnYa3eg2uuSV5TGGyvRKMlvVG96CP2RPtnyoy4dc6hJptsu5D svqx2DpQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAtBf-0004qH-QQ; Fri, 12 Oct 2018 08:52:47 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt82-0001kz-W0 for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:49:22 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 1CE6C20DB5; Fri, 12 Oct 2018 10:48:49 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id B904020DCD; Fri, 12 Oct 2018 10:48:30 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 10/18] mtd: spi-nor: Add support for X-X-X modes Date: Fri, 12 Oct 2018 10:48:17 +0200 Message-Id: <20181012084825.23697-11-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_014903_364763_F14C324F X-CRM114-Status: GOOD ( 24.07 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Some NORs only support 1-1-1 and X-X-X modes, and in the case, the benefit of using X-X-X mode is obvious, even if this implies extra complexity in the core logic, since now the protocol used for a given operation depends on the mode the NOR is currently operating in. To deal with this stateful aspect, we add a ->mode field which keeps track of the current mode. We also add a ->change_mode() hook, so that NORs can have their own procedure to switch from one mode to another, and ->adjust_op() is here to live patch spi_mem_op when a given operation is executed (depending on the mode, it might involve extending the number of dummy cycle, adding address or cmd cycles, ...). Finally, ->preferred_mode is here let the core know what mode it should enter when resuming or at init time. The preferred mode selection logic (spi_nor_select_preferred_mode()) is pretty basic and might be extended at some point. Signed-off-by: Boris Brezillon --- drivers/mtd/spi-nor/spi-nor.c | 96 +++++++++++++++++++++++++++++++++++++++++-- include/linux/mtd/spi-nor.h | 12 ++++++ 2 files changed, 105 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 42f299a0b76f..33a07d9eb7a8 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -93,10 +93,18 @@ struct flash_info { #define USE_CLSR BIT(14) /* use CLSR command */ int (*quad_enable)(struct spi_nor *nor); + int (*change_mode)(struct spi_nor *nor, u32 newmode); + void (*adjust_op)(struct spi_nor *nor, struct spi_mem_op *op); }; #define JEDEC_MFR(info) ((info)->id[0]) +static void spi_nor_adjust_op(struct spi_nor *nor, struct spi_mem_op *op) +{ + if (nor->adjust_op) + nor->adjust_op(nor, op); +} + static int spi_nor_exec_op(struct spi_nor *nor, struct spi_mem_op *op, u64 *addr, void *buf, unsigned int len) { @@ -106,6 +114,8 @@ static int spi_nor_exec_op(struct spi_nor *nor, struct spi_mem_op *op, if (!op || (len && !buf)) return -EINVAL; + spi_nor_adjust_op(nor, op); + if (op->addr.nbytes && addr) op->addr.val = *addr; @@ -150,11 +160,17 @@ static int spi_nor_nodata_op(struct spi_nor *nor, struct spi_mem_op *op) static int spi_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *val, int len) { + if (WARN_ON_ONCE(nor->mode != SPI_NOR_MODE_SPI)) + return -ENOTSUPP; + return nor->read_reg(nor, opcode, val, len); } static int spi_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *val, int len) { + if (WARN_ON_ONCE(nor->mode != SPI_NOR_MODE_SPI)) + return -ENOTSUPP; + return nor->write_reg(nor, opcode, val, len); } @@ -184,6 +200,8 @@ static ssize_t spi_nor_spimem_read_data(struct spi_nor *nor, loff_t ofs, /* convert the dummy cycles to the number of bytes */ op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8; + spi_nor_adjust_op(nor, &op); + while (remaining) { op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX; if (!usebouncebuf) @@ -243,6 +261,8 @@ static ssize_t spi_nor_spimem_write_data(struct spi_nor *nor, loff_t ofs, if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second) op.addr.nbytes = 0; + spi_nor_adjust_op(nor, &op); + op.data.nbytes = len < UINT_MAX ? len : UINT_MAX; if (!usebouncebuf) { @@ -422,6 +442,25 @@ static int write_disable(struct spi_nor *nor) return spi_nor_write_reg(nor, SPINOR_OP_WRDI, NULL, 0); } +static int spi_nor_change_mode(struct spi_nor *nor, u32 newmode) +{ + int ret; + + if (newmode == nor->mode) + return 0; + + if (!nor->change_mode) + return -ENOTSUPP; + + ret = nor->change_mode(nor, newmode); + if (ret) + return ret; + + nor->mode = newmode; + + return 0; +} + static struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd) { return mtd->priv; @@ -2902,9 +2941,6 @@ spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, /* DTR modes are not supported yet, mask them all. */ *hwcaps &= ~SNOR_HWCAPS_DTR; - /* X-X-X modes are not supported yet, mask them all. */ - *hwcaps &= ~SNOR_HWCAPS_X_X_X; - /* Start with read commands. */ for (cap = 0; cap < 32; cap++) { int idx; @@ -3884,6 +3920,46 @@ static int spi_nor_select_erase(struct spi_nor *nor, u32 wanted_size) return 0; } +static void spi_nor_select_preferred_mode(struct spi_nor *nor, u32 hwcaps) +{ + nor->preferred_mode = SPI_NOR_MODE_SPI; + + /* + * Let's just avoid using stateful modes when SNOR_F_BROKEN_RESET is + * set. + */ + if (nor->flags & SNOR_F_BROKEN_RESET) + return; + + /* + * Stateless (1-n-n or 1-1-n) opcodes should always be preferred to + * stateful (n-n-n) ones if supported. + */ + if (hwcaps & SNOR_HWCPAS_READ_OCTO && hwcaps & SNOR_HWCAPS_PP_OCTO) + return; + + if (hwcaps & SNOR_HWCAPS_OPI) { + nor->preferred_mode = SPI_NOR_MODE_OPI; + return; + } + + if (hwcaps & SNOR_HWCAPS_READ_QUAD && hwcaps & SNOR_HWCAPS_PP_QUAD) + return; + + if (hwcaps & SNOR_HWCAPS_QPI) { + nor->preferred_mode = SPI_NOR_MODE_QPI; + return; + } + + if (hwcaps & SNOR_HWCAPS_READ_DUAL) + return; + + if (hwcaps & SNOR_HWCAPS_DPI) { + nor->preferred_mode = SPI_NOR_MODE_DPI; + return; + } +} + static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info, const struct spi_nor_flash_parameter *params, const struct spi_nor_hwcaps *hwcaps) @@ -3892,6 +3968,10 @@ static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info, bool enable_quad_io; int err; + /* Set ->adjust_op() and ->change_mode(). */ + nor->adjust_op = info->adjust_op; + nor->change_mode = info->change_mode; + /* * Keep only the hardware capabilities supported by both the SPI * controller and the SPI flash memory. @@ -3951,6 +4031,8 @@ static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info, else nor->quad_enable = NULL; + spi_nor_select_preferred_mode(nor, shared_mask); + return 0; } @@ -3971,6 +4053,11 @@ static int spi_nor_init(struct spi_nor *nor) spi_nor_wait_till_ready(nor); } + err = spi_nor_change_mode(nor, nor->preferred_mode); + if (err) + dev_err(nor->dev, "failed to switch to mode %x", + nor->preferred_mode); + if (nor->quad_enable) { err = nor->quad_enable(nor); if (err) { @@ -4011,6 +4098,9 @@ static void spi_nor_resume(struct mtd_info *mtd) void spi_nor_restore(struct spi_nor *nor) { + /* Restore the NOR to SPI mode. */ + spi_nor_change_mode(nor, SPI_NOR_MODE_SPI); + /* restore the addressing mode */ if ((nor->addr_width == 4) && !(nor->info->flags & SPI_NOR_4B_OPCODES) && diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index f2154672f75a..f80aba464eb2 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -333,6 +333,14 @@ struct spi_nor_erase_map { */ struct flash_info; +enum spi_nor_mode { + SPI_NOR_MODE_SPI, + SPI_NOR_MODE_DPI, + SPI_NOR_MODE_QPI, + SPI_NOR_MODE_OPI, + SPI_NOR_NUM_MODES, +}; + /** * struct spi_nor - Structure for defining a the SPI NOR layer * @mtd: point to a mtd_info structure @@ -381,6 +389,8 @@ struct spi_nor { struct spi_mem *spimem; void *bouncebuf; unsigned int bouncebuf_size; + enum spi_nor_mode preferred_mode; + enum spi_nor_mode mode; const struct flash_info *info; u32 page_size; u8 addr_width; @@ -412,6 +422,8 @@ struct spi_nor { int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len); int (*quad_enable)(struct spi_nor *nor); int (*set_4byte)(struct spi_nor *nor, bool enable); + int (*change_mode)(struct spi_nor *nor, enum spi_nor_mode newmode); + void (*adjust_op)(struct spi_nor *nor, struct spi_mem_op *op); void *priv; }; From patchwork Fri Oct 12 08:48:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982918 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="VQWcKGEX"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42WhVT3mK4z9s3T for ; Fri, 12 Oct 2018 19:54:57 +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=c2+bw+Gpwma5Fdeaa6GzG5w9stfFJo3t4pe5WtRt9Gs=; b=VQWcKGEXwPkpxK4dXOfmIVBsKW Tef1kwNZnOGrzbbm/NQHkbjP8CpA+ocJn8njsKb22NVxft36hiOIjMvHm7c/q4BwSbLt3FA93IwKl 3cX87f7KrbJ/r3lohX8ofEYyaA69BmMX9mWwSWH8xv/EzDk2wKAcFD8J3EslsVZPSc4MXgJ6Hauu+ ywZUylXe7jt4A0kptvyQbHlBNc/gWNQAshCRs5tra/+J6h2swnNDFn4qo9QFRsYkP6BpWsya/lUYH XfavdlBdyeyWnFZIhYVHFdNcmdAcEM5j7Z+qdcKZ5btNtdYB84YiOkNKCmF3W9eZQaxyN97BWTr5n fPb3Dm+w==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAtDW-0005k9-9x; Fri, 12 Oct 2018 08:54:42 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt82-0001mB-W1 for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:49:37 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 2B2E2207BF; Fri, 12 Oct 2018 10:48:58 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id 1727D20DD2; Fri, 12 Oct 2018 10:48:31 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 11/18] mtd: spi-nor: Prepare things for 2byte opcodes Date: Fri, 12 Oct 2018 10:48:18 +0200 Message-Id: <20181012084825.23697-12-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_014903_443766_2A503C44 X-CRM114-Status: GOOD ( 16.62 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org When operating in octo mode we might have to use 2byte opcodes. Patch struct spi_nor_{read,pp}_command to take that into account. Signed-off-by: Boris Brezillon --- drivers/mtd/spi-nor/spi-nor.c | 26 ++++++++++++++++++-------- include/linux/mtd/spi-nor.h | 2 ++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 33a07d9eb7a8..86625f1e25b3 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -200,6 +200,9 @@ static ssize_t spi_nor_spimem_read_data(struct spi_nor *nor, loff_t ofs, /* convert the dummy cycles to the number of bytes */ op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8; + if (nor->read_proto & SNOR_PROTO_INST_2BYTE) + op.cmd.nbytes = 2; + spi_nor_adjust_op(nor, &op); while (remaining) { @@ -258,6 +261,9 @@ static ssize_t spi_nor_spimem_write_data(struct spi_nor *nor, loff_t ofs, op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto); op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto); + if (nor->write_proto & SNOR_PROTO_INST_2BYTE) + op.cmd.nbytes = 2; + if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second) op.addr.nbytes = 0; @@ -2433,13 +2439,13 @@ static int s3an_nor_scan(const struct flash_info *info, struct spi_nor *nor) struct spi_nor_read_command { u8 num_mode_clocks; u8 num_wait_states; - u8 opcode; - enum spi_nor_protocol proto; + u16 opcode; + u32 proto; }; struct spi_nor_pp_command { - u8 opcode; - enum spi_nor_protocol proto; + u16 opcode; + u32 proto; }; enum spi_nor_read_command_index { @@ -2499,8 +2505,7 @@ static void spi_nor_set_read_settings(struct spi_nor_read_command *read, u8 num_mode_clocks, u8 num_wait_states, - u8 opcode, - enum spi_nor_protocol proto) + u16 opcode, u32 proto) { read->num_mode_clocks = num_mode_clocks; read->num_wait_states = num_wait_states; @@ -2510,8 +2515,7 @@ spi_nor_set_read_settings(struct spi_nor_read_command *read, static void spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, - u8 opcode, - enum spi_nor_protocol proto) + u16 opcode, u32 proto) { pp->opcode = opcode; pp->proto = proto; @@ -2887,6 +2891,9 @@ static int spi_nor_spimem_check_readop(struct spi_nor *nor, op.dummy.nbytes = (read->num_mode_clocks + read->num_wait_states) * op.dummy.buswidth / 8; + if (read->proto & SNOR_PROTO_INST_2BYTE) + op.cmd.nbytes = 2; + /* * First test with 3 address bytes. The opcode itself might already * be a 4B addressing opcode but we don't care, because SPI controller @@ -2915,6 +2922,9 @@ static int spi_nor_spimem_check_progop(struct spi_nor *nor, op.addr.buswidth = spi_nor_get_protocol_addr_nbits(pp->proto); op.data.buswidth = spi_nor_get_protocol_data_nbits(pp->proto); + if (pp->proto & SNOR_PROTO_INST_2BYTE) + op.cmd.nbytes = 2; + /* * First test with 3 address bytes. The opcode itself might already * be a 4B addressing opcode but we don't care, because SPI controller diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index f80aba464eb2..5b0045720049 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -166,6 +166,8 @@ #define SNOR_PROTO_IS_DTR BIT(24) /* Double Transfer Rate */ +#define SNOR_PROTO_INST_2BYTE BIT(31) + #define SNOR_PROTO_STR(_inst_nbits, _addr_nbits, _data_nbits) \ (SNOR_PROTO_INST(_inst_nbits) | \ SNOR_PROTO_ADDR(_addr_nbits) | \ From patchwork Fri Oct 12 08:48:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982917 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="Mtngk6qI"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42WhTj4DmHz9s3T for ; Fri, 12 Oct 2018 19:54:17 +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=fcEcBLY4Ao6aGKWRnSwW/Or6Tb9VO6jDkRMQPJKUbNk=; b=Mtngk6qIBGxPLLWxSExRdOSJnz PwYyo8TnBEO3pLVhxYQesHE09BK3G6pJyaBgJpvdYz9ip34S3TOX912WXN6W7lTanoM6oGmb+Q6eA +6rseuFqkePyrgrhM3iBMA8o4v4g7BzAdLj2bUtIM2TogAwMSuPoSev6YpiCbUo2tsnnDOj9OINAK v5szqACcLDwEoCRYP8ZciS2k5ApQJ52XUdi9IOTCWQQwlQdB6Qo9XBeNQmGmCiFRHlWfpLNew67jC x3jMaW+rIr1+NldFAvkY0Ehh/QGxgjzc0Cqj/WliZT8iXszBs4Ll2bbz8241dBro6monX5T5N9JwQ QQtI3SPg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAtCu-0005Rd-QW; Fri, 12 Oct 2018 08:54:04 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt82-0001mC-VY for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:49:36 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 3551B20898; Fri, 12 Oct 2018 10:48:58 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id 663B420DD8; Fri, 12 Oct 2018 10:48:31 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 12/18] mtd: spi-nor: Provide a hook to tweak flash parameters Date: Fri, 12 Oct 2018 10:48:19 +0200 Message-Id: <20181012084825.23697-13-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_014903_361133_140E4E6A X-CRM114-Status: GOOD ( 15.67 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Some NORs implement X-X-X operations in a vendor/chip-specific way, and adding all cases to the common op selection logic would hurt readability. Add a ->tweak_params() hook to flash_info such that NORs that need this kind of customization process can specify it. Note that we need to move struct spi_nor_flash_parameter definition (and all its dependencies) before struct flash_info definition to avoid a forward declaration of struct spi_nor_flash_parameter. Signed-off-by: Boris Brezillon --- drivers/mtd/spi-nor/spi-nor.c | 135 ++++++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 65 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 86625f1e25b3..7660fe27d82a 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -43,6 +43,71 @@ #define SPI_NOR_MAX_ID_LEN 6 #define SPI_NOR_MAX_ADDR_WIDTH 4 +struct spi_nor_read_command { + u8 num_mode_clocks; + u8 num_wait_states; + u16 opcode; + u32 proto; +}; + +struct spi_nor_pp_command { + u16 opcode; + u32 proto; +}; + +enum spi_nor_read_command_index { + SNOR_CMD_READ, + SNOR_CMD_READ_FAST, + SNOR_CMD_READ_1_1_1_DTR, + + /* Dual SPI */ + SNOR_CMD_READ_1_1_2, + SNOR_CMD_READ_1_2_2, + SNOR_CMD_READ_2_2_2, + SNOR_CMD_READ_1_2_2_DTR, + + /* Quad SPI */ + SNOR_CMD_READ_1_1_4, + SNOR_CMD_READ_1_4_4, + SNOR_CMD_READ_4_4_4, + SNOR_CMD_READ_1_4_4_DTR, + + /* Octo SPI */ + SNOR_CMD_READ_1_1_8, + SNOR_CMD_READ_1_8_8, + SNOR_CMD_READ_8_8_8, + SNOR_CMD_READ_1_8_8_DTR, + + SNOR_CMD_READ_MAX +}; + +enum spi_nor_pp_command_index { + SNOR_CMD_PP, + + /* Quad SPI */ + SNOR_CMD_PP_1_1_4, + SNOR_CMD_PP_1_4_4, + SNOR_CMD_PP_4_4_4, + + /* Octo SPI */ + SNOR_CMD_PP_1_1_8, + SNOR_CMD_PP_1_8_8, + SNOR_CMD_PP_8_8_8, + + SNOR_CMD_PP_MAX +}; + +struct spi_nor_flash_parameter { + u64 size; + u32 page_size; + + struct spi_nor_hwcaps hwcaps; + struct spi_nor_read_command reads[SNOR_CMD_READ_MAX]; + struct spi_nor_pp_command page_programs[SNOR_CMD_PP_MAX]; + + int (*quad_enable)(struct spi_nor *nor); +}; + struct flash_info { char *name; @@ -93,6 +158,8 @@ struct flash_info { #define USE_CLSR BIT(14) /* use CLSR command */ int (*quad_enable)(struct spi_nor *nor); + void (*tweak_params)(struct spi_nor *nor, + struct spi_nor_flash_parameter *params); int (*change_mode)(struct spi_nor *nor, u32 newmode); void (*adjust_op)(struct spi_nor *nor, struct spi_mem_op *op); }; @@ -2436,71 +2503,6 @@ static int s3an_nor_scan(const struct flash_info *info, struct spi_nor *nor) return 0; } -struct spi_nor_read_command { - u8 num_mode_clocks; - u8 num_wait_states; - u16 opcode; - u32 proto; -}; - -struct spi_nor_pp_command { - u16 opcode; - u32 proto; -}; - -enum spi_nor_read_command_index { - SNOR_CMD_READ, - SNOR_CMD_READ_FAST, - SNOR_CMD_READ_1_1_1_DTR, - - /* Dual SPI */ - SNOR_CMD_READ_1_1_2, - SNOR_CMD_READ_1_2_2, - SNOR_CMD_READ_2_2_2, - SNOR_CMD_READ_1_2_2_DTR, - - /* Quad SPI */ - SNOR_CMD_READ_1_1_4, - SNOR_CMD_READ_1_4_4, - SNOR_CMD_READ_4_4_4, - SNOR_CMD_READ_1_4_4_DTR, - - /* Octo SPI */ - SNOR_CMD_READ_1_1_8, - SNOR_CMD_READ_1_8_8, - SNOR_CMD_READ_8_8_8, - SNOR_CMD_READ_1_8_8_DTR, - - SNOR_CMD_READ_MAX -}; - -enum spi_nor_pp_command_index { - SNOR_CMD_PP, - - /* Quad SPI */ - SNOR_CMD_PP_1_1_4, - SNOR_CMD_PP_1_4_4, - SNOR_CMD_PP_4_4_4, - - /* Octo SPI */ - SNOR_CMD_PP_1_1_8, - SNOR_CMD_PP_1_8_8, - SNOR_CMD_PP_8_8_8, - - SNOR_CMD_PP_MAX -}; - -struct spi_nor_flash_parameter { - u64 size; - u32 page_size; - - struct spi_nor_hwcaps hwcaps; - struct spi_nor_read_command reads[SNOR_CMD_READ_MAX]; - struct spi_nor_pp_command page_programs[SNOR_CMD_PP_MAX]; - - int (*quad_enable)(struct spi_nor *nor); -}; - static void spi_nor_set_read_settings(struct spi_nor_read_command *read, u8 num_mode_clocks, @@ -3775,6 +3777,9 @@ static int spi_nor_init_params(struct spi_nor *nor, memcpy(params, &sfdp_params, sizeof(*params)); } + if (info->tweak_params) + info->tweak_params(nor, params); + return 0; } From patchwork Fri Oct 12 08:48:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982914 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="ErvHAqxc"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42WhRR2s8fz9s1c for ; Fri, 12 Oct 2018 19:52:19 +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=CjvJiCOxiUo+WYJYQT2SEFTZIlwpnJiVSqDZnkJqz0Y=; b=ErvHAqxcwowp9I0qipSZdhYSLK rNLl1lz9wmqc5YMWbavtGZKRteIqEJjUP2gCYBfHStfMDi4sEBdc53AMngaAppWCzftMc+9dxHpEy WHL7r72jPNCYrG/b5ogDmyx5bVrBbctft2bqm2AfgfXmuQg+jxjQsZ2OhWWHhOaUOhzGlZ3bHcLkw UmSp6FeQ5eJ481tlou2E9KGa1i0NYOEhyihkzQUGi+i3r3CtPVGv0x7h6vkbAexvKChzswczx0JFF OQ/W1JGyVITyHfFmtcOReqC52RB9sm2AA5bxglYTKXlCE+vwmzbLzDekpVmti7jIvHjviNK/gSzM4 fFDYamRQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAtAw-0004Su-02; Fri, 12 Oct 2018 08:52:02 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt82-0001mE-VZ for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:49:21 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 3CCC720DCD; Fri, 12 Oct 2018 10:48:58 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id B1EF220DDB; Fri, 12 Oct 2018 10:48:31 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 13/18] mtd: spi-nor: Add 8-8-8 mode support to Macronix mx25uw51245g Date: Fri, 12 Oct 2018 10:48:20 +0200 Message-Id: <20181012084825.23697-14-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_014903_356561_2FC71DAE X-CRM114-Status: GOOD ( 20.92 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org mx25uw51245g support only 1-1-1 and 8-8-8. Add the necessary hooks to support 8-8-8 mode. Signed-off-by: Boris Brezillon --- drivers/mtd/spi-nor/spi-nor.c | 198 +++++++++++++++++++++++++++++++++++++----- include/linux/mtd/spi-nor.h | 10 +++ 2 files changed, 187 insertions(+), 21 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 7660fe27d82a..9cd8677b8cb2 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -166,6 +166,26 @@ struct flash_info { #define JEDEC_MFR(info) ((info)->id[0]) +static void +spi_nor_set_read_settings(struct spi_nor_read_command *read, + u8 num_mode_clocks, + u8 num_wait_states, + u16 opcode, u32 proto) +{ + read->num_mode_clocks = num_mode_clocks; + read->num_wait_states = num_wait_states; + read->opcode = opcode; + read->proto = proto; +} + +static void +spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, + u16 opcode, u32 proto) +{ + pp->opcode = opcode; + pp->proto = proto; +} + static void spi_nor_adjust_op(struct spi_nor *nor, struct spi_mem_op *op) { if (nor->adjust_op) @@ -515,6 +535,37 @@ static int write_disable(struct spi_nor *nor) return spi_nor_write_reg(nor, SPINOR_OP_WRDI, NULL, 0); } +static int read_cr2(struct spi_nor *nor, u32 addr, u8 *cr2) +{ + struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDCR2, 1), + SPI_MEM_OP_ADDR(4, addr, 1), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_IN(0, NULL, 1)); + + if (!nor->spimem) + return -ENOTSUPP; + + return spi_nor_data_op(nor, &op, cr2, 1); +} + +static int write_cr2(struct spi_nor *nor, u32 addr, u8 cr2) +{ + struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRCR2, 1), + SPI_MEM_OP_ADDR(4, addr, 1), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(0, NULL, 1)); + int ret; + + if (!nor->spimem) + return -ENOTSUPP; + + ret = write_enable(nor); + if (ret) + return ret; + + return spi_nor_data_op(nor, &op, &cr2, 1); +} + static int spi_nor_change_mode(struct spi_nor *nor, u32 newmode) { int ret; @@ -1626,6 +1677,125 @@ static int macronix_quad_enable(struct spi_nor *nor) return 0; } +static int macronix_opi_change_mode(struct spi_nor *nor, + enum spi_nor_mode newmode) +{ + int ret; + u8 val; + + ret = read_cr2(nor, CR2_REG0, &val); + if (ret) + return ret; + + val &= ~GENMASK(1, 0); + + switch (newmode) { + case SPI_NOR_MODE_SPI: + val |= CR2_REG0_MODE_SPI; + break; + + case SPI_NOR_MODE_OPI: + val |= CR2_REG0_MODE_OPI_STR; + break; + + default: + /* + * If we reach that point, there's a serious problem in the + * hwcaps selection logic. + */ + WARN_ONCE(1, "mode %08x is not supported", newmode); + return -ENOTSUPP; + } + + return write_cr2(nor, CR2_REG0, val); +} + +static void macronix_opi_adjust_op(struct spi_nor *nor, struct spi_mem_op *op) +{ + if (nor->mode == SPI_NOR_MODE_SPI) + return; + + switch (op->cmd.opcode) { + case SPINOR_OP_READ: + case SPINOR_OP_READ_FAST: + case SPINOR_OP_READ_4B: + case SPINOR_OP_READ_FAST_4B: + op->dummy.nbytes = 20; + op->cmd.opcode = 0xec; + break; + + case SPINOR_OP_PP: + op->cmd.opcode = SPINOR_OP_PP_4B; + op->addr.nbytes = 4; + break; + + case SPINOR_OP_SE: + op->cmd.opcode = SPINOR_OP_SE_4B; + op->addr.nbytes = 4; + break; + + case SPINOR_OP_BE_4K: + op->cmd.opcode = SPINOR_OP_BE_4K_4B; + op->addr.nbytes = 4; + break; + + case SPINOR_OP_RDSFDP: + op->dummy.nbytes = 20; + op->addr.nbytes = 4; + break; + + case SPINOR_OP_RDCR2: + op->dummy.nbytes = 4; + break; + + case SPINOR_OP_RDID: + case SPINOR_OP_RDSR: + op->dummy.nbytes = 4; + /* fallthrough */ + + case SPINOR_OP_WRSR: + op->addr.nbytes = 4; + op->addr.val = 0; + break; + + case SPINOR_OP_RDCR: + op->addr.nbytes = 4; + op->addr.val = 1; + break; + } + + /* Force buswidth to 8. */ + op->cmd.buswidth = 8; + + if (op->addr.nbytes) + op->addr.buswidth = 8; + + if (op->dummy.nbytes) + op->dummy.buswidth = 8; + + if (op->data.buswidth) + op->data.buswidth = 8; + + /* + * OPI mode implies 2 bytes opcodes, the first byte (MSB) being the + * original opcode, and the second the reverse of the original opcode. + */ + op->cmd.nbytes = 2; + op->cmd.opcode = (op->cmd.opcode << 8) | ((~op->cmd.opcode) & 0xff); +} + +static void macronix_opi_tweak_params(struct spi_nor *nor, + struct spi_nor_flash_parameter *params) +{ + params->hwcaps.mask |= SNOR_HWCAPS_OPI; + spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_8_8_8], + 0, 20, 0xec13, + SNOR_PROTO_8_8_8 | SNOR_PROTO_INST_2BYTE); + spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP_8_8_8], + 0x12ed, + SNOR_PROTO_8_8_8 | SNOR_PROTO_INST_2BYTE); +} + /* Used when the "_ext_id" is two bytes at most */ #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ .id = { \ @@ -1807,7 +1977,13 @@ static const struct flash_info spi_nor_ids[] = { { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) }, { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, - { "mx25uw51245g", INFO(0xc2813a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_4B_OPCODES) }, + { + "mx25uw51245g", INFO(0xc2813a, 0, 64 * 1024, 1024, + SECT_4K | SPI_NOR_4B_OPCODES) + .tweak_params = macronix_opi_tweak_params, + .adjust_op = macronix_opi_adjust_op, + .change_mode = macronix_opi_change_mode, + }, { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "mx66l1g45g", INFO(0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, @@ -2503,26 +2679,6 @@ static int s3an_nor_scan(const struct flash_info *info, struct spi_nor *nor) return 0; } -static void -spi_nor_set_read_settings(struct spi_nor_read_command *read, - u8 num_mode_clocks, - u8 num_wait_states, - u16 opcode, u32 proto) -{ - read->num_mode_clocks = num_mode_clocks; - read->num_wait_states = num_wait_states; - read->opcode = opcode; - read->proto = proto; -} - -static void -spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, - u16 opcode, u32 proto) -{ - pp->opcode = opcode; - pp->proto = proto; -} - /* * Serial Flash Discoverable Parameters (SFDP) parsing. */ diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 5b0045720049..e497f3b93a74 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -102,6 +102,9 @@ #define XSR_PAGESIZE BIT(0) /* Page size in Po2 or Linear */ #define XSR_RDY BIT(7) /* Ready */ +/* Used for Macronix flashes only. */ +#define SPINOR_OP_RDCR2 0x71 /* Read configuration register 2 */ +#define SPINOR_OP_WRCR2 0x72 /* Write configuration register 2 */ /* Used for Macronix and Winbond flashes. */ #define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */ @@ -145,6 +148,13 @@ /* Status Register 2 bits. */ #define SR2_QUAD_EN_BIT7 BIT(7) +/* Configuration register 2, offset 0 */ +#define CR2_REG0 0x0 +#define CR2_REG0_MODE_MASK GENMASK(1, 0) +#define CR2_REG0_MODE_SPI 0 +#define CR2_REG0_MODE_OPI_STR 1 +#define CR2_REG0_MODE_OPI_DTR 2 + /* Supported SPI protocols */ #define SNOR_PROTO_INST_MASK GENMASK(23, 16) #define SNOR_PROTO_INST_SHIFT 16 From patchwork Fri Oct 12 08:48:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982919 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="lHYK1ZVb"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42WhWd0KqLz9s3T for ; Fri, 12 Oct 2018 19:55:57 +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=ZREYmF61EX/i4E85k5gC9sjFsbwVJFCbBDrD0LF/qds=; b=lHYK1ZVbPfYrriLsl7zpourCW4 uqRXDyfOjvJ3Xw0BBg1t/MpGWni3lqmpi4Ojncy7a/zQ1ELOLkEY3j6mU5HyQUk3YyY0St43sYz06 fGbE7PXzVlqfIEpC33dTmwjoUkpt9QRAox7fW+ykn/pXqgqcMNnJN3wbmH6d/VMCxxec+E/z5FIkk xxGve0Ijsc5CW/3xDWsva6Z+wdd8q199glGnG3fqsB+2BPE75T1EABOexDJaKbiW7wYBGVPnjL80q 9jCXcKUzTyOIdsHpK9wk+HCYKjHAOLYtEsi/iWGOQ3jiE6rA7IC2j54lQxMJLsNx0che6qUgtM0md WrKzF1bA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAtES-0007P9-F6; Fri, 12 Oct 2018 08:55:40 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt82-0001mG-VX for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:49:47 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 3E99320DBD; Fri, 12 Oct 2018 10:48:58 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id 12FF920DDC; Fri, 12 Oct 2018 10:48:32 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 14/18] mtd: spi-nor: Clarify where DTR mode applies Date: Fri, 12 Oct 2018 10:48:21 +0200 Message-Id: <20181012084825.23697-15-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_014903_351286_3021DAD3 X-CRM114-Status: GOOD ( 16.51 ) X-Spam-Score: 0.8 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (0.8 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.8 UPPERCASE_50_75 message body is 50-75% uppercase 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org In its current state, '_DTR' means 'send everything except the instruction in DTR mode'. Clarify that by renaming the macros into _1_xD_xD so that we can later support full DTR modes (where the instruction byte is also sent in DTR mode). Signed-off-by: Boris Brezillon --- drivers/mtd/spi-nor/spi-nor.c | 22 ++++++++-------- include/linux/mtd/spi-nor.h | 61 ++++++++++++++++++++++++++----------------- 2 files changed, 48 insertions(+), 35 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 9cd8677b8cb2..98dab7f6938e 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -58,25 +58,25 @@ struct spi_nor_pp_command { enum spi_nor_read_command_index { SNOR_CMD_READ, SNOR_CMD_READ_FAST, - SNOR_CMD_READ_1_1_1_DTR, + SNOR_CMD_READ_1_1D_1D, /* Dual SPI */ SNOR_CMD_READ_1_1_2, SNOR_CMD_READ_1_2_2, SNOR_CMD_READ_2_2_2, - SNOR_CMD_READ_1_2_2_DTR, + SNOR_CMD_READ_1_2D_2D, /* Quad SPI */ SNOR_CMD_READ_1_1_4, SNOR_CMD_READ_1_4_4, SNOR_CMD_READ_4_4_4, - SNOR_CMD_READ_1_4_4_DTR, + SNOR_CMD_READ_1_4D_4D, /* Octo SPI */ SNOR_CMD_READ_1_1_8, SNOR_CMD_READ_1_8_8, SNOR_CMD_READ_8_8_8, - SNOR_CMD_READ_1_8_8_DTR, + SNOR_CMD_READ_1_8D_8D, SNOR_CMD_READ_MAX }; @@ -613,9 +613,9 @@ static u8 spi_nor_convert_3to4_read(u8 opcode) { SPINOR_OP_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B }, { SPINOR_OP_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B }, - { SPINOR_OP_READ_1_1_1_DTR, SPINOR_OP_READ_1_1_1_DTR_4B }, - { SPINOR_OP_READ_1_2_2_DTR, SPINOR_OP_READ_1_2_2_DTR_4B }, - { SPINOR_OP_READ_1_4_4_DTR, SPINOR_OP_READ_1_4_4_DTR_4B }, + { SPINOR_OP_READ_1_1D_1D, SPINOR_OP_READ_1_1D_1D_4B }, + { SPINOR_OP_READ_1_2D_2D, SPINOR_OP_READ_1_2D_2D_4B }, + { SPINOR_OP_READ_1_4D_4D, SPINOR_OP_READ_1_4D_4D_4B }, }; return spi_nor_convert_opcode(opcode, spi_nor_3to4_read, @@ -2999,19 +2999,19 @@ static int spi_nor_hwcaps_read2cmd(u32 hwcaps) static const int hwcaps_read2cmd[][2] = { { SNOR_HWCAPS_READ, SNOR_CMD_READ }, { SNOR_HWCAPS_READ_FAST, SNOR_CMD_READ_FAST }, - { SNOR_HWCAPS_READ_1_1_1_DTR, SNOR_CMD_READ_1_1_1_DTR }, + { SNOR_HWCAPS_READ_1_1D_1D, SNOR_CMD_READ_1_1D_1D }, { SNOR_HWCAPS_READ_1_1_2, SNOR_CMD_READ_1_1_2 }, { SNOR_HWCAPS_READ_1_2_2, SNOR_CMD_READ_1_2_2 }, { SNOR_HWCAPS_DPI, SNOR_CMD_READ_2_2_2 }, - { SNOR_HWCAPS_READ_1_2_2_DTR, SNOR_CMD_READ_1_2_2_DTR }, + { SNOR_HWCAPS_READ_1_2D_2D, SNOR_CMD_READ_1_2D_2D }, { SNOR_HWCAPS_READ_1_1_4, SNOR_CMD_READ_1_1_4 }, { SNOR_HWCAPS_READ_1_4_4, SNOR_CMD_READ_1_4_4 }, { SNOR_HWCAPS_QPI, SNOR_CMD_READ_4_4_4 }, - { SNOR_HWCAPS_READ_1_4_4_DTR, SNOR_CMD_READ_1_4_4_DTR }, + { SNOR_HWCAPS_READ_1_4D_4D, SNOR_CMD_READ_1_4D_4D }, { SNOR_HWCAPS_READ_1_1_8, SNOR_CMD_READ_1_1_8 }, { SNOR_HWCAPS_READ_1_8_8, SNOR_CMD_READ_1_8_8 }, { SNOR_HWCAPS_OPI, SNOR_CMD_READ_8_8_8 }, - { SNOR_HWCAPS_READ_1_8_8_DTR, SNOR_CMD_READ_1_8_8_DTR }, + { SNOR_HWCAPS_READ_1_8D_8D, SNOR_CMD_READ_1_8D_8D }, }; return spi_nor_hwcaps2cmd(hwcaps, hwcaps_read2cmd, diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index e497f3b93a74..1035706bc6db 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -81,13 +81,13 @@ #define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */ /* Double Transfer Rate opcodes - defined in JEDEC JESD216B. */ -#define SPINOR_OP_READ_1_1_1_DTR 0x0d -#define SPINOR_OP_READ_1_2_2_DTR 0xbd -#define SPINOR_OP_READ_1_4_4_DTR 0xed +#define SPINOR_OP_READ_1_1D_1D 0x0d +#define SPINOR_OP_READ_1_2D_2D 0xbd +#define SPINOR_OP_READ_1_4D_4D 0xed -#define SPINOR_OP_READ_1_1_1_DTR_4B 0x0e -#define SPINOR_OP_READ_1_2_2_DTR_4B 0xbe -#define SPINOR_OP_READ_1_4_4_DTR_4B 0xee +#define SPINOR_OP_READ_1_1D_1D_4B 0x0e +#define SPINOR_OP_READ_1_2D_2D_4B 0xbe +#define SPINOR_OP_READ_1_4D_4D_4B 0xee /* Used for SST flashes only. */ #define SPINOR_OP_BP 0x02 /* Byte program */ @@ -174,7 +174,10 @@ ((((unsigned long)(_nbits)) << SNOR_PROTO_DATA_SHIFT) & \ SNOR_PROTO_DATA_MASK) -#define SNOR_PROTO_IS_DTR BIT(24) /* Double Transfer Rate */ +/* Double Transfer Rate flags */ +#define SNOR_PROTO_INST_IS_DTR BIT(26) +#define SNOR_PROTO_ADDR_IS_DTR BIT(25) +#define SNOR_PROTO_DATA_IS_DTR BIT(24) #define SNOR_PROTO_INST_2BYTE BIT(31) @@ -182,9 +185,9 @@ (SNOR_PROTO_INST(_inst_nbits) | \ SNOR_PROTO_ADDR(_addr_nbits) | \ SNOR_PROTO_DATA(_data_nbits)) -#define SNOR_PROTO_DTR(_inst_nbits, _addr_nbits, _data_nbits) \ - (SNOR_PROTO_IS_DTR | \ - SNOR_PROTO_STR(_inst_nbits, _addr_nbits, _data_nbits)) +#define SNOR_PROTO_1_XD_XD(_nbits) \ + (SNOR_PROTO_DATA_IS_DTR | SNOR_PROTO_ADDR_IS_DTR | \ + SNOR_PROTO_STR(1, _nbits, _nbits)) enum spi_nor_protocol { SNOR_PROTO_1_1_1 = SNOR_PROTO_STR(1, 1, 1), @@ -198,15 +201,25 @@ enum spi_nor_protocol { SNOR_PROTO_4_4_4 = SNOR_PROTO_STR(4, 4, 4), SNOR_PROTO_8_8_8 = SNOR_PROTO_STR(8, 8, 8), - SNOR_PROTO_1_1_1_DTR = SNOR_PROTO_DTR(1, 1, 1), - SNOR_PROTO_1_2_2_DTR = SNOR_PROTO_DTR(1, 2, 2), - SNOR_PROTO_1_4_4_DTR = SNOR_PROTO_DTR(1, 4, 4), - SNOR_PROTO_1_8_8_DTR = SNOR_PROTO_DTR(1, 8, 8), + SNOR_PROTO_1_1D_1D = SNOR_PROTO_1_XD_XD(1), + SNOR_PROTO_1_2D_2D = SNOR_PROTO_1_XD_XD(2), + SNOR_PROTO_1_4D_4D = SNOR_PROTO_1_XD_XD(4), + SNOR_PROTO_1_8D_8D = SNOR_PROTO_1_XD_XD(8), }; -static inline bool spi_nor_protocol_is_dtr(enum spi_nor_protocol proto) +static inline bool spi_nor_protocol_inst_is_dtr(enum spi_nor_protocol proto) { - return !!(proto & SNOR_PROTO_IS_DTR); + return !!(proto & SNOR_PROTO_INST_IS_DTR); +} + +static inline bool spi_nor_protocol_addr_is_dtr(enum spi_nor_protocol proto) +{ + return !!(proto & SNOR_PROTO_ADDR_IS_DTR); +} + +static inline bool spi_nor_protocol_data_is_dtr(enum spi_nor_protocol proto) +{ + return !!(proto & SNOR_PROTO_DATA_IS_DTR); } static inline u8 spi_nor_get_protocol_inst_nbits(enum spi_nor_protocol proto) @@ -499,22 +512,22 @@ struct spi_nor_hwcaps { #define SNOR_HWCAPS_READ_MASK GENMASK(11, 0) #define SNOR_HWCAPS_READ BIT(0) #define SNOR_HWCAPS_READ_FAST BIT(1) -#define SNOR_HWCAPS_READ_1_1_1_DTR BIT(2) +#define SNOR_HWCAPS_READ_1_1D_1D BIT(2) #define SNOR_HWCAPS_READ_DUAL GENMASK(5, 3) #define SNOR_HWCAPS_READ_1_1_2 BIT(3) #define SNOR_HWCAPS_READ_1_2_2 BIT(4) -#define SNOR_HWCAPS_READ_1_2_2_DTR BIT(5) +#define SNOR_HWCAPS_READ_1_2D_2D BIT(5) #define SNOR_HWCAPS_READ_QUAD GENMASK(8, 6) #define SNOR_HWCAPS_READ_1_1_4 BIT(6) #define SNOR_HWCAPS_READ_1_4_4 BIT(7) -#define SNOR_HWCAPS_READ_1_4_4_DTR BIT(8) +#define SNOR_HWCAPS_READ_1_4D_4D BIT(8) #define SNOR_HWCPAS_READ_OCTO GENMASK(11, 9) #define SNOR_HWCAPS_READ_1_1_8 BIT(9) #define SNOR_HWCAPS_READ_1_8_8 BIT(10) -#define SNOR_HWCAPS_READ_1_8_8_DTR BIT(11) +#define SNOR_HWCAPS_READ_1_8D_8D BIT(11) /* * Page Program capabilities. @@ -553,10 +566,10 @@ struct spi_nor_hwcaps { SNOR_HWCAPS_QPI | \ SNOR_HWCAPS_OPI) -#define SNOR_HWCAPS_DTR (SNOR_HWCAPS_READ_1_1_1_DTR | \ - SNOR_HWCAPS_READ_1_2_2_DTR | \ - SNOR_HWCAPS_READ_1_4_4_DTR | \ - SNOR_HWCAPS_READ_1_8_8_DTR) +#define SNOR_HWCAPS_DTR (SNOR_HWCAPS_READ_1_1D_1D | \ + SNOR_HWCAPS_READ_1_2D_2D | \ + SNOR_HWCAPS_READ_1_4D_4D | \ + SNOR_HWCAPS_READ_1_8D_8D) #define SNOR_HWCAPS_ALL (SNOR_HWCAPS_READ_MASK | \ SNOR_HWCAPS_PP_MASK | \ From patchwork Fri Oct 12 08:48:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982934 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="jE9VqizF"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=infradead.org header.i=@infradead.org header.b="v93ZnZXy"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42Wj085hnBz9s3Z for ; Fri, 12 Oct 2018 20:17:12 +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=HRfgTBRB9ok0wFvuTBTNmSuKvZ1OTKYEbl1pzrpUP40=; b=jE9VqizFsLeKAJmK9i/OiKcSBz cug94/ix+VfTuitk8xylP4usF+aESUqMDw1rXIjG8BoQuLnYVOnB534aFSVTDsuoHoIJVINCNdjH/ 6AC6fEmV2L0vYDMWMYFEgVsbeaSQSva4hAPjlVLI5k1SsYaFOYEJPLqFcoIamv1+nNT/k5VbE8y+2 EnqC//3MBDzkwbSA3P67PTY6f7024DiHg1Ay07vIS02EhKzuzitotddGP0E/cr7h364xtDyutIKSH 2oOqWj5nA3wZhQh9mNXSeKrV+6d99K69P3sF/QT6X9x1l9ea9NFJDO3fypFNMqsKdhS1ilRxxe82q 6OKESdDQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAtZ5-0002PL-63; Fri, 12 Oct 2018 09:16:59 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAtNk-0003DT-WA for linux-mtd@bombadil.infradead.org; Fri, 12 Oct 2018 09:05:17 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=1ijd1a0LDJTCSb3nID3FkfGfiW39JH3yMZSbctNoMAw=; b=v93ZnZXyDL+QBcRdFVVhauY65 ru1b4w1WINYtrwTgeo9sM4JtO03fF40NlB6OUHaUlNIDEsdSrkVD6Cgzipvhpxn/BAfKac27srAfe 70uTs3Jzu2vQLvIUiuBD5z7sdwPGXoPkJKHiFOmO2eXyQH115cn3KRJZTL6O/gmZsKJXF6hb2MDX8 hfIEbFy+fwSeu8upptFua0/kPQWSuWedbMP4kQfE+a8ezSN3rAm4WfPLYy+hIwwcOGEvwkl+Swfok dQi+6an+xyj8fxTALQ+EcF+XYIVVj05h56qJQ1fortdBor2KaK/jANrq4TM3S3jM3xCe7UMvRyK00 hLWQ1Tcbw==; Received: from mail.bootlin.com ([62.4.15.54]) by casper.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt8V-0004Hr-VD for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:49:35 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 63E1420703; Fri, 12 Oct 2018 10:48:58 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id 60A3120DDD; Fri, 12 Oct 2018 10:48:32 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 15/18] mtd: spi-nor: Add DTR support to the spi-mem logic Date: Fri, 12 Oct 2018 10:48:22 +0200 Message-Id: <20181012084825.23697-16-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_094932_129025_A3A5AD1A X-CRM114-Status: GOOD ( 16.20 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on casper.infradead.org summary: Content analysis details: (-0.0 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Make sure op->xxx.dtr fields are properly filled and unmask DTR modes in spi_nor_spimem_adjust_hwcaps() so that DTR support detection is done through spi_mem_supports_op(). Signed-off-by: Boris Brezillon --- drivers/mtd/spi-nor/spi-nor.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 98dab7f6938e..9ff957dc351c 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -280,12 +280,18 @@ static ssize_t spi_nor_spimem_read_data(struct spi_nor *nor, loff_t ofs, /* get transfer protocols. */ op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto); + op.cmd.dtr = spi_nor_protocol_inst_is_dtr(nor->read_proto); op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->read_proto); + op.addr.dtr = spi_nor_protocol_addr_is_dtr(nor->read_proto); op.dummy.buswidth = op.addr.buswidth; + op.dummy.dtr = op.addr.dtr; op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto); + op.data.dtr = spi_nor_protocol_data_is_dtr(nor->read_proto); /* convert the dummy cycles to the number of bytes */ op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8; + if (op.dummy.dtr) + op.dummy.nbytes *= 2; if (nor->read_proto & SNOR_PROTO_INST_2BYTE) op.cmd.nbytes = 2; @@ -345,8 +351,11 @@ static ssize_t spi_nor_spimem_write_data(struct spi_nor *nor, loff_t ofs, /* get transfer protocols. */ op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto); + op.cmd.dtr = spi_nor_protocol_inst_is_dtr(nor->write_proto); op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto); + op.addr.dtr = spi_nor_protocol_addr_is_dtr(nor->write_proto); op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto); + op.data.dtr = spi_nor_protocol_data_is_dtr(nor->write_proto); if (nor->write_proto & SNOR_PROTO_INST_2BYTE) op.cmd.nbytes = 2; @@ -3043,11 +3052,17 @@ static int spi_nor_spimem_check_readop(struct spi_nor *nor, SPI_MEM_OP_DATA_IN(0, NULL, 1)); op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(read->proto); + op.cmd.dtr = spi_nor_protocol_inst_is_dtr(read->proto); op.addr.buswidth = spi_nor_get_protocol_addr_nbits(read->proto); + op.addr.dtr = spi_nor_protocol_addr_is_dtr(read->proto); op.data.buswidth = spi_nor_get_protocol_data_nbits(read->proto); + op.data.dtr = spi_nor_protocol_addr_is_dtr(read->proto); op.dummy.buswidth = op.addr.buswidth; + op.dummy.dtr = op.addr.dtr; op.dummy.nbytes = (read->num_mode_clocks + read->num_wait_states) * op.dummy.buswidth / 8; + if (op.dummy.dtr) + op.dummy.nbytes *= 2; if (read->proto & SNOR_PROTO_INST_2BYTE) op.cmd.nbytes = 2; @@ -3077,8 +3092,11 @@ static int spi_nor_spimem_check_progop(struct spi_nor *nor, SPI_MEM_OP_DATA_OUT(0, NULL, 1)); op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(pp->proto); + op.cmd.dtr = spi_nor_protocol_inst_is_dtr(pp->proto); op.addr.buswidth = spi_nor_get_protocol_addr_nbits(pp->proto); + op.addr.dtr = spi_nor_protocol_addr_is_dtr(pp->proto); op.data.buswidth = spi_nor_get_protocol_data_nbits(pp->proto); + op.data.dtr = spi_nor_protocol_addr_is_dtr(pp->proto); if (pp->proto & SNOR_PROTO_INST_2BYTE) op.cmd.nbytes = 2; @@ -3106,9 +3124,6 @@ spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, { unsigned int cap; - /* DTR modes are not supported yet, mask them all. */ - *hwcaps &= ~SNOR_HWCAPS_DTR; - /* Start with read commands. */ for (cap = 0; cap < 32; cap++) { int idx; From patchwork Fri Oct 12 08:48:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982924 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="VFq73mJr"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42WhbT0cXMz9s55 for ; Fri, 12 Oct 2018 19:59:17 +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=zZ5nH8JxezmvEap5Yk9OJ8h8v95Nal+a5lXj3jfoVik=; b=VFq73mJrd6i/rvn2QSl35cwtlD YpcmJKNr2WI4RzRZXW2gwSSqtO9IcqfIkmVgHwAnAaRdd2foBSpC4wTKalXNL+j5TrS0DQ+Um1U9T XZtQcjz2Lo4CCjZYZq/zOTgNiD5JxNPzdkRiS6Sdf4Svr9G8qs5GHYQHtEiOzT3n6HnxVgW1Gd/6H thbznLUivG/4q7xpqscSPmXF7rVnZ2usdlOxniF+5O/Ng6G5Q8RFlgJgGBR6LrMVWORyC+T5G97lA Ha45XKDWWIksfz5v8Ze5OxMKXewoyOovvQUqc9TOcTZNu6nLU9sVy7ODuwcvIPTd0/u6Nev9gaN3i 2ekb0u7w==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAtHj-0000Tt-Hb; Fri, 12 Oct 2018 08:59:03 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt8L-0001mE-PR for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:50:23 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 62B3820DD8; Fri, 12 Oct 2018 10:48:58 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id AF3FD20DDF; Fri, 12 Oct 2018 10:48:32 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 16/18] mtd: spi-nor: Add the concept of full DTR modes Date: Fri, 12 Oct 2018 10:48:23 +0200 Message-Id: <20181012084825.23697-17-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_014922_136563_8429361C X-CRM114-Status: GOOD ( 16.78 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Full DTR modes are modes where even the instruction opcode is sent using DTR. Define the relevant macros and enum to add such modes and patch spi_nor_select_preferred_mode() to select them when appropriate. Signed-off-by: Boris Brezillon --- drivers/mtd/spi-nor/spi-nor.c | 17 ++++++++++++++++- include/linux/mtd/spi-nor.h | 29 ++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 9ff957dc351c..849ba0a1c157 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -4124,6 +4124,11 @@ static void spi_nor_select_preferred_mode(struct spi_nor *nor, u32 hwcaps) if (hwcaps & SNOR_HWCPAS_READ_OCTO && hwcaps & SNOR_HWCAPS_PP_OCTO) return; + if (hwcaps & SNOR_HWCAPS_OPI_FULL_DTR) { + nor->preferred_mode = SPI_NOR_MODE_OPI_FULL_DTR; + return; + } + if (hwcaps & SNOR_HWCAPS_OPI) { nor->preferred_mode = SPI_NOR_MODE_OPI; return; @@ -4132,6 +4137,11 @@ static void spi_nor_select_preferred_mode(struct spi_nor *nor, u32 hwcaps) if (hwcaps & SNOR_HWCAPS_READ_QUAD && hwcaps & SNOR_HWCAPS_PP_QUAD) return; + if (hwcaps & SNOR_HWCAPS_QPI_FULL_DTR) { + nor->preferred_mode = SPI_NOR_MODE_QPI_FULL_DTR; + return; + } + if (hwcaps & SNOR_HWCAPS_QPI) { nor->preferred_mode = SPI_NOR_MODE_QPI; return; @@ -4140,6 +4150,11 @@ static void spi_nor_select_preferred_mode(struct spi_nor *nor, u32 hwcaps) if (hwcaps & SNOR_HWCAPS_READ_DUAL) return; + if (hwcaps & SNOR_HWCAPS_DPI_FULL_DTR) { + nor->preferred_mode = SPI_NOR_MODE_DPI_FULL_DTR; + return; + } + if (hwcaps & SNOR_HWCAPS_DPI) { nor->preferred_mode = SPI_NOR_MODE_DPI; return; @@ -4177,7 +4192,7 @@ static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info, * controller directly implements the spi_nor interface. * Yet another reason to switch to spi-mem. */ - ignored_mask = SNOR_HWCAPS_X_X_X; + ignored_mask = SNOR_HWCAPS_X_X_X | SNOR_HWCAPS_XD_XD_XD; if (shared_mask & ignored_mask) { dev_dbg(nor->dev, "SPI n-n-n protocols are not supported.\n"); diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 1035706bc6db..3735d1a0fd0d 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -188,6 +188,10 @@ #define SNOR_PROTO_1_XD_XD(_nbits) \ (SNOR_PROTO_DATA_IS_DTR | SNOR_PROTO_ADDR_IS_DTR | \ SNOR_PROTO_STR(1, _nbits, _nbits)) +#define SNOR_PROTO_XD_XD_XD(_nbits) \ + (SNOR_PROTO_INST_IS_DTR | SNOR_PROTO_DATA_IS_DTR | \ + SNOR_PROTO_ADDR_IS_DTR | \ + SNOR_PROTO_STR(_nbits, _nbits, _nbits)) enum spi_nor_protocol { SNOR_PROTO_1_1_1 = SNOR_PROTO_STR(1, 1, 1), @@ -360,9 +364,13 @@ struct flash_info; enum spi_nor_mode { SPI_NOR_MODE_SPI, + SPI_NOR_MODE_SPI_FULL_DTR, SPI_NOR_MODE_DPI, + SPI_NOR_MODE_DPI_FULL_DTR, SPI_NOR_MODE_QPI, + SPI_NOR_MODE_QPI_FULL_DTR, SPI_NOR_MODE_OPI, + SPI_NOR_MODE_OPI_FULL_DTR, SPI_NOR_NUM_MODES, }; @@ -561,19 +569,34 @@ struct spi_nor_hwcaps { #define SNOR_HWCAPS_DPI BIT(24) #define SNOR_HWCAPS_QPI BIT(25) #define SNOR_HWCAPS_OPI BIT(26) +#define SNOR_HWCAPS_SPI_FULL_DTR BIT(27) +#define SNOR_HWCAPS_DPI_FULL_DTR BIT(28) +#define SNOR_HWCAPS_QPI_FULL_DTR BIT(29) +#define SNOR_HWCAPS_OPI_FULL_DTR BIT(30) #define SNOR_HWCAPS_X_X_X (SNOR_HWCAPS_DPI | \ SNOR_HWCAPS_QPI | \ - SNOR_HWCAPS_OPI) + SNOR_HWCAPS_OPI | \ + SNOR_HWCAPS_SPI_FULL_DTR | \ + SNOR_HWCAPS_DPI_FULL_DTR | \ + SNOR_HWCAPS_QPI_FULL_DTR | \ + SNOR_HWCAPS_OPI_FULL_DTR) + +#define SNOR_HWCAPS_XD_XD_XD (SNOR_HWCAPS_SPI_FULL_DTR | \ + SNOR_HWCAPS_DPI_FULL_DTR | \ + SNOR_HWCAPS_QPI_FULL_DTR | \ + SNOR_HWCAPS_OPI_FULL_DTR) #define SNOR_HWCAPS_DTR (SNOR_HWCAPS_READ_1_1D_1D | \ SNOR_HWCAPS_READ_1_2D_2D | \ SNOR_HWCAPS_READ_1_4D_4D | \ - SNOR_HWCAPS_READ_1_8D_8D) + SNOR_HWCAPS_READ_1_8D_8D | \ + SNOR_HWCAPS_XD_XD_XD) #define SNOR_HWCAPS_ALL (SNOR_HWCAPS_READ_MASK | \ SNOR_HWCAPS_PP_MASK | \ - SNOR_HWCAPS_X_X_X) + SNOR_HWCAPS_X_X_X | \ + SNOR_HWCAPS_XD_XD_XD) /** * spi_nor_scan() - scan the SPI NOR From patchwork Fri Oct 12 08:48:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982923 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="W3QrJOTa"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42WhZm67wLz9s3Z for ; Fri, 12 Oct 2018 19:58:40 +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=Myb7y/4x09fxSq+fZ8mbwU4E7GbNQ+WpJ8brMlNeLhA=; b=W3QrJOTaAcnP8GvAzBnGaWe4Xz LSZMvy9qBM1S/xAHoKMlg0Dm1+pQdaXpbD8xfeLJ0xrb137jlPBSLdbqIQtLnpXyaXCzaTe7XFoPQ gMJRdauZuAb4/0uyN/TYUGDgBdKibZc9ezEP7awRKMnoqlwWB7jqBGS17MoUDzXKfm+hNW5Y0N2MX dIiHEvJljoUfWFkMiUEipFVml64VcqzBVnueZbRoqSm2UBTNOHyrxty4ksTBIPNnuDD2YpWeI0VTm E5v6vefRC0B+RdadoolfQ5pPjOWdPrGMK9+HHQXgoSB2e+g7HaKA+hTtvPBdiuK1fs9h9R2s3m5Sp IQkdEPBw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAtH9-0000DD-W4; Fri, 12 Oct 2018 08:58:28 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt8M-0001kz-Ot for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:50:21 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 79E0F20DDB; Fri, 12 Oct 2018 10:48:58 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id 09B3420DE0; Fri, 12 Oct 2018 10:48:33 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 17/18] mtd: spi-nor: Add 8D-8D-8D mode Date: Fri, 12 Oct 2018 10:48:24 +0200 Message-Id: <20181012084825.23697-18-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_014923_003949_78622AB0 X-CRM114-Status: GOOD ( 12.92 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Add the full octo+dtr mode. Signed-off-by: Boris Brezillon --- drivers/mtd/spi-nor/spi-nor.c | 4 ++++ include/linux/mtd/spi-nor.h | 1 + 2 files changed, 5 insertions(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 849ba0a1c157..d961e3a7b500 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -77,6 +77,7 @@ enum spi_nor_read_command_index { SNOR_CMD_READ_1_8_8, SNOR_CMD_READ_8_8_8, SNOR_CMD_READ_1_8D_8D, + SNOR_CMD_READ_8D_8D_8D, SNOR_CMD_READ_MAX }; @@ -93,6 +94,7 @@ enum spi_nor_pp_command_index { SNOR_CMD_PP_1_1_8, SNOR_CMD_PP_1_8_8, SNOR_CMD_PP_8_8_8, + SNOR_CMD_PP_8D_8D_8D, SNOR_CMD_PP_MAX }; @@ -3021,6 +3023,7 @@ static int spi_nor_hwcaps_read2cmd(u32 hwcaps) { SNOR_HWCAPS_READ_1_8_8, SNOR_CMD_READ_1_8_8 }, { SNOR_HWCAPS_OPI, SNOR_CMD_READ_8_8_8 }, { SNOR_HWCAPS_READ_1_8D_8D, SNOR_CMD_READ_1_8D_8D }, + { SNOR_HWCAPS_OPI_FULL_DTR, SNOR_CMD_READ_8D_8D_8D }, }; return spi_nor_hwcaps2cmd(hwcaps, hwcaps_read2cmd, @@ -3037,6 +3040,7 @@ static int spi_nor_hwcaps_pp2cmd(u32 hwcaps) { SNOR_HWCAPS_PP_1_1_8, SNOR_CMD_PP_1_1_8 }, { SNOR_HWCAPS_PP_1_8_8, SNOR_CMD_PP_1_8_8 }, { SNOR_HWCAPS_OPI, SNOR_CMD_PP_8_8_8 }, + { SNOR_HWCAPS_OPI_FULL_DTR, SNOR_CMD_PP_8D_8D_8D }, }; return spi_nor_hwcaps2cmd(hwcaps, hwcaps_pp2cmd, diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 3735d1a0fd0d..930fc14a7c1e 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -209,6 +209,7 @@ enum spi_nor_protocol { SNOR_PROTO_1_2D_2D = SNOR_PROTO_1_XD_XD(2), SNOR_PROTO_1_4D_4D = SNOR_PROTO_1_XD_XD(4), SNOR_PROTO_1_8D_8D = SNOR_PROTO_1_XD_XD(8), + SNOR_PROTO_8D_8D_8D = SNOR_PROTO_XD_XD_XD(8), }; static inline bool spi_nor_protocol_inst_is_dtr(enum spi_nor_protocol proto) From patchwork Fri Oct 12 08:48:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Boris Brezillon X-Patchwork-Id: 982916 X-Patchwork-Delegate: tudor.ambarus@gmail.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=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="hzkFIbps"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=infradead.org header.i=@infradead.org header.b="OyIqtTeh"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::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 42WhT11KN9z9s3Z for ; Fri, 12 Oct 2018 19:53:40 +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=H0I+9Qw8UqkpU2P/e5Ogo2MdZyT/vSTuM6BA5ACT3e8=; b=hzkFIbpsCp7rrGXmZzUZHbNE1x f4kBo1woLqJ0J1VxcTmh+4sKYeLtrXcCXeG9t/k5u+2ezVWZUwTofH+eGGI/Bo/h5oyYR8Y+e+Esn 3uJUchYXfp6Riw8hZM8ML5M5x+aj3bm2P4IYR1TJrQbkpZQHjjRZ5HL3GAw/U4s8X19CJdC7mkwBI xxKO7wSr6P8j1mOgQHbDpqTViFHcPHmoZEx9gXBl8dKHCI7/N7I67UFpLt80tVc0IcOZ320CSOhOu 06k2fYjkNmqA4QaU/r4mwLXISOpAk1NNk1EFvGJl14zA5hFM8w6PnVhrV7TphIHUgSWlZJ/Yfxck0 K4HuNqsA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAtCI-0005Ak-Kj; Fri, 12 Oct 2018 08:53:26 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt8Y-00026R-V4 for linux-mtd@bombadil.infradead.org; Fri, 12 Oct 2018 08:49:34 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=jtKEVuK6u+1xQjPVo2l+mrWpEieS+DQDZZRK5SqLe0Q=; b=OyIqtTehp56rIjCBMcnPFI5Cv 0swjMtnx/iU6BPvpLH5CNaFtDWC6U+gNlGyBDAwjpcSbhIY1Pm+Uo0Z/rHyqrdqjIXGrDZEkXL26V XdI2iIGi+ahl8jeBPtuxP6jow74/12Hm1Lp2HD5AW+eYTWa+yRBftrMPlVkcTUh/vfDN8BYGHz4jW pUAhKopdxCTXZDrBXJWCPCwOTVg8ZbW6ab+VxPpfQj4Zyp8lKrDGvDHEi3yNZ/bFB/r41IBztBuMI Pu8YAxCodyd4qgvTY9yqgjGxG8bBdFFWHkE8GZdRihVHGHWD8XyekP+sm+LqDQSC4LNrEeqiCm28S WfvMWE4Yg==; Received: from mail.bootlin.com ([62.4.15.54]) by casper.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gAt8V-0004Hu-VE for linux-mtd@lists.infradead.org; Fri, 12 Oct 2018 08:49:33 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 80B9F20DDC; Fri, 12 Oct 2018 10:48:58 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (AAubervilliers-681-1-7-245.w90-88.abo.wanadoo.fr [90.88.129.245]) by mail.bootlin.com (Postfix) with ESMTPSA id 5912F20DE1; Fri, 12 Oct 2018 10:48:33 +0200 (CEST) From: Boris Brezillon To: David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , linux-mtd@lists.infradead.org, Yogesh Gaur , Vignesh R , Cyrille Pitchen Subject: [PATCH RFC 18/18] mtd: spi-nor: Make sure the 8D-8D-8D can be selected on mx25uw51245g Date: Fri, 12 Oct 2018 10:48:25 +0200 Message-Id: <20181012084825.23697-19-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20181012084825.23697-1-boris.brezillon@bootlin.com> References: <20181012084825.23697-1-boris.brezillon@bootlin.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181012_094932_064484_125070FA X-CRM114-Status: GOOD ( 17.40 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.1 on casper.infradead.org summary: Content analysis details: (-0.0 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 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: Julien Su , Mark Brown , Mason Yang , linux-spi@vger.kernel.org, zhengxunli@mxic.com.tw MIME-Version: 1.0 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org mx25uw51245g support 8D-8D-8D mode. Patch the macronix_opi_change_mode() and macronix_opi_tweak_params() functions to support this mode. Signed-off-by: Boris Brezillon --- drivers/mtd/spi-nor/spi-nor.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index d961e3a7b500..e8bd807b7520 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1709,6 +1709,10 @@ static int macronix_opi_change_mode(struct spi_nor *nor, val |= CR2_REG0_MODE_OPI_STR; break; + case SPI_NOR_MODE_OPI_FULL_DTR: + val |= CR2_REG0_MODE_OPI_DTR; + break; + default: /* * If we reach that point, there's a serious problem in the @@ -1732,7 +1736,11 @@ static void macronix_opi_adjust_op(struct spi_nor *nor, struct spi_mem_op *op) case SPINOR_OP_READ_4B: case SPINOR_OP_READ_FAST_4B: op->dummy.nbytes = 20; - op->cmd.opcode = 0xec; + if (nor->mode == SPI_NOR_MODE_OPI_FULL_DTR) + op->cmd.opcode = 0xee; + else + op->cmd.opcode = 0xec; + break; case SPINOR_OP_PP: @@ -1781,8 +1789,11 @@ static void macronix_opi_adjust_op(struct spi_nor *nor, struct spi_mem_op *op) if (op->addr.nbytes) op->addr.buswidth = 8; - if (op->dummy.nbytes) + if (op->dummy.nbytes) { op->dummy.buswidth = 8; + if (op->dummy.dtr) + op->dummy.nbytes *= 2; + } if (op->data.buswidth) op->data.buswidth = 8; @@ -1805,6 +1816,14 @@ static void macronix_opi_tweak_params(struct spi_nor *nor, spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP_8_8_8], 0x12ed, SNOR_PROTO_8_8_8 | SNOR_PROTO_INST_2BYTE); + + params->hwcaps.mask |= SNOR_HWCAPS_OPI_FULL_DTR; + spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_8D_8D_8D], + 0, 20, 0xee11, + SNOR_PROTO_8D_8D_8D | SNOR_PROTO_INST_2BYTE); + spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP_8D_8D_8D], + 0x12ed, + SNOR_PROTO_8D_8D_8D | SNOR_PROTO_INST_2BYTE); } /* Used when the "_ext_id" is two bytes at most */