diff options
author | Tom Rini <trini@konsulko.com> | 2022-06-30 16:32:15 +0300 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2022-06-30 16:32:15 +0300 |
commit | c5e7003aa86e1bfc7371d41509e8d34cafdfeb6c (patch) | |
tree | e2786f7a1fae42434590bc2f01454337449391d7 /drivers | |
parent | 5c873269fc374674e5e8aad65ab4ed45b1fe9f65 (diff) | |
parent | 2c27fdc0705251f594ecee3de0ea195ea421e05e (diff) | |
download | u-boot-c5e7003aa86e1bfc7371d41509e8d34cafdfeb6c.tar.xz |
Merge tag 'versal-qspi-for-v2022.10' of https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze into next
Versal QSPI/OSPI changes for v2022.10
- Add new flash types
- Add cadence ospi driver for Xilinx Versal
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mtd/spi/spi-nor-ids.c | 37 | ||||
-rw-r--r-- | drivers/spi/Kconfig | 8 | ||||
-rw-r--r-- | drivers/spi/Makefile | 1 | ||||
-rw-r--r-- | drivers/spi/cadence_ospi_versal.c | 237 | ||||
-rw-r--r-- | drivers/spi/cadence_qspi.c | 40 | ||||
-rw-r--r-- | drivers/spi/cadence_qspi.h | 189 | ||||
-rw-r--r-- | drivers/spi/cadence_qspi_apb.c | 163 |
7 files changed, 520 insertions, 155 deletions
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c index 20cd4d7fc9..67278c40e3 100644 --- a/drivers/mtd/spi/spi-nor-ids.c +++ b/drivers/mtd/spi/spi-nor-ids.c @@ -82,6 +82,7 @@ const struct flash_info spi_nor_ids[] = { /* EON -- en25xxx */ { INFO("en25q32b", 0x1c3016, 0, 64 * 1024, 64, 0) }, { INFO("en25q64", 0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, + { INFO("en25q128b", 0x1c3018, 0, 64 * 1024, 256, 0) }, { INFO("en25qh128", 0x1c7018, 0, 64 * 1024, 256, 0) }, { INFO("en25s64", 0x1c3817, 0, 64 * 1024, 128, SECT_4K) }, #endif @@ -127,11 +128,17 @@ const struct flash_info spi_nor_ids[] = { SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, + { + INFO("gd25lx256e", 0xc86819, 0, 64 * 1024, 512, + SECT_4K | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) + }, #endif #ifdef CONFIG_SPI_FLASH_ISSI /* ISSI */ /* ISSI */ { INFO("is25lq040b", 0x9d4013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("is25lp008", 0x9d6014, 0, 64 * 1024, 16, SPI_NOR_QUAD_READ) }, + { INFO("is25lp016", 0x9d6015, 0, 64 * 1024, 32, SPI_NOR_QUAD_READ) }, { INFO("is25lp032", 0x9d6016, 0, 64 * 1024, 64, 0) }, { INFO("is25lp064", 0x9d6017, 0, 64 * 1024, 128, 0) }, { INFO("is25lp128", 0x9d6018, 0, 64 * 1024, 256, @@ -140,6 +147,10 @@ const struct flash_info spi_nor_ids[] = { SECT_4K | SPI_NOR_DUAL_READ) }, { INFO("is25lp512", 0x9d601a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("is25lp01g", 0x9d601b, 0, 64 * 1024, 2048, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("is25wp008", 0x9d7014, 0, 64 * 1024, 16, SPI_NOR_QUAD_READ) }, + { INFO("is25wp016", 0x9d7015, 0, 64 * 1024, 32, SPI_NOR_QUAD_READ) }, { INFO("is25wp032", 0x9d7016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { INFO("is25wp064", 0x9d7017, 0, 64 * 1024, 128, @@ -151,6 +162,10 @@ const struct flash_info spi_nor_ids[] = { SPI_NOR_4B_OPCODES) }, { INFO("is25wp512", 0x9d701a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("is25wp01g", 0x9d701b, 0, 64 * 1024, 2048, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("is25wx256", 0x9d5b19, 0, 128 * 1024, 256, + SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) }, #endif #ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */ /* Macronix */ @@ -176,8 +191,11 @@ const struct flash_info spi_nor_ids[] = { { INFO("mx25l25655e", 0xc22619, 0, 64 * 1024, 512, 0) }, { INFO("mx66l51235l", 0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { INFO("mx66u51235f", 0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx25u51245f", 0xc2953a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("mx66u1g45g", 0xc2253b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { INFO("mx66u2g45g", 0xc2253c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { INFO("mx66l1g45g", 0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("mx66l2g45g", 0xc2201c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { INFO("mx25l1633e", 0xc22415, 0, 64 * 1024, 32, SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | SECT_4K) }, { INFO("mx25r6435f", 0xc22817, 0, 64 * 1024, 128, SECT_4K) }, { INFO("mx66uw2g345g", 0xc2943c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) }, @@ -208,8 +226,10 @@ const struct flash_info spi_nor_ids[] = { { INFO("mt25qu02g", 0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, { INFO("mt25ql02g", 0x20ba22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE | SPI_NOR_4B_OPCODES) }, #ifdef CONFIG_SPI_FLASH_MT35XU + { INFO("mt35xl512aba", 0x2c5a1a, 0, 128 * 1024, 512, USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES | SPI_NOR_OCTAL_DTR_READ) }, { INFO("mt35xu512aba", 0x2c5b1a, 0, 128 * 1024, 512, USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES | SPI_NOR_OCTAL_DTR_READ) }, #endif /* CONFIG_SPI_FLASH_MT35XU */ + { INFO6("mt35xu01g", 0x2c5b1b, 0x104100, 128 * 1024, 1024, USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) }, { INFO("mt35xu02g", 0x2c5b1c, 0, 128 * 1024, 2048, USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) }, #endif #ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */ @@ -225,6 +245,7 @@ const struct flash_info spi_nor_ids[] = { { INFO("s25fl512s_256k", 0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, { INFO("s25fl512s_64k", 0x010220, 0x4d01, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, { INFO("s25fl512s_512k", 0x010220, 0x4f00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, + { INFO("s70fs01gs_256k", 0x010221, 0x4d00, 256 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { INFO("s25sl12800", 0x012018, 0x0300, 256 * 1024, 64, 0) }, { INFO("s25sl12801", 0x012018, 0x0301, 64 * 1024, 256, 0) }, { INFO6("s25fl128s", 0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, @@ -275,6 +296,7 @@ const struct flash_info spi_nor_ids[] = { { INFO("sst25wf040", 0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, { INFO("sst25wf080", 0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, { INFO("sst26vf064b", 0xbf2643, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_HAS_SST26LOCK | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("sst26wf016b", 0xbf2641, 0, 64 * 1024, 32, SECT_4K) }, { INFO("sst26wf016", 0xbf2651, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_HAS_SST26LOCK) }, { INFO("sst26wf032", 0xbf2622, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_SST26LOCK) }, { INFO("sst26wf064", 0xbf2643, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_HAS_SST26LOCK) }, @@ -312,11 +334,19 @@ const struct flash_info spi_nor_ids[] = { { INFO("w25q20ew", 0xef6012, 0, 64 * 1024, 4, SECT_4K) }, { INFO("w25q32", 0xef4016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { + INFO("w25q16dw", 0xef6015, 0, 64 * 1024, 32, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) + }, + { INFO("w25q32dw", 0xef6016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { + INFO("w25q16jv", 0xef7015, 0, 64 * 1024, 32, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) + }, + { INFO("w25q32jv", 0xef7016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) @@ -363,6 +393,11 @@ const struct flash_info spi_nor_ids[] = { SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { + INFO("w25q512jv", 0xef7119, 0, 64 * 1024, 512, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { INFO("w25q01jv", 0xef4021, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) @@ -370,6 +405,7 @@ const struct flash_info spi_nor_ids[] = { { INFO("w25q80", 0xef5014, 0, 64 * 1024, 16, SECT_4K) }, { INFO("w25q80bl", 0xef4014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { INFO("w25q16cl", 0xef4015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("w25q32bv", 0xef4016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { INFO("w25q64cv", 0xef4017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { INFO("w25q128", 0xef4018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | @@ -378,6 +414,7 @@ const struct flash_info spi_nor_ids[] = { { INFO("w25q256", 0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { INFO("w25m512jw", 0xef6119, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { INFO("w25m512jv", 0xef7119, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("w25h02jv", 0xef9022, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, #endif #ifdef CONFIG_SPI_FLASH_XMC /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */ diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index e48d72d744..766d5636c0 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -136,6 +136,14 @@ config CQSPI_REF_CLK int "Cadence QSPI reference clock value in Hz" depends on HAS_CQSPI_REF_CLK +config CADENCE_OSPI_VERSAL + bool "Configure Versal OSPI" + depends on ARCH_VERSAL && CADENCE_QSPI + imply DM_GPIO + help + This option is used to enable Versal OSPI DMA operations which + are used for ospi flash read using cadence qspi controller. + config CF_SPI bool "ColdFire SPI driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 8755408e62..4de77c260a 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -7,6 +7,7 @@ ifdef CONFIG_$(SPL_TPL_)DM_SPI obj-y += spi-uclass.o obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o +obj-$(CONFIG_CADENCE_OSPI_VERSAL) += cadence_ospi_versal.o obj-$(CONFIG_SANDBOX) += spi-emul-uclass.o obj-$(CONFIG_SOFT_SPI) += soft_spi.o obj-$(CONFIG_SPI_MEM) += spi-mem.o diff --git a/drivers/spi/cadence_ospi_versal.c b/drivers/spi/cadence_ospi_versal.c new file mode 100644 index 0000000000..52bcad053f --- /dev/null +++ b/drivers/spi/cadence_ospi_versal.c @@ -0,0 +1,237 @@ +// 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 <asm/gpio.h> +#include <asm/cache.h> +#include <cpu_func.h> +#include <zynqmp_firmware.h> +#include <asm/arch/hardware.h> +#include "cadence_qspi.h" +#include <dt-bindings/power/xlnx-versal-power.h> + +#define CMD_4BYTE_READ 0x13 +#define CMD_4BYTE_FAST_READ 0x0C + +int cadence_qspi_apb_dma_read(struct cadence_spi_plat *plat, + const struct spi_mem_op *op) +{ + u32 reg, ret, rx_rem, n_rx, bytes_to_dma, data; + u8 opcode, addr_bytes, *rxbuf, dummy_cycles; + + n_rx = op->data.nbytes; + rxbuf = op->data.buf.in; + rx_rem = n_rx % 4; + bytes_to_dma = n_rx - rx_rem; + + if (bytes_to_dma) { + cadence_qspi_apb_enable_linear_mode(false); + reg = readl(plat->regbase + CQSPI_REG_CONFIG); + reg |= CQSPI_REG_CONFIG_ENBL_DMA; + writel(reg, plat->regbase + CQSPI_REG_CONFIG); + + writel(bytes_to_dma, plat->regbase + CQSPI_REG_INDIRECTRDBYTES); + + 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(plat->trigger_address, plat->regbase + + CQSPI_DMA_SRC_RD_ADDR_REG); + writel(bytes_to_dma, plat->regbase + + CQSPI_DMA_DST_SIZE_REG); + flush_dcache_range((unsigned long)rxbuf, + (unsigned long)rxbuf + bytes_to_dma); + writel(CQSPI_DFLT_DST_CTRL_REG_VAL, + plat->regbase + CQSPI_DMA_DST_CTRL_REG); + + /* Start the indirect read transfer */ + writel(CQSPI_REG_INDIRECTRD_START, plat->regbase + + CQSPI_REG_INDIRECTRD); + /* Wait for dma to complete transfer */ + ret = cadence_qspi_apb_wait_for_dma_cmplt(plat); + if (ret) + return ret; + + /* Clear indirect completion status */ + writel(CQSPI_REG_INDIRECTRD_DONE, plat->regbase + + CQSPI_REG_INDIRECTRD); + rxbuf += bytes_to_dma; + } + + if (rx_rem) { + reg = readl(plat->regbase + CQSPI_REG_CONFIG); + reg &= ~CQSPI_REG_CONFIG_ENBL_DMA; + writel(reg, plat->regbase + CQSPI_REG_CONFIG); + + reg = readl(plat->regbase + CQSPI_REG_INDIRECTRDSTARTADDR); + reg += bytes_to_dma; + writel(reg, plat->regbase + CQSPI_REG_CMDADDRESS); + + addr_bytes = readl(plat->regbase + CQSPI_REG_SIZE) & + CQSPI_REG_SIZE_ADDRESS_MASK; + + opcode = CMD_4BYTE_FAST_READ; + dummy_cycles = 8; + writel((dummy_cycles << CQSPI_REG_RD_INSTR_DUMMY_LSB) | opcode, + plat->regbase + CQSPI_REG_RD_INSTR); + + reg = opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB; + reg |= (0x1 << CQSPI_REG_CMDCTRL_RD_EN_LSB); + reg |= (addr_bytes & CQSPI_REG_CMDCTRL_ADD_BYTES_MASK) << + CQSPI_REG_CMDCTRL_ADD_BYTES_LSB; + reg |= (0x1 << CQSPI_REG_CMDCTRL_ADDR_EN_LSB); + dummy_cycles = (readl(plat->regbase + CQSPI_REG_RD_INSTR) >> + CQSPI_REG_RD_INSTR_DUMMY_LSB) & + CQSPI_REG_RD_INSTR_DUMMY_MASK; + reg |= (dummy_cycles & CQSPI_REG_CMDCTRL_DUMMY_MASK) << + CQSPI_REG_CMDCTRL_DUMMY_LSB; + reg |= (((rx_rem - 1) & CQSPI_REG_CMDCTRL_RD_BYTES_MASK) << + CQSPI_REG_CMDCTRL_RD_BYTES_LSB); + ret = cadence_qspi_apb_exec_flash_cmd(plat->regbase, reg); + if (ret) + return ret; + + data = readl(plat->regbase + CQSPI_REG_CMDREADDATALOWER); + memcpy(rxbuf, &data, rx_rem); + } + + return 0; +} + +int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_plat *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; +} + +#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 + +void cadence_qspi_apb_enable_linear_mode(bool enable) +{ + if (CONFIG_IS_ENABLED(ZYNQMP_FIRMWARE)) { + if (enable) + /* ahb read mode */ + xilinx_pm_request(PM_IOCTL, PM_DEV_OSPI, + IOCTL_OSPI_MUX_SELECT, + PM_OSPI_MUX_SEL_LINEAR, 0, NULL); + else + /* DMA mode */ + xilinx_pm_request(PM_IOCTL, PM_DEV_OSPI, + IOCTL_OSPI_MUX_SELECT, + PM_OSPI_MUX_SEL_DMA, 0, NULL); + } else { + if (enable) + writel(readl(VERSAL_AXI_MUX_SEL) | + VERSAL_OSPI_LINEAR_MODE, VERSAL_AXI_MUX_SEL); + else + writel(readl(VERSAL_AXI_MUX_SEL) & + ~VERSAL_OSPI_LINEAR_MODE, VERSAL_AXI_MUX_SEL); + } +} diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index 7209bb43a7..907f5dadc4 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -18,7 +18,9 @@ #include <linux/err.h> #include <linux/errno.h> #include <linux/sizes.h> +#include <zynqmp_firmware.h> #include "cadence_qspi.h" +#include <dt-bindings/power/xlnx-versal-power.h> #define NSEC_PER_SEC 1000000000L @@ -27,6 +29,17 @@ #define CQSPI_READ 2 #define CQSPI_WRITE 3 +__weak int cadence_qspi_apb_dma_read(struct cadence_spi_plat *plat, + const struct spi_mem_op *op) +{ + 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); @@ -138,7 +151,7 @@ static int cadence_spi_set_speed(struct udevice *bus, uint hz) struct cadence_spi_priv *priv = dev_get_priv(bus); int err; - if (hz > plat->max_hz) + if (!hz || hz > plat->max_hz) hz = plat->max_hz; /* Disable QSPI */ @@ -185,6 +198,11 @@ static int cadence_spi_probe(struct udevice *bus) priv->regbase = plat->regbase; priv->ahbbase = plat->ahbbase; + if (CONFIG_IS_ENABLED(ZYNQMP_FIRMWARE)) + xilinx_pm_request(PM_REQUEST_NODE, PM_DEV_OSPI, + ZYNQMP_PM_CAPABILITY_ACCESS, ZYNQMP_PM_MAX_QOS, + ZYNQMP_PM_REQUEST_ACK_NO, NULL); + if (plat->ref_clk_hz == 0) { ret = clk_get_by_index(bus, 0, &clk); if (ret) { @@ -214,6 +232,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; } @@ -288,8 +316,12 @@ static int cadence_spi_mem_exec_op(struct spi_slave *spi, break; case CQSPI_READ: err = cadence_qspi_apb_read_setup(plat, op); - if (!err) - err = cadence_qspi_apb_read_execute(plat, op); + if (!err) { + if (plat->is_dma) + err = cadence_qspi_apb_dma_read(plat, op); + else + err = cadence_qspi_apb_read_execute(plat, op); + } break; case CQSPI_WRITE: err = cadence_qspi_apb_write_setup(plat, op); @@ -342,6 +374,8 @@ static int cadence_spi_of_to_plat(struct udevice *bus) if (plat->ahbsize >= SZ_8M) plat->use_dac_mode = true; + plat->is_dma = dev_read_bool(bus, "cdns,is-dma"); + /* All other paramters are embedded in the child node */ subnode = dev_read_first_subnode(bus); if (!ofnode_valid(subnode)) { diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h index a2b620a5fe..c8d16bb0e4 100644 --- a/drivers/spi/cadence_qspi.h +++ b/drivers/spi/cadence_qspi.h @@ -8,6 +8,8 @@ #define __CADENCE_QSPI_H__ #include <reset.h> +#include <linux/mtd/spi-nor.h> +#include <spi-mem.h> #define CQSPI_IS_ADDR(cmd_len) (cmd_len > 1 ? 1 : 0) @@ -15,6 +17,186 @@ #define CQSPI_DECODER_MAX_CS 16 #define CQSPI_READ_CAPTURE_MAX_DELAY 16 +#define CQSPI_REG_POLL_US 1 /* 1us */ +#define CQSPI_REG_RETRY 10000 +#define CQSPI_POLL_IDLE_RETRY 3 + +/* Transfer mode */ +#define CQSPI_INST_TYPE_SINGLE 0 +#define CQSPI_INST_TYPE_DUAL 1 +#define CQSPI_INST_TYPE_QUAD 2 +#define CQSPI_INST_TYPE_OCTAL 3 + +#define CQSPI_STIG_DATA_LEN_MAX 8 + +#define CQSPI_DUMMY_CLKS_PER_BYTE 8 +#define CQSPI_DUMMY_BYTES_MAX 4 +#define CQSPI_DUMMY_CLKS_MAX 31 + +/**************************************************************************** + * Controller's configuration and status register (offset from QSPI_BASE) + ****************************************************************************/ +#define CQSPI_REG_CONFIG 0x00 +#define CQSPI_REG_CONFIG_ENABLE BIT(0) +#define CQSPI_REG_CONFIG_CLK_POL BIT(1) +#define CQSPI_REG_CONFIG_CLK_PHA BIT(2) +#define CQSPI_REG_CONFIG_PHY_ENABLE_MASK BIT(3) +#define CQSPI_REG_CONFIG_DIRECT BIT(7) +#define CQSPI_REG_CONFIG_DECODE BIT(9) +#define CQSPI_REG_CONFIG_ENBL_DMA BIT(15) +#define CQSPI_REG_CONFIG_XIP_IMM BIT(18) +#define CQSPI_REG_CONFIG_DTR_PROT_EN_MASK BIT(24) +#define CQSPI_REG_CONFIG_CHIPSELECT_LSB 10 +#define CQSPI_REG_CONFIG_BAUD_LSB 19 +#define CQSPI_REG_CONFIG_DTR_PROTO BIT(24) +#define CQSPI_REG_CONFIG_DUAL_OPCODE BIT(30) +#define CQSPI_REG_CONFIG_IDLE_LSB 31 +#define CQSPI_REG_CONFIG_CHIPSELECT_MASK 0xF +#define CQSPI_REG_CONFIG_BAUD_MASK 0xF + +#define CQSPI_REG_RD_INSTR 0x04 +#define CQSPI_REG_RD_INSTR_OPCODE_LSB 0 +#define CQSPI_REG_RD_INSTR_TYPE_INSTR_LSB 8 +#define CQSPI_REG_RD_INSTR_TYPE_ADDR_LSB 12 +#define CQSPI_REG_RD_INSTR_TYPE_DATA_LSB 16 +#define CQSPI_REG_RD_INSTR_MODE_EN_LSB 20 +#define CQSPI_REG_RD_INSTR_DUMMY_LSB 24 +#define CQSPI_REG_RD_INSTR_TYPE_INSTR_MASK 0x3 +#define CQSPI_REG_RD_INSTR_TYPE_ADDR_MASK 0x3 +#define CQSPI_REG_RD_INSTR_TYPE_DATA_MASK 0x3 +#define CQSPI_REG_RD_INSTR_DUMMY_MASK 0x1F + +#define CQSPI_REG_WR_INSTR 0x08 +#define CQSPI_REG_WR_INSTR_OPCODE_LSB 0 +#define CQSPI_REG_WR_INSTR_TYPE_ADDR_LSB 12 +#define CQSPI_REG_WR_INSTR_TYPE_DATA_LSB 16 + +#define CQSPI_REG_DELAY 0x0C +#define CQSPI_REG_DELAY_TSLCH_LSB 0 +#define CQSPI_REG_DELAY_TCHSH_LSB 8 +#define CQSPI_REG_DELAY_TSD2D_LSB 16 +#define CQSPI_REG_DELAY_TSHSL_LSB 24 +#define CQSPI_REG_DELAY_TSLCH_MASK 0xFF +#define CQSPI_REG_DELAY_TCHSH_MASK 0xFF +#define CQSPI_REG_DELAY_TSD2D_MASK 0xFF +#define CQSPI_REG_DELAY_TSHSL_MASK 0xFF + +#define CQSPI_REG_RD_DATA_CAPTURE 0x10 +#define CQSPI_REG_RD_DATA_CAPTURE_BYPASS BIT(0) +#define CQSPI_REG_READCAPTURE_DQS_ENABLE BIT(8) +#define CQSPI_REG_RD_DATA_CAPTURE_DELAY_LSB 1 +#define CQSPI_REG_RD_DATA_CAPTURE_DELAY_MASK 0xF + +#define CQSPI_REG_SIZE 0x14 +#define CQSPI_REG_SIZE_ADDRESS_LSB 0 +#define CQSPI_REG_SIZE_PAGE_LSB 4 +#define CQSPI_REG_SIZE_BLOCK_LSB 16 +#define CQSPI_REG_SIZE_ADDRESS_MASK 0xF +#define CQSPI_REG_SIZE_PAGE_MASK 0xFFF +#define CQSPI_REG_SIZE_BLOCK_MASK 0x3F + +#define CQSPI_REG_SRAMPARTITION 0x18 +#define CQSPI_REG_INDIRECTTRIGGER 0x1C + +#define CQSPI_REG_REMAP 0x24 +#define CQSPI_REG_MODE_BIT 0x28 + +#define CQSPI_REG_SDRAMLEVEL 0x2C +#define CQSPI_REG_SDRAMLEVEL_RD_LSB 0 +#define CQSPI_REG_SDRAMLEVEL_WR_LSB 16 +#define CQSPI_REG_SDRAMLEVEL_RD_MASK 0xFFFF +#define CQSPI_REG_SDRAMLEVEL_WR_MASK 0xFFFF + +#define CQSPI_REG_WR_COMPLETION_CTRL 0x38 +#define CQSPI_REG_WR_DISABLE_AUTO_POLL BIT(14) + +#define CQSPI_REG_IRQSTATUS 0x40 +#define CQSPI_REG_IRQMASK 0x44 + +#define CQSPI_REG_INDIRECTRD 0x60 +#define CQSPI_REG_INDIRECTRD_START BIT(0) +#define CQSPI_REG_INDIRECTRD_CANCEL BIT(1) +#define CQSPI_REG_INDIRECTRD_INPROGRESS BIT(2) +#define CQSPI_REG_INDIRECTRD_DONE BIT(5) + +#define CQSPI_REG_INDIRECTRDWATERMARK 0x64 +#define CQSPI_REG_INDIRECTRDSTARTADDR 0x68 +#define CQSPI_REG_INDIRECTRDBYTES 0x6C + +#define CQSPI_REG_CMDCTRL 0x90 +#define CQSPI_REG_CMDCTRL_EXECUTE BIT(0) +#define CQSPI_REG_CMDCTRL_INPROGRESS BIT(1) +#define CQSPI_REG_CMDCTRL_DUMMY_LSB 7 +#define CQSPI_REG_CMDCTRL_WR_BYTES_LSB 12 +#define CQSPI_REG_CMDCTRL_WR_EN_LSB 15 +#define CQSPI_REG_CMDCTRL_ADD_BYTES_LSB 16 +#define CQSPI_REG_CMDCTRL_ADDR_EN_LSB 19 +#define CQSPI_REG_CMDCTRL_RD_BYTES_LSB 20 +#define CQSPI_REG_CMDCTRL_RD_EN_LSB 23 +#define CQSPI_REG_CMDCTRL_OPCODE_LSB 24 +#define CQSPI_REG_CMDCTRL_DUMMY_MASK 0x1F +#define CQSPI_REG_CMDCTRL_WR_BYTES_MASK 0x7 +#define CQSPI_REG_CMDCTRL_ADD_BYTES_MASK 0x3 +#define CQSPI_REG_CMDCTRL_RD_BYTES_MASK 0x7 +#define CQSPI_REG_CMDCTRL_OPCODE_MASK 0xFF + +#define CQSPI_REG_INDIRECTWR 0x70 +#define CQSPI_REG_INDIRECTWR_START BIT(0) +#define CQSPI_REG_INDIRECTWR_CANCEL BIT(1) +#define CQSPI_REG_INDIRECTWR_INPROGRESS BIT(2) +#define CQSPI_REG_INDIRECTWR_DONE BIT(5) + +#define CQSPI_REG_INDIRECTWRWATERMARK 0x74 +#define CQSPI_REG_INDIRECTWRSTARTADDR 0x78 +#define CQSPI_REG_INDIRECTWRBYTES 0x7C + +#define CQSPI_REG_CMDADDRESS 0x94 +#define CQSPI_REG_CMDREADDATALOWER 0xA0 +#define CQSPI_REG_CMDREADDATAUPPER 0xA4 +#define CQSPI_REG_CMDWRITEDATALOWER 0xA8 +#define CQSPI_REG_CMDWRITEDATAUPPER 0xAC + +#define CQSPI_REG_OP_EXT_LOWER 0xE0 +#define CQSPI_REG_OP_EXT_READ_LSB 24 +#define CQSPI_REG_OP_EXT_WRITE_LSB 16 +#define CQSPI_REG_OP_EXT_STIG_LSB 0 + +#define CQSPI_REG_PHY_CONFIG 0xB4 +#define CQSPI_REG_PHY_CONFIG_RESET_FLD_MASK 0x40000000 + +#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 + +#define CQSPI_REG_IS_IDLE(base) \ + ((readl((base) + CQSPI_REG_CONFIG) >> \ + CQSPI_REG_CONFIG_IDLE_LSB) & 0x1) + +#define CQSPI_GET_RD_SRAM_LEVEL(reg_base) \ + (((readl((reg_base) + CQSPI_REG_SDRAMLEVEL)) >> \ + CQSPI_REG_SDRAMLEVEL_RD_LSB) & CQSPI_REG_SDRAMLEVEL_RD_MASK) + +#define CQSPI_GET_WR_SRAM_LEVEL(reg_base) \ + (((readl((reg_base) + CQSPI_REG_SDRAMLEVEL)) >> \ + CQSPI_REG_SDRAMLEVEL_WR_LSB) & CQSPI_REG_SDRAMLEVEL_WR_MASK) + struct cadence_spi_plat { unsigned int ref_clk_hz; unsigned int max_hz; @@ -42,6 +224,7 @@ struct cadence_spi_plat { u8 addr_width; u8 data_width; bool dtr; + bool is_dma; }; struct cadence_spi_priv { @@ -96,5 +279,11 @@ void cadence_qspi_apb_enter_xip(void *reg_base, char xip_dummy); void cadence_qspi_apb_readdata_capture(void *reg_base, unsigned int bypass, unsigned int delay); unsigned int cm_get_qspi_controller_clk_hz(void); +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); +void cadence_qspi_apb_enable_linear_mode(bool enable); #endif /* __CADENCE_QSPI_H__ */ diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index 2cdf4c9c9f..c00755050e 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -38,156 +38,10 @@ #include <malloc.h> #include "cadence_qspi.h" -#define CQSPI_REG_POLL_US 1 /* 1us */ -#define CQSPI_REG_RETRY 10000 -#define CQSPI_POLL_IDLE_RETRY 3 - -/* Transfer mode */ -#define CQSPI_INST_TYPE_SINGLE 0 -#define CQSPI_INST_TYPE_DUAL 1 -#define CQSPI_INST_TYPE_QUAD 2 -#define CQSPI_INST_TYPE_OCTAL 3 - -#define CQSPI_STIG_DATA_LEN_MAX 8 - -#define CQSPI_DUMMY_CLKS_PER_BYTE 8 -#define CQSPI_DUMMY_CLKS_MAX 31 - -/**************************************************************************** - * Controller's configuration and status register (offset from QSPI_BASE) - ****************************************************************************/ -#define CQSPI_REG_CONFIG 0x00 -#define CQSPI_REG_CONFIG_ENABLE BIT(0) -#define CQSPI_REG_CONFIG_CLK_POL BIT(1) -#define CQSPI_REG_CONFIG_CLK_PHA BIT(2) -#define CQSPI_REG_CONFIG_DIRECT BIT(7) -#define CQSPI_REG_CONFIG_DECODE BIT(9) -#define CQSPI_REG_CONFIG_XIP_IMM BIT(18) -#define CQSPI_REG_CONFIG_CHIPSELECT_LSB 10 -#define CQSPI_REG_CONFIG_BAUD_LSB 19 -#define CQSPI_REG_CONFIG_DTR_PROTO BIT(24) -#define CQSPI_REG_CONFIG_DUAL_OPCODE BIT(30) -#define CQSPI_REG_CONFIG_IDLE_LSB 31 -#define CQSPI_REG_CONFIG_CHIPSELECT_MASK 0xF -#define CQSPI_REG_CONFIG_BAUD_MASK 0xF - -#define CQSPI_REG_RD_INSTR 0x04 -#define CQSPI_REG_RD_INSTR_OPCODE_LSB 0 -#define CQSPI_REG_RD_INSTR_TYPE_INSTR_LSB 8 -#define CQSPI_REG_RD_INSTR_TYPE_ADDR_LSB 12 -#define CQSPI_REG_RD_INSTR_TYPE_DATA_LSB 16 -#define CQSPI_REG_RD_INSTR_MODE_EN_LSB 20 -#define CQSPI_REG_RD_INSTR_DUMMY_LSB 24 -#define CQSPI_REG_RD_INSTR_TYPE_INSTR_MASK 0x3 -#define CQSPI_REG_RD_INSTR_TYPE_ADDR_MASK 0x3 -#define CQSPI_REG_RD_INSTR_TYPE_DATA_MASK 0x3 -#define CQSPI_REG_RD_INSTR_DUMMY_MASK 0x1F - -#define CQSPI_REG_WR_INSTR 0x08 -#define CQSPI_REG_WR_INSTR_OPCODE_LSB 0 -#define CQSPI_REG_WR_INSTR_TYPE_ADDR_LSB 12 -#define CQSPI_REG_WR_INSTR_TYPE_DATA_LSB 16 - -#define CQSPI_REG_DELAY 0x0C -#define CQSPI_REG_DELAY_TSLCH_LSB 0 -#define CQSPI_REG_DELAY_TCHSH_LSB 8 -#define CQSPI_REG_DELAY_TSD2D_LSB 16 -#define CQSPI_REG_DELAY_TSHSL_LSB 24 -#define CQSPI_REG_DELAY_TSLCH_MASK 0xFF -#define CQSPI_REG_DELAY_TCHSH_MASK 0xFF -#define CQSPI_REG_DELAY_TSD2D_MASK 0xFF -#define CQSPI_REG_DELAY_TSHSL_MASK 0xFF - -#define CQSPI_REG_RD_DATA_CAPTURE 0x10 -#define CQSPI_REG_RD_DATA_CAPTURE_BYPASS BIT(0) -#define CQSPI_REG_RD_DATA_CAPTURE_DELAY_LSB 1 -#define CQSPI_REG_RD_DATA_CAPTURE_DELAY_MASK 0xF - -#define CQSPI_REG_SIZE 0x14 -#define CQSPI_REG_SIZE_ADDRESS_LSB 0 -#define CQSPI_REG_SIZE_PAGE_LSB 4 -#define CQSPI_REG_SIZE_BLOCK_LSB 16 -#define CQSPI_REG_SIZE_ADDRESS_MASK 0xF -#define CQSPI_REG_SIZE_PAGE_MASK 0xFFF -#define CQSPI_REG_SIZE_BLOCK_MASK 0x3F - -#define CQSPI_REG_SRAMPARTITION 0x18 -#define CQSPI_REG_INDIRECTTRIGGER 0x1C - -#define CQSPI_REG_REMAP 0x24 -#define CQSPI_REG_MODE_BIT 0x28 - -#define CQSPI_REG_SDRAMLEVEL 0x2C -#define CQSPI_REG_SDRAMLEVEL_RD_LSB 0 -#define CQSPI_REG_SDRAMLEVEL_WR_LSB 16 -#define CQSPI_REG_SDRAMLEVEL_RD_MASK 0xFFFF -#define CQSPI_REG_SDRAMLEVEL_WR_MASK 0xFFFF - -#define CQSPI_REG_WR_COMPLETION_CTRL 0x38 -#define CQSPI_REG_WR_DISABLE_AUTO_POLL BIT(14) - -#define CQSPI_REG_IRQSTATUS 0x40 -#define CQSPI_REG_IRQMASK 0x44 - -#define CQSPI_REG_INDIRECTRD 0x60 -#define CQSPI_REG_INDIRECTRD_START BIT(0) -#define CQSPI_REG_INDIRECTRD_CANCEL BIT(1) -#define CQSPI_REG_INDIRECTRD_INPROGRESS BIT(2) -#define CQSPI_REG_INDIRECTRD_DONE BIT(5) - -#define CQSPI_REG_INDIRECTRDWATERMARK 0x64 -#define CQSPI_REG_INDIRECTRDSTARTADDR 0x68 -#define CQSPI_REG_INDIRECTRDBYTES 0x6C - -#define CQSPI_REG_CMDCTRL 0x90 -#define CQSPI_REG_CMDCTRL_EXECUTE BIT(0) -#define CQSPI_REG_CMDCTRL_INPROGRESS BIT(1) -#define CQSPI_REG_CMDCTRL_DUMMY_LSB 7 -#define CQSPI_REG_CMDCTRL_WR_BYTES_LSB 12 -#define CQSPI_REG_CMDCTRL_WR_EN_LSB 15 -#define CQSPI_REG_CMDCTRL_ADD_BYTES_LSB 16 -#define CQSPI_REG_CMDCTRL_ADDR_EN_LSB 19 -#define CQSPI_REG_CMDCTRL_RD_BYTES_LSB 20 -#define CQSPI_REG_CMDCTRL_RD_EN_LSB 23 -#define CQSPI_REG_CMDCTRL_OPCODE_LSB 24 -#define CQSPI_REG_CMDCTRL_DUMMY_MASK 0x1F -#define CQSPI_REG_CMDCTRL_WR_BYTES_MASK 0x7 -#define CQSPI_REG_CMDCTRL_ADD_BYTES_MASK 0x3 -#define CQSPI_REG_CMDCTRL_RD_BYTES_MASK 0x7 -#define CQSPI_REG_CMDCTRL_OPCODE_MASK 0xFF - -#define CQSPI_REG_INDIRECTWR 0x70 -#define CQSPI_REG_INDIRECTWR_START BIT(0) -#define CQSPI_REG_INDIRECTWR_CANCEL BIT(1) -#define CQSPI_REG_INDIRECTWR_INPROGRESS BIT(2) -#define CQSPI_REG_INDIRECTWR_DONE BIT(5) - -#define CQSPI_REG_INDIRECTWRWATERMARK 0x74 -#define CQSPI_REG_INDIRECTWRSTARTADDR 0x78 -#define CQSPI_REG_INDIRECTWRBYTES 0x7C - -#define CQSPI_REG_CMDADDRESS 0x94 -#define CQSPI_REG_CMDREADDATALOWER 0xA0 -#define CQSPI_REG_CMDREADDATAUPPER 0xA4 -#define CQSPI_REG_CMDWRITEDATALOWER 0xA8 -#define CQSPI_REG_CMDWRITEDATAUPPER 0xAC - -#define CQSPI_REG_OP_EXT_LOWER 0xE0 -#define CQSPI_REG_OP_EXT_READ_LSB 24 -#define CQSPI_REG_OP_EXT_WRITE_LSB 16 -#define CQSPI_REG_OP_EXT_STIG_LSB 0 - -#define CQSPI_REG_IS_IDLE(base) \ - ((readl(base + CQSPI_REG_CONFIG) >> \ - CQSPI_REG_CONFIG_IDLE_LSB) & 0x1) - -#define CQSPI_GET_RD_SRAM_LEVEL(reg_base) \ - (((readl(reg_base + CQSPI_REG_SDRAMLEVEL)) >> \ - CQSPI_REG_SDRAMLEVEL_RD_LSB) & CQSPI_REG_SDRAMLEVEL_RD_MASK) - -#define CQSPI_GET_WR_SRAM_LEVEL(reg_base) \ - (((readl(reg_base + CQSPI_REG_SDRAMLEVEL)) >> \ - CQSPI_REG_SDRAMLEVEL_WR_LSB) & CQSPI_REG_SDRAMLEVEL_WR_MASK) +__weak void cadence_qspi_apb_enable_linear_mode(bool enable) +{ + return; +} void cadence_qspi_apb_controller_enable(void *reg_base) { @@ -487,8 +341,7 @@ void cadence_qspi_apb_controller_init(struct cadence_spi_plat *plat) cadence_qspi_apb_controller_enable(plat->regbase); } -static int cadence_qspi_apb_exec_flash_cmd(void *reg_base, - unsigned int reg) +int cadence_qspi_apb_exec_flash_cmd(void *reg_base, unsigned int reg) { unsigned int retry = CQSPI_REG_RETRY; @@ -882,6 +735,9 @@ int cadence_qspi_apb_read_execute(struct cadence_spi_plat *plat, void *buf = op->data.buf.in; size_t len = op->data.nbytes; + if (CONFIG_IS_ENABLED(ARCH_VERSAL)) + cadence_qspi_apb_enable_linear_mode(true); + if (plat->use_dac_mode && (from + len < plat->ahbsize)) { if (len < 256 || dma_memcpy(buf, plat->ahbbase + from, len) < 0) { @@ -1049,6 +905,9 @@ int cadence_qspi_apb_write_execute(struct cadence_spi_plat *plat, const void *buf = op->data.buf.out; size_t len = op->data.nbytes; + if (CONFIG_IS_ENABLED(ARCH_VERSAL)) + cadence_qspi_apb_enable_linear_mode(true); + /* * Some flashes like the Cypress Semper flash expect a dummy 4-byte * address (all 0s) with the read status register command in DTR mode. |