diff options
-rw-r--r-- | arch/arm/mach-versal/include/mach/hardware.h | 11 | ||||
-rw-r--r-- | drivers/spi/cadence_ospi_versal.c | 86 | ||||
-rw-r--r-- | drivers/spi/cadence_qspi.c | 15 | ||||
-rw-r--r-- | drivers/spi/cadence_qspi.h | 1 | ||||
-rw-r--r-- | include/zynqmp_firmware.h | 2 |
5 files changed, 115 insertions, 0 deletions
diff --git a/arch/arm/mach-versal/include/mach/hardware.h b/arch/arm/mach-versal/include/mach/hardware.h index 7b728ac110..c52c9d9792 100644 --- a/arch/arm/mach-versal/include/mach/hardware.h +++ b/arch/arm/mach-versal/include/mach/hardware.h @@ -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 diff --git a/drivers/spi/cadence_ospi_versal.c b/drivers/spi/cadence_ospi_versal.c index 4b13beb57a..0caf250203 100644 --- a/drivers/spi/cadence_ospi_versal.c +++ b/drivers/spi/cadence_ospi_versal.c @@ -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 diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index f1d3050d07..923c5f5318 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -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; } diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h index a201ed7c4e..9d89e24ba4 100644 --- a/drivers/spi/cadence_qspi.h +++ b/drivers/spi/cadence_qspi.h @@ -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__ */ diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h index 76ec2141ff..6a5f01c839 100644 --- a/include/zynqmp_firmware.h +++ b/include/zynqmp_firmware.h @@ -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 |