linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RESEND v2 PATCH 0/3] spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework
@ 2020-09-24  7:11 Michal Simek
  2020-09-24  7:11 ` [RESEND v2 PATCH 1/3] spi: spi-zynqmp-gqspi: Fix kernel-doc warnings Michal Simek
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Michal Simek @ 2020-09-24  7:11 UTC (permalink / raw)
  To: broonie
  Cc: amit.kumar-mahapatra, linux-kernel, monstr, michal.simek, git,
	linux-spi, linux-arm-kernel

Hi,

I am resending this series instead of Amit because his patches are broken
in lore. Mark has reported the issue with it and I clearly see that patch
is broken in lore.
For example:
https://lore.kernel.org/linux-spi/20200922164016.30979-2-amit.kumar-mahapatra@xilinx.com/raw

There is additional = which shouldn't be there.
@@ -183,7 +184,7 @@ static u32 zynqmp_gqspi_read(struct zynqmp_qspi *xqspi,=
u32 offset)

We will investigate why this is happening but it is related to any his
setting.

Thanks,
Michal

This patch series:
 - Fixes kernel-doc warnings in ZynqMP qspi controller driver file.
 - Updates the ZynqMP qspi controller driver to use spi-mem framework.
 - Fixes incorrect indentation in ZynqMP qspi controller driver file.

Tested: flashcp and mtd_utils
Branch: for-5.10
HEAD commit: bf253e6bf6b8 (spi/for-5.10) spi: spi-imx: spi_imx_transfer(): add support for effective_speed_hz


Amit Kumar Mahapatra (3):
  spi: spi-zynqmp-gqspi: Fix kernel-doc warnings
  spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework
  spi: spi-zynqmp-gqspi: Fix incorrect indentation

 drivers/spi/spi-zynqmp-gqspi.c | 720 +++++++++++++++++++--------------
 1 file changed, 407 insertions(+), 313 deletions(-)

-- 
2.28.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [RESEND v2 PATCH 1/3] spi: spi-zynqmp-gqspi: Fix kernel-doc warnings
  2020-09-24  7:11 [RESEND v2 PATCH 0/3] spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework Michal Simek
@ 2020-09-24  7:11 ` Michal Simek
  2020-09-24  7:11 ` [RESEND v2 PATCH 2/3] spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework Michal Simek
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Michal Simek @ 2020-09-24  7:11 UTC (permalink / raw)
  To: broonie
  Cc: amit.kumar-mahapatra, linux-kernel, monstr, michal.simek, git,
	linux-spi, linux-arm-kernel

From: Amit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>

Fix kernel-doc warnings in ZynqMP qspi driver file.

Signed-off-by: Amit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
---

 drivers/spi/spi-zynqmp-gqspi.c | 45 +++++++++++++++++-----------------
 1 file changed, 23 insertions(+), 22 deletions(-)

diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
index e17a20125255..b479b9c3d1e6 100644
--- a/drivers/spi/spi-zynqmp-gqspi.c
+++ b/drivers/spi/spi-zynqmp-gqspi.c
@@ -173,9 +173,10 @@ struct zynqmp_qspi {
 };
 
 /**
- * zynqmp_gqspi_read:	For GQSPI controller read operation
+ * zynqmp_gqspi_read - For GQSPI controller read operation
  * @xqspi:	Pointer to the zynqmp_qspi structure
  * @offset:	Offset from where to read
+ * Return:      Value at the offset
  */
 static u32 zynqmp_gqspi_read(struct zynqmp_qspi *xqspi, u32 offset)
 {
@@ -183,7 +184,7 @@ static u32 zynqmp_gqspi_read(struct zynqmp_qspi *xqspi, u32 offset)
 }
 
 /**
- * zynqmp_gqspi_write:	For GQSPI controller write operation
+ * zynqmp_gqspi_write - For GQSPI controller write operation
  * @xqspi:	Pointer to the zynqmp_qspi structure
  * @offset:	Offset where to write
  * @val:	Value to be written
@@ -195,7 +196,7 @@ static inline void zynqmp_gqspi_write(struct zynqmp_qspi *xqspi, u32 offset,
 }
 
 /**
- * zynqmp_gqspi_selectslave:	For selection of slave device
+ * zynqmp_gqspi_selectslave - For selection of slave device
  * @instanceptr:	Pointer to the zynqmp_qspi structure
  * @slavecs:	For chip select
  * @slavebus:	To check which bus is selected- upper or lower
@@ -242,7 +243,7 @@ static void zynqmp_gqspi_selectslave(struct zynqmp_qspi *instanceptr,
 }
 
 /**
- * zynqmp_qspi_init_hw:	Initialize the hardware
+ * zynqmp_qspi_init_hw - Initialize the hardware
  * @xqspi:	Pointer to the zynqmp_qspi structure
  *
  * The default settings of the QSPI controller's configurable parameters on
@@ -330,7 +331,7 @@ static void zynqmp_qspi_init_hw(struct zynqmp_qspi *xqspi)
 }
 
 /**
- * zynqmp_qspi_copy_read_data:	Copy data to RX buffer
+ * zynqmp_qspi_copy_read_data - Copy data to RX buffer
  * @xqspi:	Pointer to the zynqmp_qspi structure
  * @data:	The variable where data is stored
  * @size:	Number of bytes to be copied from data to RX buffer
@@ -344,7 +345,7 @@ static void zynqmp_qspi_copy_read_data(struct zynqmp_qspi *xqspi,
 }
 
 /**
- * zynqmp_prepare_transfer_hardware:	Prepares hardware for transfer.
+ * zynqmp_prepare_transfer_hardware - Prepares hardware for transfer.
  * @master:	Pointer to the spi_master structure which provides
  *		information about the controller.
  *
@@ -361,7 +362,7 @@ static int zynqmp_prepare_transfer_hardware(struct spi_master *master)
 }
 
 /**
- * zynqmp_unprepare_transfer_hardware:	Relaxes hardware after transfer
+ * zynqmp_unprepare_transfer_hardware - Relaxes hardware after transfer
  * @master:	Pointer to the spi_master structure which provides
  *		information about the controller.
  *
@@ -378,7 +379,7 @@ static int zynqmp_unprepare_transfer_hardware(struct spi_master *master)
 }
 
 /**
- * zynqmp_qspi_chipselect:	Select or deselect the chip select line
+ * zynqmp_qspi_chipselect - Select or deselect the chip select line
  * @qspi:	Pointer to the spi_device structure
  * @is_high:	Select(0) or deselect (1) the chip select line
  */
@@ -423,7 +424,7 @@ static void zynqmp_qspi_chipselect(struct spi_device *qspi, bool is_high)
 }
 
 /**
- * zynqmp_qspi_setup_transfer:	Configure QSPI controller for specified
+ * zynqmp_qspi_setup_transfer - Configure QSPI controller for specified
  *				transfer
  * @qspi:	Pointer to the spi_device structure
  * @transfer:	Pointer to the spi_transfer structure which provides
@@ -482,7 +483,7 @@ static int zynqmp_qspi_setup_transfer(struct spi_device *qspi,
 }
 
 /**
- * zynqmp_qspi_setup:	Configure the QSPI controller
+ * zynqmp_qspi_setup - Configure the QSPI controller
  * @qspi:	Pointer to the spi_device structure
  *
  * Sets the operational mode of QSPI controller for the next QSPI transfer,
@@ -498,7 +499,7 @@ static int zynqmp_qspi_setup(struct spi_device *qspi)
 }
 
 /**
- * zynqmp_qspi_filltxfifo:	Fills the TX FIFO as long as there is room in
+ * zynqmp_qspi_filltxfifo - Fills the TX FIFO as long as there is room in
  *				the FIFO or the bytes required to be
  *				transmitted.
  * @xqspi:	Pointer to the zynqmp_qspi structure
@@ -524,7 +525,7 @@ static void zynqmp_qspi_filltxfifo(struct zynqmp_qspi *xqspi, int size)
 }
 
 /**
- * zynqmp_qspi_readrxfifo:	Fills the RX FIFO as long as there is room in
+ * zynqmp_qspi_readrxfifo - Fills the RX FIFO as long as there is room in
  *				the FIFO.
  * @xqspi:	Pointer to the zynqmp_qspi structure
  * @size:	Number of bytes to be copied from RX buffer to RX FIFO
@@ -552,7 +553,7 @@ static void zynqmp_qspi_readrxfifo(struct zynqmp_qspi *xqspi, u32 size)
 }
 
 /**
- * zynqmp_process_dma_irq:	Handler for DMA done interrupt of QSPI
+ * zynqmp_process_dma_irq - Handler for DMA done interrupt of QSPI
  *				controller
  * @xqspi:	zynqmp_qspi instance pointer
  *
@@ -600,7 +601,7 @@ static void zynqmp_process_dma_irq(struct zynqmp_qspi *xqspi)
 }
 
 /**
- * zynqmp_qspi_irq:	Interrupt service routine of the QSPI controller
+ * zynqmp_qspi_irq - Interrupt service routine of the QSPI controller
  * @irq:	IRQ number
  * @dev_id:	Pointer to the xqspi structure
  *
@@ -654,7 +655,7 @@ static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id)
 }
 
 /**
- * zynqmp_qspi_selectspimode:	Selects SPI mode - x1 or x2 or x4.
+ * zynqmp_qspi_selectspimode - Selects SPI mode - x1 or x2 or x4.
  * @xqspi:	xqspi is a pointer to the GQSPI instance
  * @spimode:	spimode - SPI or DUAL or QUAD.
  * Return:	Mask to set desired SPI mode in GENFIFO entry.
@@ -682,7 +683,7 @@ static inline u32 zynqmp_qspi_selectspimode(struct zynqmp_qspi *xqspi,
 }
 
 /**
- * zynq_qspi_setuprxdma:	This function sets up the RX DMA operation
+ * zynq_qspi_setuprxdma - This function sets up the RX DMA operation
  * @xqspi:	xqspi is a pointer to the GQSPI instance.
  */
 static void zynq_qspi_setuprxdma(struct zynqmp_qspi *xqspi)
@@ -732,7 +733,7 @@ static void zynq_qspi_setuprxdma(struct zynqmp_qspi *xqspi)
 }
 
 /**
- * zynqmp_qspi_txrxsetup:	This function checks the TX/RX buffers in
+ * zynqmp_qspi_txrxsetup - This function checks the TX/RX buffers in
  *				the transfer and sets up the GENFIFO entries,
  *				TX FIFO as required.
  * @xqspi:	xqspi is a pointer to the GQSPI instance.
@@ -783,7 +784,7 @@ static void zynqmp_qspi_txrxsetup(struct zynqmp_qspi *xqspi,
 }
 
 /**
- * zynqmp_qspi_start_transfer:	Initiates the QSPI transfer
+ * zynqmp_qspi_start_transfer - Initiates the QSPI transfer
  * @master:	Pointer to the spi_master structure which provides
  *		information about the controller.
  * @qspi:	Pointer to the spi_device structure
@@ -891,7 +892,7 @@ static int zynqmp_qspi_start_transfer(struct spi_master *master,
 }
 
 /**
- * zynqmp_qspi_suspend:	Suspend method for the QSPI driver
+ * zynqmp_qspi_suspend - Suspend method for the QSPI driver
  * @dev:	Address of the platform_device structure
  *
  * This function stops the QSPI driver queue and disables the QSPI controller
@@ -910,7 +911,7 @@ static int __maybe_unused zynqmp_qspi_suspend(struct device *dev)
 }
 
 /**
- * zynqmp_qspi_resume:	Resume method for the QSPI driver
+ * zynqmp_qspi_resume - Resume method for the QSPI driver
  * @dev:	Address of the platform_device structure
  *
  * The function starts the QSPI driver queue and initializes the QSPI
@@ -1000,7 +1001,7 @@ static const struct dev_pm_ops zynqmp_qspi_dev_pm_ops = {
 };
 
 /**
- * zynqmp_qspi_probe:	Probe method for the QSPI driver
+ * zynqmp_qspi_probe - Probe method for the QSPI driver
  * @pdev:	Pointer to the platform_device structure
  *
  * This function initializes the driver data structures and the hardware.
@@ -1112,7 +1113,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
 }
 
 /**
- * zynqmp_qspi_remove:	Remove method for the QSPI driver
+ * zynqmp_qspi_remove - Remove method for the QSPI driver
  * @pdev:	Pointer to the platform_device structure
  *
  * This function is called if a device is physically removed from the system or
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [RESEND v2 PATCH 2/3] spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework
  2020-09-24  7:11 [RESEND v2 PATCH 0/3] spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework Michal Simek
  2020-09-24  7:11 ` [RESEND v2 PATCH 1/3] spi: spi-zynqmp-gqspi: Fix kernel-doc warnings Michal Simek
@ 2020-09-24  7:11 ` Michal Simek
  2020-09-24  7:11 ` [RESEND v2 PATCH 3/3] spi: spi-zynqmp-gqspi: Fix incorrect indentation Michal Simek
  2020-09-24 12:00 ` [RESEND v2 PATCH 0/3] spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework Mark Brown
  3 siblings, 0 replies; 5+ messages in thread
From: Michal Simek @ 2020-09-24  7:11 UTC (permalink / raw)
  To: broonie
  Cc: amit.kumar-mahapatra, linux-kernel, monstr, michal.simek, git,
	linux-spi, linux-arm-kernel

From: Amit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>

Updated Zynqmp qspi controller driver to use spi-mem framework.

Signed-off-by: Amit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
---

 drivers/spi/spi-zynqmp-gqspi.c | 645 +++++++++++++++++++--------------
 1 file changed, 369 insertions(+), 276 deletions(-)

diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
index b479b9c3d1e6..7f57923f76ea 100644
--- a/drivers/spi/spi-zynqmp-gqspi.c
+++ b/drivers/spi/spi-zynqmp-gqspi.c
@@ -21,6 +21,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
+#include <linux/spi/spi-mem.h>
 
 /* Generic QSPI register offsets */
 #define GQSPI_CONFIG_OFST		0x00000100
@@ -153,6 +154,7 @@ enum mode_type {GQSPI_MODE_IO, GQSPI_MODE_DMA};
  * @dma_addr:		DMA address after mapping the kernel buffer
  * @genfifoentry:	Used for storing the genfifoentry instruction.
  * @mode:		Defines the mode in which QSPI is operating
+ * @data_completion:	completion structure
  */
 struct zynqmp_qspi {
 	void __iomem *regs;
@@ -170,6 +172,7 @@ struct zynqmp_qspi {
 	dma_addr_t dma_addr;
 	u32 genfifoentry;
 	enum mode_type mode;
+	struct completion data_completion;
 };
 
 /**
@@ -344,40 +347,6 @@ static void zynqmp_qspi_copy_read_data(struct zynqmp_qspi *xqspi,
 	xqspi->bytes_to_receive -= size;
 }
 
-/**
- * zynqmp_prepare_transfer_hardware - Prepares hardware for transfer.
- * @master:	Pointer to the spi_master structure which provides
- *		information about the controller.
- *
- * This function enables SPI master controller.
- *
- * Return:	0 on success; error value otherwise
- */
-static int zynqmp_prepare_transfer_hardware(struct spi_master *master)
-{
-	struct zynqmp_qspi *xqspi = spi_master_get_devdata(master);
-
-	zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, GQSPI_EN_MASK);
-	return 0;
-}
-
-/**
- * zynqmp_unprepare_transfer_hardware - Relaxes hardware after transfer
- * @master:	Pointer to the spi_master structure which provides
- *		information about the controller.
- *
- * This function disables the SPI master controller.
- *
- * Return:	Always 0
- */
-static int zynqmp_unprepare_transfer_hardware(struct spi_master *master)
-{
-	struct zynqmp_qspi *xqspi = spi_master_get_devdata(master);
-
-	zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, 0x0);
-	return 0;
-}
-
 /**
  * zynqmp_qspi_chipselect - Select or deselect the chip select line
  * @qspi:	Pointer to the spi_device structure
@@ -387,12 +356,14 @@ 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 = 0x0, statusreg;
+	u32 genfifoentry = 0, statusreg;
 
 	genfifoentry |= GQSPI_GENFIFO_MODE_SPI;
-	genfifoentry |= xqspi->genfifobus;
 
 	if (!is_high) {
+		xqspi->genfifobus = GQSPI_GENFIFO_BUS_LOWER;
+		xqspi->genfifocs = GQSPI_GENFIFO_CS_LOWER;
+		genfifoentry |= xqspi->genfifobus;
 		genfifoentry |= xqspi->genfifocs;
 		genfifoentry |= GQSPI_GENFIFO_CS_SETUP;
 	} else {
@@ -424,11 +395,38 @@ static void zynqmp_qspi_chipselect(struct spi_device *qspi, bool is_high)
 }
 
 /**
- * zynqmp_qspi_setup_transfer - Configure QSPI controller for specified
+ * zynqmp_qspi_selectspimode - Selects SPI mode - x1 or x2 or x4.
+ * @xqspi:	xqspi is a pointer to the GQSPI instance
+ * @spimode:	spimode - SPI or DUAL or QUAD.
+ * Return:	Mask to set desired SPI mode in GENFIFO entry.
+ */
+static inline u32 zynqmp_qspi_selectspimode(struct zynqmp_qspi *xqspi,
+					    u8 spimode)
+{
+	u32 mask = 0;
+
+	switch (spimode) {
+	case GQSPI_SELECT_MODE_DUALSPI:
+		mask = GQSPI_GENFIFO_MODE_DUALSPI;
+		break;
+	case GQSPI_SELECT_MODE_QUADSPI:
+		mask = GQSPI_GENFIFO_MODE_QUADSPI;
+		break;
+	case GQSPI_SELECT_MODE_SPI:
+		mask = GQSPI_GENFIFO_MODE_SPI;
+		break;
+	default:
+		dev_warn(xqspi->dev, "Invalid SPI mode\n");
+	}
+
+	return mask;
+}
+
+/**
+ * zynqmp_qspi_config_op - Configure QSPI controller for specified
  *				transfer
+ * @xqspi:	Pointer to the zynqmp_qspi structure
  * @qspi:	Pointer to the spi_device structure
- * @transfer:	Pointer to the spi_transfer structure which provides
- *		information about next transfer setup parameters
  *
  * Sets the operational mode of QSPI controller for the next QSPI transfer and
  * sets the requested clock frequency.
@@ -445,17 +443,11 @@ static void zynqmp_qspi_chipselect(struct spi_device *qspi, bool is_high)
  *	by the QSPI controller the driver will set the highest or lowest
  *	frequency supported by controller.
  */
-static int zynqmp_qspi_setup_transfer(struct spi_device *qspi,
-				      struct spi_transfer *transfer)
+static int zynqmp_qspi_config_op(struct zynqmp_qspi *xqspi,
+				 struct spi_device *qspi)
 {
-	struct zynqmp_qspi *xqspi = spi_master_get_devdata(qspi->master);
 	ulong clk_rate;
-	u32 config_reg, req_hz, baud_rate_val = 0;
-
-	if (transfer)
-		req_hz = transfer->speed_hz;
-	else
-		req_hz = qspi->max_speed_hz;
+	u32 config_reg, baud_rate_val = 0;
 
 	/* Set the clock frequency */
 	/* If req_hz == 0, default to lowest speed */
@@ -463,7 +455,7 @@ static int zynqmp_qspi_setup_transfer(struct spi_device *qspi,
 
 	while ((baud_rate_val < GQSPI_BAUD_DIV_MAX) &&
 	       (clk_rate /
-		(GQSPI_BAUD_DIV_SHIFT << baud_rate_val)) > req_hz)
+		(GQSPI_BAUD_DIV_SHIFT << baud_rate_val)) > qspi->max_speed_hz)
 		baud_rate_val++;
 
 	config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST);
@@ -483,7 +475,7 @@ static int zynqmp_qspi_setup_transfer(struct spi_device *qspi,
 }
 
 /**
- * zynqmp_qspi_setup - Configure the QSPI controller
+ * zynqmp_qspi_setup_op - Configure the QSPI controller
  * @qspi:	Pointer to the spi_device structure
  *
  * Sets the operational mode of QSPI controller for the next QSPI transfer,
@@ -491,10 +483,30 @@ static int zynqmp_qspi_setup_transfer(struct spi_device *qspi,
  *
  * Return:	0 on success; error value otherwise.
  */
-static int zynqmp_qspi_setup(struct spi_device *qspi)
+static int zynqmp_qspi_setup_op(struct spi_device *qspi)
 {
-	if (qspi->master->busy)
+	struct spi_controller *ctlr = qspi->master;
+	struct zynqmp_qspi *xqspi = spi_controller_get_devdata(ctlr);
+	struct device *dev = &ctlr->dev;
+	int ret;
+
+	if (ctlr->busy)
 		return -EBUSY;
+
+	ret = clk_enable(xqspi->refclk);
+	if (ret) {
+		dev_err(dev, "Cannot enable device clock.\n");
+		return ret;
+	}
+
+	ret = clk_enable(xqspi->pclk);
+	if (ret) {
+		dev_err(dev, "Cannot enable APB clock.\n");
+		clk_disable(xqspi->refclk);
+		return ret;
+	}
+	zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, GQSPI_EN_MASK);
+
 	return 0;
 }
 
@@ -552,6 +564,75 @@ static void zynqmp_qspi_readrxfifo(struct zynqmp_qspi *xqspi, u32 size)
 	}
 }
 
+/**
+ * zynqmp_qspi_fillgenfifo - Fills the GENFIFO.
+ * @xqspi:	Pointer to the zynqmp_qspi structure
+ * @nbits:	Transfer/Receive buswidth.
+ * @genfifoentry:       Variable in which GENFIFO mask is saved
+ */
+static void zynqmp_qspi_fillgenfifo(struct zynqmp_qspi *xqspi, u8 nbits,
+				    u32 genfifoentry)
+{
+	u32 transfer_len = 0;
+
+	if (xqspi->txbuf) {
+		genfifoentry &= ~GQSPI_GENFIFO_RX;
+		genfifoentry |= GQSPI_GENFIFO_DATA_XFER;
+		genfifoentry |= GQSPI_GENFIFO_TX;
+		transfer_len = xqspi->bytes_to_transfer;
+	} else {
+		genfifoentry &= ~GQSPI_GENFIFO_TX;
+		genfifoentry |= GQSPI_GENFIFO_DATA_XFER;
+		genfifoentry |= GQSPI_GENFIFO_RX;
+		if (xqspi->mode == GQSPI_MODE_DMA)
+			transfer_len = xqspi->dma_rx_bytes;
+		else
+			transfer_len = xqspi->bytes_to_receive;
+	}
+	genfifoentry |= zynqmp_qspi_selectspimode(xqspi, nbits);
+	xqspi->genfifoentry = genfifoentry;
+
+	if ((transfer_len) < GQSPI_GENFIFO_IMM_DATA_MASK) {
+		genfifoentry &= ~GQSPI_GENFIFO_IMM_DATA_MASK;
+		genfifoentry |= transfer_len;
+		zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, genfifoentry);
+	} else {
+		int tempcount = transfer_len;
+		u32 exponent = 8;	/* 2^8 = 256 */
+		u8 imm_data = tempcount & 0xFF;
+
+		tempcount &= ~(tempcount & 0xFF);
+		/* Immediate entry */
+		if (tempcount != 0) {
+			/* Exponent entries */
+			genfifoentry |= GQSPI_GENFIFO_EXP;
+			while (tempcount != 0) {
+				if (tempcount & GQSPI_GENFIFO_EXP_START) {
+					genfifoentry &=
+						~GQSPI_GENFIFO_IMM_DATA_MASK;
+					genfifoentry |= exponent;
+					zynqmp_gqspi_write(xqspi,
+							   GQSPI_GEN_FIFO_OFST,
+							   genfifoentry);
+				}
+				tempcount = tempcount >> 1;
+				exponent++;
+			}
+		}
+		if (imm_data != 0) {
+			genfifoentry &= ~GQSPI_GENFIFO_EXP;
+			genfifoentry &= ~GQSPI_GENFIFO_IMM_DATA_MASK;
+			genfifoentry |= (u8)(imm_data & 0xFF);
+			zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST,
+					   genfifoentry);
+		}
+	}
+	if (xqspi->mode == GQSPI_MODE_IO && xqspi->rxbuf) {
+		/* Dummy generic FIFO entry */
+		zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, 0x0);
+	}
+}
+
 /**
  * zynqmp_process_dma_irq - Handler for DMA done interrupt of QSPI
  *				controller
@@ -614,9 +695,8 @@ static void zynqmp_process_dma_irq(struct zynqmp_qspi *xqspi)
  */
 static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id)
 {
-	struct spi_master *master = dev_id;
-	struct zynqmp_qspi *xqspi = spi_master_get_devdata(master);
-	int ret = IRQ_NONE;
+	struct zynqmp_qspi *xqspi = (struct zynqmp_qspi *)dev_id;
+	irqreturn_t ret = IRQ_NONE;
 	u32 status, mask, dma_status = 0;
 
 	status = zynqmp_gqspi_read(xqspi, GQSPI_ISR_OFST);
@@ -648,45 +728,17 @@ static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id)
 	if ((xqspi->bytes_to_receive == 0) && (xqspi->bytes_to_transfer == 0)
 			&& ((status & GQSPI_IRQ_MASK) == GQSPI_IRQ_MASK)) {
 		zynqmp_gqspi_write(xqspi, GQSPI_IDR_OFST, GQSPI_ISR_IDR_MASK);
-		spi_finalize_current_transfer(master);
+		complete(&xqspi->data_completion);
 		ret = IRQ_HANDLED;
 	}
 	return ret;
 }
 
 /**
- * zynqmp_qspi_selectspimode - Selects SPI mode - x1 or x2 or x4.
- * @xqspi:	xqspi is a pointer to the GQSPI instance
- * @spimode:	spimode - SPI or DUAL or QUAD.
- * Return:	Mask to set desired SPI mode in GENFIFO entry.
- */
-static inline u32 zynqmp_qspi_selectspimode(struct zynqmp_qspi *xqspi,
-						u8 spimode)
-{
-	u32 mask = 0;
-
-	switch (spimode) {
-	case GQSPI_SELECT_MODE_DUALSPI:
-		mask = GQSPI_GENFIFO_MODE_DUALSPI;
-		break;
-	case GQSPI_SELECT_MODE_QUADSPI:
-		mask = GQSPI_GENFIFO_MODE_QUADSPI;
-		break;
-	case GQSPI_SELECT_MODE_SPI:
-		mask = GQSPI_GENFIFO_MODE_SPI;
-		break;
-	default:
-		dev_warn(xqspi->dev, "Invalid SPI mode\n");
-	}
-
-	return mask;
-}
-
-/**
- * zynq_qspi_setuprxdma - This function sets up the RX DMA operation
+ * zynqmp_qspi_setuprxdma - This function sets up the RX DMA operation
  * @xqspi:	xqspi is a pointer to the GQSPI instance.
  */
-static void zynq_qspi_setuprxdma(struct zynqmp_qspi *xqspi)
+static void zynqmp_qspi_setuprxdma(struct zynqmp_qspi *xqspi)
 {
 	u32 rx_bytes, rx_rem, config_reg;
 	dma_addr_t addr;
@@ -733,162 +785,44 @@ static void zynq_qspi_setuprxdma(struct zynqmp_qspi *xqspi)
 }
 
 /**
- * zynqmp_qspi_txrxsetup - This function checks the TX/RX buffers in
- *				the transfer and sets up the GENFIFO entries,
- *				TX FIFO as required.
- * @xqspi:	xqspi is a pointer to the GQSPI instance.
- * @transfer:	It is a pointer to the structure containing transfer data.
- * @genfifoentry:	genfifoentry is pointer to the variable in which
- *			GENFIFO	mask is returned to calling function
+ * zynqmp_qspi_write_op - This function sets up the GENFIFO entries,
+ *			TX FIFO, and fills the TX FIFO with as many
+ *			bytes as possible.
+ * @xqspi:	Pointer to the GQSPI instance.
+ * @tx_nbits:	Transfer buswidth.
+ * @genfifoentry:	Variable in which GENFIFO mask is returned
+ *			to calling function
  */
-static void zynqmp_qspi_txrxsetup(struct zynqmp_qspi *xqspi,
-				  struct spi_transfer *transfer,
-				  u32 *genfifoentry)
+static void zynqmp_qspi_write_op(struct zynqmp_qspi *xqspi, u8 tx_nbits,
+				 u32 genfifoentry)
 {
 	u32 config_reg;
 
-	/* Transmit */
-	if ((xqspi->txbuf != NULL) && (xqspi->rxbuf == NULL)) {
-		/* Setup data to be TXed */
-		*genfifoentry &= ~GQSPI_GENFIFO_RX;
-		*genfifoentry |= GQSPI_GENFIFO_DATA_XFER;
-		*genfifoentry |= GQSPI_GENFIFO_TX;
-		*genfifoentry |=
-			zynqmp_qspi_selectspimode(xqspi, transfer->tx_nbits);
-		xqspi->bytes_to_transfer = transfer->len;
-		if (xqspi->mode == GQSPI_MODE_DMA) {
-			config_reg = zynqmp_gqspi_read(xqspi,
-							GQSPI_CONFIG_OFST);
-			config_reg &= ~GQSPI_CFG_MODE_EN_MASK;
-			zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
-								config_reg);
-			xqspi->mode = GQSPI_MODE_IO;
-		}
-		zynqmp_qspi_filltxfifo(xqspi, GQSPI_TXD_DEPTH);
-		/* Discard RX data */
-		xqspi->bytes_to_receive = 0;
-	} else if ((xqspi->txbuf == NULL) && (xqspi->rxbuf != NULL)) {
-		/* Receive */
-
-		/* TX auto fill */
-		*genfifoentry &= ~GQSPI_GENFIFO_TX;
-		/* Setup RX */
-		*genfifoentry |= GQSPI_GENFIFO_DATA_XFER;
-		*genfifoentry |= GQSPI_GENFIFO_RX;
-		*genfifoentry |=
-			zynqmp_qspi_selectspimode(xqspi, transfer->rx_nbits);
-		xqspi->bytes_to_transfer = 0;
-		xqspi->bytes_to_receive = transfer->len;
-		zynq_qspi_setuprxdma(xqspi);
+	zynqmp_qspi_fillgenfifo(xqspi, tx_nbits, genfifoentry);
+	zynqmp_qspi_filltxfifo(xqspi, GQSPI_TXD_DEPTH);
+	if (xqspi->mode == GQSPI_MODE_DMA) {
+		config_reg = zynqmp_gqspi_read(xqspi,
+					       GQSPI_CONFIG_OFST);
+		config_reg &= ~GQSPI_CFG_MODE_EN_MASK;
+		zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
+				   config_reg);
+		xqspi->mode = GQSPI_MODE_IO;
 	}
 }
 
 /**
- * zynqmp_qspi_start_transfer - Initiates the QSPI transfer
- * @master:	Pointer to the spi_master structure which provides
- *		information about the controller.
- * @qspi:	Pointer to the spi_device structure
- * @transfer:	Pointer to the spi_transfer structure which provide information
- *		about next transfer parameters
- *
- * This function fills the TX FIFO, starts the QSPI transfer, and waits for the
- * transfer to be completed.
- *
- * Return:	Number of bytes transferred in the last transfer
+ * zynqmp_qspi_read_op - This function sets up the GENFIFO entries and
+ *				RX DMA operation.
+ * @xqspi:	xqspi is a pointer to the GQSPI instance.
+ * @rx_nbits:	Receive buswidth.
+ * @genfifoentry:	genfifoentry is pointer to the variable in which
+ *			GENFIFO	mask is returned to calling function
  */
-static int zynqmp_qspi_start_transfer(struct spi_master *master,
-				      struct spi_device *qspi,
-				      struct spi_transfer *transfer)
+static void zynqmp_qspi_read_op(struct zynqmp_qspi *xqspi, u8 rx_nbits,
+				u32 genfifoentry)
 {
-	struct zynqmp_qspi *xqspi = spi_master_get_devdata(master);
-	u32 genfifoentry = 0x0, transfer_len;
-
-	xqspi->txbuf = transfer->tx_buf;
-	xqspi->rxbuf = transfer->rx_buf;
-
-	zynqmp_qspi_setup_transfer(qspi, transfer);
-
-	genfifoentry |= xqspi->genfifocs;
-	genfifoentry |= xqspi->genfifobus;
-
-	zynqmp_qspi_txrxsetup(xqspi, transfer, &genfifoentry);
-
-	if (xqspi->mode == GQSPI_MODE_DMA)
-		transfer_len = xqspi->dma_rx_bytes;
-	else
-		transfer_len = transfer->len;
-
-	xqspi->genfifoentry = genfifoentry;
-	if ((transfer_len) < GQSPI_GENFIFO_IMM_DATA_MASK) {
-		genfifoentry &= ~GQSPI_GENFIFO_IMM_DATA_MASK;
-		genfifoentry |= transfer_len;
-		zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, genfifoentry);
-	} else {
-		int tempcount = transfer_len;
-		u32 exponent = 8;	/* 2^8 = 256 */
-		u8 imm_data = tempcount & 0xFF;
-
-		tempcount &= ~(tempcount & 0xFF);
-		/* Immediate entry */
-		if (tempcount != 0) {
-			/* Exponent entries */
-			genfifoentry |= GQSPI_GENFIFO_EXP;
-			while (tempcount != 0) {
-				if (tempcount & GQSPI_GENFIFO_EXP_START) {
-					genfifoentry &=
-					    ~GQSPI_GENFIFO_IMM_DATA_MASK;
-					genfifoentry |= exponent;
-					zynqmp_gqspi_write(xqspi,
-							   GQSPI_GEN_FIFO_OFST,
-							   genfifoentry);
-				}
-				tempcount = tempcount >> 1;
-				exponent++;
-			}
-		}
-		if (imm_data != 0) {
-			genfifoentry &= ~GQSPI_GENFIFO_EXP;
-			genfifoentry &= ~GQSPI_GENFIFO_IMM_DATA_MASK;
-			genfifoentry |= (u8) (imm_data & 0xFF);
-			zynqmp_gqspi_write(xqspi,
-					   GQSPI_GEN_FIFO_OFST, genfifoentry);
-		}
-	}
-
-	if ((xqspi->mode == GQSPI_MODE_IO) &&
-			(xqspi->rxbuf != NULL)) {
-		/* Dummy generic FIFO entry */
-		zynqmp_gqspi_write(xqspi, GQSPI_GEN_FIFO_OFST, 0x0);
-	}
-
-	/* Since we are using manual mode */
-	zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
-			   zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST) |
-			   GQSPI_CFG_START_GEN_FIFO_MASK);
-
-	if (xqspi->txbuf != NULL)
-		/* Enable interrupts for TX */
-		zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
-				   GQSPI_IER_TXEMPTY_MASK |
-					GQSPI_IER_GENFIFOEMPTY_MASK |
-					GQSPI_IER_TXNOT_FULL_MASK);
-
-	if (xqspi->rxbuf != NULL) {
-		/* Enable interrupts for RX */
-		if (xqspi->mode == GQSPI_MODE_DMA) {
-			/* Enable DMA interrupts */
-			zynqmp_gqspi_write(xqspi,
-					GQSPI_QSPIDMA_DST_I_EN_OFST,
-					GQSPI_QSPIDMA_DST_I_EN_DONE_MASK);
-		} else {
-			zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
-					GQSPI_IER_GENFIFOEMPTY_MASK |
-					GQSPI_IER_RXNEMPTY_MASK |
-					GQSPI_IER_RXEMPTY_MASK);
-		}
-	}
-
-	return transfer->len;
+	zynqmp_qspi_fillgenfifo(xqspi, rx_nbits, genfifoentry);
+	zynqmp_qspi_setuprxdma(xqspi);
 }
 
 /**
@@ -901,11 +835,12 @@ static int zynqmp_qspi_start_transfer(struct spi_master *master,
  */
 static int __maybe_unused zynqmp_qspi_suspend(struct device *dev)
 {
-	struct spi_master *master = dev_get_drvdata(dev);
+	struct spi_controller *ctlr = dev_get_drvdata(dev);
+	struct zynqmp_qspi *xqspi = spi_controller_get_devdata(ctlr);
 
-	spi_master_suspend(master);
+	spi_controller_suspend(ctlr);
 
-	zynqmp_unprepare_transfer_hardware(master);
+	zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, 0x0);
 
 	return 0;
 }
@@ -921,8 +856,8 @@ static int __maybe_unused zynqmp_qspi_suspend(struct device *dev)
  */
 static int __maybe_unused zynqmp_qspi_resume(struct device *dev)
 {
-	struct spi_master *master = dev_get_drvdata(dev);
-	struct zynqmp_qspi *xqspi = spi_master_get_devdata(master);
+	struct spi_controller *ctlr = dev_get_drvdata(dev);
+	struct zynqmp_qspi *xqspi = spi_controller_get_devdata(ctlr);
 	int ret = 0;
 
 	ret = clk_enable(xqspi->pclk);
@@ -938,7 +873,7 @@ static int __maybe_unused zynqmp_qspi_resume(struct device *dev)
 		return ret;
 	}
 
-	spi_master_resume(master);
+	spi_controller_resume(ctlr);
 
 	clk_disable(xqspi->refclk);
 	clk_disable(xqspi->pclk);
@@ -955,8 +890,7 @@ static int __maybe_unused zynqmp_qspi_resume(struct device *dev)
  */
 static int __maybe_unused zynqmp_runtime_suspend(struct device *dev)
 {
-	struct spi_master *master = dev_get_drvdata(dev);
-	struct zynqmp_qspi *xqspi = spi_master_get_devdata(master);
+	struct zynqmp_qspi *xqspi = (struct zynqmp_qspi *)dev_get_drvdata(dev);
 
 	clk_disable(xqspi->refclk);
 	clk_disable(xqspi->pclk);
@@ -974,8 +908,7 @@ static int __maybe_unused zynqmp_runtime_suspend(struct device *dev)
  */
 static int __maybe_unused zynqmp_runtime_resume(struct device *dev)
 {
-	struct spi_master *master = dev_get_drvdata(dev);
-	struct zynqmp_qspi *xqspi = spi_master_get_devdata(master);
+	struct zynqmp_qspi *xqspi = (struct zynqmp_qspi *)dev_get_drvdata(dev);
 	int ret;
 
 	ret = clk_enable(xqspi->pclk);
@@ -994,12 +927,177 @@ static int __maybe_unused zynqmp_runtime_resume(struct device *dev)
 	return 0;
 }
 
+/**
+ * zynqmp_qspi_exec_op() - Initiates the QSPI transfer
+ * @mem: The SPI memory
+ * @op: The memory operation to execute
+ *
+ * Executes a memory operation.
+ *
+ * This function first selects the chip and starts the memory operation.
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+static int zynqmp_qspi_exec_op(struct spi_mem *mem,
+			       const struct spi_mem_op *op)
+{
+	struct zynqmp_qspi *xqspi = spi_controller_get_devdata
+				    (mem->spi->master);
+	int err = 0, i;
+	u8 *tmpbuf;
+	u32 genfifoentry = 0;
+
+	dev_dbg(xqspi->dev, "cmd:%#x mode:%d.%d.%d.%d\n",
+		op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
+		op->dummy.buswidth, op->data.buswidth);
+
+	zynqmp_qspi_config_op(xqspi, mem->spi);
+	zynqmp_qspi_chipselect(mem->spi, false);
+	genfifoentry |= xqspi->genfifocs;
+	genfifoentry |= xqspi->genfifobus;
+
+	if (op->cmd.opcode) {
+		tmpbuf = kzalloc(op->cmd.nbytes, GFP_KERNEL | GFP_DMA);
+		if (!tmpbuf)
+			return -ENOMEM;
+		tmpbuf[0] = op->cmd.opcode;
+		reinit_completion(&xqspi->data_completion);
+		xqspi->txbuf = tmpbuf;
+		xqspi->rxbuf = NULL;
+		xqspi->bytes_to_transfer = op->cmd.nbytes;
+		xqspi->bytes_to_receive = 0;
+		zynqmp_qspi_write_op(xqspi, op->cmd.buswidth, genfifoentry);
+		zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
+				   zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST) |
+				   GQSPI_CFG_START_GEN_FIFO_MASK);
+		zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
+				   GQSPI_IER_GENFIFOEMPTY_MASK |
+				   GQSPI_IER_TXNOT_FULL_MASK);
+		if (!wait_for_completion_interruptible_timeout
+		    (&xqspi->data_completion, msecs_to_jiffies(1000))) {
+			err = -ETIMEDOUT;
+			kfree(tmpbuf);
+			goto return_err;
+		}
+		kfree(tmpbuf);
+	}
+
+	if (op->addr.nbytes) {
+		for (i = 0; i < op->addr.nbytes; i++) {
+			*(((u8 *)xqspi->txbuf) + i) = op->addr.val >>
+					(8 * (op->addr.nbytes - i - 1));
+		}
+
+		reinit_completion(&xqspi->data_completion);
+		xqspi->rxbuf = NULL;
+		xqspi->bytes_to_transfer = op->addr.nbytes;
+		xqspi->bytes_to_receive = 0;
+		zynqmp_qspi_write_op(xqspi, op->addr.buswidth, genfifoentry);
+		zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
+				   zynqmp_gqspi_read(xqspi,
+						     GQSPI_CONFIG_OFST) |
+				   GQSPI_CFG_START_GEN_FIFO_MASK);
+		zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
+				   GQSPI_IER_TXEMPTY_MASK |
+				   GQSPI_IER_GENFIFOEMPTY_MASK |
+				   GQSPI_IER_TXNOT_FULL_MASK);
+		if (!wait_for_completion_interruptible_timeout
+		    (&xqspi->data_completion, msecs_to_jiffies(1000))) {
+			err = -ETIMEDOUT;
+			goto return_err;
+		}
+	}
+
+	if (op->dummy.nbytes) {
+		tmpbuf = kzalloc(op->dummy.nbytes, GFP_KERNEL | GFP_DMA);
+		if (!tmpbuf)
+			return -ENOMEM;
+		memset(tmpbuf, 0xff, op->dummy.nbytes);
+		reinit_completion(&xqspi->data_completion);
+		xqspi->txbuf = tmpbuf;
+		xqspi->rxbuf = NULL;
+		xqspi->bytes_to_transfer = op->dummy.nbytes;
+		xqspi->bytes_to_receive = 0;
+		zynqmp_qspi_write_op(xqspi, op->dummy.buswidth,
+				     genfifoentry);
+		zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
+				   zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST) |
+				   GQSPI_CFG_START_GEN_FIFO_MASK);
+		zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
+				   GQSPI_IER_TXEMPTY_MASK |
+				   GQSPI_IER_GENFIFOEMPTY_MASK |
+				   GQSPI_IER_TXNOT_FULL_MASK);
+		if (!wait_for_completion_interruptible_timeout
+		    (&xqspi->data_completion, msecs_to_jiffies(1000))) {
+			err = -ETIMEDOUT;
+			kfree(tmpbuf);
+			goto return_err;
+		}
+
+		kfree(tmpbuf);
+	}
+
+	if (op->data.nbytes) {
+		reinit_completion(&xqspi->data_completion);
+		if (op->data.dir == SPI_MEM_DATA_OUT) {
+			xqspi->txbuf = (u8 *)op->data.buf.out;
+			xqspi->rxbuf = NULL;
+			xqspi->bytes_to_transfer = op->data.nbytes;
+			xqspi->bytes_to_receive = 0;
+			zynqmp_qspi_write_op(xqspi, op->data.buswidth,
+					     genfifoentry);
+			zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
+					   zynqmp_gqspi_read
+					   (xqspi, GQSPI_CONFIG_OFST) |
+					   GQSPI_CFG_START_GEN_FIFO_MASK);
+			zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
+					   GQSPI_IER_TXEMPTY_MASK |
+					   GQSPI_IER_GENFIFOEMPTY_MASK |
+					   GQSPI_IER_TXNOT_FULL_MASK);
+		} else {
+			xqspi->txbuf = NULL;
+			xqspi->rxbuf = (u8 *)op->data.buf.in;
+			xqspi->bytes_to_receive = op->data.nbytes;
+			xqspi->bytes_to_transfer = 0;
+			zynqmp_qspi_read_op(xqspi, op->data.buswidth,
+					    genfifoentry);
+			zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
+					   zynqmp_gqspi_read
+					   (xqspi, GQSPI_CONFIG_OFST) |
+					   GQSPI_CFG_START_GEN_FIFO_MASK);
+			if (xqspi->mode == GQSPI_MODE_DMA) {
+				zynqmp_gqspi_write
+					(xqspi, GQSPI_QSPIDMA_DST_I_EN_OFST,
+					 GQSPI_QSPIDMA_DST_I_EN_DONE_MASK);
+			} else {
+				zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
+						   GQSPI_IER_GENFIFOEMPTY_MASK |
+						   GQSPI_IER_RXNEMPTY_MASK |
+						   GQSPI_IER_RXEMPTY_MASK);
+			}
+		}
+		if (!wait_for_completion_interruptible_timeout
+		    (&xqspi->data_completion, msecs_to_jiffies(1000)))
+			err = -ETIMEDOUT;
+	}
+
+return_err:
+
+	zynqmp_qspi_chipselect(mem->spi, true);
+
+	return err;
+}
+
 static const struct dev_pm_ops zynqmp_qspi_dev_pm_ops = {
 	SET_RUNTIME_PM_OPS(zynqmp_runtime_suspend,
 			   zynqmp_runtime_resume, NULL)
 	SET_SYSTEM_SLEEP_PM_OPS(zynqmp_qspi_suspend, zynqmp_qspi_resume)
 };
 
+static const struct spi_controller_mem_ops zynqmp_qspi_mem_ops = {
+	.exec_op = zynqmp_qspi_exec_op,
+};
+
 /**
  * zynqmp_qspi_probe - Probe method for the QSPI driver
  * @pdev:	Pointer to the platform_device structure
@@ -1011,17 +1109,18 @@ static const struct dev_pm_ops zynqmp_qspi_dev_pm_ops = {
 static int zynqmp_qspi_probe(struct platform_device *pdev)
 {
 	int ret = 0;
-	struct spi_master *master;
+	struct spi_controller *ctlr;
 	struct zynqmp_qspi *xqspi;
 	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
 
-	master = spi_alloc_master(&pdev->dev, sizeof(*xqspi));
-	if (!master)
+	ctlr = spi_alloc_master(&pdev->dev, sizeof(*xqspi));
+	if (!ctlr)
 		return -ENOMEM;
 
-	xqspi = spi_master_get_devdata(master);
-	master->dev.of_node = pdev->dev.of_node;
-	platform_set_drvdata(pdev, master);
+	xqspi = spi_controller_get_devdata(ctlr);
+	xqspi->dev = dev;
+	platform_set_drvdata(pdev, xqspi);
 
 	xqspi->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(xqspi->regs)) {
@@ -1029,7 +1128,6 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
 		goto remove_master;
 	}
 
-	xqspi->dev = dev;
 	xqspi->pclk = devm_clk_get(&pdev->dev, "pclk");
 	if (IS_ERR(xqspi->pclk)) {
 		dev_err(dev, "pclk clock not found.\n");
@@ -1037,11 +1135,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
 		goto remove_master;
 	}
 
-	ret = clk_prepare_enable(xqspi->pclk);
-	if (ret) {
-		dev_err(dev, "Unable to enable APB clock.\n");
-		goto remove_master;
-	}
+	init_completion(&xqspi->data_completion);
 
 	xqspi->refclk = devm_clk_get(&pdev->dev, "ref_clk");
 	if (IS_ERR(xqspi->refclk)) {
@@ -1050,6 +1144,12 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
 		goto clk_dis_pclk;
 	}
 
+	ret = clk_prepare_enable(xqspi->pclk);
+	if (ret) {
+		dev_err(dev, "Unable to enable APB clock.\n");
+		goto remove_master;
+	}
+
 	ret = clk_prepare_enable(xqspi->refclk);
 	if (ret) {
 		dev_err(dev, "Unable to enable device clock.\n");
@@ -1071,32 +1171,28 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
 		goto clk_dis_all;
 	}
 	ret = devm_request_irq(&pdev->dev, xqspi->irq, zynqmp_qspi_irq,
-			       0, pdev->name, master);
+			       0, pdev->name, xqspi);
 	if (ret != 0) {
 		ret = -ENXIO;
 		dev_err(dev, "request_irq failed\n");
 		goto clk_dis_all;
 	}
 
-	master->num_chipselect = GQSPI_DEFAULT_NUM_CS;
-
-	master->setup = zynqmp_qspi_setup;
-	master->set_cs = zynqmp_qspi_chipselect;
-	master->transfer_one = zynqmp_qspi_start_transfer;
-	master->prepare_transfer_hardware = zynqmp_prepare_transfer_hardware;
-	master->unprepare_transfer_hardware =
-					zynqmp_unprepare_transfer_hardware;
-	master->max_speed_hz = clk_get_rate(xqspi->refclk) / 2;
-	master->bits_per_word_mask = SPI_BPW_MASK(8);
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD |
+	ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
+	ctlr->num_chipselect = GQSPI_DEFAULT_NUM_CS;
+	ctlr->mem_ops = &zynqmp_qspi_mem_ops;
+	ctlr->setup = zynqmp_qspi_setup_op;
+	ctlr->max_speed_hz = clk_get_rate(xqspi->refclk) / 2;
+	ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
+	ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD |
 			    SPI_TX_DUAL | SPI_TX_QUAD;
+	ctlr->dev.of_node = np;
 
-	if (master->dev.parent == NULL)
-		master->dev.parent = &master->dev;
-
-	ret = spi_register_master(master);
-	if (ret)
+	ret = devm_spi_register_controller(&pdev->dev, ctlr);
+	if (ret) {
+		dev_err(&pdev->dev, "spi_register_controller failed\n");
 		goto clk_dis_all;
+	}
 
 	return 0;
 
@@ -1107,7 +1203,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
 clk_dis_pclk:
 	clk_disable_unprepare(xqspi->pclk);
 remove_master:
-	spi_master_put(master);
+	spi_controller_put(ctlr);
 
 	return ret;
 }
@@ -1124,8 +1220,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
  */
 static int zynqmp_qspi_remove(struct platform_device *pdev)
 {
-	struct spi_master *master = platform_get_drvdata(pdev);
-	struct zynqmp_qspi *xqspi = spi_master_get_devdata(master);
+	struct zynqmp_qspi *xqspi = platform_get_drvdata(pdev);
 
 	zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, 0x0);
 	clk_disable_unprepare(xqspi->refclk);
@@ -1133,8 +1228,6 @@ static int zynqmp_qspi_remove(struct platform_device *pdev)
 	pm_runtime_set_suspended(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 
-	spi_unregister_master(master);
-
 	return 0;
 }
 
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [RESEND v2 PATCH 3/3] spi: spi-zynqmp-gqspi: Fix incorrect indentation
  2020-09-24  7:11 [RESEND v2 PATCH 0/3] spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework Michal Simek
  2020-09-24  7:11 ` [RESEND v2 PATCH 1/3] spi: spi-zynqmp-gqspi: Fix kernel-doc warnings Michal Simek
  2020-09-24  7:11 ` [RESEND v2 PATCH 2/3] spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework Michal Simek
@ 2020-09-24  7:11 ` Michal Simek
  2020-09-24 12:00 ` [RESEND v2 PATCH 0/3] spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework Mark Brown
  3 siblings, 0 replies; 5+ messages in thread
From: Michal Simek @ 2020-09-24  7:11 UTC (permalink / raw)
  To: broonie
  Cc: amit.kumar-mahapatra, linux-kernel, monstr, michal.simek, git,
	linux-spi, linux-arm-kernel

From: Amit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>

Fixed incorrect indentation in ZynqMP qspi controller driver.

Addresses-checkpatch: "Alignment should match open parenthesis"
Signed-off-by: Amit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
---

 drivers/spi/spi-zynqmp-gqspi.c | 46 +++++++++++++++++-----------------
 1 file changed, 23 insertions(+), 23 deletions(-)

diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
index 7f57923f76ea..c8fa6ee18ae7 100644
--- a/drivers/spi/spi-zynqmp-gqspi.c
+++ b/drivers/spi/spi-zynqmp-gqspi.c
@@ -326,8 +326,8 @@ static void zynqmp_qspi_init_hw(struct zynqmp_qspi *xqspi)
 				 GQSPI_SELECT_FLASH_BUS_LOWER);
 	/* Initialize DMA */
 	zynqmp_gqspi_write(xqspi,
-			GQSPI_QSPIDMA_DST_CTRL_OFST,
-			GQSPI_QSPIDMA_DST_CTRL_RESET_VAL);
+			   GQSPI_QSPIDMA_DST_CTRL_OFST,
+			   GQSPI_QSPIDMA_DST_CTRL_RESET_VAL);
 
 	/* Enable the GQSPI */
 	zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, GQSPI_EN_MASK);
@@ -374,8 +374,8 @@ static void zynqmp_qspi_chipselect(struct spi_device *qspi, bool is_high)
 
 	/* Manually start the generic FIFO command */
 	zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
-			zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST) |
-			GQSPI_CFG_START_GEN_FIFO_MASK);
+			   zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST) |
+			   GQSPI_CFG_START_GEN_FIFO_MASK);
 
 	timeout = jiffies + msecs_to_jiffies(1000);
 
@@ -384,10 +384,9 @@ static void zynqmp_qspi_chipselect(struct spi_device *qspi, bool is_high)
 		statusreg = zynqmp_gqspi_read(xqspi, GQSPI_ISR_OFST);
 
 		if ((statusreg & GQSPI_ISR_GENFIFOEMPTY_MASK) &&
-			(statusreg & GQSPI_ISR_TXEMPTY_MASK))
+		    (statusreg & GQSPI_ISR_TXEMPTY_MASK))
 			break;
-		else
-			cpu_relax();
+		cpu_relax();
 	} while (!time_after_eq(jiffies, timeout));
 
 	if (time_after_eq(jiffies, timeout))
@@ -549,7 +548,7 @@ static void zynqmp_qspi_readrxfifo(struct zynqmp_qspi *xqspi, u32 size)
 
 	while ((count < size) && (xqspi->bytes_to_receive > 0)) {
 		if (xqspi->bytes_to_receive >= 4) {
-			(*(u32 *) xqspi->rxbuf) =
+			(*(u32 *)xqspi->rxbuf) =
 			zynqmp_gqspi_read(xqspi, GQSPI_RXD_OFST);
 			xqspi->rxbuf += 4;
 			xqspi->bytes_to_receive -= 4;
@@ -645,14 +644,14 @@ static void zynqmp_process_dma_irq(struct zynqmp_qspi *xqspi)
 	u32 config_reg, genfifoentry;
 
 	dma_unmap_single(xqspi->dev, xqspi->dma_addr,
-				xqspi->dma_rx_bytes, DMA_FROM_DEVICE);
+			 xqspi->dma_rx_bytes, DMA_FROM_DEVICE);
 	xqspi->rxbuf += xqspi->dma_rx_bytes;
 	xqspi->bytes_to_receive -= xqspi->dma_rx_bytes;
 	xqspi->dma_rx_bytes = 0;
 
 	/* Disabling the DMA interrupts */
 	zynqmp_gqspi_write(xqspi, GQSPI_QSPIDMA_DST_I_DIS_OFST,
-					GQSPI_QSPIDMA_DST_I_EN_DONE_MASK);
+			   GQSPI_QSPIDMA_DST_I_EN_DONE_MASK);
 
 	if (xqspi->bytes_to_receive > 0) {
 		/* Switch to IO mode,for remaining bytes to receive */
@@ -670,14 +669,15 @@ static void zynqmp_process_dma_irq(struct zynqmp_qspi *xqspi)
 
 		/* Manual start */
 		zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
-			(zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST) |
-			GQSPI_CFG_START_GEN_FIFO_MASK));
+				   (zynqmp_gqspi_read(xqspi,
+						      GQSPI_CONFIG_OFST) |
+				   GQSPI_CFG_START_GEN_FIFO_MASK));
 
 		/* Enable the RX interrupts for IO mode */
 		zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
-				GQSPI_IER_GENFIFOEMPTY_MASK |
-				GQSPI_IER_RXNEMPTY_MASK |
-				GQSPI_IER_RXEMPTY_MASK);
+				   GQSPI_IER_GENFIFOEMPTY_MASK |
+				   GQSPI_IER_RXNEMPTY_MASK |
+				   GQSPI_IER_RXEMPTY_MASK);
 	}
 }
 
@@ -708,7 +708,7 @@ static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id)
 		dma_status =
 			zynqmp_gqspi_read(xqspi, GQSPI_QSPIDMA_DST_I_STS_OFST);
 		zynqmp_gqspi_write(xqspi, GQSPI_QSPIDMA_DST_I_STS_OFST,
-								dma_status);
+				   dma_status);
 	}
 
 	if (mask & GQSPI_ISR_TXNOT_FULL_MASK) {
@@ -725,8 +725,8 @@ static irqreturn_t zynqmp_qspi_irq(int irq, void *dev_id)
 		ret = IRQ_HANDLED;
 	}
 
-	if ((xqspi->bytes_to_receive == 0) && (xqspi->bytes_to_transfer == 0)
-			&& ((status & GQSPI_IRQ_MASK) == GQSPI_IRQ_MASK)) {
+	if (xqspi->bytes_to_receive == 0 && xqspi->bytes_to_transfer == 0 &&
+	    ((status & GQSPI_IRQ_MASK) == GQSPI_IRQ_MASK)) {
 		zynqmp_gqspi_write(xqspi, GQSPI_IDR_OFST, GQSPI_ISR_IDR_MASK);
 		complete(&xqspi->data_completion);
 		ret = IRQ_HANDLED;
@@ -744,8 +744,8 @@ static void zynqmp_qspi_setuprxdma(struct zynqmp_qspi *xqspi)
 	dma_addr_t addr;
 	u64 dma_align =  (u64)(uintptr_t)xqspi->rxbuf;
 
-	if ((xqspi->bytes_to_receive < 8) ||
-		((dma_align & GQSPI_DMA_UNALIGN) != 0x0)) {
+	if (xqspi->bytes_to_receive < 8 ||
+	    ((dma_align & GQSPI_DMA_UNALIGN) != 0x0)) {
 		/* Setting to IO mode */
 		config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST);
 		config_reg &= ~GQSPI_CFG_MODE_EN_MASK;
@@ -759,17 +759,17 @@ static void zynqmp_qspi_setuprxdma(struct zynqmp_qspi *xqspi)
 	rx_bytes = (xqspi->bytes_to_receive - rx_rem);
 
 	addr = dma_map_single(xqspi->dev, (void *)xqspi->rxbuf,
-						rx_bytes, DMA_FROM_DEVICE);
+			      rx_bytes, DMA_FROM_DEVICE);
 	if (dma_mapping_error(xqspi->dev, addr))
 		dev_err(xqspi->dev, "ERR:rxdma:memory not mapped\n");
 
 	xqspi->dma_rx_bytes = rx_bytes;
 	xqspi->dma_addr = addr;
 	zynqmp_gqspi_write(xqspi, GQSPI_QSPIDMA_DST_ADDR_OFST,
-				(u32)(addr & 0xffffffff));
+			   (u32)(addr & 0xffffffff));
 	addr = ((addr >> 16) >> 16);
 	zynqmp_gqspi_write(xqspi, GQSPI_QSPIDMA_DST_ADDR_MSB_OFST,
-				((u32)addr) & 0xfff);
+			   ((u32)addr) & 0xfff);
 
 	/* Enabling the DMA mode */
 	config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST);
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [RESEND v2 PATCH 0/3] spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework
  2020-09-24  7:11 [RESEND v2 PATCH 0/3] spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework Michal Simek
                   ` (2 preceding siblings ...)
  2020-09-24  7:11 ` [RESEND v2 PATCH 3/3] spi: spi-zynqmp-gqspi: Fix incorrect indentation Michal Simek
@ 2020-09-24 12:00 ` Mark Brown
  3 siblings, 0 replies; 5+ messages in thread
From: Mark Brown @ 2020-09-24 12:00 UTC (permalink / raw)
  To: Michal Simek
  Cc: linux-kernel, monstr, amit.kumar-mahapatra, linux-spi,
	linux-arm-kernel, git

On Thu, 24 Sep 2020 09:11:16 +0200, Michal Simek wrote:
> I am resending this series instead of Amit because his patches are broken
> in lore. Mark has reported the issue with it and I clearly see that patch
> is broken in lore.
> For example:
> https://lore.kernel.org/linux-spi/20200922164016.30979-2-amit.kumar-mahapatra@xilinx.com/raw
> 
> There is additional = which shouldn't be there.
> @@ -183,7 +184,7 @@ static u32 zynqmp_gqspi_read(struct zynqmp_qspi *xqspi,=
> u32 offset)
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[1/3] spi: spi-zynqmp-gqspi: Fix kernel-doc warnings
      commit: 91af6eb04a6bbdb8bec8ed6d8ac7850a26604bad
[2/3] spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework
      commit: 1c26372e5aa9e53391a1f8fe0dc7cd93a7e5ba9e
[3/3] spi: spi-zynqmp-gqspi: Fix incorrect indentation
      commit: f09a433b1e4057e6379b7e1207548fff30d5dca3

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-09-24 12:01 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-24  7:11 [RESEND v2 PATCH 0/3] spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework Michal Simek
2020-09-24  7:11 ` [RESEND v2 PATCH 1/3] spi: spi-zynqmp-gqspi: Fix kernel-doc warnings Michal Simek
2020-09-24  7:11 ` [RESEND v2 PATCH 2/3] spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework Michal Simek
2020-09-24  7:11 ` [RESEND v2 PATCH 3/3] spi: spi-zynqmp-gqspi: Fix incorrect indentation Michal Simek
2020-09-24 12:00 ` [RESEND v2 PATCH 0/3] spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework Mark Brown

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