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 1/2] spi: Add multiple CS support for a single SPI device
Date: Mon, 6 Jun 2022 16:56:06 +0530	[thread overview]
Message-ID: <20220606112607.20800-2-amit.kumar-mahapatra@xilinx.com> (raw)
In-Reply-To: <20220606112607.20800-1-amit.kumar-mahapatra@xilinx.com>

For supporting multiple CS the SPI device need to be aware of all the CS
values. So the "chip_select" member in the spi_device structure is now an
array that holds all the CS values.

spi_device structure now has a "cs_index_mask" member. This acts as an
index to the chip_select array. If nth bit of spi->cs_index_mask is set then
the driver would assert spi->chip_slect[n].

When flashes are connected in stacked mode SPI-NOR will enable the required
chip select by setting the appropriate bit in spi->cs_index_mask.

In parallel connection both the flashes need to be asserted simultaneously,
this can be achieved by enabling 0th(CS0) & 1st(CS1) bit in spi->cs_index_mask.

Signed-off-by: Amit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>
---
 drivers/spi/spi-zynqmp-gqspi.c | 30 ++++++++++++++++++++++++++----
 drivers/spi/spi.c              | 10 +++++++---
 include/linux/spi/spi.h        | 10 +++++++++-
 3 files changed, 42 insertions(+), 8 deletions(-)

diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
index c760aac070e5..2535a8bca4da 100644
--- a/drivers/spi/spi-zynqmp-gqspi.c
+++ b/drivers/spi/spi-zynqmp-gqspi.c
@@ -136,6 +136,11 @@
 
 #define GQSPI_MAX_NUM_CS	2	/* Maximum number of chip selects */
 
+#define GQSPI_SELECT_LOWER_CS	BIT(0)
+#define GQSPI_SELECT_UPPER_CS	BIT(1)
+#define GQSPI_SELECT_BOTH_CS	(GQSPI_SELECT_LOWER_CS | \
+				 GQSPI_SELECT_UPPER_CS)
+				 
 #define SPI_AUTOSUSPEND_TIMEOUT		3000
 enum mode_type {GQSPI_MODE_IO, GQSPI_MODE_DMA};
 
@@ -361,16 +366,33 @@ static void zynqmp_qspi_chipselect(struct spi_device *qspi, bool is_high)
 	struct zynqmp_qspi *xqspi = spi_master_get_devdata(qspi->master);
 	ulong timeout;
 	u32 genfifoentry = 0, statusreg;
+	u8 cs_index_mask = qspi->cs_index_mask;
 
 	genfifoentry |= GQSPI_GENFIFO_MODE_SPI;
 
 	if (!is_high) {
-		if (!qspi->chip_select) {
-			xqspi->genfifobus = GQSPI_GENFIFO_BUS_LOWER;
-			xqspi->genfifocs = GQSPI_GENFIFO_CS_LOWER;
-		} else {
+		/*
+		 * GQSPI controller only supports two chip selects,
+		 * CS0 and CS1
+		 */
+		if (cs_index_mask & GQSPI_SELECT_BOTH_CS) {
+
+			xqspi->genfifobus = GQSPI_GENFIFO_BUS_LOWER |
+				GQSPI_GENFIFO_BUS_UPPER;
+			xqspi->genfifocs = GQSPI_GENFIFO_CS_LOWER |
+				GQSPI_GENFIFO_CS_UPPER;
+
+		} else if ((cs_index_mask & GQSPI_SELECT_UPPER_CS) &&
+			   (qspi->chip_select[GQSPI_SELECT_UPPER_CS - 1])) {
+
 			xqspi->genfifobus = GQSPI_GENFIFO_BUS_UPPER;
 			xqspi->genfifocs = GQSPI_GENFIFO_CS_UPPER;
+
+		} else if ((cs_index_mask & GQSPI_SELECT_LOWER_CS) &&
+			   (!qspi->chip_select[GQSPI_SELECT_LOWER_CS - 1])) {
+
+			xqspi->genfifobus = GQSPI_GENFIFO_BUS_LOWER;
+			xqspi->genfifocs = GQSPI_GENFIFO_CS_LOWER;
 		}
 		genfifoentry |= xqspi->genfifobus;
 		genfifoentry |= xqspi->genfifocs;
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 2e6d6bbeb784..d3077874e6e8 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2082,6 +2082,8 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
 {
 	u32 value;
 	int rc;
+	u32 cs[SPI_CS_CNT_MAX];
+	u8 idx;
 
 	/* Mode (clock phase/polarity/etc.) */
 	if (of_property_read_bool(nc, "spi-cpha"))
@@ -2154,13 +2156,15 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
 	}
 
 	/* Device address */
-	rc = of_property_read_u32(nc, "reg", &value);
-	if (rc) {
+	rc = of_property_read_variable_u32_array(nc, "reg", &cs[0],
+						 1, SPI_CS_CNT_MAX);
+	if (rc < 0) {
 		dev_err(&ctlr->dev, "%pOF has no valid 'reg' property (%d)\n",
 			nc, rc);
 		return rc;
 	}
-	spi->chip_select = value;
+	for(idx = 0; idx < rc; idx++)
+		spi->chip_select[idx] = cs[idx];
 
 	/* Device speed */
 	if (!of_property_read_u32(nc, "spi-max-frequency", &value))
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 5f8c063ddff4..e930d987f3c2 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -18,6 +18,9 @@
 #include <uapi/linux/spi/spi.h>
 #include <linux/acpi.h>
 
+/* Max no. of CS supported per spi device */
+#define SPI_CS_CNT_MAX	2
+
 struct dma_chan;
 struct software_node;
 struct ptp_system_timestamp;
@@ -148,6 +151,7 @@ extern int spi_delay_exec(struct spi_delay *_delay, struct spi_transfer *xfer);
  *	deasserted. If @cs_change_delay is used from @spi_transfer, then the
  *	two delays will be added up.
  * @statistics: statistics for the spi_device
+ * @cs_index_mask: Bit mask of the active chipselect(s) in the chipselect array
  *
  * A @spi_device is used to interchange data between an SPI slave
  * (usually a discrete chip) and CPU memory.
@@ -163,7 +167,7 @@ struct spi_device {
 	struct spi_controller	*controller;
 	struct spi_controller	*master;	/* compatibility layer */
 	u32			max_speed_hz;
-	u8			chip_select;
+	u8			chip_select[SPI_CS_CNT_MAX];
 	u8			bits_per_word;
 	bool			rt;
 #define SPI_NO_TX	BIT(31)		/* no transmit wire */
@@ -194,6 +198,10 @@ struct spi_device {
 	/* the statistics */
 	struct spi_statistics	statistics;
 
+	/* Bit mask of the chipselect(s) that the driver
+	 * need to use form the chipselect array.
+	 */
+	u8			cs_index_mask : 2;
 	/*
 	 * likely need more hooks for more protocol options affecting how
 	 * the controller talks to each chip, like:
-- 
2.17.1


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

  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 ` Amit Kumar Mahapatra [this message]
2022-06-09 11:54   ` [RFC PATCH 1/2] spi: Add multiple CS support for a single SPI device 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 ` [RFC PATCH 2/2] mtd: spi-nor: Add support for stacked/parallel memories Amit Kumar Mahapatra

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-2-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).