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; +}