From 4bf65d74003decf21e69b8457dde5a2ecb066848 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Mon, 19 Jun 2023 22:32:55 +0530 Subject: [PATCH] drivers: wifi: Store RPU firmware patches in the external flash The internal flash utilization is almost full for Matter based applications, so, free up memory by storing the firmware patches in the external flash on supported platforms, for now only nRF5340 & nRF52840 are supported, as nRF7002 accesses external flash using SPI where XIP is not supported. Due to Nordic flash driver low-power optimizations, we need to inform the flash driver whenever XIP is being used, so, move the FW patch API to a separate C file to avoid using other RODATA to minimize this XIP management. This is disabled by default till we get the necessary DFU changes in Matter. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/CMakeLists.txt | 6 ++ drivers/wifi/nrf700x/Kconfig.nrf700x | 17 +++++ drivers/wifi/nrf700x/rpu_fw_patches.ld | 51 +++++++++++++++ .../nrf700x/zephyr/inc/zephyr_fmac_main.h | 2 + .../nrf700x/zephyr/src/zephyr_fmac_main.c | 23 +------ .../wifi/nrf700x/zephyr/src/zephyr_fw_load.c | 62 +++++++++++++++++++ 6 files changed, 141 insertions(+), 20 deletions(-) create mode 100644 drivers/wifi/nrf700x/rpu_fw_patches.ld create mode 100644 drivers/wifi/nrf700x/zephyr/src/zephyr_fw_load.c diff --git a/drivers/wifi/nrf700x/CMakeLists.txt b/drivers/wifi/nrf700x/CMakeLists.txt index c95bc699099e..af84eb884671 100644 --- a/drivers/wifi/nrf700x/CMakeLists.txt +++ b/drivers/wifi/nrf700x/CMakeLists.txt @@ -55,6 +55,7 @@ zephyr_library_sources( zephyr/src/zephyr_work.c zephyr/src/timer.c zephyr/src/zephyr_fmac_main.c + zephyr/src/zephyr_fw_load.c zephyr/src/qspi/src/device.c zephyr/src/qspi/src/rpu_hw_if.c zephyr/src/qspi/src/ficr_prog.c @@ -107,3 +108,8 @@ zephyr_library_sources_ifdef(CONFIG_NRF700X_ON_SPI zephyr_library_sources_ifdef(CONFIG_NRF700X_UTIL zephyr/src/zephyr_wifi_util.c ) + +if (CONFIG_NRF_WIFI_PATCHES_EXT_FLASH) +# Run patches from the external flash (XIP). No need to copy. +zephyr_code_relocate(FILES zephyr/src/zephyr_fw_load.c LOCATION EXTFLASH_RODATA NOCOPY) +endif() diff --git a/drivers/wifi/nrf700x/Kconfig.nrf700x b/drivers/wifi/nrf700x/Kconfig.nrf700x index fc9deb4e6084..645bdfb01f16 100644 --- a/drivers/wifi/nrf700x/Kconfig.nrf700x +++ b/drivers/wifi/nrf700x/Kconfig.nrf700x @@ -26,6 +26,23 @@ config NRF_WIFI_IF_AUTO_START bool default y +config NRF_WIFI_PATCHES_EXT_FLASH + bool "Store nRF700x FW patches in external flash" + # nRF7002 supports SPI based external flash access with no XIP + # Disable until Matter DFU changes are ready + # default y if BOARD_NRF5340DK_NRF5340_CPUAPP || BOARD_NRF52840DK_NRF52840 + # For accessing external flash + select FLASH + # For relocation code to external flash + select XIP + select BUILD_NO_GAP_FILL + select CODE_DATA_RELOCATION + select HAVE_CUSTOM_LINKER_SCRIPT + +config CUSTOM_LINKER_SCRIPT + string "Custom linker script for nRF700x FW patches" + default "${ZEPHYR_BASE}/../nrf/drivers/wifi/nrf700x/rpu_fw_patches.ld" + config NRF_WIFI_LOW_POWER bool "Enable low power mode in nRF Wi-Fi chipsets" default y diff --git a/drivers/wifi/nrf700x/rpu_fw_patches.ld b/drivers/wifi/nrf700x/rpu_fw_patches.ld new file mode 100644 index 000000000000..83fc06a28432 --- /dev/null +++ b/drivers/wifi/nrf700x/rpu_fw_patches.ld @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/** + * @file + * @brief Custom Linker command/script file + * + * Custom Linker script for the Cortex-M platforms. + */ + +#include +#include + +#include +#include + +#if CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP || CONFIG_BOARD_NRF52840DK_NRF52840 +/* + * nRF53/52 series ship an external flash that can be used for XIP using QSPI/SPI. + * + * Note: In nRF7002 external flash using is accessible only using SPI but there is no + * support for XIP, so, relocation cannot be used. + */ +#if CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP +#define EXTFLASH_BASE_ADDR 0x10000000 +#define EXTFLASH_SIZE 0x800000 +#elif CONFIG_BOARD_NRF52840DK_NRF52840 +#define EXTFLASH_BASE_ADDR 0x12000000 +#define EXTFLASH_SIZE 0x800000 +#endif /* CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP */ + +#if USE_PARTITION_MANAGER && PM_EXTERNAL_FLASH_ADDRESS +#include +#define EXTFLASH_ADDRESS (EXTFLASH_BASE_ADDR + PM_EXTERNAL_FLASH_ADDRESS) +#undef EXTFLASH_SIZE +#define EXTFLASH_SIZE (PM_EXTERNAL_FLASH_SIZE) +#else +#define EXTFLASH_ADDRESS (EXTFLASH_BASE_ADDR) +#endif /* USE_PARTITION_MANAGER && PM_EXTERNAL_FLASH_ADDRESS */ + +MEMORY +{ + EXTFLASH (wx) : ORIGIN = EXTFLASH_ADDRESS, LENGTH = EXTFLASH_SIZE +} + +#endif /* CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP || CONFIG_BOARD_NRF52840DK_NRF52840 */ + +#include diff --git a/drivers/wifi/nrf700x/zephyr/inc/zephyr_fmac_main.h b/drivers/wifi/nrf700x/zephyr/inc/zephyr_fmac_main.h index 117c2297779b..0df1b58aecb9 100644 --- a/drivers/wifi/nrf700x/zephyr/inc/zephyr_fmac_main.h +++ b/drivers/wifi/nrf700x/zephyr/inc/zephyr_fmac_main.h @@ -116,4 +116,6 @@ void wifi_nrf_scan_timeout_work(struct k_work *work); const char *wifi_nrf_get_drv_version(void); enum wifi_nrf_status wifi_nrf_fmac_dev_add_zep(struct wifi_nrf_drv_priv_zep *drv_priv_zep); enum wifi_nrf_status wifi_nrf_fmac_dev_rem_zep(struct wifi_nrf_drv_priv_zep *drv_priv_zep); +enum wifi_nrf_status wifi_nrf_fw_load(void *rpu_ctx); + #endif /* __ZEPHYR_FMAC_MAIN_H__ */ diff --git a/drivers/wifi/nrf700x/zephyr/src/zephyr_fmac_main.c b/drivers/wifi/nrf700x/zephyr/src/zephyr_fmac_main.c index 98a19be915e0..8bb9d4accac1 100644 --- a/drivers/wifi/nrf700x/zephyr/src/zephyr_fmac_main.c +++ b/drivers/wifi/nrf700x/zephyr/src/zephyr_fmac_main.c @@ -19,7 +19,7 @@ #include #include -#include + #include #include #include @@ -269,7 +269,6 @@ enum wifi_nrf_status wifi_nrf_fmac_dev_add_zep(struct wifi_nrf_drv_priv_zep *drv { enum wifi_nrf_status status = WIFI_NRF_STATUS_FAIL; struct wifi_nrf_ctx_zep *rpu_ctx_zep = NULL; - struct wifi_nrf_fmac_fw_info fw_info; void *rpu_ctx = NULL; #if defined(CONFIG_BOARD_NRF7001) enum op_band op_band = BAND_24G; @@ -302,25 +301,9 @@ enum wifi_nrf_status wifi_nrf_fmac_dev_add_zep(struct wifi_nrf_drv_priv_zep *drv rpu_ctx_zep->rpu_ctx = rpu_ctx; - memset(&fw_info, - 0, - sizeof(fw_info)); - - fw_info.lmac_patch_pri.data = wifi_nrf_lmac_patch_pri_bimg; - fw_info.lmac_patch_pri.size = sizeof(wifi_nrf_lmac_patch_pri_bimg); - fw_info.lmac_patch_sec.data = wifi_nrf_lmac_patch_sec_bin; - fw_info.lmac_patch_sec.size = sizeof(wifi_nrf_lmac_patch_sec_bin); - fw_info.umac_patch_pri.data = wifi_nrf_umac_patch_pri_bimg; - fw_info.umac_patch_pri.size = sizeof(wifi_nrf_umac_patch_pri_bimg); - fw_info.umac_patch_sec.data = wifi_nrf_umac_patch_sec_bin; - fw_info.umac_patch_sec.size = sizeof(wifi_nrf_umac_patch_sec_bin); - - /* Load the FW patches to the RPU */ - status = wifi_nrf_fmac_fw_load(rpu_ctx, - &fw_info); - + status = wifi_nrf_fw_load(rpu_ctx); if (status != WIFI_NRF_STATUS_SUCCESS) { - LOG_ERR("%s: wifi_nrf_fmac_fw_load failed\n", __func__); + LOG_ERR("%s: wifi_nrf_fw_load failed\n", __func__); goto out; } diff --git a/drivers/wifi/nrf700x/zephyr/src/zephyr_fw_load.c b/drivers/wifi/nrf700x/zephyr/src/zephyr_fw_load.c new file mode 100644 index 000000000000..f40c62a63885 --- /dev/null +++ b/drivers/wifi/nrf700x/zephyr/src/zephyr_fw_load.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/** + * @brief File containing FW load functions for Zephyr. + * + * For NRF QSPI NOR special handling is needed for this file as all RODATA of + * this file is stored in external flash, so, any use of RODATA has to be protected + * by disabling XIP and enabling it again after use. This means no LOG_* macros + * (buffered) or buffered printk can be used in this file, else it will crash. + */ +#include +#include +#include + +#include +#include +#if defined(CONFIG_NRF_WIFI_PATCHES_EXT_FLASH) && defined(CONFIG_NORDIC_QSPI_NOR) +#include +#endif /* CONFIG_NRF_WIFI_PATCHES_EXT_FLASH */ + +#include +#include + +enum wifi_nrf_status wifi_nrf_fw_load(void *rpu_ctx) +{ + enum wifi_nrf_status status = WIFI_NRF_STATUS_FAIL; + struct wifi_nrf_fmac_fw_info fw_info; +#if defined(CONFIG_NRF_WIFI_PATCHES_EXT_FLASH) && defined(CONFIG_NORDIC_QSPI_NOR) + const struct device *flash_dev = DEVICE_DT_GET(DT_INST(0, nordic_qspi_nor)); +#endif /* CONFIG_NRF_WIFI_PATCHES_EXT_FLASH */ + + memset(&fw_info, 0, sizeof(fw_info)); + fw_info.lmac_patch_pri.data = wifi_nrf_lmac_patch_pri_bimg; + fw_info.lmac_patch_pri.size = sizeof(wifi_nrf_lmac_patch_pri_bimg); + fw_info.lmac_patch_sec.data = wifi_nrf_lmac_patch_sec_bin; + fw_info.lmac_patch_sec.size = sizeof(wifi_nrf_lmac_patch_sec_bin); + fw_info.umac_patch_pri.data = wifi_nrf_umac_patch_pri_bimg; + fw_info.umac_patch_pri.size = sizeof(wifi_nrf_umac_patch_pri_bimg); + fw_info.umac_patch_sec.data = wifi_nrf_umac_patch_sec_bin; + fw_info.umac_patch_sec.size = sizeof(wifi_nrf_umac_patch_sec_bin); + +#if defined(CONFIG_NRF_WIFI_PATCHES_EXT_FLASH) && defined(CONFIG_NORDIC_QSPI_NOR) + nrf_qspi_nor_xip_enable(flash_dev, true); +#endif /* CONFIG_NRF_WIFI */ + /* Load the FW patches to the RPU */ + status = wifi_nrf_fmac_fw_load(rpu_ctx, + &fw_info); + + if (status != WIFI_NRF_STATUS_SUCCESS) { + printf("%s: wifi_nrf_fmac_fw_load failed\n", __func__); + } + +#if defined(CONFIG_NRF_WIFI_PATCHES_EXT_FLASH) && defined(CONFIG_NORDIC_QSPI_NOR) + nrf_qspi_nor_xip_enable(flash_dev, false); +#endif /* CONFIG_NRF_WIFI */ + + return status; +}