]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
spi: cadence-qspi: reset qspi flash for versal platform
authorT Karthik Reddy <t.karthik.reddy@xilinx.com>
Thu, 12 May 2022 10:05:33 +0000 (04:05 -0600)
committerMichal Simek <michal.simek@amd.com>
Wed, 29 Jun 2022 14:00:31 +0000 (16:00 +0200)
When flash operated at non default mode like DDR, flash need to be reset
to operate in SDR mode to read flash ids by spi-nor framework. Reset the
flash to the default state before using the flash. This reset is handled
by a gpio driver, in case of mini U-Boot as gpio driver is disabled, we
do raw read and write access by the registers.
Versal platform utilizes spi calibration for read delay programming, so
incase by default read delay property is set in DT. We make sure not to
use read delay from DT by overwriting read_delay with -1.

Signed-off-by: T Karthik Reddy <t.karthik.reddy@xilinx.com>
Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
Link: https://lore.kernel.org/r/20220512100535.16364-4-ashok.reddy.soma@xilinx.com
Signed-off-by: Michal Simek <michal.simek@amd.com>
arch/arm/mach-versal/include/mach/hardware.h
drivers/spi/cadence_ospi_versal.c
drivers/spi/cadence_qspi.c
drivers/spi/cadence_qspi.h
include/zynqmp_firmware.h

index 7b728ac1101813f4da1dcfe012ab17faa4378152..c52c9d979258b1ffca55a3d0e1db59b11916e089 100644 (file)
@@ -82,3 +82,14 @@ struct crp_regs {
 #define JTAG_MODE      0x00000000
 #define BOOT_MODE_USE_ALT      0x100
 #define BOOT_MODE_ALT_SHIFT    12
+
+#define FLASH_RESET_GPIO       0xc
+#define WPROT_CRP      0xF126001C
+#define RST_GPIO       0xF1260318
+#define WPROT_LPD_MIO  0xFF080728
+#define WPROT_PMC_MIO  0xF1060828
+#define BOOT_MODE_DIR  0xF1020204
+#define BOOT_MODE_OUT  0xF1020208
+#define MIO_PIN_12     0xF1060030
+#define BANK0_OUTPUT   0xF1020040
+#define BANK0_TRI      0xF1060200
index 4b13beb57a8d78e9ca5b6bb852ca50a6d04ecb7c..0caf25020343b5e1652306f84c4d46da8eabff50 100644 (file)
@@ -125,3 +125,89 @@ int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_plat *plat)
               plat->regbase + CQSPI_DMA_DST_I_STS_REG);
        return 0;
 }
+
+#if defined(CONFIG_DM_GPIO)
+int cadence_spi_versal_flash_reset(struct udevice *dev)
+{
+       struct gpio_desc gpio;
+       u32 reset_gpio;
+       int ret;
+
+       /* request gpio and set direction as output set to 1 */
+       ret = gpio_request_by_name(dev, "reset-gpios", 0, &gpio,
+                                  GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
+       if (ret) {
+               printf("%s: unable to reset ospi flash device", __func__);
+               return ret;
+       }
+
+       reset_gpio = PMIO_NODE_ID_BASE + gpio.offset;
+
+       /* Request for pin */
+       xilinx_pm_request(PM_PINCTRL_REQUEST, reset_gpio, 0, 0, 0, NULL);
+
+       /* Enable hysteresis in cmos receiver */
+       xilinx_pm_request(PM_PINCTRL_CONFIG_PARAM_SET, reset_gpio,
+                         PM_PINCTRL_CONFIG_SCHMITT_CMOS,
+                         PM_PINCTRL_INPUT_TYPE_SCHMITT, 0, NULL);
+
+       /* Disable Tri-state */
+       xilinx_pm_request(PM_PINCTRL_CONFIG_PARAM_SET, reset_gpio,
+                         PM_PINCTRL_CONFIG_TRI_STATE,
+                         PM_PINCTRL_TRI_STATE_DISABLE, 0, NULL);
+       udelay(1);
+
+       /* Set value 0 to pin */
+       dm_gpio_set_value(&gpio, 0);
+       udelay(1);
+
+       /* Set value 1 to pin */
+       dm_gpio_set_value(&gpio, 1);
+       udelay(1);
+
+       return 0;
+}
+#else
+int cadence_spi_versal_flash_reset(struct udevice *dev)
+{
+       /* CRP WPROT */
+       writel(0, WPROT_CRP);
+       /* GPIO Reset */
+       writel(0, RST_GPIO);
+
+       /* disable IOU write protection */
+       writel(0, WPROT_LPD_MIO);
+
+       /* set direction as output */
+       writel((readl(BOOT_MODE_DIR) | BIT(FLASH_RESET_GPIO)),
+              BOOT_MODE_POR_0);
+
+       /* Data output enable */
+       writel((readl(BOOT_MODE_OUT) | BIT(FLASH_RESET_GPIO)),
+              BOOT_MODE_POR_1);
+
+       /* IOU SLCR write enable */
+       writel(0, WPROT_PMC_MIO);
+
+       /* set MIO as GPIO */
+       writel(0x60, MIO_PIN_12);
+
+       /* Set value 1 to pin */
+       writel((readl(BANK0_OUTPUT) | BIT(FLASH_RESET_GPIO)), BANK0_OUTPUT);
+       udelay(10);
+
+       /* Disable Tri-state */
+       writel((readl(BANK0_TRI) & ~BIT(FLASH_RESET_GPIO)), BANK0_TRI);
+       udelay(1);
+
+       /* Set value 0 to pin */
+       writel((readl(BANK0_OUTPUT) & ~BIT(FLASH_RESET_GPIO)), BANK0_OUTPUT);
+       udelay(10);
+
+       /* Set value 1 to pin */
+       writel((readl(BANK0_OUTPUT) | BIT(FLASH_RESET_GPIO)), BANK0_OUTPUT);
+       udelay(10);
+
+       return 0;
+}
+#endif
index f1d3050d0767abe69453f7cb4714b3a0aa18d4a2..923c5f53182c68f9df0ae6c02d969bf1941d50a4 100644 (file)
@@ -33,6 +33,11 @@ __weak int cadence_qspi_apb_dma_read(struct cadence_spi_plat *plat,
        return 0;
 }
 
+__weak int cadence_qspi_versal_flash_reset(struct udevice *dev)
+{
+       return 0;
+}
+
 static int cadence_spi_write_speed(struct udevice *bus, uint hz)
 {
        struct cadence_spi_plat *plat = dev_get_plat(bus);
@@ -220,6 +225,16 @@ static int cadence_spi_probe(struct udevice *bus)
 
        plat->wr_delay = 50 * DIV_ROUND_UP(NSEC_PER_SEC, plat->ref_clk_hz);
 
+       if (CONFIG_IS_ENABLED(ARCH_VERSAL)) {
+               /* Versal platform uses spi calibration to set read delay */
+               if (plat->read_delay >= 0)
+                       plat->read_delay = -1;
+               /* Reset ospi flash device */
+               ret = cadence_qspi_versal_flash_reset(bus);
+               if (ret)
+                       return ret;
+       }
+
        return 0;
 }
 
index a201ed7c4e6ee1d04b30dcea44d71b62009c1d90..9d89e24ba49d1db20ef012f6ffd8bec160565d84 100644 (file)
@@ -283,5 +283,6 @@ int cadence_qspi_apb_dma_read(struct cadence_spi_plat *plat,
                              const struct spi_mem_op *op);
 int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_plat *plat);
 int cadence_qspi_apb_exec_flash_cmd(void *reg_base, unsigned int reg);
+int cadence_qspi_versal_flash_reset(struct udevice *dev);
 
 #endif /* __CADENCE_QSPI_H__ */
index 76ec2141ff6a80fc73965718a294ee349f5035dc..6a5f01c839145adb4a1f8570a79a155732ec54e9 100644 (file)
@@ -428,6 +428,8 @@ enum pm_gem_config_type {
 
 #define PMUFW_V1_0     ((1 << ZYNQMP_PM_VERSION_MAJOR_SHIFT) | 0)
 
+#define PMIO_NODE_ID_BASE              0x1410801B
+
 /*
  * Return payload size
  * Not every firmware call expects the same amount of return bytes, however the