[PATCH v2 2/3] bsps: Add flash wrapper for Xilinx GQSPI
aaron.nyholm at unfoldedeffective.com
aaron.nyholm at unfoldedeffective.com
Wed Jan 24 05:22:16 UTC 2024
From: Aaron Nyholm <aaron.nyholm at unfoldedeffective.com>
---
bsps/aarch64/xilinx-versal/include/bsp/irq.h | 1 +
bsps/include/dev/spi/xqspi_flash.h | 65 ++++++
bsps/include/dev/spi/xqspipsu-flash-helper.h | 20 ++
bsps/shared/dev/spi/xqspi_flash.c | 210 ++++++++++++++++++
bsps/shared/dev/spi/xqspipsu-flash-helper.c | 13 ++
spec/build/bsps/aarch64/xilinx-versal/grp.yml | 4 +
spec/build/bsps/objxilinxsupportlp64.yml | 4 +-
spec/build/bsps/objxqspiflash.yml | 22 ++
spec/build/bsps/optxilsupportpath.yml | 4 +-
9 files changed, 341 insertions(+), 2 deletions(-)
create mode 100644 bsps/include/dev/spi/xqspi_flash.h
create mode 100644 bsps/shared/dev/spi/xqspi_flash.c
create mode 100644 spec/build/bsps/objxqspiflash.yml
diff --git a/bsps/aarch64/xilinx-versal/include/bsp/irq.h b/bsps/aarch64/xilinx-versal/include/bsp/irq.h
index b34bdfd345..6f4d387e8f 100644
--- a/bsps/aarch64/xilinx-versal/include/bsp/irq.h
+++ b/bsps/aarch64/xilinx-versal/include/bsp/irq.h
@@ -61,6 +61,7 @@ extern "C" {
#define VERSAL_IRQ_ETHERNET_0_WAKEUP 89
#define VERSAL_IRQ_ETHERNET_1 90
#define VERSAL_IRQ_ETHERNET_1_WAKEUP 91
+#define VERSAL_IRQ_QSPI 157
/** @} */
diff --git a/bsps/include/dev/spi/xqspi_flash.h b/bsps/include/dev/spi/xqspi_flash.h
new file mode 100644
index 0000000000..e4bc4a5183
--- /dev/null
+++ b/bsps/include/dev/spi/xqspi_flash.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/*
+ * Copyright (C) 2023, 2023 Aaron Nyholm
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef XILINX_XQSPI_FLASH_H
+#define XILINX_XQSPI_FLASH_H
+
+#include <dev/flash/flashdev.h>
+#include <dev/spi/xqspipsu.h>
+
+#define XQSPI_MAX_REGIONS 32
+#define MAX_READ_SIZE 0x8000
+
+/*
+ * @brief Initializes a flash device using Xilinx's xqspi flash
+ * driver. The flash device is not registered in this call.
+ * If an rtems_flashdev is created using xqspi_flash_init it must be
+ * destroyed using xqspi_flash_destroy.
+ *
+ * @param[in] xQspiDev A configured XQspiPsu device to initialise.
+ *
+ * @retval A pointer to the rtems_flashdev.
+ * @retval NULL on failure.
+*/
+rtems_flashdev* xqspi_flash_init(XQspiPsu *xQspiDev);
+
+/*
+ * @brief Destroys a rtems_flashdev initialised with xqspi_flash_init.
+ * If an rtems_flashdev is created using xqspi_flash_init it must be
+ * destroyed using xqspi_flash_destroy. The XQspiPsu originally passed in
+ * is untouched.
+ *
+ * @param[in] flash The flashdev to destroy
+*/
+void xqspi_flash_destroy(rtems_flashdev* flash);
+
+typedef struct versal_xqspi_region_table {
+ rtems_flashdev_region versal_xqspi_regions[XQSPI_MAX_REGIONS];
+ uint32_t versal_xqspi_bit_allocator;
+} versal_xqspi_region_table;
+
+#endif /* XILINX_XQSPI_FLASH_H */
diff --git a/bsps/include/dev/spi/xqspipsu-flash-helper.h b/bsps/include/dev/spi/xqspipsu-flash-helper.h
index e689660881..e73952769c 100644
--- a/bsps/include/dev/spi/xqspipsu-flash-helper.h
+++ b/bsps/include/dev/spi/xqspipsu-flash-helper.h
@@ -190,3 +190,23 @@ int QspiPsu_NOR_RDSFDP(
u32 ByteCount,
u8 **ReadBfrPtr
);
+
+/**
+ * This function returns the page size of attached flash parts.
+ *
+ * @param QspiPsuPtr is a pointer to the QSPIPSU driver component to use.
+ *
+ * @return The page size of attached flash in bytes.
+ *
+ ******************************************************************************/
+u32 QspiPsu_NOR_Get_Page_Size(XQspiPsu *QspiPsuPtr);
+
+/**
+ * This function returns the JEDEC ID of attached flash parts.
+ *
+ * @param QspiPsuPtr is a pointer to the QSPIPSU driver component to use.
+ *
+ * @return The JEDEC ID of attached flash in bytes.
+ *
+ ******************************************************************************/
+u32 QspiPsu_NOR_Get_JEDEC_ID(XQspiPsu *QspiPsuPtr);
diff --git a/bsps/shared/dev/spi/xqspi_flash.c b/bsps/shared/dev/spi/xqspi_flash.c
new file mode 100644
index 0000000000..b641932abc
--- /dev/null
+++ b/bsps/shared/dev/spi/xqspi_flash.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2023, 2023 Aaron Nyholm
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bsp/irq.h>
+#include <dev/spi/xqspi_flash.h>
+#include <dev/spi/xqspipsu.h>
+#include <dev/spi/xqspipsu-flash-helper.h>
+#include <dev/spi/xqspipsu_flash_config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+static uint32_t xqspi_get_jedec_id(rtems_flashdev *flash) {
+ return QspiPsu_NOR_Get_JEDEC_ID(flash->driver);
+}
+
+static int xqspi_get_flash_type(
+ rtems_flashdev *flash,
+ rtems_flashdev_flash_type *type
+)
+{
+ *type = RTEMS_FLASHDEV_NOR;
+ return 0;
+}
+
+static int xqspi_read_wrapper(
+ rtems_flashdev *flash,
+ uintptr_t offset,
+ size_t count,
+ void *buffer
+)
+{
+ XQspiPsu *flash_driver = (XQspiPsu*)flash->driver;
+ uint8_t *tmp_buffer;
+ int status;
+ int startAlign = 0;
+
+ /* Align offset to two byte boundary */
+ if (offset%2) {
+ startAlign = 1;
+ offset = offset - 1;
+ count = count + 1;
+ }
+
+ while (count > MAX_READ_SIZE) {
+ /* Read block and copy to buffer */
+ status = QspiPsu_NOR_Read(flash_driver, (uint32_t)offset, MAX_READ_SIZE, &tmp_buffer);
+
+ if (status == 0) {
+ memcpy(buffer, tmp_buffer + startAlign, MAX_READ_SIZE - startAlign);
+ /* Update count, offset and buffer pointer */
+ count = count - MAX_READ_SIZE;
+ buffer = buffer + MAX_READ_SIZE - startAlign;
+ offset = offset + MAX_READ_SIZE;
+ /* Clear startAlign once first block read */
+ if (startAlign) {
+ startAlign = 0;
+ }
+ } else {
+ return status;
+ }
+ }
+
+ status = QspiPsu_NOR_Read(flash_driver, (uint32_t)offset, (uint32_t)count, &tmp_buffer);
+
+ if (status == 0) {
+ memcpy(buffer, tmp_buffer + startAlign, count);
+ }
+ return status;
+}
+
+static int xqspi_page_info_by_off(
+ rtems_flashdev *flash,
+ off_t search_offset,
+ off_t *page_offset,
+ size_t *page_size
+)
+{
+ *page_size = QspiPsu_NOR_Get_Page_Size(flash->driver);
+ *page_offset = search_offset - (search_offset%((off_t)(*page_size)));
+ return 0;
+}
+
+static int xqspi_page_info_by_index(
+ rtems_flashdev *flash,
+ off_t search_index,
+ off_t *page_offset,
+ size_t *page_size
+)
+{
+ *page_size = QspiPsu_NOR_Get_Page_Size(flash->driver);
+ *page_offset = *page_size * search_index;
+ return 0;
+}
+
+static int xqspi_page_count(
+ rtems_flashdev *flash,
+ int *page_count
+)
+{
+ *page_count = QspiPsu_NOR_Get_Device_Size(flash->driver) /
+ QspiPsu_NOR_Get_Page_Size(flash->driver);
+ return 0;
+}
+
+static int xqspi_write_block_size(
+ rtems_flashdev *flash,
+ size_t *write_block_size
+)
+{
+ *write_block_size = QspiPsu_NOR_Get_Page_Size(flash->driver);
+ return 0;
+}
+
+static int xqspi_write_wrapper(
+ rtems_flashdev *flash,
+ uintptr_t offset,
+ size_t count,
+ const void *buffer
+)
+{
+ XQspiPsu *flash_driver = (XQspiPsu*)flash->driver;
+ return QspiPsu_NOR_Write(flash_driver, (uint32_t)offset, (uint32_t)count, (void*)buffer);
+}
+
+static int xqspi_erase_wrapper(
+ rtems_flashdev *flash,
+ uintptr_t offset,
+ size_t count
+)
+{
+ XQspiPsu *flash_driver = (XQspiPsu*)flash->driver;
+ return QspiPsu_NOR_Erase(flash_driver, (uint32_t)offset, (uint32_t)count);
+}
+
+rtems_flashdev* xqspi_flash_init(XQspiPsu *xQspiDev)
+{
+ versal_xqspi_region_table *xtable =
+ calloc(1, sizeof(versal_xqspi_region_table));
+
+ if (xtable == NULL) {
+ free(xQspiDev);
+ return NULL;
+ }
+
+ rtems_flashdev_region_table *ftable =
+ calloc(1, sizeof(rtems_flashdev_region_table));
+
+ if (ftable == NULL) {
+ free(xtable);
+ free(xQspiDev);
+ return NULL;
+ }
+
+ ftable->regions = (rtems_flashdev_region*)(&(xtable->versal_xqspi_regions));
+ ftable->max_regions = XQSPI_MAX_REGIONS;
+ ftable->bit_allocator = &(xtable->versal_xqspi_bit_allocator);
+
+ rtems_flashdev *flash = rtems_flashdev_alloc_and_init(sizeof(rtems_flashdev));
+
+ if (flash == NULL) {
+ free(xQspiDev);
+ free(xtable);
+ free(ftable);
+ return NULL;
+ }
+
+ flash->driver = xQspiDev;
+ flash->read = &xqspi_read_wrapper;
+ flash->write = &xqspi_write_wrapper;
+ flash->erase = &xqspi_erase_wrapper;
+ flash->jedec_id = &xqspi_get_jedec_id;
+ flash->flash_type = &xqspi_get_flash_type;
+ flash->page_info_by_offset = &xqspi_page_info_by_off;
+ flash->page_info_by_index = &xqspi_page_info_by_index;
+ flash->page_count = &xqspi_page_count;
+ flash->write_block_size = &xqspi_write_block_size;
+ flash->region_table = ftable;
+
+ return flash;
+}
+
+void xqspi_flash_destroy(rtems_flashdev* flash)
+{
+ free(flash->region_table->regions);
+ free(flash->region_table);
+ rtems_flashdev_destroy_and_free(flash);
+}
diff --git a/bsps/shared/dev/spi/xqspipsu-flash-helper.c b/bsps/shared/dev/spi/xqspipsu-flash-helper.c
index 69c4035e6a..ef19f850e7 100644
--- a/bsps/shared/dev/spi/xqspipsu-flash-helper.c
+++ b/bsps/shared/dev/spi/xqspipsu-flash-helper.c
@@ -2338,3 +2338,16 @@ u32 QspiPsu_NOR_Get_Device_Size(XQspiPsu *QspiPsuPtr)
}
return Flash_Config_Table[FCTIndex].FlashDeviceSize;
}
+
+u32 QspiPsu_NOR_Get_Page_Size(XQspiPsu *QspiPsuPtr)
+{
+ if(QspiPsuPtr->Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_STACKED) {
+ return Flash_Config_Table[FCTIndex].PageSize * 2;
+ }
+ return Flash_Config_Table[FCTIndex].PageSize;
+}
+
+u32 QspiPsu_NOR_Get_JEDEC_ID(XQspiPsu *QspiPsuPtr)
+{
+ return Flash_Config_Table[FCTIndex].jedec_id;
+}
diff --git a/spec/build/bsps/aarch64/xilinx-versal/grp.yml b/spec/build/bsps/aarch64/xilinx-versal/grp.yml
index 6b4ea31133..cb8c1afc75 100644
--- a/spec/build/bsps/aarch64/xilinx-versal/grp.yml
+++ b/spec/build/bsps/aarch64/xilinx-versal/grp.yml
@@ -56,6 +56,10 @@ links:
uid: ../../objdevspixil
- role: build-dependency
uid: ../../objmem
+- role: build-dependency
+ uid: ../../objxilinxsupport
+- role: build-dependency
+ uid: ../../objxqspiflash
- role: build-dependency
uid: ../../optcachedata
- role: build-dependency
diff --git a/spec/build/bsps/objxilinxsupportlp64.yml b/spec/build/bsps/objxilinxsupportlp64.yml
index 330ffc34fd..601a717c5c 100644
--- a/spec/build/bsps/objxilinxsupportlp64.yml
+++ b/spec/build/bsps/objxilinxsupportlp64.yml
@@ -6,7 +6,9 @@ copyrights:
cppflags: []
cxxflags: []
enabled-by:
-- bsps/aarch64/xilinx_versal
+- aarch64/xilinx_versal_aiedge
+- aarch64/xilinx_versal_qemu
+- aarch64/xilinx_versal_vck190
- aarch64/xilinx_zynqmp_lp64_cfc400x
- aarch64/xilinx_zynqmp_lp64_qemu
- aarch64/xilinx_zynqmp_lp64_zu3eg
diff --git a/spec/build/bsps/objxqspiflash.yml b/spec/build/bsps/objxqspiflash.yml
new file mode 100644
index 0000000000..e1aad09adc
--- /dev/null
+++ b/spec/build/bsps/objxqspiflash.yml
@@ -0,0 +1,22 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+build-type: objects
+cflags: []
+copyrights:
+- Copyright (C) 2023 Aaron Nyholm
+cppflags: []
+cxxflags: []
+enabled-by: true
+includes:
+- bsps/include/dev/spi/
+- bsps/include/xil/
+- bsps/include/xil/${XIL_SUPPORT_PATH}/
+install:
+- destination: ${BSP_INCLUDEDIR}/dev/spi
+ source:
+ - bsps/include/dev/spi/xqspi_flash.h
+links:
+- role: build-dependency
+ uid: objxilinxsupport
+source:
+- bsps/shared/dev/spi/xqspi_flash.c
+type: build
diff --git a/spec/build/bsps/optxilsupportpath.yml b/spec/build/bsps/optxilsupportpath.yml
index 85bcc7e059..53898e6575 100644
--- a/spec/build/bsps/optxilsupportpath.yml
+++ b/spec/build/bsps/optxilsupportpath.yml
@@ -20,10 +20,12 @@ default:
- aarch64/xilinx_zynqmp_ilp32_zu3eg
value: arm/ARMv8/32bit
- enabled-by:
+ - aarch64/xilinx_versal_aiedge
+ - aarch64/xilinx_versal_qemu
+ - aarch64/xilinx_versal_vck190
- aarch64/xilinx_zynqmp_lp64_cfc400x
- aarch64/xilinx_zynqmp_lp64_qemu
- aarch64/xilinx_zynqmp_lp64_zu3eg
- - bsps/aarch64/xilinx_versal
value: arm/ARMv8/64bit
description: Set the Xilinx support path
enabled-by: true
--
2.25.1
More information about the devel
mailing list