From patchwork Wed Feb 26 09:36:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pratyush Yadav X-Patchwork-Id: 11405721 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 09BB214D5 for ; Wed, 26 Feb 2020 09:38:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id DD92C20732 for ; Wed, 26 Feb 2020 09:38:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="fxvgziQt" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727451AbgBZJhh (ORCPT ); Wed, 26 Feb 2020 04:37:37 -0500 Received: from lelv0142.ext.ti.com ([198.47.23.249]:40602 "EHLO lelv0142.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726082AbgBZJhh (ORCPT ); Wed, 26 Feb 2020 04:37:37 -0500 Received: from lelv0265.itg.ti.com ([10.180.67.224]) by lelv0142.ext.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9bDZo019716; Wed, 26 Feb 2020 03:37:13 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1582709833; bh=3zg6IMnhpry1kMZ9ELvtMgi825rhOhQg+hNu5ti2jCo=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=fxvgziQt5AQ+OrlY8ksVSMEIK6zpwuObRmhSuXV28jm7l7covCAlhgFasHjcxm9Ls 1TtY91/TGYojl0dYZ3RmHX/zjE7FD0q2A02HSbmpP24FskJV1HdsN1hR9yx11mZNue LR6CSg0lSb9YsOeEAtRnhA8nIZCNMxaSW89WF1UU= Received: from DLEE111.ent.ti.com (dlee111.ent.ti.com [157.170.170.22]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 01Q9bDoE118597 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 26 Feb 2020 03:37:13 -0600 Received: from DLEE108.ent.ti.com (157.170.170.38) by DLEE111.ent.ti.com (157.170.170.22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3; Wed, 26 Feb 2020 03:37:13 -0600 Received: from lelv0327.itg.ti.com (10.180.67.183) by DLEE108.ent.ti.com (157.170.170.38) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3 via Frontend Transport; Wed, 26 Feb 2020 03:37:13 -0600 Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9b4A6110613; Wed, 26 Feb 2020 03:37:09 -0600 From: Pratyush Yadav To: Tudor Ambarus , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Mark Brown , Rob Herring , Mark Rutland CC: Pratyush Yadav , , , , , Sekhar Nori Subject: [PATCH v2 01/11] dt-bindings: spi: allow expressing DTR capability Date: Wed, 26 Feb 2020 15:06:53 +0530 Message-ID: <20200226093703.19765-2-p.yadav@ti.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200226093703.19765-1-p.yadav@ti.com> References: <20200226093703.19765-1-p.yadav@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org Allow spi devices to express DTR receive and transmit capabilities via the properties "spi-rx-dtr" and "spi-tx-dtr". Signed-off-by: Pratyush Yadav --- .../devicetree/bindings/spi/spi-controller.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/spi/spi-controller.yaml b/Documentation/devicetree/bindings/spi/spi-controller.yaml index 1e0ca6ccf64b..7a84debed213 100644 --- a/Documentation/devicetree/bindings/spi/spi-controller.yaml +++ b/Documentation/devicetree/bindings/spi/spi-controller.yaml @@ -120,6 +120,11 @@ patternProperties: description: Delay, in microseconds, after a read transfer. + spi-rx-dtr: + $ref: /schemas/types.yaml#/definitions/flag + description: + Device supports receiving in DTR mode. + spi-tx-bus-width: allOf: - $ref: /schemas/types.yaml#/definitions/uint32 @@ -132,6 +137,11 @@ patternProperties: description: Delay, in microseconds, after a write transfer. + spi-tx-dtr: + $ref: /schemas/types.yaml#/definitions/flag + description: + Device supports transmitting in DTR mode. + required: - compatible - reg From patchwork Wed Feb 26 09:36:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pratyush Yadav X-Patchwork-Id: 11405719 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8A3C192A for ; Wed, 26 Feb 2020 09:38:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6A3E024653 for ; Wed, 26 Feb 2020 09:38:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="K6EPpPzR" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727877AbgBZJhh (ORCPT ); Wed, 26 Feb 2020 04:37:37 -0500 Received: from lelv0143.ext.ti.com ([198.47.23.248]:40056 "EHLO lelv0143.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726541AbgBZJhh (ORCPT ); Wed, 26 Feb 2020 04:37:37 -0500 Received: from lelv0265.itg.ti.com ([10.180.67.224]) by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9bHK2087084; Wed, 26 Feb 2020 03:37:17 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1582709837; bh=/RvMu+KBpcqEDFVBnIWtjiFPQ2qCDkAs2AiQIuWdFws=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=K6EPpPzRPSk4gsirOoI1fBp5truy0/o8R/d1P37k3XGPD9cbcVIhzmmEkU8XA4UO8 XCt4AtdJCY4rouVI64SzqfNU6w30qSYbkkVpf11Yo8Xoyi855W2yZMYDaIwCCOGMQc wJ/3zOV6EfUHDvbLVapgTz2frUoo/TmTXEqezsNI= Received: from DLEE115.ent.ti.com (dlee115.ent.ti.com [157.170.170.26]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 01Q9bHVR118717 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 26 Feb 2020 03:37:17 -0600 Received: from DLEE101.ent.ti.com (157.170.170.31) by DLEE115.ent.ti.com (157.170.170.26) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3; Wed, 26 Feb 2020 03:37:17 -0600 Received: from lelv0327.itg.ti.com (10.180.67.183) by DLEE101.ent.ti.com (157.170.170.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3 via Frontend Transport; Wed, 26 Feb 2020 03:37:17 -0600 Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9b4A7110613; Wed, 26 Feb 2020 03:37:13 -0600 From: Pratyush Yadav To: Tudor Ambarus , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Mark Brown , Rob Herring , Mark Rutland CC: Pratyush Yadav , , , , , Sekhar Nori Subject: [PATCH v2 02/11] spi: set mode bits for "spi-rx-dtr" and "spi-tx-dtr" Date: Wed, 26 Feb 2020 15:06:54 +0530 Message-ID: <20200226093703.19765-3-p.yadav@ti.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200226093703.19765-1-p.yadav@ti.com> References: <20200226093703.19765-1-p.yadav@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org These two DT properties express DTR receive and transmit capabilities of a SPI flash and controller. Introduce two new mode bits: SPI_RX_DTR and SPI_TX_DTR which correspond to the new DT properties. Set these bits when the two corresponding properties are present in the device tree. Also update the detection of unsupported mode bits to include the new bits. Signed-off-by: Pratyush Yadav --- drivers/spi/spi.c | 10 +++++++++- include/linux/spi/spi.h | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 38b4c78df506..25c8ed9343f9 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1927,6 +1927,13 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, } } + /* Device DTR mode. */ + if (of_property_read_bool(nc, "spi-tx-dtr")) + spi->mode |= SPI_TX_DTR; + + if (of_property_read_bool(nc, "spi-rx-dtr")) + spi->mode |= SPI_RX_DTR; + if (spi_controller_is_slave(ctlr)) { if (!of_node_name_eq(nc, "slave")) { dev_err(&ctlr->dev, "%pOF is not called 'slave'\n", @@ -3252,7 +3259,8 @@ int spi_setup(struct spi_device *spi) bad_bits &= ~SPI_CS_HIGH; ugly_bits = bad_bits & (SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL | - SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL); + SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL | + SPI_TX_DTR | SPI_RX_DTR); 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 6d16ba01ff5a..bf1108318389 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -183,6 +183,8 @@ struct spi_device { #define SPI_TX_OCTAL 0x2000 /* transmit with 8 wires */ #define SPI_RX_OCTAL 0x4000 /* receive with 8 wires */ #define SPI_3WIRE_HIZ 0x8000 /* high impedance turnaround */ +#define SPI_RX_DTR 0x10000 /* receive in DTR mode */ +#define SPI_TX_DTR 0x20000 /* transmit in DTR mode */ int irq; void *controller_state; void *controller_data; From patchwork Wed Feb 26 09:36:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pratyush Yadav X-Patchwork-Id: 11405717 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F26D014D5 for ; Wed, 26 Feb 2020 09:38:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C8D6120732 for ; Wed, 26 Feb 2020 09:38:19 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="HhaDEMx6" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727938AbgBZJhp (ORCPT ); Wed, 26 Feb 2020 04:37:45 -0500 Received: from fllv0016.ext.ti.com ([198.47.19.142]:45652 "EHLO fllv0016.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726541AbgBZJho (ORCPT ); Wed, 26 Feb 2020 04:37:44 -0500 Received: from fllv0035.itg.ti.com ([10.64.41.0]) by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9bMXC048392; Wed, 26 Feb 2020 03:37:22 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1582709842; bh=2l+gbPh3UsxLnnwcIelUMPvT/YEvl2c/dQvOKdwacuQ=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=HhaDEMx64ozp/WxJ5VYGDzXmcJVkmcGFqgdH/RVfu6gRmEj4N2MmLODZ2ka6AWONC g4hfh09oT7jzPWmzSHKEN7fF4hM0eGNHGJkihHXIo7kFR8v7krMjmnBE6IFoXKi5G+ MrM3sZR4ePD9TaRCJKkygIl1Plk26u+PKlooGVdU= Received: from DFLE111.ent.ti.com (dfle111.ent.ti.com [10.64.6.32]) by fllv0035.itg.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9bMFn086529; Wed, 26 Feb 2020 03:37:22 -0600 Received: from DFLE115.ent.ti.com (10.64.6.36) by DFLE111.ent.ti.com (10.64.6.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3; Wed, 26 Feb 2020 03:37:21 -0600 Received: from lelv0327.itg.ti.com (10.180.67.183) by DFLE115.ent.ti.com (10.64.6.36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3 via Frontend Transport; Wed, 26 Feb 2020 03:37:21 -0600 Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9b4A8110613; Wed, 26 Feb 2020 03:37:17 -0600 From: Pratyush Yadav To: Tudor Ambarus , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Mark Brown , Rob Herring , Mark Rutland CC: Pratyush Yadav , , , , , Sekhar Nori Subject: [PATCH v2 03/11] spi: spi-mem: allow specifying whether an op is DTR or not Date: Wed, 26 Feb 2020 15:06:55 +0530 Message-ID: <20200226093703.19765-4-p.yadav@ti.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200226093703.19765-1-p.yadav@ti.com> References: <20200226093703.19765-1-p.yadav@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org Each phase is given a separate 'is_dtr' field so mixed protocols like 4S-4D-4D can be supported. Also add the mode bits SPI_RX_DTR and SPI_TX_DTR so controllers can specify whether they support DTR modes or not. Signed-off-by: Pratyush Yadav --- drivers/spi/spi-mem.c | 23 +++++++++++++++++++++++ include/linux/spi/spi-mem.h | 8 ++++++++ 2 files changed, 31 insertions(+) diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index e5a46f0eb93b..cb13e0878b95 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -99,6 +99,16 @@ void spi_controller_dma_unmap_mem_op_data(struct spi_controller *ctlr, } EXPORT_SYMBOL_GPL(spi_controller_dma_unmap_mem_op_data); +static int spi_check_dtr_req(struct spi_mem *mem, bool tx) +{ + u32 mode = mem->spi->mode; + + if ((tx && (mode & SPI_TX_DTR)) || (!tx && (mode & SPI_RX_DTR))) + return 0; + + return -ENOTSUPP; +} + static int spi_check_buswidth_req(struct spi_mem *mem, u8 buswidth, bool tx) { u32 mode = mem->spi->mode; @@ -154,6 +164,19 @@ bool spi_mem_default_supports_op(struct spi_mem *mem, op->data.dir == SPI_MEM_DATA_OUT)) return false; + if (op->cmd.is_dtr && spi_check_dtr_req(mem, true)) + return false; + + if (op->addr.is_dtr && spi_check_dtr_req(mem, true)) + return false; + + if (op->dummy.is_dtr && spi_check_dtr_req(mem, true)) + return false; + + if (op->data.dir != SPI_MEM_NO_DATA && op->data.is_dtr && + spi_check_dtr_req(mem, op->data.dir == SPI_MEM_DATA_OUT)) + 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 af9ff2f0f1b2..4669082b4e3b 100644 --- a/include/linux/spi/spi-mem.h +++ b/include/linux/spi/spi-mem.h @@ -71,6 +71,7 @@ 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.opcode: operation opcode + * @cmd.is_dtr: whether the command opcode should be sent in DTR mode or not * @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 @@ -78,10 +79,13 @@ enum spi_mem_data_dir { * Note that only @addr.nbytes are taken into account in this * address value, so users should make sure the value fits in the * assigned number of bytes. + * @addr.is_dtr: whether the address should be sent in DTR mode or not * @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.is_dtr: whether the dummy bytes should be sent in DTR mode or not * @data.buswidth: number of IO lanes used to send/receive the data + * @data.is_dtr: whether the data should be sent in DTR mode or not * @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 @@ -92,21 +96,25 @@ struct spi_mem_op { struct { u8 buswidth; u8 opcode; + bool is_dtr; } cmd; struct { u8 nbytes; u8 buswidth; u64 val; + bool is_dtr; } addr; struct { u8 nbytes; u8 buswidth; + bool is_dtr; } dummy; struct { u8 buswidth; + bool is_dtr; enum spi_mem_data_dir dir; unsigned int nbytes; union { From patchwork Wed Feb 26 09:36:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pratyush Yadav X-Patchwork-Id: 11405715 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 64BC814D5 for ; Wed, 26 Feb 2020 09:38:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4338E24653 for ; Wed, 26 Feb 2020 09:38:15 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="GC3+4ikY" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728028AbgBZJh4 (ORCPT ); Wed, 26 Feb 2020 04:37:56 -0500 Received: from fllv0015.ext.ti.com ([198.47.19.141]:37304 "EHLO fllv0015.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727998AbgBZJhv (ORCPT ); Wed, 26 Feb 2020 04:37:51 -0500 Received: from lelv0265.itg.ti.com ([10.180.67.224]) by fllv0015.ext.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9bQ06108032; Wed, 26 Feb 2020 03:37:26 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1582709846; bh=UK9ViJ8/KnZTmqsh0WaZJUAW35YfoP4ZW7jL8CyJPoQ=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=GC3+4ikYVuIib89/kVsUWrJZzTCfta5uFhsQ1rmOJebR3ekvGJGeZ/1/IltvlnZ3b 1B7gis80R3HV0fd0WoUUl8MBUIm9j83v2hKHf1gn3oxlGbVRwx6L0/EUnWrtTHLrud uHENnCYDJ3D4byp3UnfSnxEEeMQh0Hbmkkz3SmfU= Received: from DLEE112.ent.ti.com (dlee112.ent.ti.com [157.170.170.23]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 01Q9bQqZ118902 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 26 Feb 2020 03:37:26 -0600 Received: from DLEE107.ent.ti.com (157.170.170.37) by DLEE112.ent.ti.com (157.170.170.23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3; Wed, 26 Feb 2020 03:37:25 -0600 Received: from lelv0327.itg.ti.com (10.180.67.183) by DLEE107.ent.ti.com (157.170.170.37) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3 via Frontend Transport; Wed, 26 Feb 2020 03:37:25 -0600 Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9b4A9110613; Wed, 26 Feb 2020 03:37:22 -0600 From: Pratyush Yadav To: Tudor Ambarus , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Mark Brown , Rob Herring , Mark Rutland CC: Pratyush Yadav , , , , , Sekhar Nori Subject: [PATCH v2 04/11] spi: spi-mem: allow specifying a command's extension Date: Wed, 26 Feb 2020 15:06:56 +0530 Message-ID: <20200226093703.19765-5-p.yadav@ti.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200226093703.19765-1-p.yadav@ti.com> References: <20200226093703.19765-1-p.yadav@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org In xSPI mode, flashes expect 2-byte opcodes. The second byte is called the "command extension". There can be 3 types of extensions in xSPI: repeat, invert, and hex. When the extension type is "repeat", the same opcode is sent twice. When it is "invert", the second byte is the inverse of the opcode. When it is "hex" an additional opcode byte based is sent with the command whose value can be anything. Signed-off-by: Pratyush Yadav --- drivers/spi/spi-mem.c | 23 +++++++++++++++++++++++ include/linux/spi/spi-mem.h | 24 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index cb13e0878b95..3838ddc9aeec 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -462,6 +462,29 @@ int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) } EXPORT_SYMBOL_GPL(spi_mem_adjust_op_size); +int spi_mem_get_cmd_ext(const struct spi_mem_op *op, u8 *ext) +{ + switch (op->cmd.ext_type) { + case SPI_MEM_EXT_INVERT: + *ext = ~op->cmd.opcode; + break; + + case SPI_MEM_EXT_REPEAT: + *ext = op->cmd.opcode; + break; + + case SPI_MEM_EXT_HEX: + *ext = op->cmd.ext; + break; + + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(spi_mem_get_cmd_ext); + static ssize_t spi_mem_no_dirmap_read(struct spi_mem_dirmap_desc *desc, u64 offs, size_t len, void *buf) { diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h index 4669082b4e3b..06ccab17e4d0 100644 --- a/include/linux/spi/spi-mem.h +++ b/include/linux/spi/spi-mem.h @@ -67,11 +67,31 @@ enum spi_mem_data_dir { SPI_MEM_DATA_OUT, }; +/** + * enum spi_mem_cmd_ext - describes the command opcode extension in DTR mode + * @SPI_MEM_EXT_NONE: no extension. This is the default, and is used in Legacy + * SPI mode + * @SPI_MEM_EXT_REPEAT: the extension is same as the opcode + * @SPI_MEM_EXT_INVERT: the extension is the bitwise inverse of the opcode + * @SPI_MEM_EXT_HEX: the extension is any hex value. The command and opcode + * combine to form a 16-bit opcode. + */ +enum spi_mem_cmd_ext { + SPI_MEM_EXT_NONE = 0, + SPI_MEM_EXT_REPEAT, + SPI_MEM_EXT_INVERT, + SPI_MEM_EXT_HEX, +}; + /** * struct spi_mem_op - describes a SPI memory operation * @cmd.buswidth: number of IO lines used to transmit the command * @cmd.opcode: operation opcode * @cmd.is_dtr: whether the command opcode should be sent in DTR mode or not + * @cmd.ext_type: type of the command opcode extension in DTR mode + * @cmd.ext: value of the command opcode extension in DTR mode. It is + * only set when 'ext_type' is 'SPI_MEM_EXT_HEX'. In all other + * cases, the extension can be directly derived from the 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 @@ -97,6 +117,8 @@ struct spi_mem_op { u8 buswidth; u8 opcode; bool is_dtr; + enum spi_mem_cmd_ext ext_type; + u8 ext; } cmd; struct { @@ -361,6 +383,8 @@ int spi_mem_driver_register_with_owner(struct spi_mem_driver *drv, void spi_mem_driver_unregister(struct spi_mem_driver *drv); +int spi_mem_get_cmd_ext(const struct spi_mem_op *op, u8 *ext); + #define spi_mem_driver_register(__drv) \ spi_mem_driver_register_with_owner(__drv, THIS_MODULE) From patchwork Wed Feb 26 09:36:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pratyush Yadav X-Patchwork-Id: 11405701 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id ACDF592A for ; Wed, 26 Feb 2020 09:37:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7AD2724653 for ; Wed, 26 Feb 2020 09:37:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="xvFFzasO" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727967AbgBZJhs (ORCPT ); Wed, 26 Feb 2020 04:37:48 -0500 Received: from fllv0016.ext.ti.com ([198.47.19.142]:45656 "EHLO fllv0016.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727964AbgBZJhs (ORCPT ); Wed, 26 Feb 2020 04:37:48 -0500 Received: from lelv0265.itg.ti.com ([10.180.67.224]) by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9bUa4048417; Wed, 26 Feb 2020 03:37:30 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1582709850; bh=M3mm3Cf772cMZOC46yELya0QzB+JBMYTKpNqzbT5+78=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=xvFFzasOWP5kbWdXgaHp6613afsmoL1nMzqiYCdfAt0AYbuS8r61IEN4iH686RyXj h91btSsp318UeCUo/7LFmtADBwsG6c6JdstMquFUoQUgeI+gfzZPpilvG/hBz3pwBH Mw4LOoS0RWfQHCknYpSr0F1TvIbz0/DEFY1ItCS4= Received: from DFLE110.ent.ti.com (dfle110.ent.ti.com [10.64.6.31]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 01Q9bUM3118977 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 26 Feb 2020 03:37:30 -0600 Received: from DFLE114.ent.ti.com (10.64.6.35) by DFLE110.ent.ti.com (10.64.6.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3; Wed, 26 Feb 2020 03:37:30 -0600 Received: from lelv0327.itg.ti.com (10.180.67.183) by DFLE114.ent.ti.com (10.64.6.35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3 via Frontend Transport; Wed, 26 Feb 2020 03:37:30 -0600 Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9b4AA110613; Wed, 26 Feb 2020 03:37:26 -0600 From: Pratyush Yadav To: Tudor Ambarus , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Mark Brown , Rob Herring , Mark Rutland CC: Pratyush Yadav , , , , , Sekhar Nori Subject: [PATCH v2 05/11] spi: cadence-quadspi: Add support for octal DTR flashes Date: Wed, 26 Feb 2020 15:06:57 +0530 Message-ID: <20200226093703.19765-6-p.yadav@ti.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200226093703.19765-1-p.yadav@ti.com> References: <20200226093703.19765-1-p.yadav@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org Set up opcode extension and enable/disable DTR mode based on whether the command is DTR or not. xSPI flashes can have a 4-byte dummy address associated with some commands like the Read Status Register command in octal DTR mode. Since the flash does not support sending the dummy address, we can not use automatic write completion polling in DTR mode. Further, no write completion polling makes it impossible to use DAC mode for DTR writes. In that mode, the controller does not know beforehand how long a write will be and so it can de-assert Chip Select (CS#) at any time. Once CS# is de-assert, the flash will go into burning phase. But since the controller does not do write completion polling, it does not know when the flash is busy and might send in writes while the flash is not ready. So, disable write completion polling and make writes go through indirect mode for DTR writes and let spi-mem take care of polling the SR. Signed-off-by: Pratyush Yadav --- drivers/spi/spi-cadence-quadspi.c | 247 ++++++++++++++++++++++++++---- 1 file changed, 214 insertions(+), 33 deletions(-) diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index 000f01c18c87..d43bf30e1cde 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -52,6 +52,7 @@ struct cqspi_flash_pdata { u8 inst_width; u8 addr_width; u8 data_width; + bool is_dtr; u8 cs; bool registered; }; @@ -111,6 +112,8 @@ struct cqspi_driver_platdata { #define CQSPI_REG_CONFIG_CHIPSELECT_LSB 10 #define CQSPI_REG_CONFIG_DMA_MASK BIT(15) #define CQSPI_REG_CONFIG_BAUD_LSB 19 +#define CQSPI_REG_CONFIG_DTR_PROTO BIT(24) +#define CQSPI_REG_CONFIG_DUAL_OPCODE BIT(30) #define CQSPI_REG_CONFIG_IDLE_LSB 31 #define CQSPI_REG_CONFIG_CHIPSELECT_MASK 0xF #define CQSPI_REG_CONFIG_BAUD_MASK 0xF @@ -217,6 +220,14 @@ struct cqspi_driver_platdata { #define CQSPI_REG_CMDWRITEDATALOWER 0xA8 #define CQSPI_REG_CMDWRITEDATAUPPER 0xAC +#define CQSPI_REG_POLLING_STATUS 0xB0 +#define CQSPI_REG_POLLING_STATUS_DUMMY_LSB 16 + +#define CQSPI_REG_OP_EXT_LOWER 0xE0 +#define CQSPI_REG_OP_EXT_READ_LSB 24 +#define CQSPI_REG_OP_EXT_WRITE_LSB 16 +#define CQSPI_REG_OP_EXT_STIG_LSB 0 + /* Interrupt status bits */ #define CQSPI_REG_IRQ_MODE_ERR BIT(0) #define CQSPI_REG_IRQ_UNDERFLOW BIT(1) @@ -291,6 +302,69 @@ static unsigned int cqspi_calc_rdreg(struct cqspi_flash_pdata *f_pdata) return rdreg; } +static int cqspi_set_protocol(struct cqspi_flash_pdata *f_pdata, + const struct spi_mem_op *op) +{ + f_pdata->inst_width = CQSPI_INST_TYPE_SINGLE; + f_pdata->addr_width = CQSPI_INST_TYPE_SINGLE; + f_pdata->data_width = CQSPI_INST_TYPE_SINGLE; + f_pdata->is_dtr = op->data.is_dtr && op->cmd.is_dtr && op->addr.is_dtr; + + switch (op->data.buswidth) { + case 0: + break; + case 1: + f_pdata->data_width = CQSPI_INST_TYPE_SINGLE; + break; + case 2: + f_pdata->data_width = CQSPI_INST_TYPE_DUAL; + break; + case 4: + f_pdata->data_width = CQSPI_INST_TYPE_QUAD; + break; + case 8: + f_pdata->data_width = CQSPI_INST_TYPE_OCTAL; + break; + default: + return -EINVAL; + } + + /* Right now we only support 8-8-8 DTR mode. */ + if (f_pdata->is_dtr) { + switch (op->cmd.buswidth) { + case 0: + break; + case 8: + f_pdata->inst_width = CQSPI_INST_TYPE_OCTAL; + break; + default: + return -EINVAL; + } + + switch (op->addr.buswidth) { + case 0: + break; + case 8: + f_pdata->addr_width = CQSPI_INST_TYPE_OCTAL; + break; + default: + return -EINVAL; + } + + switch (op->data.buswidth) { + case 0: + break; + case 8: + f_pdata->data_width = CQSPI_INST_TYPE_OCTAL; + break; + default: + return -EINVAL; + } + } + + return 0; +} + static int cqspi_wait_idle(struct cqspi_st *cqspi) { const unsigned int poll_idle_retry = 3; @@ -348,6 +422,60 @@ static int cqspi_exec_flash_cmd(struct cqspi_st *cqspi, unsigned int reg) return cqspi_wait_idle(cqspi); } +static int cqspi_setup_opcode_ext(struct cqspi_flash_pdata *f_pdata, + const struct spi_mem_op *op, + unsigned int shift) +{ + struct cqspi_st *cqspi = f_pdata->cqspi; + void __iomem *reg_base = cqspi->iobase; + int ret; + unsigned int reg; + u8 ext; + + ret = spi_mem_get_cmd_ext(op, &ext); + if (ret) + return ret; + reg = readl(reg_base + CQSPI_REG_OP_EXT_LOWER); + reg &= ~(0xff << shift); + reg |= ext << shift; + writel(reg, reg_base + CQSPI_REG_OP_EXT_LOWER); + + return 0; +} + +static int cqspi_enable_dtr(struct cqspi_flash_pdata *f_pdata, + const struct spi_mem_op *op, unsigned int shift, + bool enable) +{ + struct cqspi_st *cqspi = f_pdata->cqspi; + void __iomem *reg_base = cqspi->iobase; + unsigned int reg; + int ret; + + reg = readl(reg_base + CQSPI_REG_CONFIG); + + /* + * We enable dual byte opcode here. The callers have to set up the + * extension opcode based on which type of operation it is. + */ + if (enable) { + reg |= CQSPI_REG_CONFIG_DTR_PROTO; + reg |= CQSPI_REG_CONFIG_DUAL_OPCODE; + + /* Set up command opcode extension. */ + ret = cqspi_setup_opcode_ext(f_pdata, op, shift); + if (ret) + return ret; + } else { + reg &= ~CQSPI_REG_CONFIG_DTR_PROTO; + reg &= ~CQSPI_REG_CONFIG_DUAL_OPCODE; + } + + writel(reg, reg_base + CQSPI_REG_CONFIG); + + return cqspi_wait_idle(cqspi); +} + static int cqspi_command_read(struct cqspi_flash_pdata *f_pdata, const struct spi_mem_op *op) { @@ -361,6 +489,15 @@ static int cqspi_command_read(struct cqspi_flash_pdata *f_pdata, size_t read_len; int status; + status = cqspi_set_protocol(f_pdata, op); + if (status) + return status; + + status = cqspi_enable_dtr(f_pdata, op, CQSPI_REG_OP_EXT_STIG_LSB, + f_pdata->is_dtr); + if (status) + return status; + if (!n_rx || n_rx > CQSPI_STIG_DATA_LEN_MAX || !rxbuf) { dev_err(&cqspi->pdev->dev, "Invalid input argument, len %zu rxbuf 0x%p\n", @@ -410,6 +547,16 @@ static int cqspi_command_write(struct cqspi_flash_pdata *f_pdata, unsigned int reg; unsigned int data; size_t write_len; + int ret; + + ret = cqspi_set_protocol(f_pdata, op); + if (ret) + return ret; + + ret = cqspi_enable_dtr(f_pdata, op, CQSPI_REG_OP_EXT_STIG_LSB, + f_pdata->is_dtr); + if (ret) + return ret; if (n_tx > CQSPI_STIG_DATA_LEN_MAX || (n_tx && !txbuf)) { dev_err(&cqspi->pdev->dev, @@ -418,6 +565,9 @@ static int cqspi_command_write(struct cqspi_flash_pdata *f_pdata, return -EINVAL; } + reg = cqspi_calc_rdreg(f_pdata); + writel(reg, reg_base + CQSPI_REG_RD_INSTR); + reg = opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB; if (op->addr.nbytes) { @@ -456,16 +606,25 @@ static int cqspi_read_setup(struct cqspi_flash_pdata *f_pdata, void __iomem *reg_base = cqspi->iobase; unsigned int dummy_clk = 0; unsigned int reg; + int ret; + + ret = cqspi_enable_dtr(f_pdata, op, CQSPI_REG_OP_EXT_READ_LSB, + f_pdata->is_dtr); + if (ret) + return ret; reg = op->cmd.opcode << CQSPI_REG_RD_INSTR_OPCODE_LSB; reg |= cqspi_calc_rdreg(f_pdata); /* Setup dummy clock cycles */ - dummy_clk = op->dummy.nbytes * 8; + dummy_clk = op->dummy.nbytes * (8 / op->dummy.buswidth); + if (f_pdata->is_dtr) + dummy_clk /= 2; + if (dummy_clk > CQSPI_DUMMY_CLKS_MAX) dummy_clk = CQSPI_DUMMY_CLKS_MAX; - if (dummy_clk / 8) + if (dummy_clk) reg |= (dummy_clk & CQSPI_REG_RD_INSTR_DUMMY_MASK) << CQSPI_REG_RD_INSTR_DUMMY_LSB; @@ -575,15 +734,38 @@ static int cqspi_write_setup(struct cqspi_flash_pdata *f_pdata, const struct spi_mem_op *op) { unsigned int reg; + int ret; struct cqspi_st *cqspi = f_pdata->cqspi; void __iomem *reg_base = cqspi->iobase; + ret = cqspi_enable_dtr(f_pdata, op, CQSPI_REG_OP_EXT_WRITE_LSB, + f_pdata->is_dtr); + if (ret) + return ret; + /* Set opcode. */ reg = op->cmd.opcode << CQSPI_REG_WR_INSTR_OPCODE_LSB; + reg |= f_pdata->data_width << CQSPI_REG_WR_INSTR_TYPE_DATA_LSB; + reg |= f_pdata->addr_width << CQSPI_REG_WR_INSTR_TYPE_ADDR_LSB; writel(reg, reg_base + CQSPI_REG_WR_INSTR); reg = cqspi_calc_rdreg(f_pdata); writel(reg, reg_base + CQSPI_REG_RD_INSTR); + /* Set up the command opcode extension. */ + if (f_pdata->is_dtr) { + /* + * Some flashes like the cypress Semper flash expect a 4-byte + * dummy address with the Read SR command in DTR mode, but this + * controller does not support sending address with the Read SR + * command. So, disable write completion polling on the + * controller's side. spi-nor will take care of polling the + * status register. + */ + reg = readl(reg_base + CQSPI_REG_WR_COMPLETION_CTRL); + reg |= CQSPI_REG_WR_DISABLE_AUTO_POLL; + writel(reg, reg_base + CQSPI_REG_WR_COMPLETION_CTRL); + } + reg = readl(reg_base + CQSPI_REG_SIZE); reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK; reg |= (op->addr.nbytes - 1); @@ -833,35 +1015,6 @@ static void cqspi_configure(struct cqspi_flash_pdata *f_pdata, cqspi_controller_enable(cqspi, 1); } -static int cqspi_set_protocol(struct cqspi_flash_pdata *f_pdata, - const struct spi_mem_op *op) -{ - f_pdata->inst_width = CQSPI_INST_TYPE_SINGLE; - f_pdata->addr_width = CQSPI_INST_TYPE_SINGLE; - f_pdata->data_width = CQSPI_INST_TYPE_SINGLE; - - if (op->data.dir == SPI_MEM_DATA_IN) { - switch (op->data.buswidth) { - case 1: - f_pdata->data_width = CQSPI_INST_TYPE_SINGLE; - break; - case 2: - f_pdata->data_width = CQSPI_INST_TYPE_DUAL; - break; - case 4: - f_pdata->data_width = CQSPI_INST_TYPE_QUAD; - break; - case 8: - f_pdata->data_width = CQSPI_INST_TYPE_OCTAL; - break; - default: - return -EINVAL; - } - } - - return 0; -} - static ssize_t cqspi_write(struct cqspi_flash_pdata *f_pdata, const struct spi_mem_op *op) { @@ -879,7 +1032,16 @@ static ssize_t cqspi_write(struct cqspi_flash_pdata *f_pdata, if (ret) return ret; - if (cqspi->use_dac_mode && ((to + len) <= cqspi->ahb_size)) { + /* + * Some flashes like the Cypress Semper flash expect a dummy 4-byte + * address (all 0s) with the read status register command in DTR mode. + * But this controller does not support sending dummy address bytes to + * the flash when it is polling the write completion register in DTR + * mode. So, we can not use direct mode when in DTR mode for writing + * data. + */ + if (!f_pdata->is_dtr && cqspi->use_dac_mode + && ((to + len) <= cqspi->ahb_size)) { memcpy_toio(cqspi->ahb_base + to, buf, len); return cqspi_wait_idle(cqspi); } @@ -1006,6 +1168,23 @@ static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) return ret; } +static bool cqspi_supports_mem_op(struct spi_mem *mem, + const struct spi_mem_op *op) +{ + bool all_true, all_false; + + all_true = op->cmd.is_dtr && op->addr.is_dtr && op->dummy.is_dtr && + op->data.is_dtr; + all_false = !op->cmd.is_dtr && !op->addr.is_dtr && !op->dummy.is_dtr && + !op->data.is_dtr; + + /* Mixed DTR modes not supported. */ + if (!(all_true || all_false)) + return false; + + return spi_mem_default_supports_op(mem, op); +} + static int cqspi_of_get_flash_pdata(struct platform_device *pdev, struct cqspi_flash_pdata *f_pdata, struct device_node *np) @@ -1136,6 +1315,7 @@ static int cqspi_request_mmap_dma(struct cqspi_st *cqspi) static const struct spi_controller_mem_ops cqspi_mem_ops = { .exec_op = cqspi_exec_mem_op, + .supports_op = cqspi_supports_mem_op, }; static int cqspi_setup_flash(struct cqspi_st *cqspi) @@ -1187,7 +1367,8 @@ static int cqspi_probe(struct platform_device *pdev) dev_err(&pdev->dev, "spi_alloc_master failed\n"); return -ENOMEM; } - master->mode_bits = SPI_RX_QUAD | SPI_TX_DUAL | SPI_RX_DUAL; + master->mode_bits = SPI_RX_OCTAL | SPI_TX_OCTAL | SPI_RX_QUAD | + SPI_TX_DUAL | SPI_RX_DUAL | SPI_RX_DTR | SPI_TX_DTR; master->mem_ops = &cqspi_mem_ops; master->dev.of_node = pdev->dev.of_node; From patchwork Wed Feb 26 09:36:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pratyush Yadav X-Patchwork-Id: 11405703 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E1C1E1580 for ; Wed, 26 Feb 2020 09:37:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B852824670 for ; Wed, 26 Feb 2020 09:37:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="oQ8VOMpE" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727972AbgBZJht (ORCPT ); Wed, 26 Feb 2020 04:37:49 -0500 Received: from lelv0142.ext.ti.com ([198.47.23.249]:40650 "EHLO lelv0142.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727959AbgBZJhr (ORCPT ); Wed, 26 Feb 2020 04:37:47 -0500 Received: from fllv0035.itg.ti.com ([10.64.41.0]) by lelv0142.ext.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9bYnK019775; Wed, 26 Feb 2020 03:37:34 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1582709854; bh=im2SpjaQlIXYuNit+5LGQc96gvXnDWfnu+1Jlyi8jCs=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=oQ8VOMpEveaNjWNrvOdr4norJMwcWY/Ggi3pk8bCs87fuKMtQV8BZvP/7DAoLaA+D 0B3/7XqBjm/ZXf9Je2ShArpiVKWfYUpuXR8sjDu6zRKwoKKmgilnf6lHbgI5nEZQjw Fi68aho3SQXSkXSdGNWbxixOkgcLEU1C5GZPwnJg= Received: from DFLE105.ent.ti.com (dfle105.ent.ti.com [10.64.6.26]) by fllv0035.itg.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9bYFc086786; Wed, 26 Feb 2020 03:37:34 -0600 Received: from DFLE103.ent.ti.com (10.64.6.24) by DFLE105.ent.ti.com (10.64.6.26) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3; Wed, 26 Feb 2020 03:37:34 -0600 Received: from lelv0327.itg.ti.com (10.180.67.183) by DFLE103.ent.ti.com (10.64.6.24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3 via Frontend Transport; Wed, 26 Feb 2020 03:37:34 -0600 Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9b4AB110613; Wed, 26 Feb 2020 03:37:30 -0600 From: Pratyush Yadav To: Tudor Ambarus , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Mark Brown , Rob Herring , Mark Rutland CC: Pratyush Yadav , , , , , Sekhar Nori Subject: [PATCH v2 06/11] mtd: spi-nor: add support for DTR protocol Date: Wed, 26 Feb 2020 15:06:58 +0530 Message-ID: <20200226093703.19765-7-p.yadav@ti.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200226093703.19765-1-p.yadav@ti.com> References: <20200226093703.19765-1-p.yadav@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org Double Transfer Rate (DTR) is SPI protocol in which data is transferred on each clock edge as opposed to on each clock cycle. Make framework-level changes to allow supporting flashes in DTR mode. Right now, mixed DTR modes are not supported. So, for example a mode like 4S-4D-4D will not work. All phases need to be either DTR or STR. Signed-off-by: Pratyush Yadav --- drivers/mtd/spi-nor/spi-nor.c | 245 ++++++++++++++++++++++++++-------- include/linux/mtd/spi-nor.h | 34 +++-- 2 files changed, 213 insertions(+), 66 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 4fc632ec18fe..6102520550a1 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -238,6 +238,7 @@ struct flash_info { * status register. Must be used with * SPI_NOR_HAS_TB. */ +#define SPI_NOR_OCTAL_DTR_READ BIT(18) /* Flash supports octal DTR Read. */ /* Part specific fixup hooks. */ const struct spi_nor_fixups *fixups; @@ -245,6 +246,46 @@ struct flash_info { #define JEDEC_MFR(info) ((info)->id[0]) +/** + * spi_nor_spimem_setup_op() - Set up common properties of a spi-mem op. + * @nor: pointer to a 'struct spi_nor' + * @op: pointer to the 'struct spi_mem_op' whose properties + * need to be initialized. + * @proto: the protocol from which the properties need to be set. + */ +static void spi_nor_spimem_setup_op(const struct spi_nor *nor, + struct spi_mem_op *op, + const enum spi_nor_protocol proto) +{ + + op->cmd.buswidth = spi_nor_get_protocol_inst_nbits(proto); + + if (op->addr.nbytes) + op->addr.buswidth = spi_nor_get_protocol_addr_nbits(proto); + + if (op->dummy.nbytes) + op->dummy.buswidth = spi_nor_get_protocol_addr_nbits(proto); + + if (op->data.buf.in || op->data.buf.out) + op->data.buswidth = spi_nor_get_protocol_data_nbits(proto); + + if (spi_nor_protocol_is_dtr(proto)) { + /* + * spi-mem supports mixed DTR modes, but right now we can only + * have all phases either DTR or STR. IOW, spi-mem can have + * something like 4S-4D-4D, but spi-nor can't. So, set all 4 + * phases to either DTR or STR. + */ + op->cmd.is_dtr = op->addr.is_dtr = op->dummy.is_dtr + = op->data.is_dtr = true; + + /* 2 bytes per clock cycle in DTR mode. */ + op->dummy.nbytes *= 2; + + op->cmd.ext_type = nor->cmd_ext; + } +} + /** * spi_nor_spimem_xfer_data() - helper function to read/write data to * flash's memory region @@ -316,14 +357,12 @@ static ssize_t spi_nor_spimem_read_data(struct spi_nor *nor, loff_t from, SPI_MEM_OP_DUMMY(nor->read_dummy, 1), SPI_MEM_OP_DATA_IN(len, buf, 1)); - /* 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); + spi_nor_spimem_setup_op(nor, &op, nor->read_proto); /* convert the dummy cycles to the number of bytes */ op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8; + if (spi_nor_protocol_is_dtr(nor->read_proto)) + op.dummy.nbytes *= 2; return spi_nor_spimem_xfer_data(nor, &op); } @@ -365,13 +404,11 @@ static ssize_t spi_nor_spimem_write_data(struct spi_nor *nor, loff_t to, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_OUT(len, buf, 1)); - 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; + spi_nor_spimem_setup_op(nor, &op, nor->write_proto); + return spi_nor_spimem_xfer_data(nor, &op); } @@ -410,10 +447,16 @@ static int spi_nor_write_enable(struct spi_nor *nor) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_DATA); + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + ret = spi_mem_exec_op(nor->spimem, &op); } else { - ret = nor->controller_ops->write_reg(nor, SPINOR_OP_WREN, - NULL, 0); + if (spi_nor_protocol_is_dtr(nor->reg_proto)) + ret = -ENOTSUPP; + else + ret = nor->controller_ops->write_reg(nor, + SPINOR_OP_WREN, + NULL, 0); } if (ret) @@ -439,10 +482,16 @@ static int spi_nor_write_disable(struct spi_nor *nor) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_DATA); + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + ret = spi_mem_exec_op(nor->spimem, &op); } else { - ret = nor->controller_ops->write_reg(nor, SPINOR_OP_WRDI, - NULL, 0); + if (spi_nor_protocol_is_dtr(nor->reg_proto)) + ret = -ENOTSUPP; + else + ret = nor->controller_ops->write_reg(nor, + SPINOR_OP_WRDI, + NULL, 0); } if (ret) @@ -501,10 +550,15 @@ static int spi_nor_read_fsr(struct spi_nor *nor, u8 *fsr) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_IN(1, fsr, 1)); + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + ret = spi_mem_exec_op(nor->spimem, &op); } else { - ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDFSR, - fsr, 1); + if (spi_nor_protocol_is_dtr(nor->reg_proto)) + ret = -ENOTSUPP; + else + ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDFSR, + fsr, 1); } if (ret) @@ -533,9 +587,15 @@ static int spi_nor_read_cr(struct spi_nor *nor, u8 *cr) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_IN(1, cr, 1)); + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + ret = spi_mem_exec_op(nor->spimem, &op); } else { - ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDCR, cr, 1); + if (spi_nor_protocol_is_dtr(nor->reg_proto)) + ret = -ENOTSUPP; + else + ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDCR, + cr, 1); } if (ret) @@ -566,12 +626,17 @@ static int macronix_set_4byte(struct spi_nor *nor, bool enable) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_DATA); + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + ret = spi_mem_exec_op(nor->spimem, &op); } else { - ret = nor->controller_ops->write_reg(nor, - enable ? SPINOR_OP_EN4B : - SPINOR_OP_EX4B, - NULL, 0); + if (spi_nor_protocol_is_dtr(nor->reg_proto)) + ret = -ENOTSUPP; + else + ret = nor->controller_ops->write_reg(nor, + enable ? SPINOR_OP_EN4B : + SPINOR_OP_EX4B, + NULL, 0); } if (ret) @@ -624,10 +689,15 @@ static int spansion_set_4byte(struct spi_nor *nor, bool enable) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 1)); + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + ret = spi_mem_exec_op(nor->spimem, &op); } else { - ret = nor->controller_ops->write_reg(nor, SPINOR_OP_BRWR, - nor->bouncebuf, 1); + if (spi_nor_protocol_is_dtr(nor->reg_proto)) + ret = -ENOTSUPP; + else + ret = nor->controller_ops->write_reg(nor, SPINOR_OP_BRWR, + nor->bouncebuf, 1); } if (ret) @@ -656,10 +726,16 @@ static int spi_nor_write_ear(struct spi_nor *nor, u8 ear) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 1)); + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + ret = spi_mem_exec_op(nor->spimem, &op); } else { - ret = nor->controller_ops->write_reg(nor, SPINOR_OP_WREAR, - nor->bouncebuf, 1); + if (spi_nor_protocol_is_dtr(nor->reg_proto)) + ret = -ENOTSUPP; + else + ret = nor->controller_ops->write_reg(nor, + SPINOR_OP_WREAR, + nor->bouncebuf, 1); } if (ret) @@ -719,10 +795,16 @@ static int spi_nor_xread_sr(struct spi_nor *nor, u8 *sr) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_IN(1, sr, 1)); + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + ret = spi_mem_exec_op(nor->spimem, &op); } else { - ret = nor->controller_ops->read_reg(nor, SPINOR_OP_XRDSR, - sr, 1); + if (spi_nor_protocol_is_dtr(nor->reg_proto)) + ret = -ENOTSUPP; + else + ret = nor->controller_ops->read_reg(nor, + SPINOR_OP_XRDSR, + sr, 1); } if (ret) @@ -764,10 +846,16 @@ static void spi_nor_clear_sr(struct spi_nor *nor) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_DATA); + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + ret = spi_mem_exec_op(nor->spimem, &op); } else { - ret = nor->controller_ops->write_reg(nor, SPINOR_OP_CLSR, - NULL, 0); + if (spi_nor_protocol_is_dtr(nor->reg_proto)) + ret = -ENOTSUPP; + else + ret = nor->controller_ops->write_reg(nor, + SPINOR_OP_CLSR, + NULL, 0); } if (ret) @@ -817,10 +905,16 @@ static void spi_nor_clear_fsr(struct spi_nor *nor) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_DATA); + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + ret = spi_mem_exec_op(nor->spimem, &op); } else { - ret = nor->controller_ops->write_reg(nor, SPINOR_OP_CLFSR, - NULL, 0); + if (spi_nor_protocol_is_dtr(nor->reg_proto)) + ret = -ENOTSUPP; + else + ret = nor->controller_ops->write_reg(nor, + SPINOR_OP_CLFSR, + NULL, 0); } if (ret) @@ -950,10 +1044,16 @@ static int spi_nor_write_sr(struct spi_nor *nor, const u8 *sr, size_t len) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_OUT(len, sr, 1)); + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + ret = spi_mem_exec_op(nor->spimem, &op); } else { - ret = nor->controller_ops->write_reg(nor, SPINOR_OP_WRSR, - sr, len); + if (spi_nor_protocol_is_dtr(nor->reg_proto)) + ret = -ENOTSUPP; + else + ret = nor->controller_ops->write_reg(nor, + SPINOR_OP_WRSR, + sr, len); } if (ret) { @@ -1152,10 +1252,16 @@ static int spi_nor_write_sr2(struct spi_nor *nor, const u8 *sr2) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_OUT(1, sr2, 1)); + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + ret = spi_mem_exec_op(nor->spimem, &op); } else { - ret = nor->controller_ops->write_reg(nor, SPINOR_OP_WRSR2, - sr2, 1); + if (spi_nor_protocol_is_dtr(nor->reg_proto)) + ret = -ENOTSUPP; + else + ret = nor->controller_ops->write_reg(nor, + SPINOR_OP_WRSR2, + sr2, 1); } if (ret) { @@ -1186,10 +1292,16 @@ static int spi_nor_read_sr2(struct spi_nor *nor, u8 *sr2) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_IN(1, sr2, 1)); + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + ret = spi_mem_exec_op(nor->spimem, &op); } else { - ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDSR2, - sr2, 1); + if (spi_nor_protocol_is_dtr(nor->reg_proto)) + ret = -ENOTSUPP; + else + ret = nor->controller_ops->read_reg(nor, + SPINOR_OP_RDSR2, + sr2, 1); } if (ret) @@ -1217,10 +1329,16 @@ static int spi_nor_erase_chip(struct spi_nor *nor) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_DATA); + spi_nor_spimem_setup_op(nor, &op, nor->write_proto); + ret = spi_mem_exec_op(nor->spimem, &op); } else { - ret = nor->controller_ops->write_reg(nor, SPINOR_OP_CHIP_ERASE, - NULL, 0); + if (spi_nor_protocol_is_dtr(nor->write_proto)) + ret = -ENOTSUPP; + else + ret = nor->controller_ops->write_reg(nor, + SPINOR_OP_CHIP_ERASE, + NULL, 0); } if (ret) @@ -1379,7 +1497,11 @@ static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_DATA); + spi_nor_spimem_setup_op(nor, &op, nor->write_proto); + return spi_mem_exec_op(nor->spimem, &op); + } else if (spi_nor_protocol_is_dtr(nor->write_proto)) { + return -ENOTSUPP; } else if (nor->controller_ops->erase) { return nor->controller_ops->erase(nor, addr); } @@ -3045,6 +3167,7 @@ static int spi_nor_hwcaps_read2cmd(u32 hwcaps) { 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_READ_1_8_8_DTR, SNOR_CMD_READ_1_8_8_DTR }, + { SNOR_HWCAPS_READ_8_8_8_DTR, SNOR_CMD_READ_8_8_8_DTR }, }; return spi_nor_hwcaps2cmd(hwcaps, hwcaps_read2cmd, @@ -3061,6 +3184,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_PP_8_8_8, SNOR_CMD_PP_8_8_8 }, + { SNOR_HWCAPS_PP_8_8_8_DTR, SNOR_CMD_PP_8_8_8_DTR }, }; return spi_nor_hwcaps2cmd(hwcaps, hwcaps_pp2cmd, @@ -3184,13 +3308,11 @@ static int spi_nor_spimem_check_readop(struct spi_nor *nor, 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; + spi_nor_spimem_setup_op(nor, &op, read->proto); + return spi_nor_spimem_check_op(nor, &op); } @@ -3210,9 +3332,7 @@ static int spi_nor_spimem_check_pp(struct spi_nor *nor, 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); + spi_nor_spimem_setup_op(nor, &op, pp->proto); return spi_nor_spimem_check_op(nor, &op); } @@ -3230,11 +3350,10 @@ spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, u32 *hwcaps) struct spi_nor_flash_parameter *params = &nor->params; 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; + /* 2-2-2 and 4-4-4 modes are not supported yet, mask them all. */ + *hwcaps &= ~(SNOR_HWCAPS_READ_2_2_2 | \ + SNOR_HWCAPS_READ_4_4_4 | \ + SNOR_HWCAPS_PP_4_4_4); for (cap = 0; cap < sizeof(*hwcaps) * BITS_PER_BYTE; cap++) { int rdidx, ppidx; @@ -4240,9 +4359,16 @@ static int spi_nor_parse_4bait(struct spi_nor *nor, } /* 4BAIT is the only SFDP table that indicates page program support. */ - if (pp_hwcaps & SNOR_HWCAPS_PP) + if (pp_hwcaps & SNOR_HWCAPS_PP) { spi_nor_set_pp_settings(¶ms_pp[SNOR_CMD_PP], SPINOR_OP_PP_4B, SNOR_PROTO_1_1_1); + /* + * Since xSPI Page Program opcode is backward compatible with + * Legacy SPI, use Legacy SPI opcode there as well. + */ + spi_nor_set_pp_settings(¶ms_pp[SNOR_CMD_PP_8_8_8_DTR], + SPINOR_OP_PP_4B, SNOR_PROTO_8_8_8_DTR); + } if (pp_hwcaps & SNOR_HWCAPS_PP_1_1_4) spi_nor_set_pp_settings(¶ms_pp[SNOR_CMD_PP_1_1_4], SPINOR_OP_PP_1_1_4_4B, @@ -4797,6 +4923,13 @@ static void spi_nor_info_init_params(struct spi_nor *nor) spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP], SPINOR_OP_PP, SNOR_PROTO_1_1_1); + /* + * Since xSPI Page Program opcode is backward compatible with + * Legacy SPI, use Legacy SPI opcode there as well. + */ + spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP_8_8_8_DTR], + SPINOR_OP_PP, SNOR_PROTO_8_8_8_DTR); + /* * Sector Erase settings. Sort Erase Types in ascending order, with the * smallest erase size starting at BIT(0). @@ -4924,7 +5057,8 @@ static void spi_nor_init_params(struct spi_nor *nor) spi_nor_manufacturer_init_params(nor); - if ((nor->info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) && + if ((nor->info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_OCTAL_READ | SPI_NOR_OCTAL_DTR_READ)) && !(nor->info->flags & SPI_NOR_SKIP_SFDP)) spi_nor_sfdp_init_params(nor); @@ -4984,7 +5118,9 @@ static int spi_nor_init(struct spi_nor *nor) return err; } - if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES)) { + if (nor->addr_width == 4 && + !(nor->info->flags & SPI_NOR_OCTAL_DTR_READ) && + !(nor->flags & SNOR_F_4B_OPCODES)) { /* * If the RESET# pin isn't hooked up properly, or the system * otherwise doesn't perform a reset command in the boot @@ -5038,6 +5174,9 @@ static int spi_nor_set_addr_width(struct spi_nor *nor) { if (nor->addr_width) { /* already configured from SFDP */ + } else if (spi_nor_protocol_is_dtr(nor->read_proto)) { + /* Always use 4-byte addresses in DTR mode. */ + nor->addr_width = 4; } else if (nor->info->addr_width) { nor->addr_width = nor->info->addr_width; } else if (nor->mtd.size > 0x1000000) { diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 5abd91cc6dfa..364f37276d78 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -195,6 +195,7 @@ enum spi_nor_protocol { 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_8_8_8_DTR = SNOR_PROTO_DTR(8, 8, 8), }; static inline bool spi_nor_protocol_is_dtr(enum spi_nor_protocol proto) @@ -345,7 +346,7 @@ 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(15, 0) #define SNOR_HWCAPS_READ BIT(0) #define SNOR_HWCAPS_READ_FAST BIT(1) #define SNOR_HWCAPS_READ_1_1_1_DTR BIT(2) @@ -362,11 +363,12 @@ struct spi_nor_hwcaps { #define SNOR_HWCAPS_READ_4_4_4 BIT(9) #define SNOR_HWCAPS_READ_1_4_4_DTR BIT(10) -#define SNOR_HWCAPS_READ_OCTAL GENMASK(14, 11) +#define SNOR_HWCAPS_READ_OCTAL GENMASK(15, 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_HWCAPS_READ_8_8_8_DTR BIT(15) /* * Page Program capabilities. @@ -377,18 +379,19 @@ 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 BIT(16) +#define SNOR_HWCAPS_PP_MASK GENMASK(23, 16) +#define SNOR_HWCAPS_PP BIT(16) -#define SNOR_HWCAPS_PP_QUAD GENMASK(19, 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_QUAD GENMASK(19, 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_OCTAL 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_OCTAL GENMASK(23, 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_8_8_8_DTR BIT(23) #define SNOR_HWCAPS_X_X_X (SNOR_HWCAPS_READ_2_2_2 | \ SNOR_HWCAPS_READ_4_4_4 | \ @@ -399,7 +402,8 @@ struct spi_nor_hwcaps { #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) + SNOR_HWCAPS_READ_1_8_8_DTR | \ + SNOR_HWCAPS_READ_8_8_8_DTR) #define SNOR_HWCAPS_ALL (SNOR_HWCAPS_READ_MASK | \ SNOR_HWCAPS_PP_MASK) @@ -438,6 +442,7 @@ enum spi_nor_read_command_index { SNOR_CMD_READ_1_8_8, SNOR_CMD_READ_8_8_8, SNOR_CMD_READ_1_8_8_DTR, + SNOR_CMD_READ_8_8_8_DTR, SNOR_CMD_READ_MAX }; @@ -454,6 +459,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_8_8_8_DTR, SNOR_CMD_PP_MAX }; @@ -570,6 +576,7 @@ struct flash_info; * @program_opcode: the program opcode * @sst_write_second: used by the SST write operation * @flags: flag options for the current SPI-NOR (SNOR_F_*) + * @cmd_ext: the command opcode extension for DTR mode. * @read_proto: the SPI protocol for read operations * @write_proto: the SPI protocol for write operations * @reg_proto the SPI protocol for read_reg/write_reg/erase operations @@ -599,6 +606,7 @@ struct spi_nor { enum spi_nor_protocol reg_proto; bool sst_write_second; u32 flags; + enum spi_mem_cmd_ext cmd_ext; const struct spi_nor_controller_ops *controller_ops; From patchwork Wed Feb 26 09:36:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pratyush Yadav X-Patchwork-Id: 11405705 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AF43392A for ; Wed, 26 Feb 2020 09:37:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8EDBE24653 for ; Wed, 26 Feb 2020 09:37:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="dGKYuUek" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727959AbgBZJhv (ORCPT ); Wed, 26 Feb 2020 04:37:51 -0500 Received: from lelv0142.ext.ti.com ([198.47.23.249]:40660 "EHLO lelv0142.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727996AbgBZJhu (ORCPT ); Wed, 26 Feb 2020 04:37:50 -0500 Received: from fllv0035.itg.ti.com ([10.64.41.0]) by lelv0142.ext.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9bdv2019797; Wed, 26 Feb 2020 03:37:39 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1582709859; bh=y87/V7I5zHb8iyPROpfrmWQgIDTgx7YSXRab81S5ydQ=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=dGKYuUekGnlAQmBS0P73h9oiGmCI1KzMzEY4yzwUFrV//cwZNz9fMNEI5+giZaotJ gp6m/ODrSrxp4k5tqxEiKaFJ2zNt10UNGqvZPt87bf7E0psyI8LneSxjacf/LXq7ES YVfdgzZ9NUgOWgFJTy05qV4kZ7BQxWK65kjouB2o= Received: from DFLE113.ent.ti.com (dfle113.ent.ti.com [10.64.6.34]) by fllv0035.itg.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9bdo1086843; Wed, 26 Feb 2020 03:37:39 -0600 Received: from DFLE102.ent.ti.com (10.64.6.23) by DFLE113.ent.ti.com (10.64.6.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3; Wed, 26 Feb 2020 03:37:38 -0600 Received: from lelv0327.itg.ti.com (10.180.67.183) by DFLE102.ent.ti.com (10.64.6.23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3 via Frontend Transport; Wed, 26 Feb 2020 03:37:38 -0600 Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9b4AC110613; Wed, 26 Feb 2020 03:37:35 -0600 From: Pratyush Yadav To: Tudor Ambarus , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Mark Brown , Rob Herring , Mark Rutland CC: Pratyush Yadav , , , , , Sekhar Nori Subject: [PATCH v2 07/11] mtd: spi-nor: get command opcode extension type from BFPT Date: Wed, 26 Feb 2020 15:06:59 +0530 Message-ID: <20200226093703.19765-8-p.yadav@ti.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200226093703.19765-1-p.yadav@ti.com> References: <20200226093703.19765-1-p.yadav@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org Some devices in DTR mode expect an extra command byte called the extension. The extension can either be same as the opcode, bitwise inverse of the opcode, or another additional byte forming a 16-byte opcode. Get the extension type from the BFPT. For now, only flashes with "repeat" and "inverse" extensions are supported. As of JESD216D.01, BFPT is 20 DWORDs, so update the table size to reflect that. Signed-off-by: Pratyush Yadav --- drivers/mtd/spi-nor/spi-nor.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 6102520550a1..c86c1537f76e 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -79,11 +79,11 @@ struct sfdp_header { /* Basic Flash Parameter Table */ /* - * JESD216 rev B defines a Basic Flash Parameter Table of 16 DWORDs. - * They are indexed from 1 but C arrays are indexed from 0. + * JESD216 rev D defines a Basic Flash Parameter Table of 20 DWORDs. They are + * indexed from 1 but C arrays are indexed from 0. */ #define BFPT_DWORD(i) ((i) - 1) -#define BFPT_DWORD_MAX 16 +#define BFPT_DWORD_MAX 20 /* The first version of JESD216 defined only 9 DWORDs. */ #define BFPT_DWORD_MAX_JESD216 9 @@ -148,6 +148,12 @@ struct sfdp_header { #define BFPT_DWORD15_QER_SR2_BIT1_NO_RD (0x4UL << 20) #define BFPT_DWORD15_QER_SR2_BIT1 (0x5UL << 20) /* Spansion */ +#define BFPT_DWORD18_CMD_EXT_MASK GENMASK(30, 29) +#define BFPT_DWORD18_CMD_EXT_REP (0x0UL << 29) /* Repeat */ +#define BFPT_DWORD18_CMD_EXT_INV (0x1UL << 29) /* Invert */ +#define BFPT_DWORD18_CMD_EXT_RES (0x2UL << 29) /* Reserved */ +#define BFPT_DWORD18_CMD_EXT_16B (0x3UL << 29) /* 16-bit opcode */ + struct sfdp_bfpt { u32 dwords[BFPT_DWORD_MAX]; }; @@ -3867,6 +3873,24 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, return -EINVAL; } + /* 8D-8D-8D command extension. */ + switch (bfpt.dwords[BFPT_DWORD(18)] & BFPT_DWORD18_CMD_EXT_MASK) { + case BFPT_DWORD18_CMD_EXT_REP: + nor->cmd_ext = SPI_MEM_EXT_REPEAT; + break; + + case BFPT_DWORD18_CMD_EXT_INV: + nor->cmd_ext = SPI_MEM_EXT_INVERT; + break; + + case BFPT_DWORD18_CMD_EXT_RES: + return -EINVAL; + + case BFPT_DWORD18_CMD_EXT_16B: + dev_err(nor->dev, "16-bit opcodes not supported\n"); + return -ENOTSUPP; + } + return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt, params); } From patchwork Wed Feb 26 09:37:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pratyush Yadav X-Patchwork-Id: 11405711 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D4A1292A for ; Wed, 26 Feb 2020 09:38:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A979324653 for ; Wed, 26 Feb 2020 09:38:13 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="VZaqSjF7" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728039AbgBZJh5 (ORCPT ); Wed, 26 Feb 2020 04:37:57 -0500 Received: from fllv0015.ext.ti.com ([198.47.19.141]:37312 "EHLO fllv0015.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727457AbgBZJh4 (ORCPT ); Wed, 26 Feb 2020 04:37:56 -0500 Received: from lelv0265.itg.ti.com ([10.180.67.224]) by fllv0015.ext.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9bhV4108078; Wed, 26 Feb 2020 03:37:43 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1582709863; bh=Jpouza164p3Am9bMPwtHIxkxR6RRsJkgHYuwQqRiHbE=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=VZaqSjF7LW5P3BRIgUjtyY/DUT4wgZ0+QQrgF7rWWLUEwvYsJ09dqPCYqVn1YiR+O 1nF1BORlEpW3gG44QM0odMDWUkPyVxWKxNVqIjkjp9kPugqCMi4Lm13Eiea/8MJ5r5 pmiXE6wc5ygPw0W+zgvH3ixmUNnnRvmjjO3t8B0Q= Received: from DFLE100.ent.ti.com (dfle100.ent.ti.com [10.64.6.21]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 01Q9bhMU119099 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 26 Feb 2020 03:37:43 -0600 Received: from DFLE109.ent.ti.com (10.64.6.30) by DFLE100.ent.ti.com (10.64.6.21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3; Wed, 26 Feb 2020 03:37:43 -0600 Received: from lelv0327.itg.ti.com (10.180.67.183) by DFLE109.ent.ti.com (10.64.6.30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3 via Frontend Transport; Wed, 26 Feb 2020 03:37:42 -0600 Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9b4AD110613; Wed, 26 Feb 2020 03:37:39 -0600 From: Pratyush Yadav To: Tudor Ambarus , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Mark Brown , Rob Herring , Mark Rutland CC: Pratyush Yadav , , , , , Sekhar Nori Subject: [PATCH v2 08/11] mtd: spi-nor: parse xSPI Profile 1.0 table Date: Wed, 26 Feb 2020 15:07:00 +0530 Message-ID: <20200226093703.19765-9-p.yadav@ti.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200226093703.19765-1-p.yadav@ti.com> References: <20200226093703.19765-1-p.yadav@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org This table is indication that the flash is xSPI compliant and hence supports octal DTR mode. Extract information like the fast read opcode, the number of dummy cycles needed for a Read Status Register command, and the number of address bytes needed for a Read Status Register command. The default dummy cycles for a fast octal DTR read are set to 20. Since there is no simple way of determining the dummy cycles needed for the fast read command, flashes that use a different value should update it in their flash-specific hooks. Signed-off-by: Pratyush Yadav --- drivers/mtd/spi-nor/spi-nor.c | 80 +++++++++++++++++++++++++++++++++++ include/linux/mtd/spi-nor.h | 5 +++ 2 files changed, 85 insertions(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index c86c1537f76e..22784c403d77 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 @@ -58,12 +59,14 @@ struct sfdp_parameter_header { #define SFDP_BFPT_ID 0xff00 /* Basic Flash Parameter Table */ #define SFDP_SECTOR_MAP_ID 0xff81 /* Sector Map Table */ #define SFDP_4BAIT_ID 0xff84 /* 4-byte Address Instruction Table */ +#define SFDP_PROFILE1_ID 0xff05 /* xSPI Profile 1.0 table. */ #define SFDP_SIGNATURE 0x50444653U #define SFDP_JESD216_MAJOR 1 #define SFDP_JESD216_MINOR 0 #define SFDP_JESD216A_MINOR 5 #define SFDP_JESD216B_MINOR 6 +#define SFDP_JESD216D_MINOR 8 struct sfdp_header { u32 signature; /* Ox50444653U <=> "SFDP" */ @@ -158,6 +161,11 @@ struct sfdp_bfpt { u32 dwords[BFPT_DWORD_MAX]; }; +/* xSPI Profile 1.0 table (from JESD216D.01). */ +#define PROFILE1_DWORD1_RD_FAST_CMD GENMASK(15, 8) +#define PROFILE1_DWORD1_RDSR_DUMMY BIT(28) +#define PROFILE1_DWORD1_RDSR_ADDR_BYTES BIT(29) + /** * struct spi_nor_fixups - SPI NOR fixup hooks * @default_init: called after default flash parameters init. Used to tweak @@ -4426,6 +4434,74 @@ static int spi_nor_parse_4bait(struct spi_nor *nor, return ret; } +/** + * spi_nor_parse_profile1() - parse the xSPI Profile 1.0 table + * @nor: pointer to a 'struct spi_nor' + * @param_header: pointer to the 'struct sfdp_parameter_header' describing + * the 4-Byte Address Instruction Table length and version. + * @params: pointer to the 'struct spi_nor_flash_parameter' to be. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_parse_profile1(struct spi_nor *nor, + const struct sfdp_parameter_header *profile1_header, + struct spi_nor_flash_parameter *params) +{ + u32 *table, opcode, addr; + size_t len; + int ret, i; + + len = profile1_header->length * sizeof(*table); + table = kmalloc(len, GFP_KERNEL); + if (!table) + return -ENOMEM; + + addr = SFDP_PARAM_HEADER_PTP(profile1_header); + ret = spi_nor_read_sfdp(nor, addr, len, table); + if (ret) + goto out; + + /* Fix endianness of the table DWORDs. */ + for (i = 0; i < profile1_header->length; i++) + table[i] = le32_to_cpu(table[i]); + + /* Get 8D-8D-8D fast read opcode and dummy cycles. */ + opcode = FIELD_GET(PROFILE1_DWORD1_RD_FAST_CMD, table[0]); + + /* + * Update the fast read settings. We set the default dummy cycles to 20 + * here. Flashes can change this value if they need to when enabling + * octal mode. + */ + params->hwcaps.mask |= SNOR_HWCAPS_READ_8_8_8_DTR; + spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_8_8_8_DTR], + 0, 20, opcode, + SNOR_PROTO_8_8_8_DTR); + + /* + * Since the flash supports xSPI DTR reads, it should also support DTR + * Page Program opcodes. + */ + params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR; + + /* + * Set the Read Status Register dummy cycles and dummy address bytes. + */ + if (table[0] & PROFILE1_DWORD1_RDSR_DUMMY) + params->rdsr_dummy = 8; + else + params->rdsr_dummy = 4; + + if (table[0] & PROFILE1_DWORD1_RDSR_ADDR_BYTES) + params->rdsr_addr_nbytes = 4; + else + params->rdsr_addr_nbytes = 0; + +out: + kfree(table); + return ret; +} + /** * spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters. * @nor: pointer to a 'struct spi_nor' @@ -4527,6 +4603,10 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor, err = spi_nor_parse_4bait(nor, param_header, params); break; + case SFDP_PROFILE1_ID: + err = spi_nor_parse_profile1(nor, param_header, params); + break; + default: break; } diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 364f37276d78..f54dbd0f86ab 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -515,6 +515,9 @@ struct spi_nor_locking_ops { * * @size: the flash memory density in bytes. * @page_size: the page size of the SPI NOR flash memory. + * @rdsr_dummy: dummy cycles needed for Read Status Register command. + * @rdsr_addr_nbytes: dummy address bytes needed for Read Status Register + * command. * @hwcaps: describes the read and page program hardware * capabilities. * @reads: read capabilities ordered by priority: the higher index @@ -537,6 +540,8 @@ struct spi_nor_locking_ops { struct spi_nor_flash_parameter { u64 size; u32 page_size; + u8 rdsr_dummy; + u8 rdsr_addr_nbytes; struct spi_nor_hwcaps hwcaps; struct spi_nor_read_command reads[SNOR_CMD_READ_MAX]; From patchwork Wed Feb 26 09:37:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pratyush Yadav X-Patchwork-Id: 11405707 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E54A714D5 for ; Wed, 26 Feb 2020 09:38:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C487B24656 for ; Wed, 26 Feb 2020 09:38:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="Ye0aMPvC" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728063AbgBZJiA (ORCPT ); Wed, 26 Feb 2020 04:38:00 -0500 Received: from lelv0142.ext.ti.com ([198.47.23.249]:40678 "EHLO lelv0142.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727457AbgBZJh7 (ORCPT ); Wed, 26 Feb 2020 04:37:59 -0500 Received: from lelv0265.itg.ti.com ([10.180.67.224]) by lelv0142.ext.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9blW6019846; Wed, 26 Feb 2020 03:37:47 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1582709867; bh=n523ZBNSyrlp74g4Ue51E774uonFnpFhlNalpFEKaCk=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=Ye0aMPvC3N3BHNDkYq8jh+n26j6USlZt3ASaU/dy3r/fHsEmZelzrLqsNL/UFx/dW yVE1LPfyh+oJXlR3bERU4pkjiEwfiWooA/6rtmJOdQl+3agNMo3F0UUsh4odMrAFkJ 2yt6oeCovCC5Z7CL8NLxkinzjdty2HTIM74p1/T4= Received: from DFLE102.ent.ti.com (dfle102.ent.ti.com [10.64.6.23]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 01Q9bl3A119161 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 26 Feb 2020 03:37:47 -0600 Received: from DFLE110.ent.ti.com (10.64.6.31) by DFLE102.ent.ti.com (10.64.6.23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3; Wed, 26 Feb 2020 03:37:47 -0600 Received: from lelv0327.itg.ti.com (10.180.67.183) by DFLE110.ent.ti.com (10.64.6.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3 via Frontend Transport; Wed, 26 Feb 2020 03:37:47 -0600 Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9b4AE110613; Wed, 26 Feb 2020 03:37:43 -0600 From: Pratyush Yadav To: Tudor Ambarus , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Mark Brown , Rob Herring , Mark Rutland CC: Pratyush Yadav , , , , , Sekhar Nori Subject: [PATCH v2 09/11] mtd: spi-nor: use dummy cycle and address width info from SFDP Date: Wed, 26 Feb 2020 15:07:01 +0530 Message-ID: <20200226093703.19765-10-p.yadav@ti.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200226093703.19765-1-p.yadav@ti.com> References: <20200226093703.19765-1-p.yadav@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org The xSPI Profile 1.0 table specifies how many dummy cycles and address bytes are needed for the Read Status Register command in octal DTR mode. Use that information to send the correct Read SR command. Signed-off-by: Pratyush Yadav --- drivers/mtd/spi-nor/spi-nor.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 22784c403d77..06cfc525260c 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -525,6 +525,8 @@ static int spi_nor_write_disable(struct spi_nor *nor) static int spi_nor_read_sr(struct spi_nor *nor, u8 *sr) { int ret; + u8 addr_bytes = nor->params.rdsr_addr_nbytes; + u8 dummy = nor->params.rdsr_dummy; if (nor->spimem) { struct spi_mem_op op = @@ -533,10 +535,21 @@ static int spi_nor_read_sr(struct spi_nor *nor, u8 *sr) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_IN(1, sr, 1)); + if (spi_nor_protocol_is_dtr(nor->reg_proto)) { + op.addr.nbytes = addr_bytes; + op.addr.val = 0; + op.dummy.nbytes = dummy; + } + + spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); + ret = spi_mem_exec_op(nor->spimem, &op); } else { - ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDSR, - sr, 1); + if (spi_nor_protocol_is_dtr(nor->reg_proto)) + ret = -ENOTSUPP; + else + ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDSR, + sr, 1); } if (ret) From patchwork Wed Feb 26 09:37:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pratyush Yadav X-Patchwork-Id: 11405709 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 441B514D5 for ; Wed, 26 Feb 2020 09:38:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2391324653 for ; Wed, 26 Feb 2020 09:38:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="No0k3OIx" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728079AbgBZJiD (ORCPT ); Wed, 26 Feb 2020 04:38:03 -0500 Received: from fllv0016.ext.ti.com ([198.47.19.142]:45698 "EHLO fllv0016.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727457AbgBZJiC (ORCPT ); Wed, 26 Feb 2020 04:38:02 -0500 Received: from lelv0265.itg.ti.com ([10.180.67.224]) by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9bpYG048469; Wed, 26 Feb 2020 03:37:51 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1582709872; bh=f73KydanqCBfpggGnWafdMQaZ6wiesDHl1RvZlVeYSw=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=No0k3OIxU014MkfBvJ/fgCEQgTU7Z/CIgPHeLbBZuNxg97HCQabtuGeyb9bWOr/+H NBRwuOutUGuYTPlp9TIJ63sj5HHaz5l+8TMVBu76ri4gs1VS+EqUgVtcuc4F55DO+J 1sLHBaf1ZOvmd1rXzk0+7N8QkkBuz9qMjSA0Imuc= Received: from DFLE108.ent.ti.com (dfle108.ent.ti.com [10.64.6.29]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 01Q9bpPI119216 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 26 Feb 2020 03:37:51 -0600 Received: from DFLE113.ent.ti.com (10.64.6.34) by DFLE108.ent.ti.com (10.64.6.29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3; Wed, 26 Feb 2020 03:37:51 -0600 Received: from lelv0327.itg.ti.com (10.180.67.183) by DFLE113.ent.ti.com (10.64.6.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3 via Frontend Transport; Wed, 26 Feb 2020 03:37:51 -0600 Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9b4AF110613; Wed, 26 Feb 2020 03:37:47 -0600 From: Pratyush Yadav To: Tudor Ambarus , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Mark Brown , Rob Herring , Mark Rutland CC: Pratyush Yadav , , , , , Sekhar Nori Subject: [PATCH v2 10/11] mtd: spi-nor: enable octal DTR mode when possible Date: Wed, 26 Feb 2020 15:07:02 +0530 Message-ID: <20200226093703.19765-11-p.yadav@ti.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200226093703.19765-1-p.yadav@ti.com> References: <20200226093703.19765-1-p.yadav@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org Allow flashes to specify a hook to enable octal DTR mode. Use this hook whenever possible to get optimal transfer speeds. Signed-off-by: Pratyush Yadav --- drivers/mtd/spi-nor/spi-nor.c | 31 +++++++++++++++++++++++++++++++ include/linux/mtd/spi-nor.h | 2 ++ 2 files changed, 33 insertions(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 06cfc525260c..fdcc1b4abc3f 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -5184,6 +5184,31 @@ static void spi_nor_init_params(struct spi_nor *nor) spi_nor_late_init_params(nor); } +/** spi_nor_octal_dtr_enable() - enable Octal DTR I/O if needed + * @nor: pointer to a 'struct spi_nor' + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_octal_dtr_enable(struct spi_nor *nor) +{ + int ret; + + if (!nor->params.octal_dtr_enable) + return 0; + + if (!(spi_nor_get_protocol_width(nor->read_proto) == 8 || + spi_nor_get_protocol_width(nor->write_proto) == 8)) + return 0; + + ret = nor->params.octal_dtr_enable(nor); + if (ret) + return ret; + + nor->reg_proto = SNOR_PROTO_8_8_8_DTR; + + return 0; +} + /** * spi_nor_quad_enable() - enable Quad I/O if needed. * @nor: pointer to a 'struct spi_nor' @@ -5223,6 +5248,12 @@ static int spi_nor_init(struct spi_nor *nor) { int err; + err = spi_nor_octal_dtr_enable(nor); + if (err) { + dev_dbg(nor->dev, "octal mode not supported\n"); + return err; + } + err = spi_nor_quad_enable(nor); if (err) { dev_dbg(nor->dev, "quad mode not supported\n"); diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index f54dbd0f86ab..c653f6713cfc 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -526,6 +526,7 @@ struct spi_nor_locking_ops { * higher index in the array, the higher priority. * @erase_map: the erase map parsed from the SFDP Sector Map Parameter * Table. + * @octal_dtr_enable: enables SPI NOR octal DTR mode. * @quad_enable: enables SPI NOR quad mode. * @set_4byte: puts the SPI NOR in 4 byte addressing mode. * @convert_addr: converts an absolute address into something the flash @@ -549,6 +550,7 @@ struct spi_nor_flash_parameter { struct spi_nor_erase_map erase_map; + int (*octal_dtr_enable)(struct spi_nor *nor); int (*quad_enable)(struct spi_nor *nor); int (*set_4byte)(struct spi_nor *nor, bool enable); u32 (*convert_addr)(struct spi_nor *nor, u32 addr); From patchwork Wed Feb 26 09:37:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pratyush Yadav X-Patchwork-Id: 11405713 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 148821580 for ; Wed, 26 Feb 2020 09:38:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id DDD6E2465D for ; Wed, 26 Feb 2020 09:38:13 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="K2dTe32y" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727890AbgBZJiJ (ORCPT ); Wed, 26 Feb 2020 04:38:09 -0500 Received: from lelv0143.ext.ti.com ([198.47.23.248]:40120 "EHLO lelv0143.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727457AbgBZJiI (ORCPT ); Wed, 26 Feb 2020 04:38:08 -0500 Received: from lelv0265.itg.ti.com ([10.180.67.224]) by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9bu9B087237; Wed, 26 Feb 2020 03:37:56 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1582709876; bh=lx7klmR18LxVuDBU/ZZOyd+LtXGNVESbcjfzd3wnbNA=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=K2dTe32y4kF8csHn6wb1hcbI0Z5frqIt9bEAjintcG/+wYvrOaf3bOwTQrQywvlO3 Gbmlj6Nxz6dljt9tOtgbN9rwLwxfJSp7Q5JvxcOo6pk6phoanGnVfmVhcFWaMdv2Fp EvLtOua8qL2OaTJJFOLfDh4/oMGVbEU3SVttE1eo= Received: from DLEE108.ent.ti.com (dlee108.ent.ti.com [157.170.170.38]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 01Q9buqo119249 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 26 Feb 2020 03:37:56 -0600 Received: from DLEE103.ent.ti.com (157.170.170.33) by DLEE108.ent.ti.com (157.170.170.38) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3; Wed, 26 Feb 2020 03:37:55 -0600 Received: from lelv0327.itg.ti.com (10.180.67.183) by DLEE103.ent.ti.com (157.170.170.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1847.3 via Frontend Transport; Wed, 26 Feb 2020 03:37:55 -0600 Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id 01Q9b4AG110613; Wed, 26 Feb 2020 03:37:52 -0600 From: Pratyush Yadav To: Tudor Ambarus , Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Mark Brown , Rob Herring , Mark Rutland CC: Pratyush Yadav , , , , , Sekhar Nori Subject: [PATCH v2 11/11] mtd: spi-nor: add support for Cypress Semper flash Date: Wed, 26 Feb 2020 15:07:03 +0530 Message-ID: <20200226093703.19765-12-p.yadav@ti.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200226093703.19765-1-p.yadav@ti.com> References: <20200226093703.19765-1-p.yadav@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org The Cypress Semper flash is an xSPI compliant octal DTR flash. Add support for using it in octal DTR mode. The flash by default boots in a hybrid sector mode. Switch to uniform sector mode on boot. Use the default 20 dummy cycles for a read fast command. The SFDP programming on some older versions of the flash was incorrect. Fixes for that are included in the fixup hooks. Signed-off-by: Pratyush Yadav --- drivers/mtd/spi-nor/spi-nor.c | 191 ++++++++++++++++++++++++++++++++++ include/linux/mtd/spi-nor.h | 14 +++ 2 files changed, 205 insertions(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index fdcc1b4abc3f..a01acecaa568 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -260,6 +260,12 @@ struct flash_info { #define JEDEC_MFR(info) ((info)->id[0]) +/* Forward declarations that will be used by s28hs512t_setup(). */ +static int spi_nor_default_setup(struct spi_nor *nor, + const struct spi_nor_hwcaps *hwcaps); +static void spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, + u8 opcode, enum spi_nor_protocol proto); + /** * spi_nor_spimem_setup_op() - Set up common properties of a spi-mem op. * @nor: pointer to a 'struct spi_nor' @@ -2241,6 +2247,64 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) return ret; } +/** + * spi_nor_cypress_octal_enable() - Enable octal DTR mode on Cypress flashes. + * @nor: pointer to a 'struct spi_nor' + * + * This also sets the memory access latency cycles to 20, which is the default + * in the spi-nor framework. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_cypress_octal_enable(struct spi_nor *nor) +{ + struct spi_mem_op op; + u8 *buf = nor->bouncebuf; + u8 addr_width = 3; + int ret; + + /* Use 20 dummy cycles for memory array reads. */ + ret = spi_nor_write_enable(nor); + if (ret) + return ret; + + *buf = SPINOR_REG_CYPRESS_CFR2V_MEMLAT_8_20; + op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1), + SPI_MEM_OP_ADDR(addr_width, SPINOR_REG_CYPRESS_CFR2V, 1), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(1, buf, 1)); + ret = spi_mem_exec_op(nor->spimem, &op); + if (ret) { + dev_warn(nor->dev, + "failed to set default memory latency value: %d\n", + ret); + return ret; + } + ret = spi_nor_wait_till_ready(nor); + if (ret) + return ret; + + nor->read_dummy = 20; + + /* Set the octal and DTR enable bits. */ + ret = spi_nor_write_enable(nor); + if (ret) + return ret; + + *buf = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN; + op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1), + SPI_MEM_OP_ADDR(addr_width, SPINOR_REG_CYPRESS_CFR5V, 1), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(1, buf, 1)); + ret = spi_mem_exec_op(nor->spimem, &op); + if (ret) { + dev_warn(nor->dev, "Failed to enable octal DTR mode\n"); + return ret; + } + + return 0; +} + /** * spi_nor_sr1_bit6_quad_enable() - Set the Quad Enable BIT(6) in the Status * Register 1. @@ -2453,6 +2517,130 @@ static struct spi_nor_fixups gd25q256_fixups = { .default_init = gd25q256_default_init, }; +static int s28hs512t_setup(struct spi_nor *nor, + const struct spi_nor_hwcaps *hwcaps) +{ + struct spi_mem_op op; + u8 *buf = nor->bouncebuf; + u8 addr_width = 3; + int ret; + + if (!nor->spimem) { + dev_err(nor->dev, + "operation not supported for non-spimem drivers\n"); + return -ENOTSUPP; + } + + /* + * This Cypress flash also supports hybrid sector sizes. Make sure + * uniform sector mode is selected. This is done by setting the bit + * CFR3N[3]. + */ + op = (struct spi_mem_op) + SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 1), + SPI_MEM_OP_ADDR(addr_width, SPINOR_REG_CYPRESS_CFR3N, 1), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_IN(1, buf, 1)); + ret = spi_mem_exec_op(nor->spimem, &op); + if (ret) + return ret; + + ret = spi_nor_write_enable(nor); + if (ret) + return ret; + + /* Set the uniform sector mode bit. */ + *buf |= SPINOR_REG_CYPRESS_CFR3N_UNISECT; + op = (struct spi_mem_op) + SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1), + SPI_MEM_OP_ADDR(addr_width, SPINOR_REG_CYPRESS_CFR3N, 1), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(1, buf, 1)); + ret = spi_mem_exec_op(nor->spimem, &op); + if (ret) { + dev_err(nor->dev, "Failed to change to uniform sector mode\n"); + return ret; + } + + ret = spi_nor_wait_till_ready(nor); + if (ret) + return ret; + + return spi_nor_default_setup(nor, hwcaps); +} + +static void s28hs512t_default_init(struct spi_nor *nor) +{ + nor->params.octal_dtr_enable = spi_nor_cypress_octal_enable; + nor->params.setup = s28hs512t_setup; +} + +static void s28hs512t_post_sfdp_fixup(struct spi_nor *nor) +{ + /* + * On older versions of the flash the xSPI Profile 1.0 table has the + * 8D-8D-8D Fast Read opcode as 0x00. But it actually should be 0xEE. + */ + if (nor->params.reads[SNOR_CMD_READ_8_8_8_DTR].opcode == 0) + nor->params.reads[SNOR_CMD_READ_8_8_8_DTR].opcode = + SPINOR_OP_CYPRESS_RD_FAST; + + /* This flash is also missing the 4-byte Page Program opcode bit. */ + spi_nor_set_pp_settings(&nor->params.page_programs[SNOR_CMD_PP], + SPINOR_OP_PP_4B, SNOR_PROTO_1_1_1); + /* + * Since xSPI Page Program opcode is backward compatible with + * Legacy SPI, use Legacy SPI opcode there as well. + */ + spi_nor_set_pp_settings(&nor->params.page_programs[SNOR_CMD_PP_8_8_8_DTR], + SPINOR_OP_PP_4B, SNOR_PROTO_8_8_8_DTR); + + /* + * The xSPI Profile 1.0 table advertises the number of additional + * address bytes needed for Read Status Register command as 0 but the + * actual value for that is 4. + */ + nor->params.rdsr_addr_nbytes = 4; +} + +static int s28hs512t_post_bfpt_fixup(struct spi_nor *nor, + const struct sfdp_parameter_header *bfpt_header, + const struct sfdp_bfpt *bfpt, + struct spi_nor_flash_parameter *params) +{ + struct spi_mem_op op; + u8 *buf = nor->bouncebuf; + u8 addr_width = 3; + int ret; + + /* + * The BFPT table advertises a 512B page size but the page size is + * actually configurable (with the default being 256B). Read from + * CFR3V[4] and set the correct size. + */ + op = (struct spi_mem_op) + SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 1), + SPI_MEM_OP_ADDR(addr_width, SPINOR_REG_CYPRESS_CFR3V, 1), + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_IN(1, buf, 1)); + ret = spi_mem_exec_op(nor->spimem, &op); + if (ret) + return ret; + + if (*buf & SPINOR_REG_CYPRESS_CFR3V_PGSZ) + params->page_size = 512; + else + params->page_size = 256; + + return 0; +} + +static struct spi_nor_fixups s28hs512t_fixups = { + .default_init = s28hs512t_default_init, + .post_sfdp = s28hs512t_post_sfdp_fixup, + .post_bfpt = s28hs512t_post_bfpt_fixup, +}; + /* NOTE: double check command sets and memory organization when you add * more nor chips. This current list focusses on newer chips, which * have been converging on command sets which including JEDEC ID. @@ -2715,6 +2903,9 @@ static const struct flash_info spi_nor_ids[] = { { "s25fl064l", INFO(0x016017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "s25fl128l", INFO(0x016018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "s25fl256l", INFO(0x016019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { "s28hs512t", INFO(0x345b1a, 0, 256 * 1024, 256, SECT_4K | SPI_NOR_OCTAL_DTR_READ) + .fixups = &s28hs512t_fixups, + }, /* SST -- large erase sizes are "overlays", "sectors" are 4K */ { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index c653f6713cfc..e765272fc0f4 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -150,6 +150,20 @@ #define SR2_QUAD_EN_BIT1 BIT(1) #define SR2_QUAD_EN_BIT7 BIT(7) +/* For Cypress flash. */ +#define SPINOR_OP_RD_ANY_REG 0x65 /* Read any register */ +#define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */ +#define SPINOR_REG_CYPRESS_CFR2V 0x00800003 +#define SPINOR_REG_CYPRESS_CFR2V_MEMLAT_8_20 0x8 +#define SPINOR_REG_CYPRESS_CFR3N 0x00000004 +#define SPINOR_REG_CYPRESS_CFR3V 0x00800004 +#define SPINOR_REG_CYPRESS_CFR3V_PGSZ BIT(4) /* Page size. */ +#define SPINOR_REG_CYPRESS_CFR3N_UNISECT BIT(3) /* Uniform sector mode */ +#define SPINOR_REG_CYPRESS_CFR4V 0x00800005 +#define SPINOR_REG_CYPRESS_CFR5V 0x00800006 +#define SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN 0x3 +#define SPINOR_OP_CYPRESS_RD_FAST 0xee + /* Supported SPI protocols */ #define SNOR_PROTO_INST_MASK GENMASK(23, 16) #define SNOR_PROTO_INST_SHIFT 16