diff --git a/MAINTAINERS b/MAINTAINERS index b4d0f148c1..9dcb99e1b1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -316,6 +316,7 @@ M: Michal Simek S: Maintained T: git git://git.denx.de/u-boot-microblaze.git F: arch/arm/mach-versal/ +F: drivers/spi/cadence_ospi_versal.c ARM VERSATILE EXPRESS DRIVERS M: Liviu Dudau diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index a7bb5b35c2..4c27c05b7e 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -87,6 +87,13 @@ config CADENCE_QSPI used to access the SPI NOR flash on platforms embedding this Cadence IP core. +config CADENCE_OSPI_VERSAL + bool "Configure Versal OSPI" + depends on ARCH_VERSAL && CADENCE_QSPI + help + This option is used to enable Versal OSPI DMA operations which + are used for ospi flash read using cadence qspi controller. + config DESIGNWARE_SPI bool "Designware SPI driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 392a925795..5bf998854b 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_BCM63XX_HSSPI) += bcm63xx_hsspi.o obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o obj-$(CONFIG_BCMSTB_SPI) += bcmstb_spi.o obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o +obj-$(CONFIG_CADENCE_OSPI_VERSAL) += cadence_ospi_versal.o obj-$(CONFIG_CF_SPI) += cf_spi.o obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o obj-$(CONFIG_DESIGNWARE_SPI) += designware_spi.o diff --git a/drivers/spi/cadence_ospi_versal.c b/drivers/spi/cadence_ospi_versal.c new file mode 100644 index 0000000000..ddcacd8876 --- /dev/null +++ b/drivers/spi/cadence_ospi_versal.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) Copyright 2018 Xilinx + * + * Cadence QSPI controller DMA operations + */ + +#include +#include +#include +#include +#include +#include "cadence_qspi.h" + +#define CQSPI_DMA_DST_ADDR_REG 0x1800 +#define CQSPI_DMA_DST_SIZE_REG 0x1804 +#define CQSPI_DMA_DST_STS_REG 0x1808 +#define CQSPI_DMA_DST_CTRL_REG 0x180C +#define CQSPI_DMA_DST_I_STS_REG 0x1814 +#define CQSPI_DMA_DST_I_ENBL_REG 0x1818 +#define CQSPI_DMA_DST_I_DISBL_REG 0x181C +#define CQSPI_DMA_DST_CTRL2_REG 0x1824 +#define CQSPI_DMA_DST_ADDR_MSB_REG 0x1828 + +#define CQSPI_DMA_SRC_RD_ADDR_REG 0x1000 + +#define CQSPI_REG_DMA_PERIPH_CFG 0x20 +#define CQSPI_REG_INDIR_TRIG_ADDR_RANGE 0x80 +#define CQSPI_DFLT_INDIR_TRIG_ADDR_RANGE 6 +#define CQSPI_DFLT_DMA_PERIPH_CFG 0x602 +#define CQSPI_DFLT_DST_CTRL_REG_VAL 0xF43FFA00 + +#define CQSPI_DMA_DST_I_STS_DONE BIT(1) +#define CQSPI_DMA_TIMEOUT 10000000 + +void cadence_qspi_apb_dma_read(struct cadence_spi_platdata *plat, + unsigned int n_rx, u8 *rxbuf) +{ + writel(CQSPI_DFLT_INDIR_TRIG_ADDR_RANGE, + plat->regbase + CQSPI_REG_INDIR_TRIG_ADDR_RANGE); + writel(CQSPI_DFLT_DMA_PERIPH_CFG, + plat->regbase + CQSPI_REG_DMA_PERIPH_CFG); + writel((unsigned long)rxbuf, plat->regbase + CQSPI_DMA_DST_ADDR_REG); + writel(0x0, plat->regbase + CQSPI_DMA_SRC_RD_ADDR_REG); + writel(roundup(n_rx, 4), plat->regbase + CQSPI_DMA_DST_SIZE_REG); + flush_dcache_range((unsigned long)rxbuf, (unsigned long)rxbuf + n_rx); + writel(CQSPI_DFLT_DST_CTRL_REG_VAL, + plat->regbase + CQSPI_DMA_DST_CTRL_REG); +} + +int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_platdata *plat) +{ + u32 timeout = CQSPI_DMA_TIMEOUT; + + while (!(readl(plat->regbase + CQSPI_DMA_DST_I_STS_REG) & + CQSPI_DMA_DST_I_STS_DONE) && timeout--) + udelay(1); + + if (!timeout) { + printf("DMA timeout\n"); + return -ETIMEDOUT; + } + + writel(readl(plat->regbase + CQSPI_DMA_DST_I_STS_REG), + plat->regbase + CQSPI_DMA_DST_I_STS_REG); + return 0; +} diff --git a/include/configs/xilinx_versal.h b/include/configs/xilinx_versal.h index bfe4c43449..ce548adcd4 100644 --- a/include/configs/xilinx_versal.h +++ b/include/configs/xilinx_versal.h @@ -30,6 +30,12 @@ # define COUNTER_FREQUENCY CONFIG_COUNTER_FREQUENCY #endif +/* + * TODO: This has to be be calculated later + * using clock framework. + */ +#define CONFIG_CQSPI_REF_CLK 200000000 + /* Serial setup */ #define CONFIG_ARM_DCC #define CONFIG_CPU_ARMV8 @@ -66,6 +72,8 @@ #define CONFIG_CLOCKS +#define CONFIG_SF_DEFAULT_SPEED 30000000 + #define ENV_MEM_LAYOUT_SETTINGS \ "fdt_high=10000000\0" \ "initrd_high=10000000\0" \