From patchwork Thu Jun 4 12:44:18 2020
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Pratyush Yadav
X-Patchwork-Id: 1303501
X-Patchwork-Delegate: jagannadh.teki@gmail.com
Return-Path:
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@bilbo.ozlabs.org
Authentication-Results: ozlabs.org;
spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de
(client-ip=85.214.62.61; helo=phobos.denx.de;
envelope-from=u-boot-bounces@lists.denx.de; receiver=)
Authentication-Results: ozlabs.org;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: ozlabs.org;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.a=rsa-sha256
header.s=ti-com-17Q1 header.b=ZjGuJGW+;
dkim-atps=neutral
Received: from phobos.denx.de (phobos.denx.de [85.214.62.61])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (4096 bits))
(No client certificate requested)
by ozlabs.org (Postfix) with ESMTPS id 49d59X5cnNz9sSg
for ; Thu, 4 Jun 2020 22:45:52 +1000 (AEST)
Received: from h2850616.stratoserver.net (localhost [IPv6:::1])
by phobos.denx.de (Postfix) with ESMTP id 5BB6981868;
Thu, 4 Jun 2020 14:45:19 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de;
spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de
Authentication-Results: phobos.denx.de;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.b="ZjGuJGW+";
dkim-atps=neutral
Received: by phobos.denx.de (Postfix, from userid 109)
id 4573F813C3; Thu, 4 Jun 2020 14:45:09 +0200 (CEST)
X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de
X-Spam-Level:
X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED
autolearn=ham autolearn_force=no version=3.4.2
Received: from fllv0015.ext.ti.com (fllv0015.ext.ti.com [198.47.19.141])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by phobos.denx.de (Postfix) with ESMTPS id 9E1B580476
for ; Thu, 4 Jun 2020 14:44:58 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=p.yadav@ti.com
Received: from lelv0265.itg.ti.com ([10.180.67.224])
by fllv0015.ext.ti.com (8.15.2/8.15.2) with ESMTP id 054CiklT062805;
Thu, 4 Jun 2020 07:44:46 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com;
s=ti-com-17Q1; t=1591274686;
bh=j4PemjTCC9mQmOEjsdq26OulhEagq2GMX7uSdP110Iw=;
h=From:To:CC:Subject:Date:In-Reply-To:References;
b=ZjGuJGW+OSQ2XXAQ5THWnpVK6CxaTfWCdvrHw2nzwjF2FOKd/VgAwxupD9uxUVsCS
nPel+gI0hiOgJ1YWNgh6u2rAqHhNYX5N/s58iXgsqmd7fE0DPFkTJ49Mp4DVGRC7Id
v1sNf0QJtt1SQ7C8xyYRetWIgmAp4dlp8QLkbHM4=
Received: from DFLE115.ent.ti.com (dfle115.ent.ti.com [10.64.6.36])
by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 054Cijk0093807
(version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL);
Thu, 4 Jun 2020 07:44:45 -0500
Received: from DFLE105.ent.ti.com (10.64.6.26) 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.1979.3; Thu, 4 Jun
2020 07:44:45 -0500
Received: from fllv0040.itg.ti.com (10.64.41.20) 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.1979.3 via
Frontend Transport; Thu, 4 Jun 2020 07:44:45 -0500
Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com
[10.172.224.153])
by fllv0040.itg.ti.com (8.15.2/8.15.2) with ESMTP id 054CicBR004409;
Thu, 4 Jun 2020 07:44:42 -0500
From: Pratyush Yadav
To: Chris Packham , Jagan Teki
, Vignesh R , Ryder Lee
, Weijie Gao ,
GSS_MTK_Uboot_upstream ,
CC: Pratyush Yadav , Sekhar Nori , "Tan, Ley
Foon"
Subject: [PATCH v5 01/21] spi: spi-mem: allow specifying whether an op is DTR
or not
Date: Thu, 4 Jun 2020 18:14:18 +0530
Message-ID: <20200604124438.16783-2-p.yadav@ti.com>
X-Mailer: git-send-email 2.25.0
In-Reply-To: <20200604124438.16783-1-p.yadav@ti.com>
References: <20200604124438.16783-1-p.yadav@ti.com>
MIME-Version: 1.0
X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180
X-BeenThere: u-boot@lists.denx.de
X-Mailman-Version: 2.1.30rc1
Precedence: list
List-Id: U-Boot discussion
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
Errors-To: u-boot-bounces@lists.denx.de
Sender: "U-Boot"
X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de
X-Virus-Status: Clean
Each phase is given a separate 'dtr' field so mixed protocols like
4S-4D-4D can be supported.
Signed-off-by: Pratyush Yadav
---
drivers/spi/spi-mem.c | 3 +++
include/spi-mem.h | 8 ++++++++
2 files changed, 11 insertions(+)
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
index d344701aeb..967c241853 100644
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -159,6 +159,9 @@ bool spi_mem_default_supports_op(struct spi_slave *slave,
op->data.dir == SPI_MEM_DATA_OUT))
return false;
+ if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr)
+ return false;
+
return true;
}
EXPORT_SYMBOL_GPL(spi_mem_default_supports_op);
diff --git a/include/spi-mem.h b/include/spi-mem.h
index 893f7bd733..55e5019a1c 100644
--- a/include/spi-mem.h
+++ b/include/spi-mem.h
@@ -74,6 +74,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.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
@@ -81,10 +82,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.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.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.dtr: whether the data should be sent in DTR mode or not
* @data.dir: direction of the transfer
* @data.buf.in: input buffer
* @data.buf.out: output buffer
@@ -93,21 +97,25 @@ struct spi_mem_op {
struct {
u8 buswidth;
u8 opcode;
+ u8 dtr : 1;
} cmd;
struct {
u8 nbytes;
u8 buswidth;
+ u8 dtr : 1;
u64 val;
} addr;
struct {
u8 nbytes;
u8 buswidth;
+ u8 dtr : 1;
} dummy;
struct {
u8 buswidth;
+ u8 dtr : 1;
enum spi_mem_data_dir dir;
unsigned int nbytes;
/* buf.{in,out} must be DMA-able. */
From patchwork Thu Jun 4 12:44:19 2020
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Pratyush Yadav
X-Patchwork-Id: 1303498
X-Patchwork-Delegate: jagannadh.teki@gmail.com
Return-Path:
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@bilbo.ozlabs.org
Authentication-Results: ozlabs.org;
spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de
(client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;
envelope-from=u-boot-bounces@lists.denx.de; receiver=)
Authentication-Results: ozlabs.org;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: ozlabs.org;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.a=rsa-sha256
header.s=ti-com-17Q1 header.b=CpAhseBJ;
dkim-atps=neutral
Received: from phobos.denx.de (phobos.denx.de
[IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (4096 bits))
(No client certificate requested)
by ozlabs.org (Postfix) with ESMTPS id 49d58s2106z9sSc
for ; Thu, 4 Jun 2020 22:45:17 +1000 (AEST)
Received: from h2850616.stratoserver.net (localhost [IPv6:::1])
by phobos.denx.de (Postfix) with ESMTP id 2A76381015;
Thu, 4 Jun 2020 14:45:07 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de;
spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de
Authentication-Results: phobos.denx.de;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.b="CpAhseBJ";
dkim-atps=neutral
Received: by phobos.denx.de (Postfix, from userid 109)
id CC2DE81015; Thu, 4 Jun 2020 14:45:03 +0200 (CEST)
X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de
X-Spam-Level:
X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED
autolearn=ham autolearn_force=no version=3.4.2
Received: from lelv0142.ext.ti.com (lelv0142.ext.ti.com [198.47.23.249])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by phobos.denx.de (Postfix) with ESMTPS id 93D2180676
for ; Thu, 4 Jun 2020 14:44:59 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=p.yadav@ti.com
Received: from lelv0265.itg.ti.com ([10.180.67.224])
by lelv0142.ext.ti.com (8.15.2/8.15.2) with ESMTP id 054CingL098971;
Thu, 4 Jun 2020 07:44:49 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com;
s=ti-com-17Q1; t=1591274689;
bh=fIpxMUncsZj+G2+qpM0y0zpXMHmArjs17CIIgCcCCGo=;
h=From:To:CC:Subject:Date:In-Reply-To:References;
b=CpAhseBJdXh0rqI4FxE264dDQ0iO68yocf2b25cCdS4mmVl3ph67DYtLVEiYWYJCs
SXuRvtGR+vRXpwGKUJcE0OkUsol4QCMRHF7XeF9qH+IOBWKDtQ41R/83IgXOzabpA0
BupIMTaAVmODaXrw2eYo5QaAuorra4w8JAmTokYQ=
Received: from DFLE106.ent.ti.com (dfle106.ent.ti.com [10.64.6.27])
by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 054CimxY093857
(version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL);
Thu, 4 Jun 2020 07:44:48 -0500
Received: from DFLE108.ent.ti.com (10.64.6.29) by DFLE106.ent.ti.com
(10.64.6.27) with Microsoft SMTP Server (version=TLS1_2,
cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1979.3; Thu, 4 Jun
2020 07:44:48 -0500
Received: from fllv0040.itg.ti.com (10.64.41.20) 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.1979.3 via
Frontend Transport; Thu, 4 Jun 2020 07:44:48 -0500
Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com
[10.172.224.153])
by fllv0040.itg.ti.com (8.15.2/8.15.2) with ESMTP id 054CicBS004409;
Thu, 4 Jun 2020 07:44:46 -0500
From: Pratyush Yadav
To: Chris Packham , Jagan Teki
, Vignesh R , Ryder Lee
, Weijie Gao ,
GSS_MTK_Uboot_upstream ,
CC: Pratyush Yadav , Sekhar Nori , "Tan, Ley
Foon"
Subject: [PATCH v5 02/21] spi: spi-mem: allow specifying a command's extension
Date: Thu, 4 Jun 2020 18:14:19 +0530
Message-ID: <20200604124438.16783-3-p.yadav@ti.com>
X-Mailer: git-send-email 2.25.0
In-Reply-To: <20200604124438.16783-1-p.yadav@ti.com>
References: <20200604124438.16783-1-p.yadav@ti.com>
MIME-Version: 1.0
X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180
X-BeenThere: u-boot@lists.denx.de
X-Mailman-Version: 2.1.30rc1
Precedence: list
List-Id: U-Boot discussion
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
Errors-To: u-boot-bounces@lists.denx.de
Sender: "U-Boot"
X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de
X-Virus-Status: Clean
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.
So, make opcode a 16-bit value and add a 'nbytes', similar to how
multiple address widths are handled.
All usages of sizeof(op->cmd.opcode) also need to be changed to be
op->cmd.nbytes because that is the actual indicator of opcode size.
Signed-off-by: Pratyush Yadav
---
drivers/spi/mtk_snfi_spi.c | 3 +--
drivers/spi/spi-mem-nodm.c | 4 ++--
drivers/spi/spi-mem.c | 13 +++++++------
include/spi-mem.h | 6 +++++-
4 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/drivers/spi/mtk_snfi_spi.c b/drivers/spi/mtk_snfi_spi.c
index 2a89476515..79e9fac265 100644
--- a/drivers/spi/mtk_snfi_spi.c
+++ b/drivers/spi/mtk_snfi_spi.c
@@ -64,8 +64,7 @@ static int mtk_snfi_adjust_op_size(struct spi_slave *slave,
* or the output+input data must not exceed the GPRAM size.
*/
- nbytes = sizeof(op->cmd.opcode) + op->addr.nbytes +
- op->dummy.nbytes;
+ nbytes = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
if (nbytes + op->data.nbytes <= SNFI_GPRAM_SIZE)
return 0;
diff --git a/drivers/spi/spi-mem-nodm.c b/drivers/spi/spi-mem-nodm.c
index 765f05fe54..db54101383 100644
--- a/drivers/spi/spi-mem-nodm.c
+++ b/drivers/spi/spi-mem-nodm.c
@@ -27,7 +27,7 @@ int spi_mem_exec_op(struct spi_slave *slave,
tx_buf = op->data.buf.out;
}
- op_len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes;
+ op_len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
op_buf = calloc(1, op_len);
ret = spi_claim_bus(slave);
@@ -89,7 +89,7 @@ int spi_mem_adjust_op_size(struct spi_slave *slave,
{
unsigned int len;
- len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes;
+ len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
if (slave->max_write_size && len > slave->max_write_size)
return -EINVAL;
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
index 967c241853..34d947db5d 100644
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -162,6 +162,9 @@ bool spi_mem_default_supports_op(struct spi_slave *slave,
if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr)
return false;
+ if (op->cmd.nbytes != 1)
+ return false;
+
return true;
}
EXPORT_SYMBOL_GPL(spi_mem_default_supports_op);
@@ -268,8 +271,7 @@ int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
}
#ifndef __UBOOT__
- tmpbufsize = sizeof(op->cmd.opcode) + op->addr.nbytes +
- op->dummy.nbytes;
+ tmpbufsize = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
/*
* Allocate a buffer to transmit the CMD, ADDR cycles with kmalloc() so
@@ -284,7 +286,7 @@ int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
tmpbuf[0] = op->cmd.opcode;
xfers[xferpos].tx_buf = tmpbuf;
- xfers[xferpos].len = sizeof(op->cmd.opcode);
+ xfers[xferpos].len = op->cmd.nbytes;
xfers[xferpos].tx_nbits = op->cmd.buswidth;
spi_message_add_tail(&xfers[xferpos], &msg);
xferpos++;
@@ -348,7 +350,7 @@ int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
tx_buf = op->data.buf.out;
}
- op_len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes;
+ op_len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
/*
* Avoid using malloc() here so that we can use this code in SPL where
@@ -437,8 +439,7 @@ int spi_mem_adjust_op_size(struct spi_slave *slave, struct spi_mem_op *op)
if (!ops->mem_ops || !ops->mem_ops->exec_op) {
unsigned int len;
- len = sizeof(op->cmd.opcode) + op->addr.nbytes +
- op->dummy.nbytes;
+ len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
if (slave->max_write_size && len > slave->max_write_size)
return -EINVAL;
diff --git a/include/spi-mem.h b/include/spi-mem.h
index 55e5019a1c..9167c435f6 100644
--- a/include/spi-mem.h
+++ b/include/spi-mem.h
@@ -20,6 +20,7 @@
{ \
.buswidth = __buswidth, \
.opcode = __opcode, \
+ .nbytes = 1, \
}
#define SPI_MEM_OP_ADDR(__nbytes, __val, __buswidth) \
@@ -72,6 +73,8 @@ enum spi_mem_data_dir {
/**
* struct spi_mem_op - describes a SPI memory operation
+ * @cmd.nbytes: number of opcode bytes (only 1 or 2 are valid). The opcode is
+ * sent MSB-first.
* @cmd.buswidth: number of IO lines used to transmit the command
* @cmd.opcode: operation opcode
* @cmd.dtr: whether the command opcode should be sent in DTR mode or not
@@ -95,9 +98,10 @@ enum spi_mem_data_dir {
*/
struct spi_mem_op {
struct {
+ u8 nbytes;
u8 buswidth;
- u8 opcode;
u8 dtr : 1;
+ u16 opcode;
} cmd;
struct {
From patchwork Thu Jun 4 12:44:20 2020
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Pratyush Yadav
X-Patchwork-Id: 1303500
X-Patchwork-Delegate: jagannadh.teki@gmail.com
Return-Path:
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@bilbo.ozlabs.org
Authentication-Results: ozlabs.org;
spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de
(client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;
envelope-from=u-boot-bounces@lists.denx.de; receiver=)
Authentication-Results: ozlabs.org;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: ozlabs.org;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.a=rsa-sha256
header.s=ti-com-17Q1 header.b=ZMY/UWJG;
dkim-atps=neutral
Received: from phobos.denx.de (phobos.denx.de
[IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (4096 bits))
(No client certificate requested)
by ozlabs.org (Postfix) with ESMTPS id 49d59H0d0Mz9sSc
for ; Thu, 4 Jun 2020 22:45:39 +1000 (AEST)
Received: from h2850616.stratoserver.net (localhost [IPv6:::1])
by phobos.denx.de (Postfix) with ESMTP id 69BD081865;
Thu, 4 Jun 2020 14:45:14 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de;
spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de
Authentication-Results: phobos.denx.de;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.b="ZMY/UWJG";
dkim-atps=neutral
Received: by phobos.denx.de (Postfix, from userid 109)
id 10FC5813BC; Thu, 4 Jun 2020 14:45:10 +0200 (CEST)
X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de
X-Spam-Level:
X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED
autolearn=ham autolearn_force=no version=3.4.2
Received: from lelv0142.ext.ti.com (lelv0142.ext.ti.com [198.47.23.249])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by phobos.denx.de (Postfix) with ESMTPS id E6F258066F
for ; Thu, 4 Jun 2020 14:45:04 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=p.yadav@ti.com
Received: from fllv0035.itg.ti.com ([10.64.41.0])
by lelv0142.ext.ti.com (8.15.2/8.15.2) with ESMTP id 054CirXb098984;
Thu, 4 Jun 2020 07:44:53 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com;
s=ti-com-17Q1; t=1591274693;
bh=FV2k+PoQKyQTZ0RIKF1a3JAf9lnl73MGgMVN9nFpbkE=;
h=From:To:CC:Subject:Date:In-Reply-To:References;
b=ZMY/UWJGAOxCXjBpY3B2sX0BdHpAMplOP6dechKHRbAm/lW7jwbFPiO8zO0Uso1Zm
afGxs584cdIiynBWBJ1Kh4vjLmVrsBRgmwUlH+rR8PbFataElISv4oSyeI1XefzGGO
tlpxRv+I2/YCUvapNljoxXGdnnW2CswSWOflzzzM=
Received: from DFLE115.ent.ti.com (dfle115.ent.ti.com [10.64.6.36])
by fllv0035.itg.ti.com (8.15.2/8.15.2) with ESMTP id 054CiruQ112283;
Thu, 4 Jun 2020 07:44:53 -0500
Received: from DFLE113.ent.ti.com (10.64.6.34) 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.1979.3; Thu, 4 Jun
2020 07:44:52 -0500
Received: from fllv0040.itg.ti.com (10.64.41.20) 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.1979.3 via
Frontend Transport; Thu, 4 Jun 2020 07:44:52 -0500
Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com
[10.172.224.153])
by fllv0040.itg.ti.com (8.15.2/8.15.2) with ESMTP id 054CicBT004409;
Thu, 4 Jun 2020 07:44:49 -0500
From: Pratyush Yadav
To: Chris Packham , Jagan Teki
, Vignesh R , Ryder Lee
, Weijie Gao ,
GSS_MTK_Uboot_upstream ,
CC: Pratyush Yadav , Sekhar Nori , "Tan, Ley
Foon"
Subject: [PATCH v5 03/21] spi: cadence-qspi: Do not calibrate when device tree
sets read delay
Date: Thu, 4 Jun 2020 18:14:20 +0530
Message-ID: <20200604124438.16783-4-p.yadav@ti.com>
X-Mailer: git-send-email 2.25.0
In-Reply-To: <20200604124438.16783-1-p.yadav@ti.com>
References: <20200604124438.16783-1-p.yadav@ti.com>
MIME-Version: 1.0
X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180
X-BeenThere: u-boot@lists.denx.de
X-Mailman-Version: 2.1.30rc1
Precedence: list
List-Id: U-Boot discussion
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
Errors-To: u-boot-bounces@lists.denx.de
Sender: "U-Boot"
X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de
X-Virus-Status: Clean
If the device tree provides a read delay value, use that directly and do
not perform the calibration procedure.
This allows the device tree to over-ride the read delay value in cases
where the read delay value obtained via calibration is incorrect. One
such example is the Cypress Semper flash. It needs a read delay of 4 in
octal DTR mode. But since the calibration procedure is run before the
flash is switched in octal DTR mode, it yields a read delay of 2. A
value of 4 works for both octal DTR and legacy modes.
Signed-off-by: Pratyush Yadav
---
drivers/spi/cadence_qspi.c | 26 +++++++++++++++++++++-----
drivers/spi/cadence_qspi.h | 1 +
2 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index 1e85749209..305f2ec0df 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -141,12 +141,20 @@ static int cadence_spi_set_speed(struct udevice *bus, uint hz)
cadence_qspi_apb_controller_disable(priv->regbase);
/*
- * Calibration required for different current SCLK speed, requested
- * SCLK speed or chip select
+ * If the device tree already provides a read delay value, use that
+ * instead of calibrating.
*/
- if (priv->previous_hz != hz ||
- priv->qspi_calibrated_hz != hz ||
- priv->qspi_calibrated_cs != spi_chip_select(bus)) {
+ if (plat->read_delay >= 0) {
+ cadence_spi_write_speed(bus, hz);
+ cadence_qspi_apb_readdata_capture(priv->regbase, 1,
+ plat->read_delay);
+ } else if (priv->previous_hz != hz ||
+ priv->qspi_calibrated_hz != hz ||
+ priv->qspi_calibrated_cs != spi_chip_select(bus)) {
+ /*
+ * Calibration required for different current SCLK speed,
+ * requested SCLK speed or chip select
+ */
err = spi_calibration(bus, hz);
if (err)
return err;
@@ -320,6 +328,14 @@ static int cadence_spi_ofdata_to_platdata(struct udevice *bus)
255);
plat->tchsh_ns = ofnode_read_u32_default(subnode, "cdns,tchsh-ns", 20);
plat->tslch_ns = ofnode_read_u32_default(subnode, "cdns,tslch-ns", 20);
+ /*
+ * Read delay should be an unsigned value but we use a signed integer
+ * so that negative values can indicate that the device tree did not
+ * specify any signed values and we need to perform the calibration
+ * sequence to find it out.
+ */
+ plat->read_delay = ofnode_read_s32_default(subnode, "cdns,read-delay",
+ -1);
debug("%s: regbase=%p ahbbase=%p max-frequency=%d page-size=%d\n",
__func__, plat->regbase, plat->ahbbase, plat->max_hz,
diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h
index ae459c74a1..9dff2fdced 100644
--- a/drivers/spi/cadence_qspi.h
+++ b/drivers/spi/cadence_qspi.h
@@ -26,6 +26,7 @@ struct cadence_spi_platdata {
u32 trigger_address;
fdt_addr_t ahbsize;
bool use_dac_mode;
+ int read_delay;
/* Flash parameters */
u32 page_size;
From patchwork Thu Jun 4 12:44:21 2020
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Pratyush Yadav
X-Patchwork-Id: 1303503
X-Patchwork-Delegate: jagannadh.teki@gmail.com
Return-Path:
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@bilbo.ozlabs.org
Authentication-Results: ozlabs.org;
spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de
(client-ip=85.214.62.61; helo=phobos.denx.de;
envelope-from=u-boot-bounces@lists.denx.de; receiver=)
Authentication-Results: ozlabs.org;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: ozlabs.org;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.a=rsa-sha256
header.s=ti-com-17Q1 header.b=IllUMGE6;
dkim-atps=neutral
Received: from phobos.denx.de (phobos.denx.de [85.214.62.61])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (4096 bits))
(No client certificate requested)
by ozlabs.org (Postfix) with ESMTPS id 49d5B75Xhmz9sSy
for ; Thu, 4 Jun 2020 22:46:23 +1000 (AEST)
Received: from h2850616.stratoserver.net (localhost [IPv6:::1])
by phobos.denx.de (Postfix) with ESMTP id 617658168B;
Thu, 4 Jun 2020 14:45:25 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de;
spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de
Authentication-Results: phobos.denx.de;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.b="IllUMGE6";
dkim-atps=neutral
Received: by phobos.denx.de (Postfix, from userid 109)
id 8AD67816A4; Thu, 4 Jun 2020 14:45:15 +0200 (CEST)
X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de
X-Spam-Level:
X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED
autolearn=ham autolearn_force=no version=3.4.2
Received: from lelv0143.ext.ti.com (lelv0143.ext.ti.com [198.47.23.248])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by phobos.denx.de (Postfix) with ESMTPS id EC92880676
for ; Thu, 4 Jun 2020 14:45:05 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=p.yadav@ti.com
Received: from lelv0266.itg.ti.com ([10.180.67.225])
by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id 054CitLW096713;
Thu, 4 Jun 2020 07:44:55 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com;
s=ti-com-17Q1; t=1591274695;
bh=x2p6PZCykCm7moHtUB+3kA3p/CZSm5M+FDEhXIiHuHE=;
h=From:To:CC:Subject:Date:In-Reply-To:References;
b=IllUMGE6JjMD0PBI2hw+9eUxzIcknK5a56ec3tRn+1EcZ96dzpcaP3Tgy9bSLIwDS
8njOKdwa8TqkR5suWInVsew5CFGiXaNSsj6NYnVJREYfu9/Zk4YFMOItGgxBbKS57S
h18Yx53mo5A58FQgjQLKaUh5vct3lPt1ym2+SOOQ=
Received: from DFLE111.ent.ti.com (dfle111.ent.ti.com [10.64.6.32])
by lelv0266.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 054Citg0110800
(version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL);
Thu, 4 Jun 2020 07:44:55 -0500
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.1979.3; Thu, 4 Jun
2020 07:44:55 -0500
Received: from fllv0040.itg.ti.com (10.64.41.20) 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.1979.3 via
Frontend Transport; Thu, 4 Jun 2020 07:44:55 -0500
Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com
[10.172.224.153])
by fllv0040.itg.ti.com (8.15.2/8.15.2) with ESMTP id 054CicBU004409;
Thu, 4 Jun 2020 07:44:52 -0500
From: Pratyush Yadav
To: Chris Packham , Jagan Teki
, Vignesh R , Ryder Lee
, Weijie Gao ,
GSS_MTK_Uboot_upstream ,
CC: Pratyush Yadav , Sekhar Nori , "Tan, Ley
Foon"
Subject: [PATCH v5 04/21] spi: cadence-qspi: Add support for octal DTR flashes
Date: Thu, 4 Jun 2020 18:14:21 +0530
Message-ID: <20200604124438.16783-5-p.yadav@ti.com>
X-Mailer: git-send-email 2.25.0
In-Reply-To: <20200604124438.16783-1-p.yadav@ti.com>
References: <20200604124438.16783-1-p.yadav@ti.com>
MIME-Version: 1.0
X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180
X-BeenThere: u-boot@lists.denx.de
X-Mailman-Version: 2.1.30rc1
Precedence: list
List-Id: U-Boot discussion
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
Errors-To: u-boot-bounces@lists.denx.de
Sender: "U-Boot"
X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de
X-Virus-Status: Clean
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/cadence_qspi.c | 61 ++++++-
drivers/spi/cadence_qspi.h | 14 +-
drivers/spi/cadence_qspi_apb.c | 286 ++++++++++++++++++++++++++++++---
include/spi-mem.h | 3 +
4 files changed, 338 insertions(+), 26 deletions(-)
diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index 305f2ec0df..b0f9165bff 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -41,20 +41,22 @@ static int cadence_spi_write_speed(struct udevice *bus, uint hz)
return 0;
}
-static int cadence_spi_read_id(void *reg_base, u8 len, u8 *idcode)
+static int cadence_spi_read_id(struct cadence_spi_platdata *plat, u8 len,
+ u8 *idcode)
{
struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(0x9F, 1),
SPI_MEM_OP_NO_ADDR,
SPI_MEM_OP_NO_DUMMY,
SPI_MEM_OP_DATA_IN(len, idcode, 1));
- return cadence_qspi_apb_command_read(reg_base, &op);
+ return cadence_qspi_apb_command_read(plat, &op);
}
/* Calibration sequence to determine the read data capture delay register */
static int spi_calibration(struct udevice *bus, uint hz)
{
struct cadence_spi_priv *priv = dev_get_priv(bus);
+ struct cadence_spi_platdata *plat = bus->platdata;
void *base = priv->regbase;
unsigned int idcode = 0, temp = 0;
int err = 0, i, range_lo = -1, range_hi = -1;
@@ -69,7 +71,7 @@ static int spi_calibration(struct udevice *bus, uint hz)
cadence_qspi_apb_controller_enable(base);
/* read the ID which will be our golden value */
- err = cadence_spi_read_id(base, 3, (u8 *)&idcode);
+ err = cadence_spi_read_id(plat, 3, (u8 *)&idcode);
if (err) {
puts("SF: Calibration failed (read)\n");
return err;
@@ -88,7 +90,7 @@ static int spi_calibration(struct udevice *bus, uint hz)
cadence_qspi_apb_controller_enable(base);
/* issue a RDID to get the ID value */
- err = cadence_spi_read_id(base, 3, (u8 *)&temp);
+ err = cadence_spi_read_id(plat, 3, (u8 *)&temp);
if (err) {
puts("SF: Calibration failed (read)\n");
return err;
@@ -267,10 +269,14 @@ static int cadence_spi_mem_exec_op(struct spi_slave *spi,
switch (mode) {
case CQSPI_STIG_READ:
- err = cadence_qspi_apb_command_read(base, op);
+ err = cadence_qspi_apb_command_read_setup(plat, op);
+ if (!err)
+ err = cadence_qspi_apb_command_read(plat, op);
break;
case CQSPI_STIG_WRITE:
- err = cadence_qspi_apb_command_write(base, op);
+ err = cadence_qspi_apb_command_write_setup(plat, op);
+ if (!err)
+ err = cadence_qspi_apb_command_write(plat, op);
break;
case CQSPI_READ:
err = cadence_qspi_apb_read_setup(plat, op);
@@ -290,6 +296,48 @@ static int cadence_spi_mem_exec_op(struct spi_slave *spi,
return err;
}
+static bool cadence_spi_mem_supports_op(struct spi_slave *slave,
+ const struct spi_mem_op *op)
+{
+ bool all_true, all_false;
+ u8 buswidths[4];
+ int i;
+
+ all_true = op->cmd.dtr && op->addr.dtr && op->dummy.dtr &&
+ op->data.dtr;
+ all_false = !op->cmd.dtr && !op->addr.dtr && !op->dummy.dtr &&
+ !op->data.dtr;
+
+ /* Mixed DTR modes not supported. */
+ if (!(all_true || all_false))
+ return false;
+
+ /*
+ * Only buswidths of 1, 2, 4, and 8 are supported. 0 is allowed in case
+ * that phase does not exist.
+ */
+ buswidths[0] = op->cmd.buswidth;
+ buswidths[1] = op->addr.buswidth;
+ buswidths[2] = op->dummy.buswidth;
+ buswidths[3] = op->data.buswidth;
+ for (i = 0; i < ARRAY_SIZE(buswidths); i++) {
+ if (!(buswidths[i] == 0 || buswidths[i] == 1 ||
+ buswidths[i] == 2 || buswidths[i] == 4 ||
+ buswidths[i] == 8))
+ return false;
+ }
+
+ /*
+ * The exception to the above is the command phase. A non-existent
+ * command phase means that it is an XIP command, which we do not
+ * support.
+ */
+ if (op->cmd.buswidth == 0)
+ return false;
+
+ return true;
+}
+
static int cadence_spi_ofdata_to_platdata(struct udevice *bus)
{
struct cadence_spi_platdata *plat = bus->platdata;
@@ -346,6 +394,7 @@ static int cadence_spi_ofdata_to_platdata(struct udevice *bus)
static const struct spi_controller_mem_ops cadence_spi_mem_ops = {
.exec_op = cadence_spi_mem_exec_op,
+ .supports_op = cadence_spi_mem_supports_op,
};
static const struct dm_spi_ops cadence_spi_ops = {
diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h
index 9dff2fdced..2cf63193e9 100644
--- a/drivers/spi/cadence_qspi.h
+++ b/drivers/spi/cadence_qspi.h
@@ -35,6 +35,12 @@ struct cadence_spi_platdata {
u32 tsd2d_ns;
u32 tchsh_ns;
u32 tslch_ns;
+
+ /* Transaction protocol parameters. */
+ u8 inst_width;
+ u8 addr_width;
+ u8 data_width;
+ bool dtr;
};
struct cadence_spi_priv {
@@ -58,9 +64,13 @@ void cadence_qspi_apb_controller_enable(void *reg_base_addr);
void cadence_qspi_apb_controller_disable(void *reg_base_addr);
void cadence_qspi_apb_dac_mode_enable(void *reg_base);
-int cadence_qspi_apb_command_read(void *reg_base_addr,
+int cadence_qspi_apb_command_read_setup(struct cadence_spi_platdata *plat,
+ const struct spi_mem_op *op);
+int cadence_qspi_apb_command_read(struct cadence_spi_platdata *plat,
const struct spi_mem_op *op);
-int cadence_qspi_apb_command_write(void *reg_base_addr,
+int cadence_qspi_apb_command_write_setup(struct cadence_spi_platdata *plat,
+ const struct spi_mem_op *op);
+int cadence_qspi_apb_command_write(struct cadence_spi_platdata *plat,
const struct spi_mem_op *op);
int cadence_qspi_apb_read_setup(struct cadence_spi_platdata *plat,
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index f9675f75a4..eb4e1bc409 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -51,7 +51,7 @@
#define CQSPI_STIG_DATA_LEN_MAX 8
#define CQSPI_DUMMY_CLKS_PER_BYTE 8
-#define CQSPI_DUMMY_BYTES_MAX 4
+#define CQSPI_DUMMY_CLKS_MAX 31
/****************************************************************************
* Controller's configuration and status register (offset from QSPI_BASE)
@@ -65,6 +65,8 @@
#define CQSPI_REG_CONFIG_XIP_IMM BIT(18)
#define CQSPI_REG_CONFIG_CHIPSELECT_LSB 10
#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
@@ -83,6 +85,7 @@
#define CQSPI_REG_WR_INSTR 0x08
#define CQSPI_REG_WR_INSTR_OPCODE_LSB 0
+#define CQSPI_REG_WR_INSTR_TYPE_ADDR_LSB 12
#define CQSPI_REG_WR_INSTR_TYPE_DATA_LSB 16
#define CQSPI_REG_DELAY 0x0C
@@ -120,6 +123,9 @@
#define CQSPI_REG_SDRAMLEVEL_RD_MASK 0xFFFF
#define CQSPI_REG_SDRAMLEVEL_WR_MASK 0xFFFF
+#define CQSPI_REG_WR_COMPLETION_CTRL 0x38
+#define CQSPI_REG_WR_DISABLE_AUTO_POLL BIT(14)
+
#define CQSPI_REG_IRQSTATUS 0x40
#define CQSPI_REG_IRQMASK 0x44
@@ -166,6 +172,11 @@
#define CQSPI_REG_CMDWRITEDATALOWER 0xA8
#define CQSPI_REG_CMDWRITEDATAUPPER 0xAC
+#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
+
#define CQSPI_REG_IS_IDLE(base) \
((readl(base + CQSPI_REG_CONFIG) >> \
CQSPI_REG_CONFIG_IDLE_LSB) & 0x1)
@@ -203,6 +214,75 @@ void cadence_qspi_apb_dac_mode_enable(void *reg_base)
writel(reg, reg_base + CQSPI_REG_CONFIG);
}
+static unsigned int cadence_qspi_calc_dummy(const struct spi_mem_op *op,
+ bool dtr)
+{
+ unsigned int dummy_clk;
+
+ dummy_clk = op->dummy.nbytes * (8 / op->dummy.buswidth);
+ if (dtr)
+ dummy_clk /= 2;
+
+ return dummy_clk;
+}
+
+static u32 cadence_qspi_calc_rdreg(struct cadence_spi_platdata *plat)
+{
+ u32 rdreg = 0;
+
+ rdreg |= plat->inst_width << CQSPI_REG_RD_INSTR_TYPE_INSTR_LSB;
+ rdreg |= plat->addr_width << CQSPI_REG_RD_INSTR_TYPE_ADDR_LSB;
+ rdreg |= plat->data_width << CQSPI_REG_RD_INSTR_TYPE_DATA_LSB;
+
+ return rdreg;
+}
+
+static int cadence_qspi_buswidth_to_inst_type(u8 buswidth)
+{
+ switch (buswidth) {
+ case 0:
+ case 1:
+ return CQSPI_INST_TYPE_SINGLE;
+
+ case 2:
+ return CQSPI_INST_TYPE_DUAL;
+
+ case 4:
+ return CQSPI_INST_TYPE_QUAD;
+
+ case 8:
+ return CQSPI_INST_TYPE_OCTAL;
+
+ default:
+ return -ENOTSUPP;
+ }
+}
+
+static int cadence_qspi_set_protocol(struct cadence_spi_platdata *plat,
+ const struct spi_mem_op *op)
+{
+ int ret;
+
+ plat->dtr = op->data.dtr && op->cmd.dtr && op->addr.dtr;
+
+ ret = cadence_qspi_buswidth_to_inst_type(op->cmd.buswidth);
+ if (ret < 0)
+ return ret;
+ plat->inst_width = ret;
+
+ ret = cadence_qspi_buswidth_to_inst_type(op->addr.buswidth);
+ if (ret < 0)
+ return ret;
+ plat->addr_width = ret;
+
+ ret = cadence_qspi_buswidth_to_inst_type(op->data.buswidth);
+ if (ret < 0)
+ return ret;
+ plat->data_width = ret;
+
+ return 0;
+}
+
/* Return 1 if idle, otherwise return 0 (busy). */
static unsigned int cadence_qspi_wait_idle(void *reg_base)
{
@@ -434,21 +514,109 @@ static int cadence_qspi_apb_exec_flash_cmd(void *reg_base,
return 0;
}
+static int cadence_qspi_setup_opcode_ext(struct cadence_spi_platdata *plat,
+ const struct spi_mem_op *op,
+ unsigned int shift)
+{
+ unsigned int reg;
+ u8 ext;
+
+ if (op->cmd.nbytes != 2)
+ return -EINVAL;
+
+ /* Opcode extension is the LSB. */
+ ext = op->cmd.opcode & 0xff;
+
+ reg = readl(plat->regbase + CQSPI_REG_OP_EXT_LOWER);
+ reg &= ~(0xff << shift);
+ reg |= ext << shift;
+ writel(reg, plat->regbase + CQSPI_REG_OP_EXT_LOWER);
+
+ return 0;
+}
+
+static int cadence_qspi_enable_dtr(struct cadence_spi_platdata *plat,
+ const struct spi_mem_op *op,
+ unsigned int shift,
+ bool enable)
+{
+ unsigned int reg;
+ int ret;
+
+ reg = readl(plat->regbase + CQSPI_REG_CONFIG);
+
+ if (enable) {
+ reg |= CQSPI_REG_CONFIG_DTR_PROTO;
+ reg |= CQSPI_REG_CONFIG_DUAL_OPCODE;
+
+ /* Set up command opcode extension. */
+ ret = cadence_qspi_setup_opcode_ext(plat, op, shift);
+ if (ret)
+ return ret;
+ } else {
+ reg &= ~CQSPI_REG_CONFIG_DTR_PROTO;
+ reg &= ~CQSPI_REG_CONFIG_DUAL_OPCODE;
+ }
+
+ writel(reg, plat->regbase + CQSPI_REG_CONFIG);
+
+ return 0;
+}
+
+int cadence_qspi_apb_command_read_setup(struct cadence_spi_platdata *plat,
+ const struct spi_mem_op *op)
+{
+ int ret;
+ unsigned int reg;
+
+ ret = cadence_qspi_set_protocol(plat, op);
+ if (ret)
+ return ret;
+
+ ret = cadence_qspi_enable_dtr(plat, op, CQSPI_REG_OP_EXT_STIG_LSB,
+ plat->dtr);
+ if (ret)
+ return ret;
+
+ reg = cadence_qspi_calc_rdreg(plat);
+ writel(reg, plat->regbase + CQSPI_REG_RD_INSTR);
+
+ return 0;
+}
+
/* For command RDID, RDSR. */
-int cadence_qspi_apb_command_read(void *reg_base, const struct spi_mem_op *op)
+int cadence_qspi_apb_command_read(struct cadence_spi_platdata *plat,
+ const struct spi_mem_op *op)
{
+ void *reg_base = plat->regbase;
unsigned int reg;
unsigned int read_len;
int status;
unsigned int rxlen = op->data.nbytes;
void *rxbuf = op->data.buf.in;
+ unsigned int dummy_clk;
+ u8 opcode;
if (rxlen > CQSPI_STIG_DATA_LEN_MAX || !rxbuf) {
printf("QSPI: Invalid input arguments rxlen %u\n", rxlen);
return -EINVAL;
}
- reg = op->cmd.opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB;
+ if (plat->dtr)
+ opcode = op->cmd.opcode >> 8;
+ else
+ opcode = op->cmd.opcode;
+
+ reg = opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB;
+
+ /* Set up dummy cycles. */
+ dummy_clk = cadence_qspi_calc_dummy(op, plat->dtr);
+ if (dummy_clk > CQSPI_DUMMY_CLKS_MAX)
+ return -ENOTSUPP;
+
+ if (dummy_clk)
+ reg |= (dummy_clk & CQSPI_REG_CMDCTRL_DUMMY_MASK)
+ << CQSPI_REG_CMDCTRL_DUMMY_LSB;
reg |= (0x1 << CQSPI_REG_CMDCTRL_RD_EN_LSB);
@@ -475,15 +643,39 @@ int cadence_qspi_apb_command_read(void *reg_base, const struct spi_mem_op *op)
return 0;
}
+int cadence_qspi_apb_command_write_setup(struct cadence_spi_platdata *plat,
+ const struct spi_mem_op *op)
+{
+ int ret;
+ unsigned int reg;
+
+ ret = cadence_qspi_set_protocol(plat, op);
+ if (ret)
+ return ret;
+
+ ret = cadence_qspi_enable_dtr(plat, op, CQSPI_REG_OP_EXT_STIG_LSB,
+ plat->dtr);
+ if (ret)
+ return ret;
+
+ reg = cadence_qspi_calc_rdreg(plat);
+ writel(reg, plat->regbase + CQSPI_REG_RD_INSTR);
+
+ return 0;
+}
+
/* For commands: WRSR, WREN, WRDI, CHIP_ERASE, BE, etc. */
-int cadence_qspi_apb_command_write(void *reg_base, const struct spi_mem_op *op)
+int cadence_qspi_apb_command_write(struct cadence_spi_platdata *plat,
+ const struct spi_mem_op *op)
{
unsigned int reg = 0;
unsigned int wr_data;
unsigned int wr_len;
unsigned int txlen = op->data.nbytes;
const void *txbuf = op->data.buf.out;
+ void *reg_base = plat->regbase;
u32 addr;
+ u8 opcode;
/* Reorder address to SPI bus order if only transferring address */
if (!txlen) {
@@ -499,7 +691,12 @@ int cadence_qspi_apb_command_write(void *reg_base, const struct spi_mem_op *op)
return -EINVAL;
}
- reg |= op->cmd.opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB;
+ if (plat->dtr)
+ opcode = op->cmd.opcode >> 8;
+ else
+ opcode = op->cmd.opcode;
+
+ reg |= opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB;
if (txlen) {
/* writing data = yes */
@@ -533,29 +730,39 @@ int cadence_qspi_apb_read_setup(struct cadence_spi_platdata *plat,
unsigned int rd_reg;
unsigned int dummy_clk;
unsigned int dummy_bytes = op->dummy.nbytes;
+ int ret;
+ u8 opcode;
+
+ ret = cadence_qspi_set_protocol(plat, op);
+ if (ret)
+ return ret;
+
+ ret = cadence_qspi_enable_dtr(plat, op, CQSPI_REG_OP_EXT_READ_LSB,
+ plat->dtr);
+ if (ret)
+ return ret;
/* Setup the indirect trigger address */
writel(plat->trigger_address,
plat->regbase + CQSPI_REG_INDIRECTTRIGGER);
/* Configure the opcode */
- rd_reg = op->cmd.opcode << CQSPI_REG_RD_INSTR_OPCODE_LSB;
+ if (plat->dtr)
+ opcode = op->cmd.opcode >> 8;
+ else
+ opcode = op->cmd.opcode;
- if (op->data.buswidth == 8)
- /* Instruction and address at DQ0, data at DQ0-7. */
- rd_reg |= CQSPI_INST_TYPE_OCTAL << CQSPI_REG_RD_INSTR_TYPE_DATA_LSB;
- else if (op->data.buswidth == 4)
- /* Instruction and address at DQ0, data at DQ0-3. */
- rd_reg |= CQSPI_INST_TYPE_QUAD << CQSPI_REG_RD_INSTR_TYPE_DATA_LSB;
+ rd_reg = opcode << CQSPI_REG_RD_INSTR_OPCODE_LSB;
+ rd_reg |= cadence_qspi_calc_rdreg(plat);
writel(op->addr.val, plat->regbase + CQSPI_REG_INDIRECTRDSTARTADDR);
if (dummy_bytes) {
- if (dummy_bytes > CQSPI_DUMMY_BYTES_MAX)
- dummy_bytes = CQSPI_DUMMY_BYTES_MAX;
-
/* Convert to clock cycles. */
- dummy_clk = dummy_bytes * CQSPI_DUMMY_CLKS_PER_BYTE;
+ dummy_clk = cadence_qspi_calc_dummy(op, plat->dtr);
+
+ if (dummy_clk > CQSPI_DUMMY_CLKS_MAX)
+ return -ENOTSUPP;
if (dummy_clk)
rd_reg |= (dummy_clk & CQSPI_REG_RD_INSTR_DUMMY_MASK)
@@ -682,17 +889,52 @@ int cadence_qspi_apb_write_setup(struct cadence_spi_platdata *plat,
const struct spi_mem_op *op)
{
unsigned int reg;
+ int ret;
+ u8 opcode;
+
+ ret = cadence_qspi_set_protocol(plat, op);
+ if (ret)
+ return ret;
+
+ ret = cadence_qspi_enable_dtr(plat, op, CQSPI_REG_OP_EXT_WRITE_LSB,
+ plat->dtr);
+ if (ret)
+ return ret;
/* Setup the indirect trigger address */
writel(plat->trigger_address,
plat->regbase + CQSPI_REG_INDIRECTTRIGGER);
/* Configure the opcode */
- reg = op->cmd.opcode << CQSPI_REG_WR_INSTR_OPCODE_LSB;
+ if (plat->dtr)
+ opcode = op->cmd.opcode >> 8;
+ else
+ opcode = op->cmd.opcode;
+
+ reg = opcode << CQSPI_REG_WR_INSTR_OPCODE_LSB;
+ reg |= plat->data_width << CQSPI_REG_WR_INSTR_TYPE_DATA_LSB;
+ reg |= plat->addr_width << CQSPI_REG_WR_INSTR_TYPE_ADDR_LSB;
writel(reg, plat->regbase + CQSPI_REG_WR_INSTR);
+ reg = cadence_qspi_calc_rdreg(plat);
+ writel(reg, plat->regbase + CQSPI_REG_RD_INSTR);
+
writel(op->addr.val, plat->regbase + CQSPI_REG_INDIRECTWRSTARTADDR);
+ if (plat->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(plat->regbase + CQSPI_REG_WR_COMPLETION_CTRL);
+ reg |= CQSPI_REG_WR_DISABLE_AUTO_POLL;
+ writel(reg, plat->regbase + CQSPI_REG_WR_COMPLETION_CTRL);
+ }
+
reg = readl(plat->regbase + CQSPI_REG_SIZE);
reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK;
reg |= (op->addr.nbytes - 1);
@@ -781,7 +1023,15 @@ int cadence_qspi_apb_write_execute(struct cadence_spi_platdata *plat,
const void *buf = op->data.buf.out;
size_t len = op->data.nbytes;
- if (plat->use_dac_mode && (to + len < plat->ahbsize)) {
+ /*
+ * 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 (!plat->dtr && plat->use_dac_mode && (to + len < plat->ahbsize)) {
memcpy_toio(plat->ahbbase + to, buf, len);
if (!cadence_qspi_wait_idle(plat->regbase))
return -EIO;
diff --git a/include/spi-mem.h b/include/spi-mem.h
index 9167c435f6..67e4d85e9c 100644
--- a/include/spi-mem.h
+++ b/include/spi-mem.h
@@ -253,6 +253,9 @@ int spi_mem_adjust_op_size(struct spi_slave *slave, struct spi_mem_op *op);
bool spi_mem_supports_op(struct spi_slave *slave, const struct spi_mem_op *op);
+bool spi_mem_default_supports_op(struct spi_slave *slave,
+ const struct spi_mem_op *op);
+
int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op);
#ifndef __UBOOT__
From patchwork Thu Jun 4 12:44:22 2020
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Pratyush Yadav
X-Patchwork-Id: 1303502
X-Patchwork-Delegate: jagannadh.teki@gmail.com
Return-Path:
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@bilbo.ozlabs.org
Authentication-Results: ozlabs.org;
spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de
(client-ip=85.214.62.61; helo=phobos.denx.de;
envelope-from=u-boot-bounces@lists.denx.de; receiver=)
Authentication-Results: ozlabs.org;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: ozlabs.org;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.a=rsa-sha256
header.s=ti-com-17Q1 header.b=hn2jVVH1;
dkim-atps=neutral
Received: from phobos.denx.de (phobos.denx.de [85.214.62.61])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (4096 bits))
(No client certificate requested)
by ozlabs.org (Postfix) with ESMTPS id 49d59r5PMRz9sSc
for ; Thu, 4 Jun 2020 22:46:08 +1000 (AEST)
Received: from h2850616.stratoserver.net (localhost [IPv6:::1])
by phobos.denx.de (Postfix) with ESMTP id 1592D813A9;
Thu, 4 Jun 2020 14:45:23 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de;
spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de
Authentication-Results: phobos.denx.de;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.b="hn2jVVH1";
dkim-atps=neutral
Received: by phobos.denx.de (Postfix, from userid 109)
id A73DE8168D; Thu, 4 Jun 2020 14:45:14 +0200 (CEST)
X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de
X-Spam-Level:
X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED
autolearn=ham autolearn_force=no version=3.4.2
Received: from fllv0016.ext.ti.com (fllv0016.ext.ti.com [198.47.19.142])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by phobos.denx.de (Postfix) with ESMTPS id 2BB48813A9
for ; Thu, 4 Jun 2020 14:45:08 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=p.yadav@ti.com
Received: from lelv0266.itg.ti.com ([10.180.67.225])
by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id 054Cixpg010067;
Thu, 4 Jun 2020 07:44:59 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com;
s=ti-com-17Q1; t=1591274699;
bh=MotLbf8ksEaUfoVpsYDLObGua5ApONbzcRUd0lMJLIs=;
h=From:To:CC:Subject:Date:In-Reply-To:References;
b=hn2jVVH1bOcJZwH0Nviooj6UNAXNVHdlxFknG4O6/LC1+1bE3nsyamKyE+jfemPGu
XLnYYVGIqaGFz+nSmGKml33ys1olbY8paqQCM2ZR0kgWzbw9ZSFtr+YYvcUgcO1SdU
B/vU8wVlonFINHKvNV/ZqQeOhChuNdEchFj2iiqM=
Received: from DLEE108.ent.ti.com (dlee108.ent.ti.com [157.170.170.38])
by lelv0266.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 054Cixgf110830
(version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL);
Thu, 4 Jun 2020 07:44:59 -0500
Received: from DLEE105.ent.ti.com (157.170.170.35) 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.1979.3; Thu, 4 Jun
2020 07:44:58 -0500
Received: from fllv0040.itg.ti.com (10.64.41.20) by DLEE105.ent.ti.com
(157.170.170.35) with Microsoft SMTP Server (version=TLS1_2,
cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1979.3 via
Frontend Transport; Thu, 4 Jun 2020 07:44:58 -0500
Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com
[10.172.224.153])
by fllv0040.itg.ti.com (8.15.2/8.15.2) with ESMTP id 054CicBV004409;
Thu, 4 Jun 2020 07:44:55 -0500
From: Pratyush Yadav
To: Chris Packham , Jagan Teki
, Vignesh R , Ryder Lee
, Weijie Gao ,
GSS_MTK_Uboot_upstream ,
CC: Pratyush Yadav , Sekhar Nori , "Tan, Ley
Foon"
Subject: [PATCH v5 05/21] arm: mvebu: x530: Disable smart hwcaps selection
Date: Thu, 4 Jun 2020 18:14:22 +0530
Message-ID: <20200604124438.16783-6-p.yadav@ti.com>
X-Mailer: git-send-email 2.25.0
In-Reply-To: <20200604124438.16783-1-p.yadav@ti.com>
References: <20200604124438.16783-1-p.yadav@ti.com>
MIME-Version: 1.0
X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180
X-BeenThere: u-boot@lists.denx.de
X-Mailman-Version: 2.1.30rc1
Precedence: list
List-Id: U-Boot discussion
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
Errors-To: u-boot-bounces@lists.denx.de
Sender: "U-Boot"
X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de
X-Virus-Status: Clean
The option SPI_FLASH_SMART_HWCAPS will be introduced in a future commit.
It is enabled by default. It updates the hwcaps selection of SPI NOR to
use the SPI MEM's supports_op() hook. But this leads to a code size
increase and so the SPL binary exceeds the size limit.
So, use the old hwcaps selection logic here to make sure the SPL size
does not exceed the limit.
Signed-off-by: Pratyush Yadav
---
configs/x530_defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/configs/x530_defconfig b/configs/x530_defconfig
index 67c8fbf663..35e2d53285 100644
--- a/configs/x530_defconfig
+++ b/configs/x530_defconfig
@@ -58,6 +58,7 @@ CONFIG_SYS_NAND_USE_FLASH_BBT=y
CONFIG_NAND_PXA3XX=y
CONFIG_SF_DEFAULT_BUS=1
CONFIG_SF_DEFAULT_SPEED=50000000
+CONFIG_SPI_FLASH_SMART_HWCAPS=n
CONFIG_SPI_FLASH_BAR=y
CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SPI_FLASH_STMICRO=y
From patchwork Thu Jun 4 12:44:23 2020
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Pratyush Yadav
X-Patchwork-Id: 1303504
X-Patchwork-Delegate: jagannadh.teki@gmail.com
Return-Path:
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@bilbo.ozlabs.org
Authentication-Results: ozlabs.org;
spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de
(client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;
envelope-from=u-boot-bounces@lists.denx.de; receiver=)
Authentication-Results: ozlabs.org;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: ozlabs.org;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.a=rsa-sha256
header.s=ti-com-17Q1 header.b=Is3OIFrK;
dkim-atps=neutral
Received: from phobos.denx.de (phobos.denx.de
[IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (4096 bits))
(No client certificate requested)
by ozlabs.org (Postfix) with ESMTPS id 49d5BT1DjVz9sSc
for ; Thu, 4 Jun 2020 22:46:41 +1000 (AEST)
Received: from h2850616.stratoserver.net (localhost [IPv6:::1])
by phobos.denx.de (Postfix) with ESMTP id C5485819B8;
Thu, 4 Jun 2020 14:45:28 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de;
spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de
Authentication-Results: phobos.denx.de;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.b="Is3OIFrK";
dkim-atps=neutral
Received: by phobos.denx.de (Postfix, from userid 109)
id 72A898179A; Thu, 4 Jun 2020 14:45:19 +0200 (CEST)
X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de
X-Spam-Level:
X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED
autolearn=ham autolearn_force=no version=3.4.2
Received: from fllv0015.ext.ti.com (fllv0015.ext.ti.com [198.47.19.141])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by phobos.denx.de (Postfix) with ESMTPS id 064BF8066F
for ; Thu, 4 Jun 2020 14:45:10 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=p.yadav@ti.com
Received: from fllv0035.itg.ti.com ([10.64.41.0])
by fllv0015.ext.ti.com (8.15.2/8.15.2) with ESMTP id 054Cj2a1062866;
Thu, 4 Jun 2020 07:45:02 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com;
s=ti-com-17Q1; t=1591274702;
bh=JNO7CUE8hvIXdac+5QRFehoHzb2EI6MVuci8TTAqU68=;
h=From:To:CC:Subject:Date:In-Reply-To:References;
b=Is3OIFrKf2HhyiGsjF34VInJlXfwItkObOMid1nCvF2wqX6E0IunczGtx7tjdxw4Q
iMytq9vlpcZvP0rN2FRmXtQiOTc5QPBtmVKhS36xnqawzimqpMbW4zCVnFYT3A655c
9J70B+vJf38YwS044dpbvYGzhhjaCW3DQMZmNBbo=
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 054Cj26n112437;
Thu, 4 Jun 2020 07:45:02 -0500
Received: from DFLE111.ent.ti.com (10.64.6.32) 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.1979.3; Thu, 4 Jun
2020 07:45:01 -0500
Received: from fllv0040.itg.ti.com (10.64.41.20) 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.1979.3 via
Frontend Transport; Thu, 4 Jun 2020 07:45:01 -0500
Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com
[10.172.224.153])
by fllv0040.itg.ti.com (8.15.2/8.15.2) with ESMTP id 054CicBW004409;
Thu, 4 Jun 2020 07:44:59 -0500
From: Pratyush Yadav
To: Chris Packham , Jagan Teki
, Vignesh R , Ryder Lee
, Weijie Gao ,
GSS_MTK_Uboot_upstream ,
CC: Pratyush Yadav , Sekhar Nori , "Tan, Ley
Foon"
Subject: [PATCH v5 06/21] mtd: spi-nor-core: Add a ->setup() hook
Date: Thu, 4 Jun 2020 18:14:23 +0530
Message-ID: <20200604124438.16783-7-p.yadav@ti.com>
X-Mailer: git-send-email 2.25.0
In-Reply-To: <20200604124438.16783-1-p.yadav@ti.com>
References: <20200604124438.16783-1-p.yadav@ti.com>
MIME-Version: 1.0
X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180
X-BeenThere: u-boot@lists.denx.de
X-Mailman-Version: 2.1.30rc1
Precedence: list
List-Id: U-Boot discussion
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
Errors-To: u-boot-bounces@lists.denx.de
Sender: "U-Boot"
X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de
X-Virus-Status: Clean
nor->setup() can be used by flashes to configure settings in case they
have any peculiarities that can't be easily expressed by the generic
spi-nor framework. This includes things like different opcodes, dummy
cycles, page size, uniform/non-uniform sector sizes, etc.
Move related declarations to avoid forward declarations.
Inspired by the Linux kernel's setup() hook.
Signed-off-by: Pratyush Yadav
---
drivers/mtd/spi/spi-nor-core.c | 84 +++------------
drivers/mtd/spi/spi-nor-tiny.c | 22 ----
include/linux/mtd/spi-nor.h | 192 ++++++++++++++++++++++-----------
3 files changed, 147 insertions(+), 151 deletions(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 1e3f51d2ac..084d593ed5 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -1447,71 +1447,6 @@ static int spansion_no_read_cr_quad_enable(struct spi_nor *nor)
#endif /* CONFIG_SPI_FLASH_SFDP_SUPPORT */
#endif /* CONFIG_SPI_FLASH_SPANSION */
-struct spi_nor_read_command {
- u8 num_mode_clocks;
- u8 num_wait_states;
- u8 opcode;
- enum spi_nor_protocol proto;
-};
-
-struct spi_nor_pp_command {
- u8 opcode;
- enum spi_nor_protocol proto;
-};
-
-enum spi_nor_read_command_index {
- SNOR_CMD_READ,
- SNOR_CMD_READ_FAST,
- SNOR_CMD_READ_1_1_1_DTR,
-
- /* Dual SPI */
- SNOR_CMD_READ_1_1_2,
- SNOR_CMD_READ_1_2_2,
- SNOR_CMD_READ_2_2_2,
- SNOR_CMD_READ_1_2_2_DTR,
-
- /* Quad SPI */
- SNOR_CMD_READ_1_1_4,
- SNOR_CMD_READ_1_4_4,
- SNOR_CMD_READ_4_4_4,
- SNOR_CMD_READ_1_4_4_DTR,
-
- /* Octo SPI */
- SNOR_CMD_READ_1_1_8,
- SNOR_CMD_READ_1_8_8,
- SNOR_CMD_READ_8_8_8,
- SNOR_CMD_READ_1_8_8_DTR,
-
- SNOR_CMD_READ_MAX
-};
-
-enum spi_nor_pp_command_index {
- SNOR_CMD_PP,
-
- /* Quad SPI */
- SNOR_CMD_PP_1_1_4,
- SNOR_CMD_PP_1_4_4,
- SNOR_CMD_PP_4_4_4,
-
- /* Octo SPI */
- SNOR_CMD_PP_1_1_8,
- SNOR_CMD_PP_1_8_8,
- SNOR_CMD_PP_8_8_8,
-
- SNOR_CMD_PP_MAX
-};
-
-struct spi_nor_flash_parameter {
- u64 size;
- u32 page_size;
-
- struct spi_nor_hwcaps hwcaps;
- struct spi_nor_read_command reads[SNOR_CMD_READ_MAX];
- struct spi_nor_pp_command page_programs[SNOR_CMD_PP_MAX];
-
- int (*quad_enable)(struct spi_nor *nor);
-};
-
static void
spi_nor_set_read_settings(struct spi_nor_read_command *read,
u8 num_mode_clocks,
@@ -2372,9 +2307,10 @@ static int spi_nor_select_erase(struct spi_nor *nor,
return 0;
}
-static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info,
- const struct spi_nor_flash_parameter *params,
- const struct spi_nor_hwcaps *hwcaps)
+static int spi_nor_default_setup(struct spi_nor *nor,
+ const struct flash_info *info,
+ const struct spi_nor_flash_parameter *params,
+ const struct spi_nor_hwcaps *hwcaps)
{
u32 ignored_mask, shared_mask;
bool enable_quad_io;
@@ -2433,6 +2369,16 @@ static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info,
return 0;
}
+static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info,
+ const struct spi_nor_flash_parameter *params,
+ const struct spi_nor_hwcaps *hwcaps)
+{
+ if (!nor->setup)
+ return 0;
+
+ return nor->setup(nor, info, params, hwcaps);
+}
+
static int spi_nor_init(struct spi_nor *nor)
{
int err;
@@ -2498,6 +2444,8 @@ int spi_nor_scan(struct spi_nor *nor)
nor->read_reg = spi_nor_read_reg;
nor->write_reg = spi_nor_write_reg;
+ nor->setup = spi_nor_default_setup;
+
if (spi->mode & SPI_RX_OCTAL) {
hwcaps.mask |= SNOR_HWCAPS_READ_1_1_8;
diff --git a/drivers/mtd/spi/spi-nor-tiny.c b/drivers/mtd/spi/spi-nor-tiny.c
index 9f676c649d..825700b0cf 100644
--- a/drivers/mtd/spi/spi-nor-tiny.c
+++ b/drivers/mtd/spi/spi-nor-tiny.c
@@ -544,28 +544,6 @@ static int spansion_read_cr_quad_enable(struct spi_nor *nor)
}
#endif /* CONFIG_SPI_FLASH_SPANSION */
-struct spi_nor_read_command {
- u8 num_mode_clocks;
- u8 num_wait_states;
- u8 opcode;
- enum spi_nor_protocol proto;
-};
-
-enum spi_nor_read_command_index {
- SNOR_CMD_READ,
- SNOR_CMD_READ_FAST,
-
- /* Quad SPI */
- SNOR_CMD_READ_1_1_4,
-
- SNOR_CMD_READ_MAX
-};
-
-struct spi_nor_flash_parameter {
- struct spi_nor_hwcaps hwcaps;
- struct spi_nor_read_command reads[SNOR_CMD_READ_MAX];
-};
-
static void
spi_nor_set_read_settings(struct spi_nor_read_command *read,
u8 num_mode_clocks,
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 233fdc341a..922e795ea6 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -249,6 +249,134 @@ enum spi_nor_option_flags {
SNOR_F_BROKEN_RESET = BIT(6),
};
+struct spi_nor;
+
+/**
+ * struct spi_nor_hwcaps - Structure for describing the hardware capabilies
+ * supported by the SPI controller (bus master).
+ * @mask: the bitmask listing all the supported hw capabilies
+ */
+struct spi_nor_hwcaps {
+ u32 mask;
+};
+
+/*
+ *(Fast) Read capabilities.
+ * MUST be ordered by priority: the higher bit position, the higher priority.
+ * As a matter of performances, it is relevant to use Octo SPI protocols first,
+ * 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 BIT(0)
+#define SNOR_HWCAPS_READ_FAST BIT(1)
+#define SNOR_HWCAPS_READ_1_1_1_DTR BIT(2)
+
+#define SNOR_HWCAPS_READ_DUAL GENMASK(6, 3)
+#define SNOR_HWCAPS_READ_1_1_2 BIT(3)
+#define SNOR_HWCAPS_READ_1_2_2 BIT(4)
+#define SNOR_HWCAPS_READ_2_2_2 BIT(5)
+#define SNOR_HWCAPS_READ_1_2_2_DTR BIT(6)
+
+#define SNOR_HWCAPS_READ_QUAD GENMASK(10, 7)
+#define SNOR_HWCAPS_READ_1_1_4 BIT(7)
+#define SNOR_HWCAPS_READ_1_4_4 BIT(8)
+#define SNOR_HWCAPS_READ_4_4_4 BIT(9)
+#define SNOR_HWCAPS_READ_1_4_4_DTR BIT(10)
+
+#define SNOR_HWCPAS_READ_OCTO GENMASK(14, 11)
+#define SNOR_HWCAPS_READ_1_1_8 BIT(11)
+#define SNOR_HWCAPS_READ_1_8_8 BIT(12)
+#define SNOR_HWCAPS_READ_8_8_8 BIT(13)
+#define SNOR_HWCAPS_READ_1_8_8_DTR BIT(14)
+
+/*
+ * Page Program capabilities.
+ * MUST be ordered by priority: the higher bit position, the higher priority.
+ * Like (Fast) Read capabilities, Octo/Quad SPI protocols are preferred to the
+ * legacy SPI 1-1-1 protocol.
+ * Note that Dual Page Programs are not supported because there is no existing
+ * 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_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_OCTO GENMASK(22, 20)
+#define SNOR_HWCAPS_PP_1_1_8 BIT(20)
+#define SNOR_HWCAPS_PP_1_8_8 BIT(21)
+#define SNOR_HWCAPS_PP_8_8_8 BIT(22)
+
+struct spi_nor_read_command {
+ u8 num_mode_clocks;
+ u8 num_wait_states;
+ u8 opcode;
+ enum spi_nor_protocol proto;
+};
+
+struct spi_nor_pp_command {
+ u8 opcode;
+ enum spi_nor_protocol proto;
+};
+
+enum spi_nor_read_command_index {
+ SNOR_CMD_READ,
+ SNOR_CMD_READ_FAST,
+ SNOR_CMD_READ_1_1_1_DTR,
+
+ /* Dual SPI */
+ SNOR_CMD_READ_1_1_2,
+ SNOR_CMD_READ_1_2_2,
+ SNOR_CMD_READ_2_2_2,
+ SNOR_CMD_READ_1_2_2_DTR,
+
+ /* Quad SPI */
+ SNOR_CMD_READ_1_1_4,
+ SNOR_CMD_READ_1_4_4,
+ SNOR_CMD_READ_4_4_4,
+ SNOR_CMD_READ_1_4_4_DTR,
+
+ /* Octo SPI */
+ SNOR_CMD_READ_1_1_8,
+ SNOR_CMD_READ_1_8_8,
+ SNOR_CMD_READ_8_8_8,
+ SNOR_CMD_READ_1_8_8_DTR,
+
+ SNOR_CMD_READ_MAX
+};
+
+enum spi_nor_pp_command_index {
+ SNOR_CMD_PP,
+
+ /* Quad SPI */
+ SNOR_CMD_PP_1_1_4,
+ SNOR_CMD_PP_1_4_4,
+ SNOR_CMD_PP_4_4_4,
+
+ /* Octo SPI */
+ SNOR_CMD_PP_1_1_8,
+ SNOR_CMD_PP_1_8_8,
+ SNOR_CMD_PP_8_8_8,
+
+ SNOR_CMD_PP_MAX
+};
+
+struct spi_nor_flash_parameter {
+ u64 size;
+ u32 page_size;
+
+ struct spi_nor_hwcaps hwcaps;
+ struct spi_nor_read_command reads[SNOR_CMD_READ_MAX];
+ struct spi_nor_pp_command page_programs[SNOR_CMD_PP_MAX];
+
+ int (*quad_enable)(struct spi_nor *nor);
+};
+
/**
* struct flash_info - Forward declaration of a structure used internally by
* spi_nor_scan()
@@ -328,6 +456,9 @@ struct spi_nor {
u32 flags;
u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE];
+ int (*setup)(struct spi_nor *nor, const struct flash_info *info,
+ const struct spi_nor_flash_parameter *params,
+ const struct spi_nor_hwcaps *hwcaps);
int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);
void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);
int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
@@ -364,67 +495,6 @@ device_node *spi_nor_get_flash_node(struct spi_nor *nor)
return mtd_get_of_node(&nor->mtd);
}
-/**
- * struct spi_nor_hwcaps - Structure for describing the hardware capabilies
- * supported by the SPI controller (bus master).
- * @mask: the bitmask listing all the supported hw capabilies
- */
-struct spi_nor_hwcaps {
- u32 mask;
-};
-
-/*
- *(Fast) Read capabilities.
- * MUST be ordered by priority: the higher bit position, the higher priority.
- * As a matter of performances, it is relevant to use Octo SPI protocols first,
- * 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 BIT(0)
-#define SNOR_HWCAPS_READ_FAST BIT(1)
-#define SNOR_HWCAPS_READ_1_1_1_DTR BIT(2)
-
-#define SNOR_HWCAPS_READ_DUAL GENMASK(6, 3)
-#define SNOR_HWCAPS_READ_1_1_2 BIT(3)
-#define SNOR_HWCAPS_READ_1_2_2 BIT(4)
-#define SNOR_HWCAPS_READ_2_2_2 BIT(5)
-#define SNOR_HWCAPS_READ_1_2_2_DTR BIT(6)
-
-#define SNOR_HWCAPS_READ_QUAD GENMASK(10, 7)
-#define SNOR_HWCAPS_READ_1_1_4 BIT(7)
-#define SNOR_HWCAPS_READ_1_4_4 BIT(8)
-#define SNOR_HWCAPS_READ_4_4_4 BIT(9)
-#define SNOR_HWCAPS_READ_1_4_4_DTR BIT(10)
-
-#define SNOR_HWCPAS_READ_OCTO GENMASK(14, 11)
-#define SNOR_HWCAPS_READ_1_1_8 BIT(11)
-#define SNOR_HWCAPS_READ_1_8_8 BIT(12)
-#define SNOR_HWCAPS_READ_8_8_8 BIT(13)
-#define SNOR_HWCAPS_READ_1_8_8_DTR BIT(14)
-
-/*
- * Page Program capabilities.
- * MUST be ordered by priority: the higher bit position, the higher priority.
- * Like (Fast) Read capabilities, Octo/Quad SPI protocols are preferred to the
- * legacy SPI 1-1-1 protocol.
- * Note that Dual Page Programs are not supported because there is no existing
- * 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_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_OCTO GENMASK(22, 20)
-#define SNOR_HWCAPS_PP_1_1_8 BIT(20)
-#define SNOR_HWCAPS_PP_1_8_8 BIT(21)
-#define SNOR_HWCAPS_PP_8_8_8 BIT(22)
-
/**
* spi_nor_scan() - scan the SPI NOR
* @nor: the spi_nor structure
From patchwork Thu Jun 4 12:44:24 2020
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Pratyush Yadav
X-Patchwork-Id: 1303505
X-Patchwork-Delegate: jagannadh.teki@gmail.com
Return-Path:
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@bilbo.ozlabs.org
Authentication-Results: ozlabs.org;
spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de
(client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;
envelope-from=u-boot-bounces@lists.denx.de; receiver=)
Authentication-Results: ozlabs.org;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: ozlabs.org;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.a=rsa-sha256
header.s=ti-com-17Q1 header.b=GGTU8AsK;
dkim-atps=neutral
Received: from phobos.denx.de (phobos.denx.de
[IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (4096 bits))
(No client certificate requested)
by ozlabs.org (Postfix) with ESMTPS id 49d5Bk4Pnwz9sSc
for ; Thu, 4 Jun 2020 22:46:54 +1000 (AEST)
Received: from h2850616.stratoserver.net (localhost [IPv6:::1])
by phobos.denx.de (Postfix) with ESMTP id C870B819F4;
Thu, 4 Jun 2020 14:45:31 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de;
spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de
Authentication-Results: phobos.denx.de;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.b="GGTU8AsK";
dkim-atps=neutral
Received: by phobos.denx.de (Postfix, from userid 109)
id 0186E81688; Thu, 4 Jun 2020 14:45:22 +0200 (CEST)
X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de
X-Spam-Level:
X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED
autolearn=ham autolearn_force=no version=3.4.2
Received: from fllv0016.ext.ti.com (fllv0016.ext.ti.com [198.47.19.142])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by phobos.denx.de (Postfix) with ESMTPS id 2149F81777
for ; Thu, 4 Jun 2020 14:45:13 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=p.yadav@ti.com
Received: from lelv0265.itg.ti.com ([10.180.67.224])
by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id 054Cj5Ai010119;
Thu, 4 Jun 2020 07:45:05 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com;
s=ti-com-17Q1; t=1591274705;
bh=s8Atx1x501feMOqKqU8/5ivPVIE/6RtVXmF2j9ZNUfg=;
h=From:To:CC:Subject:Date:In-Reply-To:References;
b=GGTU8AsKoZYoeW346NWMUpPAAagqTN3jLN87ZoWA5bjBuoS/2169pd2qibSqU40mU
vY/yoQh0EBJLr5f74or5JenA4P3ITkemg3b0nPCzyfyKyj/MJZ9Q2WBWqqBF5fQpyA
J+C+9BBBvgDYtwXXCxyK2Peie/Ygs9CwGa7QmLBE=
Received: from DLEE113.ent.ti.com (dlee113.ent.ti.com [157.170.170.24])
by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 054Cj3Uk094490
(version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL);
Thu, 4 Jun 2020 07:45:05 -0500
Received: from DLEE115.ent.ti.com (157.170.170.26) by DLEE113.ent.ti.com
(157.170.170.24) with Microsoft SMTP Server (version=TLS1_2,
cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1979.3; Thu, 4 Jun
2020 07:45:05 -0500
Received: from fllv0040.itg.ti.com (10.64.41.20) 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.1979.3 via
Frontend Transport; Thu, 4 Jun 2020 07:45:05 -0500
Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com
[10.172.224.153])
by fllv0040.itg.ti.com (8.15.2/8.15.2) with ESMTP id 054CicBX004409;
Thu, 4 Jun 2020 07:45:02 -0500
From: Pratyush Yadav
To: Chris Packham , Jagan Teki
, Vignesh R , Ryder Lee
, Weijie Gao ,
GSS_MTK_Uboot_upstream ,
CC: Pratyush Yadav , Sekhar Nori , "Tan, Ley
Foon"
Subject: [PATCH v5 07/21] mtd: spi-nor-core: Move SFDP related declarations to
top
Date: Thu, 4 Jun 2020 18:14:24 +0530
Message-ID: <20200604124438.16783-8-p.yadav@ti.com>
X-Mailer: git-send-email 2.25.0
In-Reply-To: <20200604124438.16783-1-p.yadav@ti.com>
References: <20200604124438.16783-1-p.yadav@ti.com>
MIME-Version: 1.0
X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180
X-BeenThere: u-boot@lists.denx.de
X-Mailman-Version: 2.1.30rc1
Precedence: list
List-Id: U-Boot discussion
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
Errors-To: u-boot-bounces@lists.denx.de
Sender: "U-Boot"
X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de
X-Virus-Status: Clean
These structures will be used in a later commit inside another structure
definition. Also take the declarations out of the ifdef since they won't
affect the final binary anyway and will be used in a later commit.
Signed-off-by: Pratyush Yadav
---
drivers/mtd/spi/spi-nor-core.c | 224 ++++++++++++++++-----------------
1 file changed, 112 insertions(+), 112 deletions(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 084d593ed5..28f5f877b4 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -38,6 +38,118 @@
#define DEFAULT_READY_WAIT_JIFFIES (40UL * HZ)
+struct sfdp_parameter_header {
+ u8 id_lsb;
+ u8 minor;
+ u8 major;
+ u8 length; /* in double words */
+ u8 parameter_table_pointer[3]; /* byte address */
+ u8 id_msb;
+};
+
+#define SFDP_PARAM_HEADER_ID(p) (((p)->id_msb << 8) | (p)->id_lsb)
+#define SFDP_PARAM_HEADER_PTP(p) \
+ (((p)->parameter_table_pointer[2] << 16) | \
+ ((p)->parameter_table_pointer[1] << 8) | \
+ ((p)->parameter_table_pointer[0] << 0))
+
+#define SFDP_BFPT_ID 0xff00 /* Basic Flash Parameter Table */
+#define SFDP_SECTOR_MAP_ID 0xff81 /* Sector Map Table */
+#define SFDP_SST_ID 0x01bf /* Manufacturer specific 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
+
+struct sfdp_header {
+ u32 signature; /* Ox50444653U <=> "SFDP" */
+ u8 minor;
+ u8 major;
+ u8 nph; /* 0-base number of parameter headers */
+ u8 unused;
+
+ /* Basic Flash Parameter Table. */
+ struct sfdp_parameter_header bfpt_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.
+ */
+#define BFPT_DWORD(i) ((i) - 1)
+#define BFPT_DWORD_MAX 16
+
+/* The first version of JESB216 defined only 9 DWORDs. */
+#define BFPT_DWORD_MAX_JESD216 9
+
+/* 1st DWORD. */
+#define BFPT_DWORD1_FAST_READ_1_1_2 BIT(16)
+#define BFPT_DWORD1_ADDRESS_BYTES_MASK GENMASK(18, 17)
+#define BFPT_DWORD1_ADDRESS_BYTES_3_ONLY (0x0UL << 17)
+#define BFPT_DWORD1_ADDRESS_BYTES_3_OR_4 (0x1UL << 17)
+#define BFPT_DWORD1_ADDRESS_BYTES_4_ONLY (0x2UL << 17)
+#define BFPT_DWORD1_DTR BIT(19)
+#define BFPT_DWORD1_FAST_READ_1_2_2 BIT(20)
+#define BFPT_DWORD1_FAST_READ_1_4_4 BIT(21)
+#define BFPT_DWORD1_FAST_READ_1_1_4 BIT(22)
+
+/* 5th DWORD. */
+#define BFPT_DWORD5_FAST_READ_2_2_2 BIT(0)
+#define BFPT_DWORD5_FAST_READ_4_4_4 BIT(4)
+
+/* 11th DWORD. */
+#define BFPT_DWORD11_PAGE_SIZE_SHIFT 4
+#define BFPT_DWORD11_PAGE_SIZE_MASK GENMASK(7, 4)
+
+/* 15th DWORD. */
+
+/*
+ * (from JESD216 rev B)
+ * Quad Enable Requirements (QER):
+ * - 000b: Device does not have a QE bit. Device detects 1-1-4 and 1-4-4
+ * reads based on instruction. DQ3/HOLD# functions are hold during
+ * instruction phase.
+ * - 001b: QE is bit 1 of status register 2. It is set via Write Status with
+ * two data bytes where bit 1 of the second byte is one.
+ * [...]
+ * Writing only one byte to the status register has the side-effect of
+ * clearing status register 2, including the QE bit. The 100b code is
+ * used if writing one byte to the status register does not modify
+ * status register 2.
+ * - 010b: QE is bit 6 of status register 1. It is set via Write Status with
+ * one data byte where bit 6 is one.
+ * [...]
+ * - 011b: QE is bit 7 of status register 2. It is set via Write status
+ * register 2 instruction 3Eh with one data byte where bit 7 is one.
+ * [...]
+ * The status register 2 is read using instruction 3Fh.
+ * - 100b: QE is bit 1 of status register 2. It is set via Write Status with
+ * two data bytes where bit 1 of the second byte is one.
+ * [...]
+ * In contrast to the 001b code, writing one byte to the status
+ * register does not modify status register 2.
+ * - 101b: QE is bit 1 of status register 2. Status register 1 is read using
+ * Read Status instruction 05h. Status register2 is read using
+ * instruction 35h. QE is set via Writ Status instruction 01h with
+ * two data bytes where bit 1 of the second byte is one.
+ * [...]
+ */
+#define BFPT_DWORD15_QER_MASK GENMASK(22, 20)
+#define BFPT_DWORD15_QER_NONE (0x0UL << 20) /* Micron */
+#define BFPT_DWORD15_QER_SR2_BIT1_BUGGY (0x1UL << 20)
+#define BFPT_DWORD15_QER_SR1_BIT6 (0x2UL << 20) /* Macronix */
+#define BFPT_DWORD15_QER_SR2_BIT7 (0x3UL << 20)
+#define BFPT_DWORD15_QER_SR2_BIT1_NO_RD (0x4UL << 20)
+#define BFPT_DWORD15_QER_SR2_BIT1 (0x5UL << 20) /* Spansion */
+
+struct sfdp_bfpt {
+ u32 dwords[BFPT_DWORD_MAX];
+};
+
static int spi_nor_read_write_reg(struct spi_nor *nor, struct spi_mem_op
*op, void *buf)
{
@@ -1524,118 +1636,6 @@ read_err:
return ret;
}
-struct sfdp_parameter_header {
- u8 id_lsb;
- u8 minor;
- u8 major;
- u8 length; /* in double words */
- u8 parameter_table_pointer[3]; /* byte address */
- u8 id_msb;
-};
-
-#define SFDP_PARAM_HEADER_ID(p) (((p)->id_msb << 8) | (p)->id_lsb)
-#define SFDP_PARAM_HEADER_PTP(p) \
- (((p)->parameter_table_pointer[2] << 16) | \
- ((p)->parameter_table_pointer[1] << 8) | \
- ((p)->parameter_table_pointer[0] << 0))
-
-#define SFDP_BFPT_ID 0xff00 /* Basic Flash Parameter Table */
-#define SFDP_SECTOR_MAP_ID 0xff81 /* Sector Map Table */
-#define SFDP_SST_ID 0x01bf /* Manufacturer specific 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
-
-struct sfdp_header {
- u32 signature; /* Ox50444653U <=> "SFDP" */
- u8 minor;
- u8 major;
- u8 nph; /* 0-base number of parameter headers */
- u8 unused;
-
- /* Basic Flash Parameter Table. */
- struct sfdp_parameter_header bfpt_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.
- */
-#define BFPT_DWORD(i) ((i) - 1)
-#define BFPT_DWORD_MAX 16
-
-/* The first version of JESB216 defined only 9 DWORDs. */
-#define BFPT_DWORD_MAX_JESD216 9
-
-/* 1st DWORD. */
-#define BFPT_DWORD1_FAST_READ_1_1_2 BIT(16)
-#define BFPT_DWORD1_ADDRESS_BYTES_MASK GENMASK(18, 17)
-#define BFPT_DWORD1_ADDRESS_BYTES_3_ONLY (0x0UL << 17)
-#define BFPT_DWORD1_ADDRESS_BYTES_3_OR_4 (0x1UL << 17)
-#define BFPT_DWORD1_ADDRESS_BYTES_4_ONLY (0x2UL << 17)
-#define BFPT_DWORD1_DTR BIT(19)
-#define BFPT_DWORD1_FAST_READ_1_2_2 BIT(20)
-#define BFPT_DWORD1_FAST_READ_1_4_4 BIT(21)
-#define BFPT_DWORD1_FAST_READ_1_1_4 BIT(22)
-
-/* 5th DWORD. */
-#define BFPT_DWORD5_FAST_READ_2_2_2 BIT(0)
-#define BFPT_DWORD5_FAST_READ_4_4_4 BIT(4)
-
-/* 11th DWORD. */
-#define BFPT_DWORD11_PAGE_SIZE_SHIFT 4
-#define BFPT_DWORD11_PAGE_SIZE_MASK GENMASK(7, 4)
-
-/* 15th DWORD. */
-
-/*
- * (from JESD216 rev B)
- * Quad Enable Requirements (QER):
- * - 000b: Device does not have a QE bit. Device detects 1-1-4 and 1-4-4
- * reads based on instruction. DQ3/HOLD# functions are hold during
- * instruction phase.
- * - 001b: QE is bit 1 of status register 2. It is set via Write Status with
- * two data bytes where bit 1 of the second byte is one.
- * [...]
- * Writing only one byte to the status register has the side-effect of
- * clearing status register 2, including the QE bit. The 100b code is
- * used if writing one byte to the status register does not modify
- * status register 2.
- * - 010b: QE is bit 6 of status register 1. It is set via Write Status with
- * one data byte where bit 6 is one.
- * [...]
- * - 011b: QE is bit 7 of status register 2. It is set via Write status
- * register 2 instruction 3Eh with one data byte where bit 7 is one.
- * [...]
- * The status register 2 is read using instruction 3Fh.
- * - 100b: QE is bit 1 of status register 2. It is set via Write Status with
- * two data bytes where bit 1 of the second byte is one.
- * [...]
- * In contrast to the 001b code, writing one byte to the status
- * register does not modify status register 2.
- * - 101b: QE is bit 1 of status register 2. Status register 1 is read using
- * Read Status instruction 05h. Status register2 is read using
- * instruction 35h. QE is set via Writ Status instruction 01h with
- * two data bytes where bit 1 of the second byte is one.
- * [...]
- */
-#define BFPT_DWORD15_QER_MASK GENMASK(22, 20)
-#define BFPT_DWORD15_QER_NONE (0x0UL << 20) /* Micron */
-#define BFPT_DWORD15_QER_SR2_BIT1_BUGGY (0x1UL << 20)
-#define BFPT_DWORD15_QER_SR1_BIT6 (0x2UL << 20) /* Macronix */
-#define BFPT_DWORD15_QER_SR2_BIT7 (0x3UL << 20)
-#define BFPT_DWORD15_QER_SR2_BIT1_NO_RD (0x4UL << 20)
-#define BFPT_DWORD15_QER_SR2_BIT1 (0x5UL << 20) /* Spansion */
-
-struct sfdp_bfpt {
- u32 dwords[BFPT_DWORD_MAX];
-};
-
/* Fast Read settings. */
static void
From patchwork Thu Jun 4 12:44:25 2020
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Pratyush Yadav
X-Patchwork-Id: 1303506
X-Patchwork-Delegate: jagannadh.teki@gmail.com
Return-Path:
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@bilbo.ozlabs.org
Authentication-Results: ozlabs.org;
spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de
(client-ip=85.214.62.61; helo=phobos.denx.de;
envelope-from=u-boot-bounces@lists.denx.de; receiver=)
Authentication-Results: ozlabs.org;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: ozlabs.org;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.a=rsa-sha256
header.s=ti-com-17Q1 header.b=EKtQQPt0;
dkim-atps=neutral
Received: from phobos.denx.de (phobos.denx.de [85.214.62.61])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (4096 bits))
(No client certificate requested)
by ozlabs.org (Postfix) with ESMTPS id 49d5C151pzz9sSc
for ; Thu, 4 Jun 2020 22:47:09 +1000 (AEST)
Received: from h2850616.stratoserver.net (localhost [IPv6:::1])
by phobos.denx.de (Postfix) with ESMTP id 829E180676;
Thu, 4 Jun 2020 14:45:34 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de;
spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de
Authentication-Results: phobos.denx.de;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.b="EKtQQPt0";
dkim-atps=neutral
Received: by phobos.denx.de (Postfix, from userid 109)
id 6B05381777; Thu, 4 Jun 2020 14:45:24 +0200 (CEST)
X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de
X-Spam-Level:
X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED
autolearn=ham autolearn_force=no version=3.4.2
Received: from fllv0015.ext.ti.com (fllv0015.ext.ti.com [198.47.19.141])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by phobos.denx.de (Postfix) with ESMTPS id 9D29C8164F
for ; Thu, 4 Jun 2020 14:45:16 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=p.yadav@ti.com
Received: from fllv0034.itg.ti.com ([10.64.40.246])
by fllv0015.ext.ti.com (8.15.2/8.15.2) with ESMTP id 054Cj88x062891;
Thu, 4 Jun 2020 07:45:08 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com;
s=ti-com-17Q1; t=1591274708;
bh=buytqRviPFD8uRFKWOIxYLgabxqWl4Xe1ahQO/ZBois=;
h=From:To:CC:Subject:Date:In-Reply-To:References;
b=EKtQQPt0LqBydmTPf5TZ5NKzCJszaYH8US1pLLcMG00oRLZx+Sa1CzKGCvmiL/J6g
mxgtDqUEIPwdSrEf2HXMscagdx/jVfiLIHcI6vZRRMPcIfFTTElrsjMUqmREtOjb4L
PeCGJQrBDse2S/2Dvd0pUFMJrp7IWs9sMW+khxf8=
Received: from DLEE100.ent.ti.com (dlee100.ent.ti.com [157.170.170.30])
by fllv0034.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 054Cj8oU049946
(version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL);
Thu, 4 Jun 2020 07:45:08 -0500
Received: from DLEE110.ent.ti.com (157.170.170.21) by DLEE100.ent.ti.com
(157.170.170.30) with Microsoft SMTP Server (version=TLS1_2,
cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1979.3; Thu, 4 Jun
2020 07:45:08 -0500
Received: from fllv0040.itg.ti.com (10.64.41.20) by DLEE110.ent.ti.com
(157.170.170.21) with Microsoft SMTP Server (version=TLS1_2,
cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1979.3 via
Frontend Transport; Thu, 4 Jun 2020 07:45:08 -0500
Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com
[10.172.224.153])
by fllv0040.itg.ti.com (8.15.2/8.15.2) with ESMTP id 054CicBY004409;
Thu, 4 Jun 2020 07:45:05 -0500
From: Pratyush Yadav
To: Chris Packham , Jagan Teki
, Vignesh R , Ryder Lee
, Weijie Gao ,
GSS_MTK_Uboot_upstream ,
CC: Pratyush Yadav , Sekhar Nori , "Tan, Ley
Foon"
Subject: [PATCH v5 08/21] mtd: spi-nor-core: Introduce flash-specific fixup
hooks
Date: Thu, 4 Jun 2020 18:14:25 +0530
Message-ID: <20200604124438.16783-9-p.yadav@ti.com>
X-Mailer: git-send-email 2.25.0
In-Reply-To: <20200604124438.16783-1-p.yadav@ti.com>
References: <20200604124438.16783-1-p.yadav@ti.com>
MIME-Version: 1.0
X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180
X-BeenThere: u-boot@lists.denx.de
X-Mailman-Version: 2.1.30rc1
Precedence: list
List-Id: U-Boot discussion
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
Errors-To: u-boot-bounces@lists.denx.de
Sender: "U-Boot"
X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de
X-Virus-Status: Clean
Sometimes the information in a flash's SFDP tables is wrong. Sometimes
some information just can't be expressed in the SFDP table. So,
introduce the fixup hooks to allow tailoring settings for a specific
flash.
Three hooks are added: default_init, post_sfdp, and post_bfpt. These
allow tweaking the flash settings at different point in the probe
sequence. Since the hooks reside in nor->info, set that value just
before the call to spi_nor_init_params().
The hooks and at what points they are executed mimics Linux's spi-nor
framework. One major difference is that Linux puts the struct
spi_nor_fixups in nor->info. This is not possible in U-Boot because the
spi-nor-ids list is shared between spi-nor-core.c and spi-nor-tiny.c.
Since spi-nor-tiny shouldn't have those fixup hooks populated, add a
separate function that lets flashes populate their fixup hooks.
Signed-off-by: Pratyush Yadav
---
drivers/mtd/spi/spi-nor-core.c | 78 ++++++++++++++++++++++++++++++++--
include/linux/mtd/spi-nor.h | 2 +
2 files changed, 77 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 28f5f877b4..2494c2e724 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -150,6 +150,31 @@ struct sfdp_bfpt {
u32 dwords[BFPT_DWORD_MAX];
};
+/**
+ * struct spi_nor_fixups - SPI NOR fixup hooks
+ * @default_init: called after default flash parameters init. Used to tweak
+ * flash parameters when information provided by the flash_info
+ * table is incomplete or wrong.
+ * @post_bfpt: called after the BFPT table has been parsed
+ * @post_sfdp: called after SFDP has been parsed (is also called for SPI NORs
+ * that do not support RDSFDP). Typically used to tweak various
+ * parameters that could not be extracted by other means (i.e.
+ * when information provided by the SFDP/flash_info tables are
+ * incomplete or wrong).
+ *
+ * Those hooks can be used to tweak the SPI NOR configuration when the SFDP
+ * table is broken or not available.
+ */
+struct spi_nor_fixups {
+ void (*default_init)(struct spi_nor *nor);
+ int (*post_bfpt)(struct spi_nor *nor,
+ const struct sfdp_parameter_header *bfpt_header,
+ const struct sfdp_bfpt *bfpt,
+ struct spi_nor_flash_parameter *params);
+ void (*post_sfdp)(struct spi_nor *nor,
+ struct spi_nor_flash_parameter *params);
+};
+
static int spi_nor_read_write_reg(struct spi_nor *nor, struct spi_mem_op
*op, void *buf)
{
@@ -1747,6 +1772,18 @@ static const struct sfdp_bfpt_erase sfdp_bfpt_erases[] = {
static int spi_nor_hwcaps_read2cmd(u32 hwcaps);
+static int
+spi_nor_post_bfpt_fixups(struct spi_nor *nor,
+ const struct sfdp_parameter_header *bfpt_header,
+ const struct sfdp_bfpt *bfpt,
+ struct spi_nor_flash_parameter *params)
+{
+ if (nor->fixups && nor->fixups->post_bfpt)
+ return nor->fixups->post_bfpt(nor, bfpt_header, bfpt, params);
+
+ return 0;
+}
+
/**
* spi_nor_parse_bfpt() - read and parse the Basic Flash Parameter Table.
* @nor: pointer to a 'struct spi_nor'
@@ -1885,7 +1922,8 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
/* Stop here if not JESD216 rev A or later. */
if (bfpt_header->length < BFPT_DWORD_MAX)
- return 0;
+ return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt,
+ params);
/* Page size: this field specifies 'N' so the page size = 2^N bytes. */
params->page_size = bfpt.dwords[BFPT_DWORD(11)];
@@ -1918,7 +1956,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
return -EINVAL;
}
- return 0;
+ return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt, params);
}
/**
@@ -2081,6 +2119,29 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
}
#endif /* SPI_FLASH_SFDP_SUPPORT */
+/**
+ * spi_nor_post_sfdp_fixups() - Updates the flash's parameters and settings
+ * after SFDP has been parsed (is also called for SPI NORs that do not
+ * support RDSFDP).
+ * @nor: pointer to a 'struct spi_nor'
+ *
+ * Typically used to tweak various parameters that could not be extracted by
+ * other means (i.e. when information provided by the SFDP/flash_info tables
+ * are incomplete or wrong).
+ */
+static void spi_nor_post_sfdp_fixups(struct spi_nor *nor,
+ struct spi_nor_flash_parameter *params)
+{
+ if (nor->fixups && nor->fixups->post_sfdp)
+ nor->fixups->post_sfdp(nor, params);
+}
+
+static void spi_nor_default_init_fixups(struct spi_nor *nor)
+{
+ if (nor->fixups && nor->fixups->default_init)
+ nor->fixups->default_init(nor);
+}
+
static int spi_nor_init_params(struct spi_nor *nor,
const struct flash_info *info,
struct spi_nor_flash_parameter *params)
@@ -2159,6 +2220,8 @@ static int spi_nor_init_params(struct spi_nor *nor,
}
}
+ spi_nor_default_init_fixups(nor);
+
/* Override the parameters with data read from SFDP tables. */
nor->addr_width = 0;
nor->mtd.erasesize = 0;
@@ -2175,6 +2238,8 @@ static int spi_nor_init_params(struct spi_nor *nor,
}
}
+ spi_nor_post_sfdp_fixups(nor, params);
+
return 0;
}
@@ -2422,6 +2487,10 @@ static int spi_nor_init(struct spi_nor *nor)
return 0;
}
+void spi_nor_set_fixups(struct spi_nor *nor)
+{
+}
+
int spi_nor_scan(struct spi_nor *nor)
{
struct spi_nor_flash_parameter params;
@@ -2470,6 +2539,10 @@ int spi_nor_scan(struct spi_nor *nor)
info = spi_nor_read_id(nor);
if (IS_ERR_OR_NULL(info))
return -ENOENT;
+ nor->info = info;
+
+ spi_nor_set_fixups(nor);
+
/* Parse the Serial Flash Discoverable Parameters table. */
ret = spi_nor_init_params(nor, info, ¶ms);
if (ret)
@@ -2569,7 +2642,6 @@ int spi_nor_scan(struct spi_nor *nor)
}
/* Send all the required SPI flash commands to initialize device */
- nor->info = info;
ret = spi_nor_init(nor);
if (ret)
return ret;
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 922e795ea6..5842e9d6ee 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -414,6 +414,7 @@ struct flash_info;
* @write_proto: the SPI protocol for write operations
* @reg_proto the SPI protocol for read_reg/write_reg/erase operations
* @cmd_buf: used by the write_reg
+ * @fixups: flash-specific fixup hooks.
* @prepare: [OPTIONAL] do some preparations for the
* read/write/erase/lock/unlock operations
* @unprepare: [OPTIONAL] do some post work after the
@@ -455,6 +456,7 @@ struct spi_nor {
bool sst_write_second;
u32 flags;
u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE];
+ struct spi_nor_fixups *fixups;
int (*setup)(struct spi_nor *nor, const struct flash_info *info,
const struct spi_nor_flash_parameter *params,
From patchwork Thu Jun 4 12:44:26 2020
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Pratyush Yadav
X-Patchwork-Id: 1303507
X-Patchwork-Delegate: jagannadh.teki@gmail.com
Return-Path:
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@bilbo.ozlabs.org
Authentication-Results: ozlabs.org;
spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de
(client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;
envelope-from=u-boot-bounces@lists.denx.de; receiver=)
Authentication-Results: ozlabs.org;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: ozlabs.org;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.a=rsa-sha256
header.s=ti-com-17Q1 header.b=N3HosGcM;
dkim-atps=neutral
Received: from phobos.denx.de (phobos.denx.de
[IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (4096 bits))
(No client certificate requested)
by ozlabs.org (Postfix) with ESMTPS id 49d5CG4S0cz9sSc
for ; Thu, 4 Jun 2020 22:47:22 +1000 (AEST)
Received: from h2850616.stratoserver.net (localhost [IPv6:::1])
by phobos.denx.de (Postfix) with ESMTP id BE1A381C73;
Thu, 4 Jun 2020 14:45:36 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de;
spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de
Authentication-Results: phobos.denx.de;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.b="N3HosGcM";
dkim-atps=neutral
Received: by phobos.denx.de (Postfix, from userid 109)
id CFBC8819A6; Thu, 4 Jun 2020 14:45:27 +0200 (CEST)
X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de
X-Spam-Level:
X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED
autolearn=ham autolearn_force=no version=3.4.2
Received: from fllv0015.ext.ti.com (fllv0015.ext.ti.com [198.47.19.141])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by phobos.denx.de (Postfix) with ESMTPS id 5771C818C7
for ; Thu, 4 Jun 2020 14:45:21 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=p.yadav@ti.com
Received: from fllv0034.itg.ti.com ([10.64.40.246])
by fllv0015.ext.ti.com (8.15.2/8.15.2) with ESMTP id 054CjBcX062898;
Thu, 4 Jun 2020 07:45:11 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com;
s=ti-com-17Q1; t=1591274711;
bh=mqU6CilfrTE+17YNaPfmHWBzXh5dncp2MOM3NXz/t+Q=;
h=From:To:CC:Subject:Date:In-Reply-To:References;
b=N3HosGcMrN+UcDQVNPMR/JRdzcO9dLf7LlfhBuSYmAp7taZ+9QEyNfHsJ4v4KJ81m
LKg+P/SH62VnqkMDNRz2HqvdW+MlsQa4eqFpzJkb5VbxBbQzgf6CeLDdhtwQcwYeC9
V/JIrNmQmITstZdcZkBGMUjPvF0kf48CdxmOGhPY=
Received: from DFLE112.ent.ti.com (dfle112.ent.ti.com [10.64.6.33])
by fllv0034.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 054CjBX8050015
(version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL);
Thu, 4 Jun 2020 07:45:11 -0500
Received: from DFLE113.ent.ti.com (10.64.6.34) by DFLE112.ent.ti.com
(10.64.6.33) with Microsoft SMTP Server (version=TLS1_2,
cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1979.3; Thu, 4 Jun
2020 07:45:11 -0500
Received: from fllv0040.itg.ti.com (10.64.41.20) 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.1979.3 via
Frontend Transport; Thu, 4 Jun 2020 07:45:11 -0500
Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com
[10.172.224.153])
by fllv0040.itg.ti.com (8.15.2/8.15.2) with ESMTP id 054CicBZ004409;
Thu, 4 Jun 2020 07:45:08 -0500
From: Pratyush Yadav
To: Chris Packham , Jagan Teki
, Vignesh R , Ryder Lee
, Weijie Gao ,
GSS_MTK_Uboot_upstream ,
CC: Pratyush Yadav , Sekhar Nori , "Tan, Ley
Foon"
Subject: [PATCH v5 09/21] mtd: spi-nor-core: Rework hwcaps selection
Date: Thu, 4 Jun 2020 18:14:26 +0530
Message-ID: <20200604124438.16783-10-p.yadav@ti.com>
X-Mailer: git-send-email 2.25.0
In-Reply-To: <20200604124438.16783-1-p.yadav@ti.com>
References: <20200604124438.16783-1-p.yadav@ti.com>
MIME-Version: 1.0
X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180
X-BeenThere: u-boot@lists.denx.de
X-Mailman-Version: 2.1.30rc1
Precedence: list
List-Id: U-Boot discussion
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
Errors-To: u-boot-bounces@lists.denx.de
Sender: "U-Boot"
X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de
X-Virus-Status: Clean
The spi-mem layer provides a spi_mem_supports_op() function to check
whether a specific operation is supported by the controller or not.
This is much more accurate than the hwcaps selection logic based on
SPI_{RX,TX}_ flags.
Rework the hwcaps selection logic to use spi_mem_supports_op().
To make sure the build doesn't break for boards not using CONFIG_DM_SPI,
add a simple SPI_{RX,TX}_ based hwcaps selection logic in spi-mem-nodm
similar to spi_mem_default_supports_op(). This change is only
compile-tested.
To avoid SPL size problems on the x530 board, the old hwcaps selection
is still kept around. Leaving the code in-place was getting difficult to
read and understand, so the code is restructured to have it all in one
isolated function. As a result of this, the parameter hwcaps to
spi_nor_setup() is no longer needed. Remove it.
Based on the Linux commit c76f5089796a (mtd: spi-nor: Rework hwcaps
selection for the spi-mem case, 2019-08-06)
Signed-off-by: Pratyush Yadav
---
drivers/mtd/spi/Kconfig | 9 ++
drivers/mtd/spi/spi-nor-core.c | 244 ++++++++++++++++++++++++++-------
drivers/spi/spi-mem-nodm.c | 62 +++++++++
include/linux/mtd/spi-nor.h | 17 ++-
4 files changed, 280 insertions(+), 52 deletions(-)
diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig
index 018e8c597e..09ec18cdf2 100644
--- a/drivers/mtd/spi/Kconfig
+++ b/drivers/mtd/spi/Kconfig
@@ -88,6 +88,15 @@ config SPI_FLASH_SFDP_SUPPORT
SPI NOR flashes using Serial Flash Discoverable Parameters (SFDP)
tables as per JESD216 standard.
+config SPI_FLASH_SMART_HWCAPS
+ bool "Smart hardware capability detection based on SPI MEM supports_op() hook"
+ default y
+ help
+ Enable support for smart hardware capability detection based on SPI
+ MEM supports_op() hook that lets controllers express whether they
+ can support a type of operation in a much more refined way compared
+ to using flags like SPI_RX_DUAL, SPI_TX_QUAD, etc.
+
config SPI_FLASH_BAR
bool "SPI flash Bank/Extended address register support"
help
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 2494c2e724..a50575ca8b 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -2294,6 +2294,194 @@ static int spi_nor_hwcaps_pp2cmd(u32 hwcaps)
ARRAY_SIZE(hwcaps_pp2cmd));
}
+#ifdef CONFIG_SPI_FLASH_SMART_HWCAPS
+/**
+ * spi_nor_check_op - check if the operation is supported by controller
+ * @nor: pointer to a 'struct spi_nor'
+ * @op: pointer to op template to be checked
+ *
+ * Returns 0 if operation is supported, -ENOTSUPP otherwise.
+ */
+static int spi_nor_check_op(struct spi_nor *nor,
+ struct spi_mem_op *op)
+{
+ /*
+ * First test with 4 address bytes. The opcode itself might be a 3B
+ * addressing opcode but we don't care, because SPI controller
+ * implementation should not check the opcode, but just the sequence.
+ */
+ op->addr.nbytes = 4;
+ if (!spi_mem_supports_op(nor->spi, op)) {
+ if (nor->mtd.size > SZ_16M)
+ return -ENOTSUPP;
+
+ /* If flash size <= 16MB, 3 address bytes are sufficient */
+ op->addr.nbytes = 3;
+ if (!spi_mem_supports_op(nor->spi, op))
+ return -ENOTSUPP;
+ }
+
+ return 0;
+}
+
+/**
+ * spi_nor_check_readop - check if the read op is supported by controller
+ * @nor: pointer to a 'struct spi_nor'
+ * @read: pointer to op template to be checked
+ *
+ * Returns 0 if operation is supported, -ENOTSUPP otherwise.
+ */
+static int spi_nor_check_readop(struct spi_nor *nor,
+ const struct spi_nor_read_command *read)
+{
+ struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(read->opcode, 1),
+ SPI_MEM_OP_ADDR(3, 0, 1),
+ SPI_MEM_OP_DUMMY(0, 1),
+ SPI_MEM_OP_DATA_IN(0, NULL, 1));
+
+ op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(read->proto);
+ op.addr.buswidth = spi_nor_get_protocol_addr_nbits(read->proto);
+ op.data.buswidth = spi_nor_get_protocol_data_nbits(read->proto);
+ op.dummy.buswidth = op.addr.buswidth;
+ op.dummy.nbytes = (read->num_mode_clocks + read->num_wait_states) *
+ op.dummy.buswidth / 8;
+
+ return spi_nor_check_op(nor, &op);
+}
+
+/**
+ * spi_nor_check_pp - check if the page program op is supported by controller
+ * @nor: pointer to a 'struct spi_nor'
+ * @pp: pointer to op template to be checked
+ *
+ * Returns 0 if operation is supported, -ENOTSUPP otherwise.
+ */
+static int spi_nor_check_pp(struct spi_nor *nor,
+ const struct spi_nor_pp_command *pp)
+{
+ struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(pp->opcode, 1),
+ SPI_MEM_OP_ADDR(3, 0, 1),
+ SPI_MEM_OP_NO_DUMMY,
+ SPI_MEM_OP_DATA_OUT(0, NULL, 1));
+
+ op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(pp->proto);
+ op.addr.buswidth = spi_nor_get_protocol_addr_nbits(pp->proto);
+ op.data.buswidth = spi_nor_get_protocol_data_nbits(pp->proto);
+
+ return spi_nor_check_op(nor, &op);
+}
+
+/**
+ * spi_nor_adjust_hwcaps - Find optimal Read/Write protocol based on SPI
+ * controller capabilities
+ * @nor: pointer to a 'struct spi_nor'
+ * @params: pointer to the 'struct spi_nor_flash_parameter'
+ * representing SPI NOR flash capabilities
+ * @hwcaps: pointer to resulting capabilities after adjusting
+ * according to controller and flash's capability
+ *
+ * Discard caps based on what the SPI controller actually supports (using
+ * spi_mem_supports_op()).
+ */
+static void
+spi_nor_adjust_hwcaps(struct spi_nor *nor,
+ const struct spi_nor_flash_parameter *params,
+ u32 *hwcaps)
+{
+ unsigned int cap;
+
+ /*
+ * Enable all caps by default. We will mask them after checking what's
+ * really supported using spi_mem_supports_op().
+ */
+ *hwcaps = SNOR_HWCAPS_ALL;
+
+ /* 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;
+
+ for (cap = 0; cap < sizeof(*hwcaps) * BITS_PER_BYTE; cap++) {
+ int rdidx, ppidx;
+
+ if (!(*hwcaps & BIT(cap)))
+ continue;
+
+ rdidx = spi_nor_hwcaps_read2cmd(BIT(cap));
+ if (rdidx >= 0 &&
+ spi_nor_check_readop(nor, ¶ms->reads[rdidx]))
+ *hwcaps &= ~BIT(cap);
+
+ ppidx = spi_nor_hwcaps_pp2cmd(BIT(cap));
+ if (ppidx < 0)
+ continue;
+
+ if (spi_nor_check_pp(nor, ¶ms->page_programs[ppidx]))
+ *hwcaps &= ~BIT(cap);
+ }
+}
+#else
+/**
+ * spi_nor_adjust_hwcaps - Find optimal Read/Write protocol based on SPI
+ * controller capabilities
+ * @nor: pointer to a 'struct spi_nor'
+ * @params: pointer to the 'struct spi_nor_flash_parameter'
+ * representing SPI NOR flash capabilities
+ * @hwcaps: pointer to resulting capabilities after adjusting
+ * according to controller and flash's capability
+ *
+ * Select caps based on what the SPI controller and SPI flash both support.
+ */
+static void
+spi_nor_adjust_hwcaps(struct spi_nor *nor,
+ const struct spi_nor_flash_parameter *params,
+ u32 *hwcaps)
+{
+ struct spi_slave *spi = nor->spi;
+ u32 ignored_mask = (SNOR_HWCAPS_READ_2_2_2 |
+ SNOR_HWCAPS_READ_4_4_4 |
+ SNOR_HWCAPS_READ_8_8_8 |
+ SNOR_HWCAPS_PP_4_4_4 |
+ SNOR_HWCAPS_PP_8_8_8);
+ u32 spi_hwcaps = (SNOR_HWCAPS_READ | SNOR_HWCAPS_READ_FAST |
+ SNOR_HWCAPS_PP);
+
+ /* Get the hardware capabilities the SPI controller supports. */
+ if (spi->mode & SPI_RX_OCTAL) {
+ spi_hwcaps |= SNOR_HWCAPS_READ_1_1_8;
+
+ if (spi->mode & SPI_TX_OCTAL)
+ spi_hwcaps |= (SNOR_HWCAPS_READ_1_8_8 |
+ SNOR_HWCAPS_PP_1_1_8 |
+ SNOR_HWCAPS_PP_1_8_8);
+ } else if (spi->mode & SPI_RX_QUAD) {
+ spi_hwcaps |= SNOR_HWCAPS_READ_1_1_4;
+
+ if (spi->mode & SPI_TX_QUAD)
+ spi_hwcaps |= (SNOR_HWCAPS_READ_1_4_4 |
+ SNOR_HWCAPS_PP_1_1_4 |
+ SNOR_HWCAPS_PP_1_4_4);
+ } else if (spi->mode & SPI_RX_DUAL) {
+ spi_hwcaps |= SNOR_HWCAPS_READ_1_1_2;
+
+ if (spi->mode & SPI_TX_DUAL)
+ spi_hwcaps |= SNOR_HWCAPS_READ_1_2_2;
+ }
+
+ /*
+ * Keep only the hardware capabilities supported by both the SPI
+ * controller and the SPI flash memory.
+ */
+ *hwcaps = spi_hwcaps & params->hwcaps.mask;
+ if (*hwcaps & ignored_mask) {
+ dev_dbg(nor->dev,
+ "SPI n-n-n protocols are not supported yet.\n");
+ *hwcaps &= ~ignored_mask;
+ }
+}
+#endif /* CONFIG_SPI_FLASH_SMART_HWCAPS */
+
static int spi_nor_select_read(struct spi_nor *nor,
const struct spi_nor_flash_parameter *params,
u32 shared_hwcaps)
@@ -2374,30 +2562,13 @@ static int spi_nor_select_erase(struct spi_nor *nor,
static int spi_nor_default_setup(struct spi_nor *nor,
const struct flash_info *info,
- const struct spi_nor_flash_parameter *params,
- const struct spi_nor_hwcaps *hwcaps)
+ const struct spi_nor_flash_parameter *params)
{
- u32 ignored_mask, shared_mask;
+ u32 shared_mask;
bool enable_quad_io;
int err;
- /*
- * Keep only the hardware capabilities supported by both the SPI
- * controller and the SPI flash memory.
- */
- shared_mask = hwcaps->mask & params->hwcaps.mask;
-
- /* SPI n-n-n protocols are not supported yet. */
- ignored_mask = (SNOR_HWCAPS_READ_2_2_2 |
- SNOR_HWCAPS_READ_4_4_4 |
- SNOR_HWCAPS_READ_8_8_8 |
- SNOR_HWCAPS_PP_4_4_4 |
- SNOR_HWCAPS_PP_8_8_8);
- if (shared_mask & ignored_mask) {
- dev_dbg(nor->dev,
- "SPI n-n-n protocols are not supported yet.\n");
- shared_mask &= ~ignored_mask;
- }
+ spi_nor_adjust_hwcaps(nor, params, &shared_mask);
/* Select the (Fast) Read command. */
err = spi_nor_select_read(nor, params, shared_mask);
@@ -2435,13 +2606,12 @@ static int spi_nor_default_setup(struct spi_nor *nor,
}
static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info,
- const struct spi_nor_flash_parameter *params,
- const struct spi_nor_hwcaps *hwcaps)
+ const struct spi_nor_flash_parameter *params)
{
if (!nor->setup)
return 0;
- return nor->setup(nor, info, params, hwcaps);
+ return nor->setup(nor, info, params);
}
static int spi_nor_init(struct spi_nor *nor)
@@ -2496,11 +2666,6 @@ int spi_nor_scan(struct spi_nor *nor)
struct spi_nor_flash_parameter params;
const struct flash_info *info = NULL;
struct mtd_info *mtd = &nor->mtd;
- struct spi_nor_hwcaps hwcaps = {
- .mask = SNOR_HWCAPS_READ |
- SNOR_HWCAPS_READ_FAST |
- SNOR_HWCAPS_PP,
- };
struct spi_slave *spi = nor->spi;
int ret;
@@ -2515,27 +2680,6 @@ int spi_nor_scan(struct spi_nor *nor)
nor->setup = spi_nor_default_setup;
- if (spi->mode & SPI_RX_OCTAL) {
- hwcaps.mask |= SNOR_HWCAPS_READ_1_1_8;
-
- if (spi->mode & SPI_TX_OCTAL)
- hwcaps.mask |= (SNOR_HWCAPS_READ_1_8_8 |
- SNOR_HWCAPS_PP_1_1_8 |
- SNOR_HWCAPS_PP_1_8_8);
- } else if (spi->mode & SPI_RX_QUAD) {
- hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4;
-
- if (spi->mode & SPI_TX_QUAD)
- hwcaps.mask |= (SNOR_HWCAPS_READ_1_4_4 |
- SNOR_HWCAPS_PP_1_1_4 |
- SNOR_HWCAPS_PP_1_4_4);
- } else if (spi->mode & SPI_RX_DUAL) {
- hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2;
-
- if (spi->mode & SPI_TX_DUAL)
- hwcaps.mask |= SNOR_HWCAPS_READ_1_2_2;
- }
-
info = spi_nor_read_id(nor);
if (IS_ERR_OR_NULL(info))
return -ENOENT;
@@ -2609,7 +2753,7 @@ int spi_nor_scan(struct spi_nor *nor)
* - set the SPI protocols for register and memory accesses.
* - set the Quad Enable bit if needed (required by SPI x-y-4 protos).
*/
- ret = spi_nor_setup(nor, info, ¶ms, &hwcaps);
+ ret = spi_nor_setup(nor, info, ¶ms);
if (ret)
return ret;
diff --git a/drivers/spi/spi-mem-nodm.c b/drivers/spi/spi-mem-nodm.c
index db54101383..050d25040c 100644
--- a/drivers/spi/spi-mem-nodm.c
+++ b/drivers/spi/spi-mem-nodm.c
@@ -105,3 +105,65 @@ int spi_mem_adjust_op_size(struct spi_slave *slave,
return 0;
}
+
+static int spi_check_buswidth_req(struct spi_slave *slave, u8 buswidth, bool tx)
+{
+ u32 mode = slave->mode;
+
+ switch (buswidth) {
+ case 1:
+ return 0;
+
+ case 2:
+ if ((tx && (mode & (SPI_TX_DUAL | SPI_TX_QUAD))) ||
+ (!tx && (mode & (SPI_RX_DUAL | SPI_RX_QUAD))))
+ return 0;
+
+ break;
+
+ case 4:
+ if ((tx && (mode & SPI_TX_QUAD)) ||
+ (!tx && (mode & SPI_RX_QUAD)))
+ return 0;
+
+ break;
+ case 8:
+ if ((tx && (mode & SPI_TX_OCTAL)) ||
+ (!tx && (mode & SPI_RX_OCTAL)))
+ return 0;
+
+ break;
+
+ default:
+ break;
+ }
+
+ return -ENOTSUPP;
+}
+
+bool spi_mem_supports_op(struct spi_slave *slave, const struct spi_mem_op *op)
+{
+ if (spi_check_buswidth_req(slave, op->cmd.buswidth, true))
+ return false;
+
+ if (op->addr.nbytes &&
+ spi_check_buswidth_req(slave, op->addr.buswidth, true))
+ return false;
+
+ if (op->dummy.nbytes &&
+ spi_check_buswidth_req(slave, op->dummy.buswidth, true))
+ return false;
+
+ if (op->data.dir != SPI_MEM_NO_DATA &&
+ spi_check_buswidth_req(slave, op->data.buswidth,
+ op->data.dir == SPI_MEM_DATA_OUT))
+ return false;
+
+ if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr)
+ return false;
+
+ if (op->cmd.nbytes != 1)
+ return false;
+
+ return true;
+}
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 5842e9d6ee..cca7919fdd 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -312,6 +312,20 @@ struct spi_nor_hwcaps {
#define SNOR_HWCAPS_PP_1_8_8 BIT(21)
#define SNOR_HWCAPS_PP_8_8_8 BIT(22)
+#define SNOR_HWCAPS_X_X_X (SNOR_HWCAPS_READ_2_2_2 | \
+ SNOR_HWCAPS_READ_4_4_4 | \
+ SNOR_HWCAPS_READ_8_8_8 | \
+ SNOR_HWCAPS_PP_4_4_4 | \
+ SNOR_HWCAPS_PP_8_8_8)
+
+#define SNOR_HWCAPS_DTR (SNOR_HWCAPS_READ_1_1_1_DTR | \
+ SNOR_HWCAPS_READ_1_2_2_DTR | \
+ SNOR_HWCAPS_READ_1_4_4_DTR | \
+ SNOR_HWCAPS_READ_1_8_8_DTR)
+
+#define SNOR_HWCAPS_ALL (SNOR_HWCAPS_READ_MASK | \
+ SNOR_HWCAPS_PP_MASK)
+
struct spi_nor_read_command {
u8 num_mode_clocks;
u8 num_wait_states;
@@ -459,8 +473,7 @@ struct spi_nor {
struct spi_nor_fixups *fixups;
int (*setup)(struct spi_nor *nor, const struct flash_info *info,
- const struct spi_nor_flash_parameter *params,
- const struct spi_nor_hwcaps *hwcaps);
+ const struct spi_nor_flash_parameter *params);
int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);
void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);
int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
From patchwork Thu Jun 4 12:44:27 2020
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Pratyush Yadav
X-Patchwork-Id: 1303508
X-Patchwork-Delegate: jagannadh.teki@gmail.com
Return-Path:
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@bilbo.ozlabs.org
Authentication-Results: ozlabs.org;
spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de
(client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;
envelope-from=u-boot-bounces@lists.denx.de; receiver=)
Authentication-Results: ozlabs.org;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: ozlabs.org;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.a=rsa-sha256
header.s=ti-com-17Q1 header.b=F9NK6uuy;
dkim-atps=neutral
Received: from phobos.denx.de (phobos.denx.de
[IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (4096 bits))
(No client certificate requested)
by ozlabs.org (Postfix) with ESMTPS id 49d5CY5JC3z9sSc
for ; Thu, 4 Jun 2020 22:47:37 +1000 (AEST)
Received: from h2850616.stratoserver.net (localhost [IPv6:::1])
by phobos.denx.de (Postfix) with ESMTP id 57B7B81734;
Thu, 4 Jun 2020 14:45:39 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de;
spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de
Authentication-Results: phobos.denx.de;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.b="F9NK6uuy";
dkim-atps=neutral
Received: by phobos.denx.de (Postfix, from userid 109)
id 851B581C6A; Thu, 4 Jun 2020 14:45:32 +0200 (CEST)
X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de
X-Spam-Level:
X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,
DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED
autolearn=ham autolearn_force=no version=3.4.2
Received: from fllv0015.ext.ti.com (fllv0015.ext.ti.com [198.47.19.141])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by phobos.denx.de (Postfix) with ESMTPS id 64E6681734
for ; Thu, 4 Jun 2020 14:45:24 +0200 (CEST)
Authentication-Results: phobos.denx.de;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=p.yadav@ti.com
Received: from fllv0035.itg.ti.com ([10.64.41.0])
by fllv0015.ext.ti.com (8.15.2/8.15.2) with ESMTP id 054CjFNq062908;
Thu, 4 Jun 2020 07:45:15 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com;
s=ti-com-17Q1; t=1591274715;
bh=Mh4Pphx0vsLwmOYZYdzyvr4YTnzB+4Bx6w9Bx2ekoZs=;
h=From:To:CC:Subject:Date:In-Reply-To:References;
b=F9NK6uuynH5k5SNYqD0N6GE3n16tGKSwaJkE8EN8KC5UDdPFEEUEzAs1pfOC4s0gS
RNsl2enHF+1qRDxl3LMEWK3yR5W3HKSrTakpTWNIZ2Y791MjysRxE0USoY+j7tD3mz
8Mwea/xzTpDcY1GMiesrY1YGaXL7C+Ovy65S3gg0=
Received: from DFLE106.ent.ti.com (dfle106.ent.ti.com [10.64.6.27])
by fllv0035.itg.ti.com (8.15.2/8.15.2) with ESMTP id 054CjF37113441;
Thu, 4 Jun 2020 07:45:15 -0500
Received: from DFLE103.ent.ti.com (10.64.6.24) by DFLE106.ent.ti.com
(10.64.6.27) with Microsoft SMTP Server (version=TLS1_2,
cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1979.3; Thu, 4 Jun
2020 07:45:14 -0500
Received: from fllv0040.itg.ti.com (10.64.41.20) 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.1979.3 via
Frontend Transport; Thu, 4 Jun 2020 07:45:14 -0500
Received: from pratyush-OptiPlex-790.dhcp.ti.com (ileax41-snat.itg.ti.com
[10.172.224.153])
by fllv0040.itg.ti.com (8.15.2/8.15.2) with ESMTP id 054CicBa004409;
Thu, 4 Jun 2020 07:45:12 -0500
From: Pratyush Yadav
To: Chris Packham , Jagan Teki
, Vignesh R , Ryder Lee
, Weijie Gao ,
GSS_MTK_Uboot_upstream ,
CC: Pratyush Yadav , Sekhar Nori , "Tan, Ley
Foon"
Subject: [PATCH v5 10/21] mtd: spi-nor-core: Add support for DTR protocol
Date: Thu, 4 Jun 2020 18:14:27 +0530
Message-ID: <20200604124438.16783-11-p.yadav@ti.com>
X-Mailer: git-send-email 2.25.0
In-Reply-To: <20200604124438.16783-1-p.yadav@ti.com>
References: <20200604124438.16783-1-p.yadav@ti.com>
MIME-Version: 1.0
X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180
X-BeenThere: u-boot@lists.denx.de
X-Mailman-Version: 2.1.30rc1
Precedence: list
List-Id: U-Boot discussion
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
Errors-To: u-boot-bounces@lists.denx.de
Sender: "U-Boot"
X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de
X-Virus-Status: Clean
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/sf_internal.h | 1 +
drivers/mtd/spi/spi-nor-core.c | 124 +++++++++++++++++++++++++++++----
include/linux/mtd/spi-nor.h | 50 +++++++++----
3 files changed, 149 insertions(+), 26 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index dabd40a4cc..aed7c8ab0c 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -68,6 +68,7 @@ struct flash_info {
#define USE_CLSR BIT(14) /* use CLSR command */
#define SPI_NOR_HAS_SST26LOCK BIT(15) /* Flash supports lock/unlock via BPR */
#define SPI_NOR_OCTAL_READ BIT(16) /* Flash supports Octal Read */
+#define SPI_NOR_OCTAL_DTR_READ BIT(17) /* Flash supports Octal DTR Read */
};
extern const struct flash_info spi_nor_ids[];
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index a50575ca8b..8eead6a89b 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -175,6 +175,76 @@ struct spi_nor_fixups {
struct spi_nor_flash_parameter *params);
};
+/**
+ * spi_nor_get_cmd_ext() - Get the command opcode extension based on the
+ * extension type.
+ * @nor: pointer to a 'struct spi_nor'
+ * @op: pointer to the 'struct spi_mem_op' whose properties
+ * need to be initialized.
+ *
+ * Right now, only "repeat" and "invert" are supported.
+ *
+ * Return: The opcode extension.
+ */
+static u8 spi_nor_get_cmd_ext(const struct spi_nor *nor,
+ const struct spi_mem_op *op)
+{
+ switch (nor->cmd_ext_type) {
+ case SPI_NOR_EXT_INVERT:
+ return ~op->cmd.opcode;
+
+ case SPI_NOR_EXT_REPEAT:
+ return op->cmd.opcode;
+
+ default:
+ dev_err(nor->dev, "Unknown command extension type\n");
+ return 0;
+ }
+}
+
+/**
+ * spi_nor_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_setup_op(const struct spi_nor *nor,
+ struct spi_mem_op *op,
+ const enum spi_nor_protocol proto)
+{
+ u8 ext;
+
+ 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.nbytes)
+ 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.dtr = op->addr.dtr = op->dummy.dtr =
+ op->data.dtr = true;
+
+ /* 2 bytes per clock cycle in DTR mode. */
+ op->dummy.nbytes *= 2;
+
+ ext = spi_nor_get_cmd_ext(nor, op);
+ op->cmd.opcode = (op->cmd.opcode << 8) | ext;
+ op->cmd.nbytes = 2;
+ }
+}
+
static int spi_nor_read_write_reg(struct spi_nor *nor, struct spi_mem_op
*op, void *buf)
{
@@ -193,6 +263,8 @@ static int spi_nor_read_reg(struct spi_nor *nor, u8 code, u8 *val, int len)
SPI_MEM_OP_DATA_IN(len, NULL, 1));
int ret;
+ spi_nor_setup_op(nor, &op, nor->reg_proto);
+
ret = spi_nor_read_write_reg(nor, &op, val);
if (ret < 0)
dev_dbg(nor->dev, "error %d reading %x\n", ret, code);
@@ -207,6 +279,8 @@ static int spi_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
SPI_MEM_OP_NO_DUMMY,
SPI_MEM_OP_DATA_OUT(len, NULL, 1));
+ spi_nor_setup_op(nor, &op, nor->reg_proto);
+
return spi_nor_read_write_reg(nor, &op, buf);
}
@@ -221,14 +295,12 @@ static ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len,
size_t remaining = len;
int ret;
- /* get transfer protocols. */
- op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto);
- op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->read_proto);
- op.dummy.buswidth = op.addr.buswidth;
- op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto);
+ spi_nor_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;
while (remaining) {
op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX;
@@ -258,14 +330,11 @@ static ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
SPI_MEM_OP_DATA_OUT(len, buf, 1));
int ret;
- /* get transfer protocols. */
- op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto);
- op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto);
- op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto);
-
if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second)
op.addr.nbytes = 0;
+ spi_nor_setup_op(nor, &op, nor->write_proto);
+
ret = spi_mem_adjust_op_size(nor->spi, &op);
if (ret)
return ret;
@@ -668,6 +737,8 @@ static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr)
SPI_MEM_OP_NO_DUMMY,
SPI_MEM_OP_NO_DATA);
+ spi_nor_setup_op(nor, &op, nor->write_proto);
+
if (nor->erase)
return nor->erase(nor, addr);
@@ -2187,11 +2258,25 @@ static int spi_nor_init_params(struct spi_nor *nor,
SNOR_PROTO_1_1_8);
}
+ if (info->flags & SPI_NOR_OCTAL_DTR_READ) {
+ 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, SPINOR_OP_READ_FAST,
+ SNOR_PROTO_8_8_8_DTR);
+ }
+
/* Page Program settings. */
params->hwcaps.mask |= SNOR_HWCAPS_PP;
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);
+
if (info->flags & SPI_NOR_QUAD_READ) {
params->hwcaps.mask |= SNOR_HWCAPS_PP_1_1_4;
spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP_1_1_4],
@@ -2225,7 +2310,8 @@ static int spi_nor_init_params(struct spi_nor *nor,
/* Override the parameters with data read from SFDP tables. */
nor->addr_width = 0;
nor->mtd.erasesize = 0;
- if ((info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) &&
+ if ((info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_OCTAL_DTR_READ)) &&
!(info->flags & SPI_NOR_SKIP_SFDP)) {
struct spi_nor_flash_parameter sfdp_params;
@@ -2272,6 +2358,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,
@@ -2288,6 +2375,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,
@@ -2396,12 +2484,16 @@ spi_nor_adjust_hwcaps(struct spi_nor *nor,
*/
*hwcaps = SNOR_HWCAPS_ALL;
- /* 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;
+ /*
+ * If the reset line is broken, we do not want to enter a stateful
+ * mode.
+ */
+ if (nor->flags & SNOR_F_BROKEN_RESET)
+ *hwcaps &= ~(SNOR_HWCAPS_X_X_X | SNOR_HWCAPS_X_X_X_DTR);
+
for (cap = 0; cap < sizeof(*hwcaps) * BITS_PER_BYTE; cap++) {
int rdidx, ppidx;
@@ -2640,6 +2732,7 @@ static int spi_nor_init(struct spi_nor *nor)
}
if (nor->addr_width == 4 &&
+ !(nor->info->flags & SPI_NOR_OCTAL_DTR_READ) &&
(JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) &&
!(nor->info->flags & SPI_NOR_4B_OPCODES)) {
/*
@@ -2759,6 +2852,9 @@ int spi_nor_scan(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 (info->addr_width) {
nor->addr_width = info->addr_width;
} else if (mtd->size > SZ_16M) {
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index cca7919fdd..d511b093c0 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -200,6 +200,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)
@@ -267,7 +268,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)
@@ -284,11 +285,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_HWCPAS_READ_OCTO GENMASK(14, 11)
+#define SNOR_HWCPAS_READ_OCTO 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.
@@ -299,18 +301,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_OCTO GENMASK(22, 20)
-#define SNOR_HWCAPS_PP_1_1_8 BIT(20)
-#define SNOR_HWCAPS_PP_1_8_8 BIT(21)
-#define SNOR_HWCAPS_PP_8_8_8 BIT(22)
+#define SNOR_HWCAPS_PP_OCTO GENMASK(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 | \
@@ -318,6 +321,9 @@ struct spi_nor_hwcaps {
SNOR_HWCAPS_PP_4_4_4 | \
SNOR_HWCAPS_PP_8_8_8)
+#define SNOR_HWCAPS_X_X_X_DTR (SNOR_HWCAPS_READ_8_8_8_DTR | \
+ SNOR_HWCAPS_PP_8_8_8_DTR)
+
#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 | \
@@ -360,6 +366,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
};
@@ -376,6 +383,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
};
@@ -391,6 +399,22 @@ struct spi_nor_flash_parameter {
int (*quad_enable)(struct spi_nor *nor);
};
+/**
+ * enum spi_nor_cmd_ext - describes the command opcode extension in DTR mode
+ * @SPI_MEM_NOR_NONE: no extension. This is the default, and is used in Legacy
+ * SPI mode
+ * @SPI_MEM_NOR_REPEAT: the extension is same as the opcode
+ * @SPI_MEM_NOR_INVERT: the extension is the bitwise inverse of the opcode
+ * @SPI_MEM_NOR_HEX: the extension is any hex value. The command and opcode
+ * combine to form a 16-bit opcode.
+ */
+enum spi_nor_cmd_ext {
+ SPI_NOR_EXT_NONE = 0,
+ SPI_NOR_EXT_REPEAT,
+ SPI_NOR_EXT_INVERT,
+ SPI_NOR_EXT_HEX,
+};
+
/**
* struct flash_info - Forward declaration of a structure used internally by
* spi_nor_scan()
@@ -428,6 +452,7 @@ struct flash_info;
* @write_proto: the SPI protocol for write operations
* @reg_proto the SPI protocol for read_reg/write_reg/erase operations
* @cmd_buf: used by the write_reg
+ * @cmd_ext_type: the command opcode extension for DTR mode.
* @fixups: flash-specific fixup hooks.
* @prepare: [OPTIONAL] do some preparations for the
* read/write/erase/lock/unlock operations
@@ -470,6 +495,7 @@ struct spi_nor {
bool sst_write_second;
u32 flags;
u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE];
+ enum spi_nor_cmd_ext cmd_ext_type;
struct spi_nor_fixups *fixups;
int (*setup)(struct spi_nor *nor, const struct flash_info *info,
From patchwork Thu Jun 4 12:44:28 2020
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Pratyush Yadav
X-Patchwork-Id: 1303510
X-Patchwork-Delegate: jagannadh.teki@gmail.com
Return-Path:
X-Original-To: incoming@patchwork.ozlabs.org
Delivered-To: patchwork-incoming@bilbo.ozlabs.org
Authentication-Results: ozlabs.org;
spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de
(client-ip=85.214.62.61; helo=phobos.denx.de;
envelope-from=u-boot-bounces@lists.denx.de; receiver=)
Authentication-Results: ozlabs.org;
dmarc=pass (p=quarantine dis=none) header.from=ti.com
Authentication-Results: ozlabs.org;
dkim=pass (1024-bit key;
unprotected) header.d=ti.com header.i=@ti.com header.a=rsa-sha256
header.s=ti-com-17Q1 header.b=ssQT8xxT;
dkim-atps=neutral
Received: from phobos.denx.de (phobos.denx.de [85.214.62.61])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (4096 bits))
(No client certificate requested)
by ozlabs.org (Postfix) with ESMTPS id 49d5D44KRHz9sSg
for