Skip to content

Commit

Permalink
drivers: wifi: Store RPU firmware patches in the external flash
Browse files Browse the repository at this point in the history
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 <Chaitanya.Tata@nordicsemi.no>
  • Loading branch information
krish2718 authored and rlubos committed Jul 7, 2023
1 parent 7996061 commit 4bf65d7
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 20 deletions.
6 changes: 6 additions & 0 deletions drivers/wifi/nrf700x/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
17 changes: 17 additions & 0 deletions drivers/wifi/nrf700x/Kconfig.nrf700x
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
51 changes: 51 additions & 0 deletions drivers/wifi/nrf700x/rpu_fw_patches.ld
Original file line number Diff line number Diff line change
@@ -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 <zephyr/linker/sections.h>
#include <zephyr/devicetree.h>

#include <zephyr/linker/linker-defs.h>
#include <zephyr/linker/linker-tool.h>

#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 <pm_config.h>
#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 <zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld>
2 changes: 2 additions & 0 deletions drivers/wifi/nrf700x/zephyr/inc/zephyr_fmac_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__ */
23 changes: 3 additions & 20 deletions drivers/wifi/nrf700x/zephyr/src/zephyr_fmac_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include <zephyr/net/wifi_mgmt.h>
#include <net/l2_wifi_connect.h>

#include <rpu_fw_patches.h>

#include <util.h>
#include <fmac_api.h>
#include <zephyr_fmac_main.h>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down
62 changes: 62 additions & 0 deletions drivers/wifi/nrf700x/zephyr/src/zephyr_fw_load.c
Original file line number Diff line number Diff line change
@@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#if defined(CONFIG_NRF_WIFI_PATCHES_EXT_FLASH) && defined(CONFIG_NORDIC_QSPI_NOR)
#include <zephyr/drivers/flash/nrf_qspi_nor.h>
#endif /* CONFIG_NRF_WIFI_PATCHES_EXT_FLASH */

#include <zephyr_fmac_main.h>
#include <rpu_fw_patches.h>

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

0 comments on commit 4bf65d7

Please sign in to comment.