lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Tue, 5 Apr 2022 16:30:37 +0530
From:   Sai Krishna Potthuri <lakshmi.sai.krishna.potthuri@...inx.com>
To:     Mark Brown <broonie@...nel.org>, Rob Herring <robh+dt@...nel.org>,
        Pratyush Yadav <p.yadav@...com>
CC:     <linux-kernel@...r.kernel.org>, <devicetree@...r.kernel.org>,
        <linux-spi@...r.kernel.org>,
        Michal Simek <michal.simek@...inx.com>, <git@...inx.com>,
        <saikrishna12468@...il.com>, <sgoud@...inx.com>,
        "Sai Krishna Potthuri" <lakshmi.sai.krishna.potthuri@...inx.com>
Subject: [PATCH 2/2] spi: cadence-quadspi: Add support for OSPI device reset

Cadence OSPI controller always start in SDR mode and it doesn't know
the current mode of the flash device (SDR or DDR). This creates issue
during Cadence OSPI driver probe if OSPI flash device is in DDR mode.
This patch add OSPI flash device reset using HW reset pin for Xilinx
Versal platform, this will make sure both Controller and Flash device
are in same mode (SDR).
Xilinx Versal platform has a dedicated pin used for OSPI device reset.
As part of the reset sequence, configure the pin to enable
hysteresis and set the direction of the pin to output before toggling
the pin. Provided the required delay ranges while toggling the pin to
meet the most of the OSPI flash devices reset pulse width, reset recovery
and CS high to reset high timings.

Signed-off-by: Sai Krishna Potthuri <lakshmi.sai.krishna.potthuri@...inx.com>
---
 drivers/spi/spi-cadence-quadspi.c | 72 +++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
index b808c94641fa..6e5b5b180347 100644
--- a/drivers/spi/spi-cadence-quadspi.c
+++ b/drivers/spi/spi-cadence-quadspi.c
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
@@ -96,6 +97,7 @@ struct cqspi_driver_platdata {
 	int (*indirect_read_dma)(struct cqspi_flash_pdata *f_pdata,
 				 u_char *rxbuf, loff_t from_addr, size_t n_rx);
 	u32 (*get_dma_status)(struct cqspi_st *cqspi);
+	int (*device_hw_reset)(struct cqspi_st *cqspi);
 };
 
 /* Operation timeout value */
@@ -281,6 +283,7 @@ struct cqspi_driver_platdata {
 #define CQSPI_DMA_UNALIGN		0x3
 
 #define CQSPI_REG_VERSAL_DMA_VAL		0x602
+#define CQSPI_VERSAL_MIO_NODE_ID_12	0x14108027
 
 static int cqspi_wait_for_bit(void __iomem *reg, const u32 mask, bool clr)
 {
@@ -835,6 +838,68 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
 	return ret;
 }
 
+static int cqspi_versal_device_reset(struct cqspi_st *cqspi)
+{
+	struct platform_device *pdev = cqspi->pdev;
+	int ret;
+	int gpio;
+	enum of_gpio_flags flags;
+
+	gpio = of_get_named_gpio_flags(pdev->dev.of_node,
+				       "reset-gpios", 0, &flags);
+	if (!gpio_is_valid(gpio))
+		return gpio;
+
+	ret = devm_gpio_request_one(&pdev->dev, gpio, flags,
+				    "flash-reset");
+	if (ret) {
+		dev_err(&pdev->dev,
+			"failed to get reset-gpios: %d\n", ret);
+		return ret;
+	}
+
+	/* Request for PIN */
+	ret = zynqmp_pm_pinctrl_request(CQSPI_VERSAL_MIO_NODE_ID_12);
+	if (ret)
+		return ret;
+
+	/* Enable hysteresis in cmos receiver */
+	ret = zynqmp_pm_pinctrl_set_config(CQSPI_VERSAL_MIO_NODE_ID_12,
+					   PM_PINCTRL_CONFIG_SCHMITT_CMOS,
+					   PM_PINCTRL_INPUT_TYPE_SCHMITT);
+	if (ret)
+		return ret;
+
+	/* Set the direction as output and enable the output */
+	gpio_direction_output(gpio, 1);
+
+	/*
+	 * Experimental Minimum Chip select high to Reset delay value
+	 * based on the supported OSPI flash device spec.
+	 */
+	usleep_range(1, 5);
+
+	/* Set value 0 to pin */
+	gpio_set_value(gpio, 0);
+
+	/*
+	 * Experimental Minimum Reset pulse width value based on the
+	 * supported OSPI flash device spec.
+	 */
+	usleep_range(10, 15);
+
+	/* Set value 1 to pin */
+	gpio_set_value(gpio, 1);
+
+	/*
+	 * Experimental Minimum Reset recovery delay value based on the
+	 * supported OSPI flash device spec.
+	 */
+	usleep_range(35, 40);
+
+	return 0;
+}
+
 static int cqspi_versal_indirect_read_dma(struct cqspi_flash_pdata *f_pdata,
 					  u_char *rxbuf, loff_t from_addr,
 					  size_t n_rx)
@@ -1783,6 +1848,12 @@ static int cqspi_probe(struct platform_device *pdev)
 		goto probe_setup_failed;
 	}
 
+	if (ddata->device_hw_reset) {
+		ret = ddata->device_hw_reset(cqspi);
+		if (ret)
+			goto probe_setup_failed;
+	}
+
 	if (cqspi->use_direct_mode) {
 		ret = cqspi_request_mmap_dma(cqspi);
 		if (ret == -EPROBE_DEFER)
@@ -1878,6 +1949,7 @@ static const struct cqspi_driver_platdata versal_ospi = {
 	.quirks = CQSPI_DISABLE_DAC_MODE | CQSPI_SUPPORT_EXTERNAL_DMA,
 	.indirect_read_dma = cqspi_versal_indirect_read_dma,
 	.get_dma_status = cqspi_get_versal_dma_status,
+	.device_hw_reset = cqspi_versal_device_reset,
 };
 
 static const struct of_device_id cqspi_dt_ids[] = {
-- 
2.17.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ