linux-mtd.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: Amit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>
To: <broonie@kernel.org>, <p.yadav@ti.com>,
	<miquel.raynal@bootlin.com>, <richard@nod.at>, <vigneshr@ti.com>
Cc: <git@xilinx.com>, <michal.simek@xilinx.com>,
	<linux-spi@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>,
	<linux-kernel@vger.kernel.org>, <michael@walle.cc>,
	<linux-mtd@lists.infradead.org>,
	Amit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>
Subject: [RFC PATCH 2/2] mtd: spi-nor: Add support for stacked/parallel memories
Date: Mon, 6 Jun 2022 16:56:07 +0530	[thread overview]
Message-ID: <20220606112607.20800-3-amit.kumar-mahapatra@xilinx.com> (raw)
In-Reply-To: <20220606112607.20800-1-amit.kumar-mahapatra@xilinx.com>

While initializing the flash parameter structure, size of each flash is
updated with the values coming from "stacked-memories" and
"parallel-memories" DT properties.

Two new nor->flags (SNOR_F_HAS_STACKED and SNOR_F_HAS_PARALLEL) are added
to distinguish between the stacked and parallel configuration.

In parallel configuration all the operations need to be performed on both
the flashes simultaneously, So during each operation SPI-NOR needs to set
0th bit(CS0) & 1st bit(CS1) in nor->spimem->spi->cs_index_mask. The GQSPI
driver will then assert CS0 & CS1.

In stacked configuration the SPI-NOR, with individual flash size information,
will determining the flash on which the operation need to be performed and
it will set the appropriate CS bit in nor->spimem->spi->cs_index_mask.

Signed-off-by: Amit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>
---
 drivers/mtd/spi-nor/core.c  | 104 +++++++++++++++++++++++++++++++-----
 drivers/mtd/spi-nor/core.h  |   5 ++
 include/linux/mtd/spi-nor.h |   8 ++-
 3 files changed, 104 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 502967c76c5f..5d9bbb28659a 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2463,6 +2463,9 @@ static void spi_nor_init_fixup_flags(struct spi_nor *nor)
  */
 static void spi_nor_late_init_params(struct spi_nor *nor)
 {
+	struct device_node *np = spi_nor_get_flash_node(nor);
+	u64 flash_size[SNOR_FLASH_CNT_MAX];
+
 	if (nor->manufacturer && nor->manufacturer->fixups &&
 	    nor->manufacturer->fixups->late_init)
 		nor->manufacturer->fixups->late_init(nor);
@@ -2479,6 +2482,27 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
 	 */
 	if (nor->flags & SNOR_F_HAS_LOCK && !nor->params->locking_ops)
 		spi_nor_init_default_locking_ops(nor);
+
+	/*
+	 * The flashes that are connected in stacked mode should be of same make.
+	 * Except the flash size all other properties are identical for all the
+	 * flashes connected in stacked mode.
+	 * The flashes that are connected in parallel mode should be identical.
+	 */
+	if (!of_property_read_u64_array(np, "stacked-memories", &flash_size[0], SNOR_FLASH_CNT_MAX)) {
+		nor->flags |= SNOR_F_HAS_STACKED;
+	} else if (!of_property_read_u64_array(np, "parallel-memories", &flash_size[0], SNOR_FLASH_CNT_MAX)){
+		nor->flags |= SNOR_F_HAS_PARALLEL;
+	}
+
+	if (nor->flags & (SNOR_F_HAS_STACKED | SNOR_F_HAS_PARALLEL)) {
+		nor->params[1] = devm_kzalloc(nor->dev, sizeof(*nor->params[0]), GFP_KERNEL);
+		if (!nor->params[1])
+			return -ENOMEM;
+		memcpy(nor->params[1], nor->params[0], sizeof(*nor->params[0]));
+		nor->params[1]->size = flash_size[1];
+	}
+	return 0;
 }
 
 /**
@@ -2614,8 +2638,8 @@ static int spi_nor_init_params(struct spi_nor *nor)
 {
 	int ret;
 
-	nor->params = devm_kzalloc(nor->dev, sizeof(*nor->params), GFP_KERNEL);
-	if (!nor->params)
+	nor->params[0] = devm_kzalloc(nor->dev, sizeof(*nor->params[0]), GFP_KERNEL);
+	if (!nor->params[0])
 		return -ENOMEM;
 
 	spi_nor_init_default_params(nor);
@@ -2677,19 +2701,51 @@ static int spi_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
  */
 static int spi_nor_quad_enable(struct spi_nor *nor)
 {
-	if (!nor->params->quad_enable)
-		return 0;
+	u8 idx;
+	int err;
 
-	if (!(spi_nor_get_protocol_width(nor->read_proto) == 4 ||
-	      spi_nor_get_protocol_width(nor->write_proto) == 4))
-		return 0;
+	if (nor->flags & SNOR_F_HAS_PARALLEL) {
+		if (!nor->params[0]->quad_enable)
+			return 0;
 
-	return nor->params->quad_enable(nor);
+		if (!(spi_nor_get_protocol_width(nor->read_proto) == 4 ||
+		    spi_nor_get_protocol_width(nor->write_proto) == 4))
+			return 0;
+		/*
+		 * In parallel mode both chip selects i.e., CS0 &
+		 * CS1 need to be asserted simulatneously.
+		 */
+		 nor->spimem->spi->cs_index_mask = SPI_NOR_ENABLE_BOTH_CS;
+		err = nor->params[0]->quad_enable(nor);
+	} else {
+		for (idx = 0; idx < SNOR_FLASH_CNT_MAX; idx++) {
+			if (nor->params[idx] != NULL) {
+
+				if (!nor->params[idx]->quad_enable)
+					return 0;
+
+				if (!(spi_nor_get_protocol_width(nor->read_proto) == 4 ||
+				    spi_nor_get_protocol_width(nor->write_proto) == 4))
+					return 0;
+
+				/*
+				 * Set the appropriate CS index before
+				 * issuing the command.
+				 */
+				nor->spimem->spi->cs_index_mask = 0x01 << idx;
+				err = nor->params[idx]->quad_enable(nor);
+				if (err)
+					return err;
+			}
+		}
+	}
+	return err;
 }
 
 static int spi_nor_init(struct spi_nor *nor)
 {
 	int err;
+	int idx;
 
 	err = spi_nor_octal_dtr_enable(nor, true);
 	if (err) {
@@ -2730,7 +2786,25 @@ static int spi_nor_init(struct spi_nor *nor)
 		 */
 		WARN_ONCE(nor->flags & SNOR_F_BROKEN_RESET,
 			  "enabling reset hack; may not recover from unexpected reboots\n");
-		nor->params->set_4byte_addr_mode(nor, true);
+		if (nor->flags & SNOR_F_HAS_PARALLEL) {
+			/*
+			 * In parallel mode both chip selects i.e., CS0 &
+			 * CS1 need to be asserted simulatneously.
+			 */
+			nor->spimem->spi->cs_index_mask = SPI_NOR_ENABLE_BOTH_CS;
+			nor->params[0]->set_4byte_addr_mode(nor, true);
+		} else {
+			for (idx = 0; idx < SNOR_FLASH_CNT_MAX; idx++) {
+				if (nor->params[idx] != NULL) {
+					/*
+					 * Select the appropriate CS index before
+					 * issuing the command.
+					 */
+					nor->spimem->spi->cs_index_mask = 0x01 << idx;
+					nor->params[idx]->set_4byte_addr_mode(nor, true);
+				}
+			}
+		}
 	}
 
 	return 0;
@@ -2913,6 +2987,8 @@ static void spi_nor_set_mtd_info(struct spi_nor *nor)
 {
 	struct mtd_info *mtd = &nor->mtd;
 	struct device *dev = nor->dev;
+	u64 total_sz =0;
+	int idx;
 
 	spi_nor_set_mtd_locking_ops(nor);
 	spi_nor_set_mtd_otp_ops(nor);
@@ -2926,9 +3002,13 @@ static void spi_nor_set_mtd_info(struct spi_nor *nor)
 		mtd->flags |= MTD_NO_ERASE;
 	else
 		mtd->_erase = spi_nor_erase;
-	mtd->writesize = nor->params->writesize;
-	mtd->writebufsize = nor->params->page_size;
-	mtd->size = nor->params->size;
+	mtd->writesize = nor->params[0]->writesize;
+	mtd->writebufsize = nor->params[0]->page_size;
+	for (idx = 0; idx < SNOR_FLASH_CNT_MAX; idx++) {
+		if (nor->params[idx] != NULL)
+			total_sz += nor->params[idx]->size;
+	}
+	mtd->size = total_sz;
 	mtd->_read = spi_nor_read;
 	/* Might be already set by some SST flashes. */
 	if (!mtd->_write)
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 3f841ec36e56..4e8bf3cbe331 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -11,6 +11,9 @@
 
 #define SPI_NOR_MAX_ID_LEN	6
 
+/* In parallel configuration enable both CS */
+#define SPI_NOR_ENABLE_BOTH_CS	(BIT(0) | BIT(1))
+
 /* Standard SPI NOR flash operations. */
 #define SPI_NOR_READID_OP(naddr, ndummy, buf, len)			\
 	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 0),			\
@@ -130,6 +133,8 @@ enum spi_nor_option_flags {
 	SNOR_F_IO_MODE_EN_VOLATILE = BIT(11),
 	SNOR_F_SOFT_RESET	= BIT(12),
 	SNOR_F_SWP_IS_VOLATILE	= BIT(13),
+	SNOR_F_HAS_STACKED	= BIT(14),
+	SNOR_F_HAS_PARALLEL	= BIT(15),
 };
 
 struct spi_nor_read_command {
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 1ede4c89805a..40800e7235ee 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -128,6 +128,12 @@
 #define SR2_LB3			BIT(5)	/* Security Register Lock Bit 3 */
 #define SR2_QUAD_EN_BIT7	BIT(7)
 
+/*
+ * Maximum number of flashes that can be connected
+ * in stacked/parallel configuration
+ */
+#define	SNOR_FLASH_CNT_MAX	2
+
 /* Supported SPI protocols */
 #define SNOR_PROTO_INST_MASK	GENMASK(23, 16)
 #define SNOR_PROTO_INST_SHIFT	16
@@ -397,7 +403,7 @@ struct spi_nor {
 
 	const struct spi_nor_controller_ops *controller_ops;
 
-	struct spi_nor_flash_parameter *params;
+	struct spi_nor_flash_parameter *params[SNOR_FLASH_CNT_MAX];
 
 	struct {
 		struct spi_mem_dirmap_desc *rdesc;
-- 
2.17.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

      parent reply	other threads:[~2022-06-06 11:27 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-06 11:26 [RFC PATCH 0/2] spi: Add support for stacked/parallel memories Amit Kumar Mahapatra
2022-06-06 11:26 ` [RFC PATCH 1/2] spi: Add multiple CS support for a single SPI device Amit Kumar Mahapatra
2022-06-09 11:54   ` Mark Brown
2022-06-23 11:39     ` Mahapatra, Amit Kumar
2022-06-23 12:06       ` Mark Brown
2022-07-15 15:35         ` Mahapatra, Amit Kumar
2022-07-15 15:54           ` Mark Brown
2022-07-19 13:21             ` Mahapatra, Amit Kumar
2022-07-19 17:53               ` Mark Brown
2022-07-27 13:02                 ` Mahapatra, Amit Kumar
2022-07-11 12:47     ` Michal Simek
2022-07-11 14:52       ` Mark Brown
2022-07-15 15:36         ` Mahapatra, Amit Kumar
2022-07-15 16:03           ` Mark Brown
2022-06-06 11:26 ` Amit Kumar Mahapatra [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220606112607.20800-3-amit.kumar-mahapatra@xilinx.com \
    --to=amit.kumar-mahapatra@xilinx.com \
    --cc=broonie@kernel.org \
    --cc=git@xilinx.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=linux-spi@vger.kernel.org \
    --cc=michael@walle.cc \
    --cc=michal.simek@xilinx.com \
    --cc=miquel.raynal@bootlin.com \
    --cc=p.yadav@ti.com \
    --cc=richard@nod.at \
    --cc=vigneshr@ti.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).