2022-10-11 07:04:27

by Mahapatra, Amit Kumar

[permalink] [raw]
Subject: [PATCH v4 0/7] spi: spi-zyqnmp-gqspi: Add tap delay and Versal platform support

- Fix kernel-doc warnings in GQSPI driver.
- Avoid setting CPOL, CPHA & baud rate multiple times.
- Add Versal platform support in GQSPI driver.
- Add tap delay support in GQSPI driver.
---
BRANCH: mtd/next

changes in v2:
- Used of_device_get_match_data( ) API to retrive match->data.
- Removed oneOf and used only enum.
changes in v3:
- Arrange compatible string in alphabetical order.
changes in v4:
- Used subject prefixes matching the subsystem
---
Amit Kumar Mahapatra (5):
spi: spi-zynqmp-gqspi: Fix kernel-doc warnings
spi: spi-zynqmp-gqspi: Set CPOL and CPHA during hardware init
spi: spi-zynqmp-gqspi: Avoid setting baud rate multiple times for same
SPI frequency
spi: dt-bindings: zynqmp-qspi: Add support for Xilinx Versal QSPI
spi: spi-zynqmp-gqspi: Add tap delay support for GQSPI controller on
Versal platform

Naga Sureshkumar Relli (1):
spi: spi-zynqmp-gqspi: Add tap delay support for ZynqMP GQSPI
Controller

Rajan Vaja (1):
firmware: xilinx: Add qspi firmware interface

.../bindings/spi/spi-zynqmp-qspi.yaml | 4 +-
drivers/firmware/xilinx/zynqmp.c | 7 +
drivers/spi/spi-zynqmp-gqspi.c | 191 ++++++++++++++----
include/linux/firmware/xlnx-zynqmp.h | 19 ++
4 files changed, 184 insertions(+), 37 deletions(-)

--
2.17.1


2022-10-11 07:08:34

by Mahapatra, Amit Kumar

[permalink] [raw]
Subject: [PATCH v4 3/7] spi: spi-zynqmp-gqspi: Avoid setting baud rate multiple times for same SPI frequency

During every transfer the GQSPI driver configures the baud rate value. But
when there is no change in the SPI clock frequency the driver should avoid
rewriting the same baud rate value to the configuration register. Update
GQSPI driver to rewrite the baud rate value if there is any change in SPI
clock frequency.

Signed-off-by: Amit Kumar Mahapatra <[email protected]>
---
drivers/spi/spi-zynqmp-gqspi.c | 49 ++++++++++++++++++++++++----------
1 file changed, 35 insertions(+), 14 deletions(-)

diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
index 1b56dd29057f..0fecea338027 100644
--- a/drivers/spi/spi-zynqmp-gqspi.c
+++ b/drivers/spi/spi-zynqmp-gqspi.c
@@ -159,6 +159,7 @@ enum mode_type {GQSPI_MODE_IO, GQSPI_MODE_DMA};
* @mode: Defines the mode in which QSPI is operating
* @data_completion: completion structure
* @op_lock: Operational lock
+ * @speed_hz: Current SPI bus clock speed in hz
*/
struct zynqmp_qspi {
struct spi_controller *ctlr;
@@ -179,6 +180,7 @@ struct zynqmp_qspi {
enum mode_type mode;
struct completion data_completion;
struct mutex op_lock;
+ u32 speed_hz;
};

/**
@@ -273,7 +275,8 @@ static void zynqmp_gqspi_selectslave(struct zynqmp_qspi *instanceptr,
*/
static void zynqmp_qspi_init_hw(struct zynqmp_qspi *xqspi)
{
- u32 config_reg;
+ u32 config_reg, baud_rate_val = 0;
+ ulong clk_rate;

/* Select the GQSPI mode */
zynqmp_gqspi_write(xqspi, GQSPI_SEL_OFST, GQSPI_SEL_MASK);
@@ -318,6 +321,16 @@ static void zynqmp_qspi_init_hw(struct zynqmp_qspi *xqspi)
else
config_reg &= ~GQSPI_CFG_CLK_POL_MASK;

+ /* Set the clock frequency */
+ clk_rate = clk_get_rate(xqspi->refclk);
+ while ((baud_rate_val < GQSPI_BAUD_DIV_MAX) &&
+ (clk_rate /
+ (GQSPI_BAUD_DIV_SHIFT << baud_rate_val)) > xqspi->speed_hz)
+ baud_rate_val++;
+
+ config_reg &= ~GQSPI_CFG_BAUD_RATE_DIV_MASK;
+ config_reg |= (baud_rate_val << GQSPI_CFG_BAUD_RATE_DIV_SHIFT);
+
zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg);

/* Clear the TX and RX FIFO */
@@ -466,22 +479,29 @@ static int zynqmp_qspi_config_op(struct zynqmp_qspi *xqspi,
struct spi_device *qspi)
{
ulong clk_rate;
- u32 config_reg, baud_rate_val = 0;
+ u32 config_reg, req_speed_hz, baud_rate_val = 0;

- /* Set the clock frequency */
- /* If req_hz == 0, default to lowest speed */
- clk_rate = clk_get_rate(xqspi->refclk);
+ req_speed_hz = qspi->max_speed_hz;

- while ((baud_rate_val < GQSPI_BAUD_DIV_MAX) &&
- (clk_rate /
- (GQSPI_BAUD_DIV_SHIFT << baud_rate_val)) > qspi->max_speed_hz)
- baud_rate_val++;
+ if (xqspi->speed_hz != req_speed_hz) {
+ xqspi->speed_hz = req_speed_hz;

- config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST);
+ /* Set the clock frequency */
+ /* If req_speed_hz == 0, default to lowest speed */
+ clk_rate = clk_get_rate(xqspi->refclk);

- config_reg &= ~GQSPI_CFG_BAUD_RATE_DIV_MASK;
- config_reg |= (baud_rate_val << GQSPI_CFG_BAUD_RATE_DIV_SHIFT);
- zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg);
+ while ((baud_rate_val < GQSPI_BAUD_DIV_MAX) &&
+ (clk_rate /
+ (GQSPI_BAUD_DIV_SHIFT << baud_rate_val)) >
+ req_speed_hz)
+ baud_rate_val++;
+
+ config_reg = zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST);
+
+ config_reg &= ~GQSPI_CFG_BAUD_RATE_DIV_MASK;
+ config_reg |= (baud_rate_val << GQSPI_CFG_BAUD_RATE_DIV_SHIFT);
+ zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg);
+ }
return 0;
}

@@ -1173,6 +1193,8 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)

ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD |
SPI_TX_DUAL | SPI_TX_QUAD;
+ ctlr->max_speed_hz = clk_get_rate(xqspi->refclk) / 2;
+ xqspi->speed_hz = ctlr->max_speed_hz;

/* QSPI controller initializations */
zynqmp_qspi_init_hw(xqspi);
@@ -1209,7 +1231,6 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
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->dev.of_node = np;
ctlr->auto_runtime_pm = true;
--
2.17.1

2022-10-11 07:42:03

by Mahapatra, Amit Kumar

[permalink] [raw]
Subject: [PATCH v4 5/7] spi: spi-zynqmp-gqspi: Add tap delay support for ZynqMP GQSPI Controller

From: Naga Sureshkumar Relli <[email protected]>

GQSPI controller uses the internal clock for loopback mode. The loopback
mode is used with the high-speed Quad SPI timing mode, where the memory
interface clock needs to be greater than 40 MHz. Based on the tap delay
value programmed, the internal clock is delayed and used for capturing
the data.
Based upon the frequency of operation set the recommended tap delay
values in GQSPI driver.

Signed-off-by: Naga Sureshkumar Relli <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
Signed-off-by: Amit Kumar Mahapatra <[email protected]>
---
drivers/spi/spi-zynqmp-gqspi.c | 50 +++++++++++++++++++++++++++++++---
1 file changed, 46 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
index 0fecea338027..c11736d96f33 100644
--- a/drivers/spi/spi-zynqmp-gqspi.c
+++ b/drivers/spi/spi-zynqmp-gqspi.c
@@ -48,6 +48,7 @@
#define GQSPI_QSPIDMA_DST_I_MASK_OFST 0x00000820
#define GQSPI_QSPIDMA_DST_ADDR_OFST 0x00000800
#define GQSPI_QSPIDMA_DST_ADDR_MSB_OFST 0x00000828
+#define GQSPI_DATA_DLY_ADJ_OFST 0x000001F8

/* GQSPI register bit masks */
#define GQSPI_SEL_MASK 0x00000001
@@ -136,6 +137,16 @@

#define GQSPI_MAX_NUM_CS 2 /* Maximum number of chip selects */

+#define GQSPI_USE_DATA_DLY 0x1
+#define GQSPI_USE_DATA_DLY_SHIFT 31
+#define GQSPI_DATA_DLY_ADJ_VALUE 0x2
+#define GQSPI_DATA_DLY_ADJ_SHIFT 28
+
+#define GQSPI_FREQ_37_5MHZ 37500000
+#define GQSPI_FREQ_40MHZ 40000000
+#define GQSPI_FREQ_100MHZ 100000000
+#define GQSPI_FREQ_150MHZ 150000000
+
#define SPI_AUTOSUSPEND_TIMEOUT 3000
enum mode_type {GQSPI_MODE_IO, GQSPI_MODE_DMA};

@@ -253,6 +264,37 @@ static void zynqmp_gqspi_selectslave(struct zynqmp_qspi *instanceptr,
}
}

+/**
+ * zynqmp_qspi_set_tapdelay: To configure qspi tap delays
+ * @xqspi: Pointer to the zynqmp_qspi structure
+ * @baudrateval: Buadrate to configure
+ */
+static void zynqmp_qspi_set_tapdelay(struct zynqmp_qspi *xqspi, u32 baudrateval)
+{
+ u32 lpbkdlyadj = 0, datadlyadj = 0, clk_rate;
+ u32 reqhz = 0;
+
+ clk_rate = clk_get_rate(xqspi->refclk);
+ reqhz = (clk_rate / (GQSPI_BAUD_DIV_SHIFT << baudrateval));
+
+ if (reqhz <= GQSPI_FREQ_40MHZ) {
+ zynqmp_pm_set_tapdelay_bypass(PM_TAPDELAY_QSPI,
+ PM_TAPDELAY_BYPASS_ENABLE);
+ } else if (reqhz <= GQSPI_FREQ_100MHZ) {
+ zynqmp_pm_set_tapdelay_bypass(PM_TAPDELAY_QSPI,
+ PM_TAPDELAY_BYPASS_ENABLE);
+ lpbkdlyadj |= (GQSPI_LPBK_DLY_ADJ_USE_LPBK_MASK);
+ datadlyadj |= ((GQSPI_USE_DATA_DLY <<
+ GQSPI_USE_DATA_DLY_SHIFT) |
+ (GQSPI_DATA_DLY_ADJ_VALUE <<
+ GQSPI_DATA_DLY_ADJ_SHIFT));
+ } else if (reqhz <= GQSPI_FREQ_150MHZ) {
+ lpbkdlyadj |= GQSPI_LPBK_DLY_ADJ_USE_LPBK_MASK;
+ }
+ zynqmp_gqspi_write(xqspi, GQSPI_LPBK_DLY_ADJ_OFST, lpbkdlyadj);
+ zynqmp_gqspi_write(xqspi, GQSPI_DATA_DLY_ADJ_OFST, datadlyadj);
+}
+
/**
* zynqmp_qspi_init_hw - Initialize the hardware
* @xqspi: Pointer to the zynqmp_qspi structure
@@ -333,15 +375,14 @@ static void zynqmp_qspi_init_hw(struct zynqmp_qspi *xqspi)

zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg);

+ /* Set the tapdelay for clock frequency */
+ zynqmp_qspi_set_tapdelay(xqspi, baud_rate_val);
+
/* Clear the TX and RX FIFO */
zynqmp_gqspi_write(xqspi, GQSPI_FIFO_CTRL_OFST,
GQSPI_FIFO_CTRL_RST_RX_FIFO_MASK |
GQSPI_FIFO_CTRL_RST_TX_FIFO_MASK |
GQSPI_FIFO_CTRL_RST_GEN_FIFO_MASK);
- /* Set by default to allow for high frequencies */
- zynqmp_gqspi_write(xqspi, GQSPI_LPBK_DLY_ADJ_OFST,
- zynqmp_gqspi_read(xqspi, GQSPI_LPBK_DLY_ADJ_OFST) |
- GQSPI_LPBK_DLY_ADJ_USE_LPBK_MASK);
/* Reset thresholds */
zynqmp_gqspi_write(xqspi, GQSPI_TX_THRESHOLD_OFST,
GQSPI_TX_FIFO_THRESHOLD_RESET_VAL);
@@ -501,6 +542,7 @@ static int zynqmp_qspi_config_op(struct zynqmp_qspi *xqspi,
config_reg &= ~GQSPI_CFG_BAUD_RATE_DIV_MASK;
config_reg |= (baud_rate_val << GQSPI_CFG_BAUD_RATE_DIV_SHIFT);
zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST, config_reg);
+ zynqmp_qspi_set_tapdelay(xqspi, baud_rate_val);
}
return 0;
}
--
2.17.1

2022-10-19 17:56:47

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH v4 0/7] spi: spi-zyqnmp-gqspi: Add tap delay and Versal platform support

On Tue, 11 Oct 2022 11:50:33 +0530, Amit Kumar Mahapatra wrote:
> - Fix kernel-doc warnings in GQSPI driver.
> - Avoid setting CPOL, CPHA & baud rate multiple times.
> - Add Versal platform support in GQSPI driver.
> - Add tap delay support in GQSPI driver.
>

Applied to

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

Thanks!

[1/7] spi: spi-zynqmp-gqspi: Fix kernel-doc warnings
commit: b3b953084b1bd0e74785bc5017444dd56952fb39
[2/7] spi: spi-zynqmp-gqspi: Set CPOL and CPHA during hardware init
commit: 22742b8bbdd9fee1ae30be49c7e7e3becba96fc1
[3/7] spi: spi-zynqmp-gqspi: Avoid setting baud rate multiple times for same SPI frequency
commit: 21764a49d32e041e9d118a7b38c14e3e02fae129
[4/7] firmware: xilinx: Add qspi firmware interface
commit: 1e400cb9cff2157f89ca95aba4589f95253425ba
[5/7] spi: spi-zynqmp-gqspi: Add tap delay support for ZynqMP GQSPI Controller
commit: fae7b3c3ecd76a911a1f0e45d2258a420559cbf6
[6/7] spi: dt-bindings: zynqmp-qspi: Add support for Xilinx Versal QSPI
commit: 824590249b3cdf57d090d4c912f1497b8e61458f
[7/7] spi: spi-zynqmp-gqspi: Add tap delay support for GQSPI controller on Versal platform
commit: 29f4d95b97bcabc0cd83c34495224b24490f0fe0

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