arm64: versal: Add OSPI driver support

This patch adds support for OSPI driver to Versal platforms.
It uses cadence qspi driver with octal support and defines
DMA hooks that are required for performing DMA read operations.

Signed-off-by: Siva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
This commit is contained in:
Siva Durga Prasad Paladugu
2018-08-11 14:22:40 +05:30
committed by Michal Simek
parent 77f9d1dde4
commit 1497925b31
5 changed files with 84 additions and 0 deletions

View File

@@ -316,6 +316,7 @@ M: Michal Simek <michal.simek@xilinx.com>
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 <liviu.dudau@foss.arm.com>

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,67 @@
// SPDX-License-Identifier: GPL-2.0
/*
* (C) Copyright 2018 Xilinx
*
* Cadence QSPI controller DMA operations
*/
#include <clk.h>
#include <common.h>
#include <memalign.h>
#include <wait_bit.h>
#include <asm/io.h>
#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;
}

View File

@@ -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" \