drivers: wifi: Add nRF70 Wi-Fi driver
Driver for Nordic nRF70 Wi-Fi6 companion chipset, depends on hal_nordic/nrf_wifi for OS agnostic part of the driver. This supports (Q)SPI interface to communicate from host to chip. Signed-off-by: Chaitanya Tata <Chaitanya.Tata@nordicsemi.no>
This commit is contained in:
parent
d1f2e7d6e7
commit
638ce2fbfd
39 changed files with 13719 additions and 0 deletions
|
@ -2097,6 +2097,27 @@ Release Notes:
|
|||
labels:
|
||||
- "area: Wi-Fi"
|
||||
|
||||
"Drivers: Wi-Fi as nRF Wi-Fi":
|
||||
status: maintained
|
||||
maintainers:
|
||||
- krish2718
|
||||
- jukkar
|
||||
files:
|
||||
- drivers/wifi/nrfwifi/
|
||||
- dts/bindings/wifi/nordic,nrf70.yaml
|
||||
- dts/bindings/wifi/nordic,nrf70-qspi.yaml
|
||||
- dts/bindings/wifi/nordic,nrf70-spi.yaml
|
||||
- dts/bindings/wifi/nordic,nrf70-coex.yaml
|
||||
- dts/bindings/wifi/nordic,nrf7002-qspi.yaml
|
||||
- dts/bindings/wifi/nordic,nrf7002-spi.yaml
|
||||
- dts/bindings/wifi/nordic,nrf7000-qspi.yaml
|
||||
- dts/bindings/wifi/nordic,nrf7000-spi.yaml
|
||||
- dts/bindings/wifi/nordic,nrf7001-qspi.yaml
|
||||
- dts/bindings/wifi/nordic,nrf7001-spi.yaml
|
||||
- boards/shields/nrf7002ek/
|
||||
labels:
|
||||
- "area: Wi-Fi"
|
||||
|
||||
"Drivers: Memory Management":
|
||||
status: maintained
|
||||
maintainers:
|
||||
|
|
|
@ -9,3 +9,4 @@ add_subdirectory_ifdef(CONFIG_WIFI_ESWIFI eswifi)
|
|||
add_subdirectory_ifdef(CONFIG_WIFI_SIMPLELINK simplelink)
|
||||
add_subdirectory_ifdef(CONFIG_WIFI_WINC1500 winc1500)
|
||||
add_subdirectory_ifdef(CONFIG_WIFI_AIROC infineon)
|
||||
add_subdirectory_ifdef(CONFIG_WIFI_NRF70 nrfwifi)
|
||||
|
|
|
@ -41,5 +41,6 @@ source "drivers/wifi/eswifi/Kconfig.eswifi"
|
|||
source "drivers/wifi/esp_at/Kconfig.esp_at"
|
||||
source "drivers/wifi/esp32/Kconfig.esp32"
|
||||
source "drivers/wifi/infineon/Kconfig.airoc"
|
||||
source "drivers/wifi/nrfwifi/Kconfig.nrfwifi"
|
||||
|
||||
endif # WIFI
|
||||
|
|
288
drivers/wifi/nrfwifi/CMakeLists.txt
Normal file
288
drivers/wifi/nrfwifi/CMakeLists.txt
Normal file
|
@ -0,0 +1,288 @@
|
|||
#
|
||||
# Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
zephyr_library()
|
||||
|
||||
set(OS_AGNOSTIC_BASE ${ZEPHYR_HAL_NORDIC_MODULE_DIR}/drivers/nrf_wifi)
|
||||
set(FW_BINS_BASE ${ZEPHYR_HAL_NORDIC_MODULE_DIR}/zephyr/blobs/wifi_fw_bins)
|
||||
|
||||
zephyr_include_directories(
|
||||
inc
|
||||
${OS_AGNOSTIC_BASE}/utils/inc
|
||||
${OS_AGNOSTIC_BASE}/os_if/inc
|
||||
${OS_AGNOSTIC_BASE}/bus_if/bus/qspi/inc
|
||||
${OS_AGNOSTIC_BASE}/bus_if/bal/inc
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/inc
|
||||
${OS_AGNOSTIC_BASE}/fw_load/mips/fw/inc
|
||||
${OS_AGNOSTIC_BASE}/hw_if/hal/inc
|
||||
src/qspi/inc
|
||||
# for net_sprint_ll_addr
|
||||
${ZEPHYR_BASE}/subsys/net/ip
|
||||
${OS_AGNOSTIC_BASE}/hw_if/hal/inc/fw
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/inc/fw
|
||||
)
|
||||
|
||||
zephyr_include_directories_ifdef(CONFIG_NRF70_RADIO_TEST
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/inc/radio_test
|
||||
)
|
||||
|
||||
zephyr_include_directories_ifndef(CONFIG_NRF70_RADIO_TEST
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/inc/default
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_NRF70_SR_COEX
|
||||
src/coex.c
|
||||
)
|
||||
|
||||
zephyr_library_sources(
|
||||
${OS_AGNOSTIC_BASE}/os_if/src/osal.c
|
||||
${OS_AGNOSTIC_BASE}/utils/src/list.c
|
||||
${OS_AGNOSTIC_BASE}/utils/src/queue.c
|
||||
${OS_AGNOSTIC_BASE}/utils/src/util.c
|
||||
${OS_AGNOSTIC_BASE}/hw_if/hal/src/hal_api.c
|
||||
${OS_AGNOSTIC_BASE}/hw_if/hal/src/hal_fw_patch_loader.c
|
||||
${OS_AGNOSTIC_BASE}/hw_if/hal/src/hal_interrupt.c
|
||||
${OS_AGNOSTIC_BASE}/hw_if/hal/src/hal_mem.c
|
||||
${OS_AGNOSTIC_BASE}/hw_if/hal/src/hal_reg.c
|
||||
${OS_AGNOSTIC_BASE}/hw_if/hal/src/hpqm.c
|
||||
${OS_AGNOSTIC_BASE}/hw_if/hal/src/pal.c
|
||||
${OS_AGNOSTIC_BASE}/bus_if/bal/src/bal.c
|
||||
${OS_AGNOSTIC_BASE}/bus_if/bus/qspi/src/qspi.c
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/src/cmd.c
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/src/event.c
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/src/fmac_api_common.c
|
||||
src/shim.c
|
||||
src/work.c
|
||||
src/timer.c
|
||||
src/fmac_main.c
|
||||
src/fw_load.c
|
||||
src/qspi/src/device.c
|
||||
src/qspi/src/rpu_hw_if.c
|
||||
src/qspi/src/ficr_prog.c
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifndef(CONFIG_NRF70_RADIO_TEST
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/src/rx.c
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/src/fmac_vif.c
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/src/fmac_util.c
|
||||
src/net_if.c
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/src/default/fmac_api.c
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_NET_L2_WIFI_MGMT
|
||||
src/wifi_mgmt_scan.c
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_NRF70_SYSTEM_MODE
|
||||
src/wifi_mgmt.c
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_NRF70_SCAN_ONLY
|
||||
src/wifi_mgmt_scan.c
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_NRF70_RADIO_TEST
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/src/radio_test/fmac_api.c
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/src/fmac_util.c
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_NRF70_DATA_TX
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/src/tx.c
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/src/fmac_peer.c
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_NRF70_STA_MODE
|
||||
src/wpa_supp_if.c
|
||||
src/wifi_mgmt.c
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/src/fmac_peer.c
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/src/fmac_util.c
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_NRF70_AP_MODE
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/src/fmac_ap.c
|
||||
)
|
||||
|
||||
|
||||
# Without WPA supplicant we only support scan
|
||||
zephyr_library_sources_ifdef(CONFIG_NRF70_STA_MODE
|
||||
src/wpa_supp_if.c
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/src/fmac_peer.c
|
||||
${OS_AGNOSTIC_BASE}/fw_if/umac_if/src/fmac_util.c
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_NRF70_ON_QSPI
|
||||
src/qspi/src/qspi_if.c
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_NRF70_ON_SPI
|
||||
src/qspi/src/spi_if.c
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_NRF70_UTIL
|
||||
src/wifi_util.c
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF70_ON_QSPI
|
||||
# These are XIP related anomalies and aren't applicable for nRF7002 and cause
|
||||
# throughput issues.
|
||||
-DNRF53_ERRATA_43_ENABLE_WORKAROUND=0
|
||||
-DNRF52_ERRATA_215_ENABLE_WORKAROUND=0
|
||||
# nRF70 QSPI doesn't use 192MHz clock and most samples use 128MHz, this can cause anomaly 159
|
||||
# but as its rare and not seen in most cases, we can disable it.
|
||||
# Alternative is 128MHz CPU should be disabled that impacts Wi-Fi performance.
|
||||
-DNRF53_ERRATA_159_ENABLE_WORKAROUND=0
|
||||
)
|
||||
|
||||
# RPU FW patch binaries based on the selected configuration
|
||||
if(CONFIG_NRF70_SYSTEM_MODE)
|
||||
set(NRF70_PATCH ${FW_BINS_BASE}/default/nrf70.bin)
|
||||
elseif(CONFIG_NRF70_RADIO_TEST)
|
||||
set(NRF70_PATCH ${FW_BINS_BASE}/radio_test/nrf70.bin)
|
||||
elseif(CONFIG_NRF70_SCAN_ONLY)
|
||||
set(NRF70_PATCH ${FW_BINS_BASE}/scan_only/nrf70.bin)
|
||||
elseif (CONFIG_NRF70_SYSTEM_WITH_RAW_MODES)
|
||||
set(NRF70_PATCH ${FW_BINS_BASE}/system_with_raw/nrf70.bin)
|
||||
else()
|
||||
# Error
|
||||
message(FATAL_ERROR "Unsupported nRF70 patch configuration")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS ${NRF70_PATCH})
|
||||
message(FATAL_ERROR "
|
||||
------------------------------------------------------------------------
|
||||
Missing blobs for nRF70 device driver, please install by running:
|
||||
$ west update
|
||||
$ west blobs fetch hal_nordic
|
||||
------------------------------------------------------------------------")
|
||||
endif()
|
||||
|
||||
zephyr_compile_definitions(
|
||||
-DCONFIG_NRF_WIFI_FW_BIN=${NRF70_PATCH}
|
||||
)
|
||||
|
||||
# Translate the configuration to the OS agnostic code
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF_WIFI_LOW_POWER
|
||||
-DNRF_WIFI_LOW_POWER
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF_WIFI_RPU_RECOVERY
|
||||
-DNRF_WIFI_RPU_RECOVERY
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF_WIFI_AP_DEAD_DETECT_TIMEOUT
|
||||
-DNRF_WIFI_AP_DEAD_DETECT_TIMEOUT=${CONFIG_NRF_WIFI_AP_DEAD_DETECT_TIMEOUT}
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF_WIFI_IFACE_MTU
|
||||
-DNRF_WIFI_IFACE_MTU=${CONFIG_NRF_WIFI_IFACE_MTU}
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF70_STA_MODE
|
||||
-DNRF70_STA_MODE
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF70_DATA_TX
|
||||
-DNRF70_DATA_TX
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF70_RAW_DATA_TX
|
||||
-DNRF70_RAW_DATA_TX
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF70_RAW_DATA_RX
|
||||
-DNRF70_RAW_DATA_RX
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF70_PROMISC_DATA_RX
|
||||
-DNRF70_PROMISC_DATA_RX
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF70_TX_DONE_WQ_ENABLED
|
||||
-DNRF70_TX_DONE_WQ_ENABLED
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF70_RX_WQ_ENABLED
|
||||
-DNRF70_RX_WQ_ENABLED
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF70_UTIL
|
||||
-DNRF70_UTIL
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF70_RADIO_TEST
|
||||
-DNRF70_RADIO_TEST
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF70_TCP_IP_CHECKSUM_OFFLOAD
|
||||
-DNRF70_TCP_IP_CHECKSUM_OFFLOAD
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF70_RPU_EXTEND_TWT_SP
|
||||
-DNRF70_RPU_EXTEND_TWT_SP
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF70_SYSTEM_WITH_RAW_MODES
|
||||
-DNRF70_SYSTEM_WITH_RAW_MODES
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF70_SCAN_ONLY
|
||||
-DNRF70_SCAN_ONLY
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF70_SYSTEM_MODE
|
||||
-DNRF70_SYSTEM_MODE
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF70_2_4G_ONLY
|
||||
-DNRF70_2_4G_ONLY
|
||||
)
|
||||
|
||||
zephyr_compile_definitions_ifdef(CONFIG_NRF70_LOG_VERBOSE
|
||||
-DNRF70_LOG_VERBOSE
|
||||
)
|
||||
|
||||
zephyr_compile_definitions(
|
||||
-DNRF70_RX_NUM_BUFS=${CONFIG_NRF70_RX_NUM_BUFS}
|
||||
-DNRF70_MAX_TX_TOKENS=${CONFIG_NRF70_MAX_TX_TOKENS}
|
||||
-DNRF70_RX_MAX_DATA_SIZE=${CONFIG_NRF70_RX_MAX_DATA_SIZE}
|
||||
-DNRF70_MAX_TX_PENDING_QLEN=${CONFIG_NRF70_MAX_TX_PENDING_QLEN}
|
||||
-DNRF70_RPU_PS_IDLE_TIMEOUT_MS=${CONFIG_NRF70_RPU_PS_IDLE_TIMEOUT_MS}
|
||||
-DNRF70_REG_DOMAIN=${CONFIG_NRF70_REG_DOMAIN}
|
||||
-DNRF70_BAND_2G_LOWER_EDGE_BACKOFF_DSSS=${CONFIG_NRF70_BAND_2G_LOWER_EDGE_BACKOFF_DSSS}
|
||||
-DNRF70_BAND_2G_LOWER_EDGE_BACKOFF_HT=${CONFIG_NRF70_BAND_2G_LOWER_EDGE_BACKOFF_HT}
|
||||
-DNRF70_BAND_2G_LOWER_EDGE_BACKOFF_HE=${CONFIG_NRF70_BAND_2G_LOWER_EDGE_BACKOFF_HE}
|
||||
-DNRF70_BAND_2G_UPPER_EDGE_BACKOFF_DSSS=${CONFIG_NRF70_BAND_2G_UPPER_EDGE_BACKOFF_DSSS}
|
||||
-DNRF70_BAND_2G_UPPER_EDGE_BACKOFF_HT=${CONFIG_NRF70_BAND_2G_UPPER_EDGE_BACKOFF_HT}
|
||||
-DNRF70_BAND_2G_UPPER_EDGE_BACKOFF_HE=${CONFIG_NRF70_BAND_2G_UPPER_EDGE_BACKOFF_HE}
|
||||
-DNRF70_BAND_UNII_1_LOWER_EDGE_BACKOFF_HT=${CONFIG_NRF70_BAND_UNII_1_LOWER_EDGE_BACKOFF_HT}
|
||||
-DNRF70_BAND_UNII_1_LOWER_EDGE_BACKOFF_HE=${CONFIG_NRF70_BAND_UNII_1_LOWER_EDGE_BACKOFF_HE}
|
||||
-DNRF70_BAND_UNII_1_UPPER_EDGE_BACKOFF_HT=${CONFIG_NRF70_BAND_UNII_1_UPPER_EDGE_BACKOFF_HT}
|
||||
-DNRF70_BAND_UNII_1_UPPER_EDGE_BACKOFF_HE=${CONFIG_NRF70_BAND_UNII_1_UPPER_EDGE_BACKOFF_HE}
|
||||
-DNRF70_BAND_UNII_2A_LOWER_EDGE_BACKOFF_HT=${CONFIG_NRF70_BAND_UNII_2A_LOWER_EDGE_BACKOFF_HT}
|
||||
-DNRF70_BAND_UNII_2A_LOWER_EDGE_BACKOFF_HE=${CONFIG_NRF70_BAND_UNII_2A_LOWER_EDGE_BACKOFF_HE}
|
||||
-DNRF70_BAND_UNII_2A_UPPER_EDGE_BACKOFF_HT=${CONFIG_NRF70_BAND_UNII_2A_UPPER_EDGE_BACKOFF_HT}
|
||||
-DNRF70_BAND_UNII_2A_UPPER_EDGE_BACKOFF_HE=${CONFIG_NRF70_BAND_UNII_2A_UPPER_EDGE_BACKOFF_HE}
|
||||
-DNRF70_BAND_UNII_2C_LOWER_EDGE_BACKOFF_HT=${CONFIG_NRF70_BAND_UNII_2C_LOWER_EDGE_BACKOFF_HT}
|
||||
-DNRF70_BAND_UNII_2C_LOWER_EDGE_BACKOFF_HE=${CONFIG_NRF70_BAND_UNII_2C_LOWER_EDGE_BACKOFF_HE}
|
||||
-DNRF70_BAND_UNII_2C_UPPER_EDGE_BACKOFF_HT=${CONFIG_NRF70_BAND_UNII_2C_UPPER_EDGE_BACKOFF_HT}
|
||||
-DNRF70_BAND_UNII_2C_UPPER_EDGE_BACKOFF_HE=${CONFIG_NRF70_BAND_UNII_2C_UPPER_EDGE_BACKOFF_HE}
|
||||
-DNRF70_BAND_UNII_3_LOWER_EDGE_BACKOFF_HT=${CONFIG_NRF70_BAND_UNII_3_LOWER_EDGE_BACKOFF_HT}
|
||||
-DNRF70_BAND_UNII_3_LOWER_EDGE_BACKOFF_HE=${CONFIG_NRF70_BAND_UNII_3_LOWER_EDGE_BACKOFF_HE}
|
||||
-DNRF70_BAND_UNII_3_UPPER_EDGE_BACKOFF_HT=${CONFIG_NRF70_BAND_UNII_3_UPPER_EDGE_BACKOFF_HT}
|
||||
-DNRF70_BAND_UNII_3_UPPER_EDGE_BACKOFF_HE=${CONFIG_NRF70_BAND_UNII_3_UPPER_EDGE_BACKOFF_HE}
|
||||
-DNRF70_BAND_UNII_4_LOWER_EDGE_BACKOFF_HT=${CONFIG_NRF70_BAND_UNII_4_LOWER_EDGE_BACKOFF_HT}
|
||||
-DNRF70_BAND_UNII_4_LOWER_EDGE_BACKOFF_HE=${CONFIG_NRF70_BAND_UNII_4_LOWER_EDGE_BACKOFF_HE}
|
||||
-DNRF70_BAND_UNII_4_UPPER_EDGE_BACKOFF_HT=${CONFIG_NRF70_BAND_UNII_4_UPPER_EDGE_BACKOFF_HT}
|
||||
-DNRF70_BAND_UNII_4_UPPER_EDGE_BACKOFF_HE=${CONFIG_NRF70_BAND_UNII_4_UPPER_EDGE_BACKOFF_HE}
|
||||
-DNRF70_PCB_LOSS_2G=${CONFIG_NRF70_PCB_LOSS_2G}
|
||||
-DNRF70_PCB_LOSS_5G_BAND1=${CONFIG_NRF70_PCB_LOSS_5G_BAND1}
|
||||
-DNRF70_PCB_LOSS_5G_BAND2=${CONFIG_NRF70_PCB_LOSS_5G_BAND2}
|
||||
-DNRF70_PCB_LOSS_5G_BAND3=${CONFIG_NRF70_PCB_LOSS_5G_BAND3}
|
||||
-DNRF70_ANT_GAIN_2G=${CONFIG_NRF70_ANT_GAIN_2G}
|
||||
-DNRF70_ANT_GAIN_5G_BAND1=${CONFIG_NRF70_ANT_GAIN_5G_BAND1}
|
||||
-DNRF70_ANT_GAIN_5G_BAND2=${CONFIG_NRF70_ANT_GAIN_5G_BAND2}
|
||||
-DNRF70_ANT_GAIN_5G_BAND3=${CONFIG_NRF70_ANT_GAIN_5G_BAND3}
|
||||
)
|
670
drivers/wifi/nrfwifi/Kconfig.nrfwifi
Normal file
670
drivers/wifi/nrfwifi/Kconfig.nrfwifi
Normal file
|
@ -0,0 +1,670 @@
|
|||
# Nordic Wi-Fi driver for nRF70 series SoCs
|
||||
#
|
||||
# Copyright (c) 2024 Nordic Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
menuconfig WIFI_NRF70
|
||||
bool "nRF70 driver"
|
||||
select NET_L2_WIFI_MGMT if NETWORKING
|
||||
select NET_L2_ETHERNET_MGMT if NETWORKING && NET_L2_ETHERNET
|
||||
select WIFI_USE_NATIVE_NETWORKING if NETWORKING
|
||||
select EXPERIMENTAL if !SOC_SERIES_NRF53X && !SOC_SERIES_NRF91X
|
||||
default y
|
||||
depends on \
|
||||
DT_HAS_NORDIC_NRF7002_SPI_ENABLED || DT_HAS_NORDIC_NRF7002_QSPI_ENABLED || \
|
||||
DT_HAS_NORDIC_NRF7001_SPI_ENABLED || DT_HAS_NORDIC_NRF7001_QSPI_ENABLED || \
|
||||
DT_HAS_NORDIC_NRF7000_SPI_ENABLED || DT_HAS_NORDIC_NRF7000_QSPI_ENABLED
|
||||
help
|
||||
Nordic Wi-Fi Driver
|
||||
|
||||
if WIFI_NRF70
|
||||
# Hidden symbols for internal use
|
||||
config WIFI_NRF7002
|
||||
bool
|
||||
default y if DT_HAS_NORDIC_NRF7002_SPI_ENABLED || DT_HAS_NORDIC_NRF7002_QSPI_ENABLED
|
||||
|
||||
config WIFI_NRF7001
|
||||
bool
|
||||
default y if DT_HAS_NORDIC_NRF7001_SPI_ENABLED || DT_HAS_NORDIC_NRF7001_QSPI_ENABLED
|
||||
|
||||
config WIFI_NRF7000
|
||||
bool
|
||||
default y if DT_HAS_NORDIC_NRF7000_SPI_ENABLED || DT_HAS_NORDIC_NRF7000_QSPI_ENABLED
|
||||
|
||||
|
||||
module = WIFI_NRF70_BUS
|
||||
module-dep = LOG
|
||||
module-str = Log level for Wi-Fi nRF70 bus layers
|
||||
module-help = Sets log level for Wi-Fi nRF70 bus layers
|
||||
source "subsys/net/Kconfig.template.log_config.net"
|
||||
|
||||
config WIFI_NRF70_BUS_LOG_LEVEL
|
||||
# Enable error by default
|
||||
default 1
|
||||
|
||||
choice NRF70_OPER_MODES
|
||||
bool "nRF70 operating modes"
|
||||
default NRF70_SYSTEM_WITH_RAW_MODES if !WIFI_NRF7000 && \
|
||||
(NRF70_RAW_DATA_TX || NRF70_RAW_DATA_RX || NRF70_PROMISC_DATA_RX)
|
||||
default NRF70_SYSTEM_MODE if !WIFI_NRF7000
|
||||
default NRF70_SCAN_ONLY if WIFI_NRF7000
|
||||
help
|
||||
Select the operating mode of the nRF70 driver
|
||||
|
||||
config NRF70_SYSTEM_MODE
|
||||
bool "nRF70 system mode"
|
||||
depends on WIFI_NRF7002 || WIFI_NRF7001
|
||||
select WIFI_NM_WPA_SUPPLICANT
|
||||
help
|
||||
Select this option to enable system mode of the nRF70 driver
|
||||
|
||||
config NRF70_SCAN_ONLY
|
||||
bool "nRF70 scan only mode"
|
||||
depends on WIFI_NRF7000
|
||||
help
|
||||
Select this option to enable scan only mode of the nRF70 driver
|
||||
|
||||
config NRF70_RADIO_TEST
|
||||
bool "Radio test mode of the nRF70 driver"
|
||||
|
||||
config NRF70_SYSTEM_WITH_RAW_MODES
|
||||
bool "nRF70 system mode with raw modes"
|
||||
depends on WIFI_NRF7002 || WIFI_NRF7001
|
||||
select WIFI_NM_WPA_SUPPLICANT
|
||||
help
|
||||
Select this option to enable system mode of the nRF70 driver with raw modes
|
||||
|
||||
endchoice
|
||||
|
||||
config NET_L2_ETHERNET
|
||||
default y if !NRF70_RADIO_TEST
|
||||
|
||||
config HEAP_MEM_POOL_ADD_SIZE_NRF70
|
||||
# Use a maximum that works for typical usecases and boards, each sample/app can override
|
||||
# this value if needed by using CONFIG_HEAP_MEM_POOL_IGNORE_MIN
|
||||
def_int 25000 if NRF70_SCAN_ONLY
|
||||
def_int 150000
|
||||
|
||||
if NRF70_SYSTEM_MODE || NRF70_SYSTEM_WITH_RAW_MODES
|
||||
config NRF70_STA_MODE
|
||||
bool "nRF70 STA mode"
|
||||
default y
|
||||
help
|
||||
Select this option to enable STA mode of the nRF70 driver
|
||||
|
||||
config NRF70_AP_MODE
|
||||
bool "Access point mode"
|
||||
depends on WIFI_NM_WPA_SUPPLICANT_AP
|
||||
|
||||
config NRF70_P2P_MODE
|
||||
bool "P2P support in driver"
|
||||
endif # NRF70_SYSTEM_MODE || NRF70_SYSTEM_WITH_RAW_MODES
|
||||
|
||||
config NRF70_RAW_DATA_TX
|
||||
bool "RAW TX data path in the driver"
|
||||
select EXPERIMENTAL
|
||||
|
||||
config NRF70_RAW_DATA_RX
|
||||
bool "RAW RX sniffer operation in the driver"
|
||||
select EXPERIMENTAL
|
||||
|
||||
config NRF70_PROMISC_DATA_RX
|
||||
bool "promiscuous RX sniffer operation in the driver"
|
||||
select WIFI_NM_WPA_SUPPLICANT
|
||||
select EXPERIMENTAL
|
||||
select NET_PROMISCUOUS_MODE
|
||||
|
||||
config NRF70_DATA_TX
|
||||
bool "TX data path in the driver"
|
||||
default y if NRF70_SYSTEM_MODE || NRF70_SYSTEM_WITH_RAW_MODES
|
||||
|
||||
config NRF_WIFI_IF_AUTO_START
|
||||
bool "Wi-Fi interface auto start on boot"
|
||||
default y
|
||||
|
||||
config NRF_WIFI_PATCHES_BUILTIN
|
||||
bool "Store nRF70 FW patches as part of the driver"
|
||||
default y
|
||||
help
|
||||
Select this option to store nRF70 FW patches as part of the driver.
|
||||
This option impacts the code memory footprint of the driver.
|
||||
|
||||
config CUSTOM_LINKER_SCRIPT
|
||||
string "Custom linker script for nRF70 FW patches"
|
||||
default "${ZEPHYR_BASE}/../nrf/drivers/wifi/nrf70/rpu_fw_patches.ld"
|
||||
|
||||
config NRF_WIFI_LOW_POWER
|
||||
bool "low power mode in nRF Wi-Fi chipsets"
|
||||
default y
|
||||
|
||||
config NRF70_TCP_IP_CHECKSUM_OFFLOAD
|
||||
bool "TCP/IP checksum offload"
|
||||
default y
|
||||
|
||||
config NRF70_REG_DOMAIN
|
||||
string "The ISO/IEC alpha2 country code for the country in which this device is currently operating. Default 00 (World regulatory)"
|
||||
# 00 is used for World regulatory
|
||||
default "00"
|
||||
|
||||
# Making calls to RPU from net_mgmt callbacks.
|
||||
#
|
||||
# If WPA supplicant is enabled, then don't override as it has higher
|
||||
# stack requirements.
|
||||
config NET_MGMT_EVENT_STACK_SIZE
|
||||
default 2048 if !WIFI_NM_WPA_SUPPLICANT
|
||||
|
||||
config NRF70_LOG_VERBOSE
|
||||
bool "Maintains the verbosity of information in logs"
|
||||
default y
|
||||
|
||||
module = WIFI_NRF70
|
||||
module-dep = LOG
|
||||
module-str = Log level for Wi-Fi nRF70 driver
|
||||
module-help = Sets log level for Wi-Fi nRF70 driver
|
||||
source "subsys/logging/Kconfig.template.log_config"
|
||||
|
||||
config WIFI_NRF70_LOG_LEVEL
|
||||
# Enable error by default
|
||||
default 1
|
||||
|
||||
config NRF70_ON_QSPI
|
||||
def_bool DT_HAS_NORDIC_NRF7002_QSPI_ENABLED || \
|
||||
DT_HAS_NORDIC_NRF7001_QSPI_ENABLED || \
|
||||
DT_HAS_NORDIC_NRF7000_QSPI_ENABLED
|
||||
select NRFX_QSPI
|
||||
|
||||
config NRF70_ON_SPI
|
||||
def_bool DT_HAS_NORDIC_NRF7002_SPI_ENABLED || \
|
||||
DT_HAS_NORDIC_NRF7001_SPI_ENABLED || \
|
||||
DT_HAS_NORDIC_NRF7000_SPI_ENABLED
|
||||
select SPI
|
||||
|
||||
config NRF70_2_4G_ONLY
|
||||
def_bool y if WIFI_NRF7001
|
||||
|
||||
# Wi-Fi and SR Coexistence Hardware configuration.
|
||||
config NRF70_SR_COEX
|
||||
bool "Wi-Fi and SR coexistence support"
|
||||
|
||||
config NRF70_SR_COEX_RF_SWITCH
|
||||
bool "GPIO configuration to control SR side RF switch position"
|
||||
|
||||
config NRF70_WORKQ_STACK_SIZE
|
||||
int "Stack size for workqueue"
|
||||
default 4096
|
||||
|
||||
config NRF70_WORKQ_MAX_ITEMS
|
||||
int "Maximum work items for all workqueues"
|
||||
default 100
|
||||
|
||||
config NRF70_MAX_TX_PENDING_QLEN
|
||||
int "Maximum number of pending TX packets"
|
||||
default 18
|
||||
|
||||
config NRF70_UTIL
|
||||
depends on SHELL
|
||||
bool "Utility shell in nRF70 driver"
|
||||
|
||||
config NRF70_QSPI_LOW_POWER
|
||||
bool "low power mode in QSPI"
|
||||
default y if NRF_WIFI_LOW_POWER
|
||||
|
||||
config NRF70_PCB_LOSS_2G
|
||||
int "PCB loss for 2.4 GHz band"
|
||||
default 0
|
||||
range 0 4
|
||||
help
|
||||
Specifies PCB loss from the antenna connector to the RF pin.
|
||||
The values are in dB scale in steps of 1dB and range of 0-4dB.
|
||||
The loss is considered in the RX path only.
|
||||
|
||||
config NRF70_PCB_LOSS_5G_BAND1
|
||||
int "PCB loss for 5 GHz band (5150 MHz - 5350 MHz, Channel-32 - Channel-68)"
|
||||
default 0
|
||||
range 0 4
|
||||
help
|
||||
Specifies PCB loss from the antenna connector to the RF pin.
|
||||
The values are in dB scale in steps of 1dB and range of 0-4dB.
|
||||
The loss is considered in the RX path only.
|
||||
|
||||
config NRF70_PCB_LOSS_5G_BAND2
|
||||
int "PCB loss for 5 GHz band (5470 MHz - 5730 MHz, Channel-96 - Channel-144)"
|
||||
default 0
|
||||
range 0 4
|
||||
help
|
||||
Specifies PCB loss from the antenna connector to the RF pin.
|
||||
The values are in dB scale in steps of 1dB and range of 0-4dB.
|
||||
The loss is considered in the RX path only.
|
||||
|
||||
config NRF70_PCB_LOSS_5G_BAND3
|
||||
int "PCB loss for 5 GHz band (5730 MHz - 5895 MHz, Channel-149 - Channel-177)"
|
||||
default 0
|
||||
range 0 4
|
||||
help
|
||||
Specifies PCB loss from the antenna connector to the RF pin.
|
||||
The values are in dB scale in steps of 1dB and range of 0-4dB.
|
||||
The loss is considered in the RX path only.
|
||||
|
||||
config NRF70_ANT_GAIN_2G
|
||||
int "Antenna gain for 2.4 GHz band"
|
||||
default 0
|
||||
range 0 6
|
||||
|
||||
config NRF70_ANT_GAIN_5G_BAND1
|
||||
int "Antenna gain for 5 GHz band (5150 MHz - 5350 MHz)"
|
||||
default 0
|
||||
range 0 6
|
||||
|
||||
config NRF70_ANT_GAIN_5G_BAND2
|
||||
int "Antenna gain for 5 GHz band (5470 MHz - 5730 MHz)"
|
||||
default 0
|
||||
range 0 6
|
||||
|
||||
config NRF70_ANT_GAIN_5G_BAND3
|
||||
int "Antenna gain for 5 GHz band (5730 MHz - 5895 MHz)"
|
||||
default 0
|
||||
range 0 6
|
||||
|
||||
config NRF70_BAND_2G_LOWER_EDGE_BACKOFF_DSSS
|
||||
int "DSSS Transmit power backoff (in dB) for lower edge of 2.4 GHz frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_2G_LOWER_EDGE_BACKOFF_HT
|
||||
int "HT/VHT Transmit power backoff (in dB) for lower edge of 2.4 GHz frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_2G_LOWER_EDGE_BACKOFF_HE
|
||||
int "HE Transmit power backoff (in dB) for lower edge of 2.4 GHz frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_2G_UPPER_EDGE_BACKOFF_DSSS
|
||||
int "DSSS Transmit power backoff (in dB) for upper edge of 2.4 GHz frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_2G_UPPER_EDGE_BACKOFF_HT
|
||||
int "HT/VHT Transmit power backoff (in dB) for upper edge of 2.4 GHz frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_2G_UPPER_EDGE_BACKOFF_HE
|
||||
int "HE Transmit power backoff (in dB) for upper edge of 2.4 GHz frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_1_LOWER_EDGE_BACKOFF_HT
|
||||
int "HT/VHT Transmit power backoff (in dB) for lower edge of UNII-1 frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_1_LOWER_EDGE_BACKOFF_HE
|
||||
int "HE Transmit power backoff (in dB) for lower edge of UNII-1 frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_1_UPPER_EDGE_BACKOFF_HT
|
||||
int "HT/VHT Transmit power backoff (in dB) for upper edge of UNII-1 frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_1_UPPER_EDGE_BACKOFF_HE
|
||||
int "HE Transmit power backoff (in dB) for upper edge of UNII-1 frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_2A_LOWER_EDGE_BACKOFF_HT
|
||||
int "HT/VHT Transmit power backoff (in dB) for lower edge of UNII-2A frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_2A_LOWER_EDGE_BACKOFF_HE
|
||||
int "HE Transmit power backoff (in dB) for lower edge of UNII-2A frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_2A_UPPER_EDGE_BACKOFF_HT
|
||||
int "HT/VHT Transmit power backoff (in dB) for upper edge of UNII-2A frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_2A_UPPER_EDGE_BACKOFF_HE
|
||||
int "HE Transmit power backoff (in dB) for upper edge of UNII-2A frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_2C_LOWER_EDGE_BACKOFF_HT
|
||||
int "HT/VHT Transmit power backoff (in dB) for lower edge of UNII-2C frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_2C_LOWER_EDGE_BACKOFF_HE
|
||||
int "HE Transmit power backoff (in dB) for lower edge of UNII-2C frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_2C_UPPER_EDGE_BACKOFF_HT
|
||||
int "HT/VHT Transmit power backoff (in dB) for upper edge of UNII-2C frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_2C_UPPER_EDGE_BACKOFF_HE
|
||||
int "HE Transmit power backoff (in dB) for upper edge of UNII-2C frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_3_LOWER_EDGE_BACKOFF_HT
|
||||
int "HT/VHT Transmit power backoff (in dB) for lower edge of UNII-3 frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_3_LOWER_EDGE_BACKOFF_HE
|
||||
int "HE Transmit power backoff (in dB) for lower edge of UNII-3 frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_3_UPPER_EDGE_BACKOFF_HT
|
||||
int "HT/VHT Transmit power backoff (in dB) for upper edge of UNII-3 frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_3_UPPER_EDGE_BACKOFF_HE
|
||||
int "HE Transmit power backoff (in dB) for upper edge of UNII-3 frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_4_LOWER_EDGE_BACKOFF_HT
|
||||
int "HT/VHT Transmit power backoff (in dB) for lower edge of UNII-4 frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_4_LOWER_EDGE_BACKOFF_HE
|
||||
int "HE Transmit power backoff (in dB) for lower edge of UNII-4 frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_4_UPPER_EDGE_BACKOFF_HT
|
||||
int "HT/VHT Transmit power backoff (in dB) for upper edge of UNII-4 frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
config NRF70_BAND_UNII_4_UPPER_EDGE_BACKOFF_HE
|
||||
int "HE Transmit power backoff (in dB) for upper edge of UNII-4 frequency band"
|
||||
default 0
|
||||
range 0 10
|
||||
|
||||
# Performance fine tuning options
|
||||
|
||||
config NRF70_RX_NUM_BUFS
|
||||
int "Number of RX buffers"
|
||||
default 48
|
||||
|
||||
config NRF70_MAX_TX_AGGREGATION
|
||||
int "Maximum number of TX packets to aggregate"
|
||||
default 12
|
||||
|
||||
config NRF70_MAX_TX_TOKENS
|
||||
int "Maximum number of TX tokens"
|
||||
range 5 12 if !NRF70_RADIO_TEST
|
||||
default 10
|
||||
|
||||
config NRF70_TX_MAX_DATA_SIZE
|
||||
int "Maximum size of TX data"
|
||||
default 1600
|
||||
|
||||
config NRF70_RX_MAX_DATA_SIZE
|
||||
int "Maximum size of RX data"
|
||||
default 1600
|
||||
|
||||
config NRF70_TX_DONE_WQ_ENABLED
|
||||
bool "TX done workqueue (impacts performance negatively)"
|
||||
|
||||
config NRF70_RX_WQ_ENABLED
|
||||
bool "RX workqueue"
|
||||
|
||||
# Use for IRQ processing (TODO: using for BH processing causes issues)
|
||||
config NUM_METAIRQ_PRIORITIES
|
||||
default 1
|
||||
|
||||
config NRF70_IRQ_WQ_PRIORITY
|
||||
int "Priority of the workqueue for handling IRQs"
|
||||
default -15
|
||||
|
||||
config NRF70_BH_WQ_PRIORITY
|
||||
int "Priority of the workqueue for handling bottom half"
|
||||
default 0
|
||||
|
||||
config NRF70_IRQ_WQ_STACK_SIZE
|
||||
int "Stack size of the workqueue for handling IRQs"
|
||||
default 2048
|
||||
|
||||
config NRF70_BH_WQ_STACK_SIZE
|
||||
int "Stack size of the workqueue for handling bottom half"
|
||||
default 2048
|
||||
|
||||
if NRF70_TX_DONE_WQ_ENABLED
|
||||
config NRF70_TX_DONE_WQ_PRIORITY
|
||||
int "Priority of the workqueue for handling TX done"
|
||||
default 0
|
||||
|
||||
config NRF70_TX_DONE_WQ_STACK_SIZE
|
||||
int "Stack size of the workqueue for handling TX done"
|
||||
default 2048
|
||||
endif # NRF70_TX_DONE_WQ_ENABLED
|
||||
if NRF70_RX_WQ_ENABLED
|
||||
config NRF70_RX_WQ_PRIORITY
|
||||
int "Priority of the workqueue for handling RX"
|
||||
default 0
|
||||
|
||||
config NRF70_RX_WQ_STACK_SIZE
|
||||
int "Stack size of the workqueue for handling RX"
|
||||
default 2048
|
||||
endif # NRF70_RX_WQ_ENABLED
|
||||
|
||||
if NRF_WIFI_LOW_POWER
|
||||
config NRF70_RPU_PS_IDLE_TIMEOUT_MS
|
||||
int "RPU power save idle timeout in milliseconds"
|
||||
default 10
|
||||
|
||||
config NRF70_RPU_EXTEND_TWT_SP
|
||||
bool "extending TWT service period"
|
||||
help
|
||||
In case frames accepted before beginning of SP are not
|
||||
transmitted before the SP completes then typically they are
|
||||
dropped to conform to SP window as per specification i.e., no
|
||||
transmission outside SP window.
|
||||
|
||||
This feature mitigates the frame loss by transmitting even after SP
|
||||
completion by using standard contention mechanism which is allowed
|
||||
in specification but not recommended. As the device is actively transmitting
|
||||
beyond SP, the power consumption increases depending on the amount
|
||||
of traffic available at the start of SP.
|
||||
|
||||
Please note that if a frame is sent after SP starts it will be queued and this
|
||||
mechanism is not used.
|
||||
endif # NRF_WIFI_LOW_POWER
|
||||
|
||||
config WIFI_FIXED_MAC_ADDRESS
|
||||
string "WiFi Fixed MAC address in format XX:XX:XX:XX:XX:XX"
|
||||
help
|
||||
This overrides the MAC address read from OTP. Strictly for testing purposes only.
|
||||
|
||||
choice
|
||||
prompt "Wi-Fi MAC address type"
|
||||
default WIFI_OTP_MAC_ADDRESS if WIFI_FIXED_MAC_ADDRESS = ""
|
||||
default WIFI_FIXED_MAC_ADDRESS_ENABLED if WIFI_FIXED_MAC_ADDRESS != ""
|
||||
help
|
||||
Select the type of MAC address to be used by the Wi-Fi driver
|
||||
|
||||
config WIFI_OTP_MAC_ADDRESS
|
||||
bool "Use MAC address from OTP"
|
||||
help
|
||||
This option uses the MAC address stored in the OTP memory of the nRF70.
|
||||
|
||||
config WIFI_FIXED_MAC_ADDRESS_ENABLED
|
||||
bool "fixed MAC address"
|
||||
help
|
||||
Enable fixed MAC address
|
||||
|
||||
config WIFI_RANDOM_MAC_ADDRESS
|
||||
bool "random MAC address generation at runtime"
|
||||
depends on ENTROPY_GENERATOR
|
||||
help
|
||||
This option enables random MAC address generation at runtime.
|
||||
The random MAC address is generated using the entropy device random generator.
|
||||
|
||||
endchoice
|
||||
|
||||
config NRF70_RSSI_STALE_TIMEOUT_MS
|
||||
int "RSSI stale timeout in milliseconds"
|
||||
default 1000
|
||||
help
|
||||
RSSI stale timeout is the period after which driver queries
|
||||
RPU to get the RSSI the value.
|
||||
If data is active (e.g. ping), driver stores the RSSI value from
|
||||
the received frames and provides this stored information
|
||||
to wpa_supplicant. In this case a higher value will be suitable
|
||||
as stored RSSI value at driver will be updated regularly.
|
||||
If data is not active or after the stale timeout duration,
|
||||
driver queries the RPU to get the RSSI value
|
||||
and provides it to wpa_supplicant. The value should be set to lower
|
||||
value as driver does not store it and requires RPU to provide the
|
||||
info.
|
||||
|
||||
if NETWORKING
|
||||
# Finetune defaults for certain system components used by the driver
|
||||
config SYSTEM_WORKQUEUE_STACK_SIZE
|
||||
default 4096
|
||||
|
||||
config NET_TX_STACK_SIZE
|
||||
default 4096
|
||||
|
||||
config NET_RX_STACK_SIZE
|
||||
default 4096
|
||||
|
||||
config NET_TC_TX_COUNT
|
||||
default 1
|
||||
|
||||
endif # NETWORKING
|
||||
|
||||
config MAIN_STACK_SIZE
|
||||
default 4096
|
||||
|
||||
config SHELL_STACK_SIZE
|
||||
default 4096
|
||||
|
||||
# Override the Wi-Fi subsytems WIFI_MGMT_SCAN_SSID_FILT_MAX parameter,
|
||||
# since we support a maximum of 2 SSIDs for scan result filtering.
|
||||
config WIFI_MGMT_SCAN_SSID_FILT_MAX
|
||||
default 2
|
||||
|
||||
config NRF_WIFI_SCAN_MAX_BSS_CNT
|
||||
int "Maximum number of scan results to return."
|
||||
default 0
|
||||
range 0 65535
|
||||
help
|
||||
Maximum number of scan results to return. 0 represents unlimited number of BSSes.
|
||||
|
||||
config NRF_WIFI_BEAMFORMING
|
||||
bool "Wi-Fi beamforming. Enabling beamforming can provide slight improvement in performance where as disabling it can provide better power saving in low network activity applications"
|
||||
default y
|
||||
|
||||
config WIFI_NRF70_SCAN_TIMEOUT_S
|
||||
int "Scan timeout in seconds"
|
||||
default 30
|
||||
|
||||
menu "nRF Wi-Fi operation band(s)"
|
||||
visible if !NRF70_2_4G_ONLY
|
||||
|
||||
config NRF_WIFI_2G_BAND
|
||||
bool "Set operation band to 2.4GHz"
|
||||
default y if NRF70_2_4G_ONLY
|
||||
|
||||
config NRF_WIFI_5G_BAND
|
||||
bool "Set operation band to 5GHz"
|
||||
depends on !NRF70_2_4G_ONLY
|
||||
|
||||
config NRF_WIFI_OP_BAND
|
||||
int "Options to set operation band"
|
||||
default 1 if NRF_WIFI_2G_BAND
|
||||
default 2 if NRF_WIFI_5G_BAND
|
||||
default 3
|
||||
help
|
||||
Set this option to select frequency band
|
||||
1 - 2.4GHz
|
||||
2 - 5GHz
|
||||
3 - All ( 2.4GHz and 5GHz )
|
||||
endmenu
|
||||
|
||||
config NRF_WIFI_IFACE_MTU
|
||||
int "MTU for Wi-Fi interface"
|
||||
range 576 2304 if NET_IPV4
|
||||
range 1280 2304 if NET_IPV6
|
||||
default 1500
|
||||
|
||||
config WIFI_NRF70_SKIP_LOCAL_ADMIN_MAC
|
||||
bool "Suppress networks with non-individual MAC address as BSSID in the scan results"
|
||||
help
|
||||
Wi-Fi access points use locally administered MAC address to manage
|
||||
multiple virtual interfaces, for geo-location usecase these networks
|
||||
from the virtual interfaces do not help in anyway as they are co-located with the primary interface
|
||||
that has globally unique MAC address.
|
||||
|
||||
So, to save resources, this option drops such networks from the scan results.
|
||||
|
||||
config WIFI_NRF70_SCAN_DISABLE_DFS_CHANNELS
|
||||
bool "Disables DFS channels in scan operation"
|
||||
help
|
||||
This option disables inclusion of DFS channels in scan operation.
|
||||
This is useful to reduce the scan time, as DFS channels are seldom used.
|
||||
|
||||
config NET_INTERFACE_NAME_LEN
|
||||
# nordic_wlanN
|
||||
default 15
|
||||
|
||||
config NRF_WIFI_AP_DEAD_DETECT_TIMEOUT
|
||||
int "Access point dead detection timeout in seconds"
|
||||
range 1 30
|
||||
default 20
|
||||
help
|
||||
The number of seconds after which AP is declared dead if no beacons
|
||||
are received from the AP. Used to detect AP silently going down e.g., power off.
|
||||
|
||||
config NRF_WIFI_RPU_RECOVERY
|
||||
bool "RPU recovery mechanism"
|
||||
select EXPERIMENTAL
|
||||
help
|
||||
Enable RPU recovery mechanism to recover from RPU (nRF70) hang.
|
||||
This feature performs an interface reset (down and up) which triggers
|
||||
a RPU coldboot. Application's network connection will be lost during
|
||||
the recovery process and it is application's responsibility to
|
||||
re-establish the network connection.
|
||||
|
||||
if NRF_WIFI_RPU_RECOVERY
|
||||
|
||||
config NRF_WIFI_RPU_RECOVERY_PROPAGATION_DELAY_MS
|
||||
int "RPU recovery propagation delay in milliseconds"
|
||||
default 10
|
||||
help
|
||||
Propagation delay in milliseconds to wait after RPU is powered down
|
||||
before powering it up. This delay is required to ensure that the recovery
|
||||
is propagted to all the applications and stack and have enough time to
|
||||
clean up the resources.
|
||||
|
||||
config NET_MGMT_EVENT_QUEUE_SIZE
|
||||
# Doing interface down and up even with delay puts a lot of events in the queue
|
||||
default 16
|
||||
endif # NRF_WIFI_RPU_RECOVERY
|
||||
|
||||
config NRF_WIFI_COMBINED_BUCKEN_IOVDD_GPIO
|
||||
bool
|
||||
help
|
||||
Enable this option to use a single GPIO to control both buck enable and IOVDD enable,
|
||||
there will be a internal hardware switch to add delay between the two operations. This
|
||||
is typically 4ms delay for nRF70.
|
||||
|
||||
endif # WIFI_NRF70
|
84
drivers/wifi/nrfwifi/inc/coex.h
Normal file
84
drivers/wifi/nrfwifi/inc/coex.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Header containing Coexistence APIs.
|
||||
*/
|
||||
|
||||
#ifndef __COEX_H__
|
||||
#define __COEX_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Indicates WLAN frequency band of operation */
|
||||
enum nrf_wifi_pta_wlan_op_band {
|
||||
NRF_WIFI_PTA_WLAN_OP_BAND_2_4_GHZ = 0,
|
||||
NRF_WIFI_PTA_WLAN_OP_BAND_5_GHZ,
|
||||
NRF_WIFI_PTA_WLAN_OP_BAND_NONE = 0xFF
|
||||
};
|
||||
|
||||
/**
|
||||
* @function nrf_wifi_coex_config_pta(enum nrf_wifi_pta_wlan_op_band wlan_band,
|
||||
* bool separate_antennas, bool is_sr_protocol_ble)
|
||||
*
|
||||
* @brief Function used to configure PTA tables of coexistence hardware.
|
||||
*
|
||||
* @param[in] enum nrf_wifi_pta_wlan_op_band wlan_band
|
||||
* @param[in] separate_antennas
|
||||
* Indicates whether separate antenans are used or not.
|
||||
* @param[in] is_sr_protocol_ble
|
||||
* Indicates if SR protocol is Bluetooth LE or not.
|
||||
* @return Returns status of configuration.
|
||||
* Returns zero upon successful configuration.
|
||||
* Returns non-zero upon unsuccessful configuration.
|
||||
*/
|
||||
int nrf_wifi_coex_config_pta(enum nrf_wifi_pta_wlan_op_band wlan_band, bool separate_antennas,
|
||||
bool is_sr_protocol_ble);
|
||||
|
||||
#if defined(CONFIG_NRF70_SR_COEX_RF_SWITCH) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @function nrf_wifi_config_sr_switch(bool separate_antennas)
|
||||
*
|
||||
* @brief Function used to configure SR side switch (nRF5340 side switch in nRF7002 DK).
|
||||
*
|
||||
* @param[in] separate_antennas
|
||||
* Indicates whether separate antenans are used or not.
|
||||
*
|
||||
* @return Returns status of configuration.
|
||||
* Returns zero upon successful configuration.
|
||||
* Returns non-zero upon unsuccessful configuration.
|
||||
*/
|
||||
int nrf_wifi_config_sr_switch(bool separate_antennas);
|
||||
#endif /* CONFIG_NRF70_SR_COEX_RF_SWITCH */
|
||||
|
||||
/**
|
||||
* @function nrf_wifi_coex_config_non_pta(bool separate_antennas)
|
||||
*
|
||||
* @brief Function used to configure non-PTA registers of coexistence hardware.
|
||||
*
|
||||
* @param[in] separate_antennas
|
||||
* Indicates whether separate antenans are used or not.
|
||||
* @param[in] is_sr_protocol_ble
|
||||
* Indicates if SR protocol is Bluetooth LE or not.
|
||||
*
|
||||
* @return Returns status of configuration.
|
||||
* Returns zero upon successful configuration.
|
||||
* Returns non-zero upon unsuccessful configuration.
|
||||
*/
|
||||
int nrf_wifi_coex_config_non_pta(bool separate_antennas, bool is_sr_protocol_ble);
|
||||
|
||||
/**
|
||||
* @function nrf_wifi_coex_hw_reset(void)
|
||||
*
|
||||
* @brief Function used to reset coexistence hardware.
|
||||
*
|
||||
* @return Returns status of configuration.
|
||||
* Returns zero upon successful configuration.
|
||||
* Returns non-zero upon unsuccessful configuration.
|
||||
*/
|
||||
int nrf_wifi_coex_hw_reset(void);
|
||||
|
||||
#endif /* __COEX_H__ */
|
182
drivers/wifi/nrfwifi/inc/coex_struct.h
Normal file
182
drivers/wifi/nrfwifi/inc/coex_struct.h
Normal file
|
@ -0,0 +1,182 @@
|
|||
/**
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Structures and related enumerations used in Coexistence.
|
||||
*/
|
||||
|
||||
#ifndef __COEX_STRUCT_H__
|
||||
#define __COEX_STRUCT_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Max size of message buffer (exchanged between host and MAC). This is in "bytes" */
|
||||
#define MAX_MESSAGE_BUF_SIZE 320
|
||||
/* Number of elements in coex_ch_configuration other than configbuf[] */
|
||||
#define NUM_ELEMENTS_EXCL_CONFIGBUF 4
|
||||
/* Each configuration value is of type uint32_t */
|
||||
#define MAX_NUM_CONFIG_VALUES ((MAX_MESSAGE_BUF_SIZE-\
|
||||
(NUM_ELEMENTS_EXCL_CONFIGBUF*sizeof(uint32_t)))>>2)
|
||||
/* Number of elements in coex_sr_traffic_info other than sr_traffic_info[] */
|
||||
#define NUM_ELEMENTS_EXCL_SRINFOBUF 1
|
||||
/* Each SR Traffic Info is of type uint32_t */
|
||||
#define MAX_SR_TRAFFIC_BUF_SIZE 32
|
||||
|
||||
enum {
|
||||
/** Used two different values for AGGREGATION module because offset from base is
|
||||
* beyond supported message buffer size for WAIT_STATE_1_TIME register
|
||||
*/
|
||||
COEX_HARDWARE = 1,
|
||||
MAC_CTRL,
|
||||
MAC_CTRL_AGG_WAIT_STATE_1_TIME,
|
||||
MAC_CTRL_AGG,
|
||||
MAC_CTRL_DEAGG,
|
||||
WLAN_CTRL,
|
||||
};
|
||||
|
||||
/* IDs of different messages posted from Coexistence Driver to Coexistence Manager */
|
||||
enum {
|
||||
/* To insturct Coexistence Manager to collect and post SR traffic information */
|
||||
COLLECT_SR_TRAFFIC_INFO = 1,
|
||||
/* To insturct Coexistence Manager to allocate a priority window to SR */
|
||||
ALLOCATE_PTI_WINDOW,
|
||||
/* To do configuration of hardware related to coexistence */
|
||||
HW_CONFIGURATION,
|
||||
/* To start allocating periodic priority windows to Wi-Fi and SR */
|
||||
ALLOCATE_PPW,
|
||||
/* To start allocating virtual priority windows to Wi-Fi */
|
||||
ALLOCATE_VPW,
|
||||
/* To configure CM SW parameters */
|
||||
SW_CONFIGURATION,
|
||||
/* To control sheliak side switch */
|
||||
UPDATE_SWITCH_CONFIG
|
||||
};
|
||||
|
||||
/* ID(s) of different messages posted from Coexistence Manager to Coexistence Driver */
|
||||
enum {
|
||||
/* To post SR traffic information */
|
||||
SR_TRAFFIC_INFO = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* struct coex_collect_sr_traffic_info - Message from CD to CM to request SR traffic info.
|
||||
* @message_id: Indicates message ID. This is to be set to COLLECT_SR_TRAFFIC_INFO.
|
||||
* @num_sets_requested: Indicates the number of sets of duration and periodicity to be collected.
|
||||
*
|
||||
* Message from CD to CM to request SR traffic information.
|
||||
*/
|
||||
struct coex_collect_sr_traffic_info {
|
||||
uint32_t message_id;
|
||||
uint32_t num_sets_requested;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct coex_ch_configuration -Message from CD to CM to configure CH.
|
||||
* @message_id: Indicates message ID. This is to be set to HW_CONFIGURATION.
|
||||
* @num_reg_to_config: Indicates the number of registers to be configured.
|
||||
* @hw_to_config: Indicates the hardware block that is to be configured.
|
||||
* @hw_block_base_addr: Base address of the hardware block to be configured.
|
||||
* @configbuf: Configuration buffer that holds packed offset and configuration value.
|
||||
*
|
||||
* Message from CD to CM to configure CH
|
||||
*/
|
||||
struct coex_ch_configuration {
|
||||
uint32_t message_id;
|
||||
uint32_t num_reg_to_config;
|
||||
uint32_t hw_to_config;
|
||||
uint32_t hw_block_base_addr;
|
||||
uint32_t configbuf[MAX_NUM_CONFIG_VALUES];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct coex_allocate_pti_window - Message to CM to request a priority window.
|
||||
* @message_id: Indicates message ID. This is to be set to ALLOCATE_PTI_WINDOW.
|
||||
* @device_req_window: Indicates device requesting a priority window.
|
||||
* @window_start_or_end: Indicates if request is posted to START or END a priority window.
|
||||
* @imp_of_request: Indicates importance of activity for which the window is requested.
|
||||
* @can_be_deferred: activity of Wi-Fi/SR, for which window is requested can be deferred or not.
|
||||
*
|
||||
* Message to CM to request a priority window
|
||||
*/
|
||||
struct coex_allocate_pti_window {
|
||||
uint32_t message_id;
|
||||
uint32_t device_req_window;
|
||||
uint32_t window_start_or_end;
|
||||
uint32_t imp_of_request;
|
||||
uint32_t can_be_deferred;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct coex_allocate_ppw - Message from CD to CM to allocate Periodic Priority Windows.
|
||||
* @message_id: Indicates message ID. This is to be set to ALLOCATE_PPW.
|
||||
* @start_or_stop: Indiates start or stop allocation of PPWs.
|
||||
* @first_pti_window: Indicates first priority window in the series of PPWs.
|
||||
* @ps_mechanism: Indicates recommended powersave mechanism for Wi-Fi's downlink.
|
||||
* @wifi_window_duration: Indicates duration of Wi-Fi priority window.
|
||||
* @sr_window_duration: Indicates duration of SR priority window.
|
||||
*
|
||||
* Message from CD to CM to allocate Periodic Priority Windows.
|
||||
*/
|
||||
struct coex_allocate_ppw {
|
||||
uint32_t message_id;
|
||||
uint32_t start_or_stop;
|
||||
uint32_t first_pti_window;
|
||||
uint32_t ps_mechanism;
|
||||
uint32_t wifi_window_duration;
|
||||
uint32_t sr_window_duration;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct coex_allocate_vpw - Message from CD to CM to allocate Virtual Priority Windows.
|
||||
* @message_id: Indicates message ID. This is to be set to ALLOCATE_VPW.
|
||||
* @start_or_stop: Indicates start or stop allocation of VPWs.
|
||||
* @wifi_window_duration: Indicates duration of Wi-Fi virtual priority window.
|
||||
* @ps_mechanism: Indicates recommended powersave mechanism for Wi-Fi's downlink.
|
||||
*
|
||||
* Message from CD to CM to allocate Virtual Priority Windows.
|
||||
*/
|
||||
struct coex_allocate_vpw {
|
||||
uint32_t message_id;
|
||||
uint32_t start_or_stop;
|
||||
uint32_t wifi_window_duration;
|
||||
uint32_t ps_mechanism;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct coex_config_cm_params - Message from CD to CM to configure CM parameters
|
||||
* @message_id: Indicates message ID. This is to be set to SW_CONFIGURATION.
|
||||
* @first_isr_trigger_period: microseconds . used to trigger the ISR mechanism.
|
||||
* @sr_window_poll_periodicity_vpw: microseconds. This is used to poll through SR window.
|
||||
* that comes after Wi-Fi window ends and next SR activity starts, in the case of VPWs.
|
||||
* @lead_time_from_end_of_wlan_win: microseconds. Lead time from the end of Wi-Fi window.
|
||||
* (to inform AP that Wi-Fi is entering powersave) in the case of PPW and VPW generation.
|
||||
* @sr_window_poll_count_threshold: This is equal to "Wi-Fi contention timeout.
|
||||
* threshold"/sr_window_poll_periodicity_vpw.
|
||||
*
|
||||
* Message from CD to CM to configure CM parameters.
|
||||
*/
|
||||
struct coex_config_cm_params {
|
||||
uint32_t message_id;
|
||||
uint32_t first_isr_trigger_period;
|
||||
uint32_t sr_window_poll_periodicity_vpw;
|
||||
uint32_t lead_time_from_end_of_wlan_win;
|
||||
uint32_t sr_window_poll_count_threshold;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct coex_sr_traffic_info - Message from CM to CD to post SR traffic information.
|
||||
* @message_id: Indicates message ID. This is to be set to SR_TRAFFIC_INFO.
|
||||
* @sr_traffic_info: Traffic information buffer.
|
||||
*
|
||||
* Message from CM to CD to post SR traffic inforamtion
|
||||
*/
|
||||
struct coex_sr_traffic_info {
|
||||
uint32_t message_id;
|
||||
uint32_t sr_traffic_info[MAX_SR_TRAFFIC_BUF_SIZE];
|
||||
};
|
||||
|
||||
#endif /* __COEX_STRUCT_H__ */
|
133
drivers/wifi/nrfwifi/inc/fmac_main.h
Normal file
133
drivers/wifi/nrfwifi/inc/fmac_main.h
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Header containing FMAC interface specific declarations for the
|
||||
* Zephyr OS layer of the Wi-Fi driver.
|
||||
*/
|
||||
|
||||
#ifndef __ZEPHYR_FMAC_MAIN_H__
|
||||
#define __ZEPHYR_FMAC_MAIN_H__
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/version.h>
|
||||
#include <zephyr/net/net_if.h>
|
||||
#ifndef CONFIG_NRF70_RADIO_TEST
|
||||
#include <zephyr/net/wifi_mgmt.h>
|
||||
#include <zephyr/net/ethernet.h>
|
||||
#ifdef CONFIG_NETWORKING
|
||||
#include <net_if.h>
|
||||
#endif /* CONFIG_NETWORKING */
|
||||
#ifdef CONFIG_NRF70_STA_MODE
|
||||
#include <drivers/driver_zephyr.h>
|
||||
#endif /* CONFIG_NRF70_STA_MODE */
|
||||
#endif /* !CONFIG_NRF70_RADIO_TEST */
|
||||
|
||||
#include <fmac_api.h>
|
||||
#include <host_rpu_umac_if.h>
|
||||
|
||||
#define NRF70_DRIVER_VERSION "1."KERNEL_VERSION_STRING
|
||||
|
||||
#ifndef CONFIG_NRF70_RADIO_TEST
|
||||
struct nrf_wifi_vif_ctx_zep {
|
||||
const struct device *zep_dev_ctx;
|
||||
struct net_if *zep_net_if_ctx;
|
||||
void *supp_drv_if_ctx;
|
||||
void *rpu_ctx_zep;
|
||||
unsigned char vif_idx;
|
||||
struct k_mutex vif_lock;
|
||||
|
||||
scan_result_cb_t disp_scan_cb;
|
||||
bool scan_in_progress;
|
||||
int scan_type;
|
||||
uint16_t max_bss_cnt;
|
||||
unsigned int scan_res_cnt;
|
||||
struct k_work_delayable scan_timeout_work;
|
||||
|
||||
struct net_eth_addr mac_addr;
|
||||
int if_type;
|
||||
char ifname[16];
|
||||
enum nrf_wifi_fmac_if_op_state if_op_state;
|
||||
bool set_if_event_received;
|
||||
int set_if_status;
|
||||
#ifdef CONFIG_NET_STATISTICS_ETHERNET
|
||||
struct net_stats_eth eth_stats;
|
||||
#endif /* CONFIG_NET_STATISTICS_ETHERNET */
|
||||
#ifdef CONFIG_NRF70_STA_MODE
|
||||
unsigned int assoc_freq;
|
||||
enum nrf_wifi_fmac_if_carr_state if_carr_state;
|
||||
struct wpa_signal_info *signal_info;
|
||||
struct wpa_conn_info *conn_info;
|
||||
struct zep_wpa_supp_dev_callbk_fns supp_callbk_fns;
|
||||
unsigned char twt_flows_map;
|
||||
unsigned char twt_flow_in_progress_map;
|
||||
struct wifi_ps_config *ps_info;
|
||||
bool ps_config_info_evnt;
|
||||
bool authorized;
|
||||
bool cookie_resp_received;
|
||||
#ifdef CONFIG_NRF70_DATA_TX
|
||||
struct k_work nrf_wifi_net_iface_work;
|
||||
#endif /* CONFIG_NRF70_DATA_TX */
|
||||
unsigned long rssi_record_timestamp_us;
|
||||
signed short rssi;
|
||||
#endif /* CONFIG_NRF70_STA_MODE */
|
||||
#ifdef CONFIG_NRF70_AP_MODE
|
||||
int inactive_time_sec;
|
||||
#endif /* CONFIG_NRF70_AP_MODE */
|
||||
#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY
|
||||
struct k_work nrf_wifi_rpu_recovery_work;
|
||||
#endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */
|
||||
};
|
||||
|
||||
struct nrf_wifi_vif_ctx_map {
|
||||
const char *ifname;
|
||||
struct nrf_wifi_vif_ctx_zep *vif_ctx;
|
||||
};
|
||||
#endif /* !CONFIG_NRF70_RADIO_TEST */
|
||||
|
||||
struct nrf_wifi_ctx_zep {
|
||||
void *drv_priv_zep;
|
||||
void *rpu_ctx;
|
||||
#ifdef CONFIG_NRF70_RADIO_TEST
|
||||
struct rpu_conf_params conf_params;
|
||||
bool rf_test_run;
|
||||
unsigned char rf_test;
|
||||
#else /* CONFIG_NRF70_RADIO_TEST */
|
||||
struct nrf_wifi_vif_ctx_zep vif_ctx_zep[MAX_NUM_VIFS];
|
||||
#ifdef CONFIG_NRF70_UTIL
|
||||
struct rpu_conf_params conf_params;
|
||||
#endif /* CONFIG_NRF70_UTIL */
|
||||
#endif /* CONFIG_NRF70_RADIO_TEST */
|
||||
unsigned char *extended_capa, *extended_capa_mask;
|
||||
unsigned int extended_capa_len;
|
||||
struct k_mutex rpu_lock;
|
||||
};
|
||||
|
||||
struct nrf_wifi_drv_priv_zep {
|
||||
struct nrf_wifi_fmac_priv *fmac_priv;
|
||||
/* TODO: Replace with a linked list to handle unlimited RPUs */
|
||||
struct nrf_wifi_ctx_zep rpu_ctx_zep;
|
||||
};
|
||||
|
||||
extern struct nrf_wifi_drv_priv_zep rpu_drv_priv_zep;
|
||||
|
||||
void nrf_wifi_scan_timeout_work(struct k_work *work);
|
||||
void configure_tx_pwr_settings(struct nrf_wifi_tx_pwr_ctrl_params *tx_pwr_ctrl_params,
|
||||
struct nrf_wifi_tx_pwr_ceil_params *tx_pwr_ceil_params);
|
||||
void configure_board_dep_params(struct nrf_wifi_board_params *board_params);
|
||||
void set_tx_pwr_ceil_default(struct nrf_wifi_tx_pwr_ceil_params *pwr_ceil_params);
|
||||
const char *nrf_wifi_get_drv_version(void);
|
||||
enum nrf_wifi_status nrf_wifi_fmac_dev_add_zep(struct nrf_wifi_drv_priv_zep *drv_priv_zep);
|
||||
enum nrf_wifi_status nrf_wifi_fmac_dev_rem_zep(struct nrf_wifi_drv_priv_zep *drv_priv_zep);
|
||||
enum nrf_wifi_status nrf_wifi_fw_load(void *rpu_ctx);
|
||||
struct nrf_wifi_vif_ctx_zep *nrf_wifi_get_vif_ctx(struct net_if *iface);
|
||||
void nrf_wifi_rpu_recovery_cb(void *vif_ctx,
|
||||
void *event_data,
|
||||
unsigned int event_len);
|
||||
|
||||
#endif /* __ZEPHYR_FMAC_MAIN_H__ */
|
64
drivers/wifi/nrfwifi/inc/net_if.h
Normal file
64
drivers/wifi/nrfwifi/inc/net_if.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Header containing network stack interface specific declarations for
|
||||
* the Zephyr OS layer of the Wi-Fi driver.
|
||||
*/
|
||||
|
||||
#ifndef __ZEPHYR_NET_IF_H__
|
||||
#define __ZEPHYR_NET_IF_H__
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/net/net_pkt.h>
|
||||
#include <zephyr/net/net_if.h>
|
||||
#include <zephyr/net/ethernet.h>
|
||||
#include <fmac_structs.h>
|
||||
#include <zephyr/net/wifi_mgmt.h>
|
||||
|
||||
#define UNICAST_MASK GENMASK(7, 1)
|
||||
#define LOCAL_BIT BIT(1)
|
||||
|
||||
void nrf_wifi_if_init_zep(struct net_if *iface);
|
||||
|
||||
int nrf_wifi_if_start_zep(const struct device *dev);
|
||||
|
||||
int nrf_wifi_if_stop_zep(const struct device *dev);
|
||||
|
||||
int nrf_wifi_if_set_config_zep(const struct device *dev,
|
||||
enum ethernet_config_type type,
|
||||
const struct ethernet_config *config);
|
||||
|
||||
int nrf_wifi_if_get_config_zep(const struct device *dev,
|
||||
enum ethernet_config_type type,
|
||||
struct ethernet_config *config);
|
||||
|
||||
enum ethernet_hw_caps nrf_wifi_if_caps_get(const struct device *dev);
|
||||
|
||||
int nrf_wifi_if_send(const struct device *dev,
|
||||
struct net_pkt *pkt);
|
||||
|
||||
void nrf_wifi_if_rx_frm(void *os_vif_ctx,
|
||||
void *frm);
|
||||
|
||||
#if defined(CONFIG_NRF70_RAW_DATA_RX) || defined(CONFIG_NRF70_PROMISC_DATA_RX)
|
||||
void nrf_wifi_if_sniffer_rx_frm(void *os_vif_ctx,
|
||||
void *frm,
|
||||
struct raw_rx_pkt_header *raw_rx_hdr,
|
||||
bool pkt_free);
|
||||
#endif /* CONFIG_NRF70_RAW_DATA_RX || CONFIG_NRF70_PROMISC_DATA_RX */
|
||||
|
||||
enum nrf_wifi_status nrf_wifi_if_carr_state_chg(void *os_vif_ctx,
|
||||
enum nrf_wifi_fmac_if_carr_state carr_state);
|
||||
|
||||
int nrf_wifi_stats_get(const struct device *dev,
|
||||
struct net_stats_wifi *stats);
|
||||
|
||||
struct net_stats_eth *nrf_wifi_eth_stats_get(const struct device *dev);
|
||||
|
||||
void nrf_wifi_set_iface_event_handler(void *os_vif_ctx,
|
||||
struct nrf_wifi_umac_event_set_interface *event,
|
||||
unsigned int event_len);
|
||||
#endif /* __ZEPHYR_NET_IF_H__ */
|
75
drivers/wifi/nrfwifi/inc/wifi_mgmt.h
Normal file
75
drivers/wifi/nrfwifi/inc/wifi_mgmt.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Header containing WiFi management operation implementations
|
||||
* for the Zephyr OS.
|
||||
*/
|
||||
|
||||
#ifndef __ZEPHYR_WIFI_MGMT_H__
|
||||
#define __ZEPHYR_WIFI_MGMT_H__
|
||||
#include <math.h>
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/net/wifi_mgmt.h>
|
||||
|
||||
#include "osal_api.h"
|
||||
|
||||
/** Filter setting defines for sniffer mode. */
|
||||
#define WIFI_MGMT_DATA_CTRL_FILTER_SETTING 0xE
|
||||
#define WIFI_ALL_FILTER_SETTING 0xF
|
||||
|
||||
struct twt_interval_float {
|
||||
unsigned short mantissa;
|
||||
unsigned char exponent;
|
||||
};
|
||||
|
||||
int nrf_wifi_set_power_save(const struct device *dev,
|
||||
struct wifi_ps_params *params);
|
||||
|
||||
int nrf_wifi_set_twt(const struct device *dev,
|
||||
struct wifi_twt_params *twt_params);
|
||||
|
||||
void nrf_wifi_event_proc_twt_setup_zep(void *vif_ctx,
|
||||
struct nrf_wifi_umac_cmd_config_twt *twt_setup_info,
|
||||
unsigned int event_len);
|
||||
|
||||
void nrf_wifi_event_proc_twt_teardown_zep(void *vif_ctx,
|
||||
struct nrf_wifi_umac_cmd_teardown_twt *twt_teardown_info,
|
||||
unsigned int event_len);
|
||||
|
||||
void nrf_wifi_event_proc_twt_sleep_zep(void *vif_ctx,
|
||||
struct nrf_wifi_umac_event_twt_sleep *twt_sleep_info,
|
||||
unsigned int event_len);
|
||||
|
||||
int nrf_wifi_twt_teardown_flows(struct nrf_wifi_vif_ctx_zep *vif_ctx_zep,
|
||||
unsigned char start_flow_id, unsigned char end_flow_id);
|
||||
|
||||
int nrf_wifi_get_power_save_config(const struct device *dev,
|
||||
struct wifi_ps_config *ps_config);
|
||||
|
||||
void nrf_wifi_event_proc_get_power_save_info(void *vif_ctx,
|
||||
struct nrf_wifi_umac_event_power_save_info *ps_info,
|
||||
unsigned int event_len);
|
||||
|
||||
#ifdef CONFIG_NRF70_SYSTEM_WITH_RAW_MODES
|
||||
int nrf_wifi_mode(const struct device *dev,
|
||||
struct wifi_mode_info *mode);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NRF70_RAW_DATA_TX) || defined(CONFIG_NRF70_RAW_DATA_RX)
|
||||
int nrf_wifi_channel(const struct device *dev,
|
||||
struct wifi_channel_info *channel);
|
||||
#endif /* CONFIG_NRF70_RAW_DATA_TX || CONFIG_NRF70_RAW_DATA_RX */
|
||||
|
||||
#if defined(CONFIG_NRF70_RAW_DATA_RX) || defined(CONFIG_NRF70_PROMISC_DATA_RX)
|
||||
int nrf_wifi_filter(const struct device *dev,
|
||||
struct wifi_filter_info *filter);
|
||||
#endif /* CONFIG_NRF70_RAW_DATA_RX || CONFIG_NRF70_PROMISC_DATA_RX */
|
||||
|
||||
int nrf_wifi_set_rts_threshold(const struct device *dev,
|
||||
unsigned int rts_threshold);
|
||||
#endif /* __ZEPHYR_WIFI_MGMT_H__ */
|
34
drivers/wifi/nrfwifi/inc/wifi_mgmt_scan.h
Normal file
34
drivers/wifi/nrfwifi/inc/wifi_mgmt_scan.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Header containing display scan specific declarations for the
|
||||
* Zephyr OS layer of the Wi-Fi driver.
|
||||
*/
|
||||
|
||||
#ifndef __ZEPHYR_DISP_SCAN_H__
|
||||
#define __ZEPHYR_DISP_SCAN_H__
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/net/wifi_mgmt.h>
|
||||
|
||||
#include "osal_api.h"
|
||||
int nrf_wifi_disp_scan_zep(const struct device *dev, struct wifi_scan_params *params,
|
||||
scan_result_cb_t cb);
|
||||
|
||||
enum nrf_wifi_status nrf_wifi_disp_scan_res_get_zep(struct nrf_wifi_vif_ctx_zep *vif_ctx_zep);
|
||||
|
||||
void nrf_wifi_event_proc_disp_scan_res_zep(void *vif_ctx,
|
||||
struct nrf_wifi_umac_event_new_scan_display_results *scan_res,
|
||||
unsigned int event_len,
|
||||
bool is_last);
|
||||
|
||||
#ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS
|
||||
void nrf_wifi_rx_bcn_prb_resp_frm(void *vif_ctx,
|
||||
void *frm,
|
||||
unsigned short frequency,
|
||||
signed short signal);
|
||||
#endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */
|
||||
#endif /* __ZEPHYR_DISP_SCAN_H__ */
|
143
drivers/wifi/nrfwifi/inc/wpa_supp_if.h
Normal file
143
drivers/wifi/nrfwifi/inc/wpa_supp_if.h
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Header containing WPA supplicant interface specific declarations for
|
||||
* the Zephyr OS layer of the Wi-Fi driver.
|
||||
*/
|
||||
|
||||
#ifndef __ZEPHYR_WPA_SUPP_IF_H__
|
||||
#define __ZEPHYR_WPA_SUPP_IF_H__
|
||||
|
||||
|
||||
#define RPU_RESP_EVENT_TIMEOUT 5000
|
||||
#ifdef CONFIG_NRF70_STA_MODE
|
||||
#include <drivers/driver_zephyr.h>
|
||||
|
||||
void *nrf_wifi_wpa_supp_dev_init(void *supp_drv_if_ctx, const char *iface_name,
|
||||
struct zep_wpa_supp_dev_callbk_fns *supp_callbk_fns);
|
||||
|
||||
void nrf_wifi_wpa_supp_dev_deinit(void *if_priv);
|
||||
|
||||
int nrf_wifi_wpa_supp_scan2(void *if_priv, struct wpa_driver_scan_params *params);
|
||||
|
||||
int nrf_wifi_wpa_supp_scan_abort(void *if_priv);
|
||||
|
||||
int nrf_wifi_wpa_supp_scan_results_get(void *if_priv);
|
||||
|
||||
int nrf_wifi_wpa_supp_deauthenticate(void *if_priv, const char *addr, unsigned short reason_code);
|
||||
|
||||
int nrf_wifi_wpa_supp_authenticate(void *if_priv, struct wpa_driver_auth_params *params,
|
||||
struct wpa_bss *curr_bss);
|
||||
|
||||
int nrf_wifi_wpa_supp_associate(void *if_priv, struct wpa_driver_associate_params *params);
|
||||
|
||||
int nrf_wifi_wpa_set_supp_port(void *if_priv, int authorized, char *bssid);
|
||||
|
||||
int nrf_wifi_wpa_supp_signal_poll(void *if_priv, struct wpa_signal_info *si,
|
||||
unsigned char *bssid);
|
||||
|
||||
int nrf_wifi_nl80211_send_mlme(void *if_priv, const u8 *data, size_t data_len, int noack,
|
||||
unsigned int freq, int no_cck, int offchanok, unsigned int wait_time,
|
||||
int cookie);
|
||||
|
||||
int nrf_wifi_supp_get_wiphy(void *if_priv);
|
||||
|
||||
int nrf_wifi_supp_register_frame(void *if_priv,
|
||||
u16 type, const u8 *match, size_t match_len,
|
||||
bool multicast);
|
||||
|
||||
int nrf_wifi_wpa_supp_set_key(void *if_priv,
|
||||
const unsigned char *ifname,
|
||||
enum wpa_alg alg,
|
||||
const unsigned char *addr,
|
||||
int key_idx,
|
||||
int set_tx,
|
||||
const unsigned char *seq,
|
||||
size_t seq_len,
|
||||
const unsigned char *key,
|
||||
size_t key_len,
|
||||
enum key_flag key_flag);
|
||||
|
||||
void nrf_wifi_wpa_supp_event_proc_scan_start(void *if_priv);
|
||||
|
||||
void nrf_wifi_wpa_supp_event_proc_scan_done(void *if_priv,
|
||||
struct nrf_wifi_umac_event_trigger_scan *scan_done_event,
|
||||
unsigned int event_len,
|
||||
int aborted);
|
||||
|
||||
void nrf_wifi_wpa_supp_event_proc_scan_res(void *if_priv,
|
||||
struct nrf_wifi_umac_event_new_scan_results *scan_res,
|
||||
unsigned int event_len,
|
||||
bool more_res);
|
||||
|
||||
void nrf_wifi_wpa_supp_event_proc_auth_resp(void *if_priv,
|
||||
struct nrf_wifi_umac_event_mlme *auth_resp,
|
||||
unsigned int event_len);
|
||||
|
||||
void nrf_wifi_wpa_supp_event_proc_assoc_resp(void *if_priv,
|
||||
struct nrf_wifi_umac_event_mlme *assoc_resp,
|
||||
unsigned int event_len);
|
||||
|
||||
void nrf_wifi_wpa_supp_event_proc_deauth(void *if_priv,
|
||||
struct nrf_wifi_umac_event_mlme *deauth,
|
||||
unsigned int event_len);
|
||||
|
||||
void nrf_wifi_wpa_supp_event_proc_disassoc(void *if_priv,
|
||||
struct nrf_wifi_umac_event_mlme *disassoc,
|
||||
unsigned int event_len);
|
||||
|
||||
void nrf_wifi_wpa_supp_event_proc_get_sta(void *if_priv,
|
||||
struct nrf_wifi_umac_event_new_station *info,
|
||||
unsigned int event_len);
|
||||
|
||||
void nrf_wifi_wpa_supp_event_proc_get_if(void *if_priv,
|
||||
struct nrf_wifi_interface_info *info,
|
||||
unsigned int event_len);
|
||||
|
||||
void nrf_wifi_wpa_supp_event_mgmt_tx_status(void *if_priv,
|
||||
struct nrf_wifi_umac_event_mlme *mlme_event,
|
||||
unsigned int event_len);
|
||||
|
||||
|
||||
void nrf_wifi_wpa_supp_event_proc_unprot_mgmt(void *if_priv,
|
||||
struct nrf_wifi_umac_event_mlme *unprot_mgmt,
|
||||
unsigned int event_len);
|
||||
|
||||
void nrf_wifi_wpa_supp_event_get_wiphy(void *if_priv,
|
||||
struct nrf_wifi_event_get_wiphy *get_wiphy,
|
||||
unsigned int event_len);
|
||||
|
||||
void nrf_wifi_wpa_supp_event_mgmt_rx_callbk_fn(void *if_priv,
|
||||
struct nrf_wifi_umac_event_mlme *mgmt_rx_event,
|
||||
unsigned int event_len);
|
||||
|
||||
int nrf_wifi_supp_get_capa(void *if_priv, struct wpa_driver_capa *capa);
|
||||
|
||||
void nrf_wifi_wpa_supp_event_mac_chgd(void *if_priv);
|
||||
int nrf_wifi_supp_get_conn_info(void *if_priv, struct wpa_conn_info *info);
|
||||
|
||||
void nrf_wifi_supp_event_proc_get_conn_info(void *os_vif_ctx,
|
||||
struct nrf_wifi_umac_event_conn_info *info,
|
||||
unsigned int event_len);
|
||||
|
||||
#endif /* CONFIG_NRF70_STA_MODE */
|
||||
#ifdef CONFIG_NRF70_AP_MODE
|
||||
int nrf_wifi_wpa_supp_init_ap(void *if_priv, struct wpa_driver_associate_params *params);
|
||||
int nrf_wifi_wpa_supp_start_ap(void *if_priv, struct wpa_driver_ap_params *params);
|
||||
int nrf_wifi_wpa_supp_change_beacon(void *if_priv, struct wpa_driver_ap_params *params);
|
||||
int nrf_wifi_wpa_supp_stop_ap(void *if_priv);
|
||||
int nrf_wifi_wpa_supp_deinit_ap(void *if_priv);
|
||||
int nrf_wifi_wpa_supp_sta_add(void *if_priv, struct hostapd_sta_add_params *params);
|
||||
int nrf_wifi_wpa_supp_sta_remove(void *if_priv, const u8 *addr);
|
||||
int nrf_wifi_supp_register_mgmt_frame(void *if_priv,
|
||||
u16 frame_type, size_t match_len, const u8 *match);
|
||||
int nrf_wifi_wpa_supp_sta_set_flags(void *if_priv, const u8 *addr,
|
||||
unsigned int total_flags, unsigned int flags_or,
|
||||
unsigned int flags_and);
|
||||
int nrf_wifi_wpa_supp_sta_get_inact_sec(void *if_priv, const u8 *addr);
|
||||
#endif /* CONFIG_NRF70_AP_MODE */
|
||||
#endif /* __ZEPHYR_WPA_SUPP_IF_H__ */
|
51
drivers/wifi/nrfwifi/rpu_fw_patches.ld
Normal file
51
drivers/wifi/nrfwifi/rpu_fw_patches.ld
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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/cortex_m/scripts/linker.ld>
|
333
drivers/wifi/nrfwifi/src/coex.c
Normal file
333
drivers/wifi/nrfwifi/src/coex.c
Normal file
|
@ -0,0 +1,333 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief Coexistence functions
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
|
||||
#include "coex.h"
|
||||
#include "coex_struct.h"
|
||||
#include "fmac_main.h"
|
||||
#include "fmac_api.h"
|
||||
|
||||
LOG_MODULE_DECLARE(wifi_nrf, CONFIG_WIFI_NRF70_LOG_LEVEL);
|
||||
|
||||
extern struct nrf_wifi_drv_priv_zep rpu_drv_priv_zep;
|
||||
static struct nrf_wifi_ctx_zep *rpu_ctx = &rpu_drv_priv_zep.rpu_ctx_zep;
|
||||
|
||||
#define CH_BASE_ADDRESS ABS_EXT_SYS_WLANSYSCOEX_CH_CONTROL
|
||||
#define COEX_CONFIG_FIXED_PARAMS 4
|
||||
#define COEX_REG_CFG_OFFSET_SHIFT 24
|
||||
|
||||
/* copied from uccp530_77_registers_ext_sys_bus.h of UCCP toolkit */
|
||||
#define EXT_SYS_WLANSYSCOEX_CH_CONTROL 0x0000
|
||||
#define ABS_EXT_SYS_WLANSYSCOEX_CH_CONTROL 0xA401BC00UL
|
||||
#define EXT_SYS_WLANSYSCOEX_CH_TIME_REFERENCE 0x0004
|
||||
#define EXT_SYS_WLANSYSCOEX_CH_SR_INFO_STATUS 0x0040
|
||||
#define EXT_SYS_WLANSYSCOEX_CH_NO_WINDOW_LOOKUP_0 0x008C
|
||||
#define EXT_SYS_WLANSYSCOEX_CH_NO_WINDOW_LOOKUP_44 0x013C
|
||||
#define EXT_SYS_WLANSYSCOEX_RESET_SHIFT 0
|
||||
|
||||
/* copied from uccp530_77_registers.h of UCCP toolkit */
|
||||
#define ABS_PMB_WLAN_MAC_CTRL_PULSED_SOFTWARE_RESET 0xA5009A00UL
|
||||
|
||||
#ifdef CONFIG_NRF70_SR_COEX_RF_SWITCH
|
||||
#define NRF_RADIO_COEX_NODE DT_NODELABEL(nrf70)
|
||||
static const struct gpio_dt_spec sr_rf_switch_spec =
|
||||
GPIO_DT_SPEC_GET(NRF_RADIO_COEX_NODE, srrf_switch_gpios);
|
||||
#endif /* CONFIG_NRF70_SR_COEX_RF_SWITCH */
|
||||
|
||||
/* PTA registers configuration of Coexistence Hardware */
|
||||
/* Separate antenna configuration, WLAN in 2.4GHz. For BLE protocol. */
|
||||
const uint16_t config_buffer_SEA_ble[] = {
|
||||
0x0019, 0x00F6, 0x0008, 0x0062, 0x00F5,
|
||||
0x00F5, 0x0019, 0x0019, 0x0074, 0x0074,
|
||||
0x0008, 0x01E2, 0x00D5, 0x00D5, 0x01F6,
|
||||
0x01F6, 0x0061, 0x0061, 0x01E2, 0x0008,
|
||||
0x0004, 0x0004, 0x0019, 0x0019, 0x0008,
|
||||
0x0008, 0x00F5, 0x00F5, 0x00D5, 0x00D5,
|
||||
0x0008, 0x01E2, 0x0051, 0x0051, 0x0074,
|
||||
0x0074, 0x00F6, 0x0019, 0x0062, 0x0019,
|
||||
0x00F6, 0x0008, 0x0062, 0x0008, 0x001A
|
||||
};
|
||||
|
||||
/* Separate antenna configuration, WLAN in 2.4GHz. For non BLE protocol */
|
||||
const uint16_t config_buffer_SEA_non_ble[] = {
|
||||
0x0019, 0x00F6, 0x0008, 0x0062, 0x00F5,
|
||||
0x00F5, 0x0061, 0x0061, 0x0074, 0x0074,
|
||||
0x01E2, 0x01E2, 0x00D5, 0x00D5, 0x01F6,
|
||||
0x01F6, 0x0061, 0x0061, 0x01E2, 0x01E2,
|
||||
0x00C4, 0x00C4, 0x0061, 0x0061, 0x0008,
|
||||
0x0008, 0x00F5, 0x00F5, 0x00D5, 0x00D5,
|
||||
0x0162, 0x0162, 0x0019, 0x0019, 0x01F6,
|
||||
0x01F6, 0x00F6, 0x0019, 0x0062, 0x0019,
|
||||
0x00F6, 0x0008, 0x0062, 0x0008, 0x001A
|
||||
};
|
||||
|
||||
/* Shared antenna configuration, WLAN in 2.4GHz. */
|
||||
const uint16_t config_buffer_SHA[] = {
|
||||
0x0019, 0x00F6, 0x0008, 0x00E2, 0x0015,
|
||||
0x00F5, 0x0019, 0x0019, 0x0004, 0x01F6,
|
||||
0x0008, 0x01E2, 0x00F5, 0x00F5, 0x01F6,
|
||||
0x01F6, 0x00E1, 0x00E1, 0x01E2, 0x0008,
|
||||
0x0004, 0x0004, 0x0019, 0x0019, 0x0008,
|
||||
0x0008, 0x0015, 0x00F5, 0x00F5, 0x00F5,
|
||||
0x0008, 0x01E2, 0x00E1, 0x00E1, 0x0004,
|
||||
0x01F6, 0x00F6, 0x0019, 0x00E2, 0x0019,
|
||||
0x00F6, 0x0008, 0x00E2, 0x0008, 0x001A
|
||||
};
|
||||
|
||||
/* Shared/separate antennas, WLAN in 5GHz */
|
||||
const uint16_t config_buffer_5G[] = {
|
||||
0x0039, 0x0076, 0x0028, 0x0062, 0x0075,
|
||||
0x0075, 0x0061, 0x0061, 0x0074, 0x0074,
|
||||
0x0060, 0x0060, 0x0075, 0x0075, 0x0064,
|
||||
0x0064, 0x0071, 0x0071, 0x0060, 0x0060,
|
||||
0x0064, 0x0064, 0x0061, 0x0061, 0x0060,
|
||||
0x0060, 0x0075, 0x0075, 0x0075, 0x0075,
|
||||
0x0060, 0x0060, 0x0071, 0x0071, 0x0074,
|
||||
0x0074, 0x0076, 0x0039, 0x0062, 0x0039,
|
||||
0x0076, 0x0028, 0x0062, 0x0028, 0x003A
|
||||
};
|
||||
|
||||
/* non-PTA register configuration of coexistence hardware */
|
||||
/* Shared antenna */
|
||||
const uint32_t ch_config_sha[] = {
|
||||
0x00000028, 0x00000000, 0x001e1023, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000021, 0x000002ca, 0x00000050, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
/* Separate antennas. For BLE protocol. */
|
||||
const uint32_t ch_config_sep_ble[] = {
|
||||
0x00000028, 0x00000000, 0x001e1023, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000021, 0x000002ca, 0x00000055, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
/* Separate antennas. For non BLE protocol. */
|
||||
const uint32_t ch_config_sep_non_ble[] = {
|
||||
0x00000028, 0x00000000, 0x001e1023, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000021, 0x000002ca, 0x00000055, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
int nrf_wifi_coex_config_non_pta(bool separate_antennas, bool is_sr_protocol_ble)
|
||||
{
|
||||
enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
|
||||
struct coex_ch_configuration params = { 0 };
|
||||
const uint32_t *config_buffer_ptr = NULL;
|
||||
uint32_t start_offset = 0;
|
||||
uint32_t num_reg_to_config = 1;
|
||||
uint32_t cmd_len, index;
|
||||
|
||||
/* Offset from the base address of CH */
|
||||
start_offset = ((EXT_SYS_WLANSYSCOEX_CH_TIME_REFERENCE -
|
||||
EXT_SYS_WLANSYSCOEX_CH_CONTROL) >> 2);
|
||||
/* Number of registers to be configured */
|
||||
num_reg_to_config = ((EXT_SYS_WLANSYSCOEX_CH_SR_INFO_STATUS -
|
||||
EXT_SYS_WLANSYSCOEX_CH_TIME_REFERENCE) >> 2) + 1;
|
||||
|
||||
if (separate_antennas) {
|
||||
if (is_sr_protocol_ble) {
|
||||
config_buffer_ptr = ch_config_sep_ble;
|
||||
} else {
|
||||
config_buffer_ptr = ch_config_sep_non_ble;
|
||||
}
|
||||
} else {
|
||||
config_buffer_ptr = ch_config_sha;
|
||||
}
|
||||
|
||||
params.message_id = HW_CONFIGURATION;
|
||||
params.num_reg_to_config = num_reg_to_config;
|
||||
params.hw_to_config = COEX_HARDWARE;
|
||||
params.hw_block_base_addr = CH_BASE_ADDRESS;
|
||||
|
||||
for (index = 0; index < num_reg_to_config; index++) {
|
||||
params.configbuf[index] = (start_offset << COEX_REG_CFG_OFFSET_SHIFT) |
|
||||
(*(config_buffer_ptr + index));
|
||||
start_offset++;
|
||||
}
|
||||
|
||||
cmd_len = (COEX_CONFIG_FIXED_PARAMS + num_reg_to_config) * sizeof(uint32_t);
|
||||
status = nrf_wifi_fmac_conf_srcoex(rpu_ctx->rpu_ctx,
|
||||
(void *)(¶ms), cmd_len);
|
||||
if (status != NRF_WIFI_STATUS_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nrf_wifi_coex_config_pta(enum nrf_wifi_pta_wlan_op_band wlan_band, bool separate_antennas,
|
||||
bool is_sr_protocol_ble)
|
||||
{
|
||||
enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
|
||||
struct coex_ch_configuration params = { 0 };
|
||||
const uint16_t *config_buffer_ptr = NULL;
|
||||
uint32_t start_offset = 0;
|
||||
uint32_t num_reg_to_config = 1;
|
||||
uint32_t cmd_len, index;
|
||||
|
||||
/* common for both SHA and SEA */
|
||||
/* Indicates offset from the base address of CH */
|
||||
start_offset = ((EXT_SYS_WLANSYSCOEX_CH_NO_WINDOW_LOOKUP_0 -
|
||||
EXT_SYS_WLANSYSCOEX_CH_CONTROL) >> 2);
|
||||
/* Number of contiguous registers to be configured starting from base+offset */
|
||||
num_reg_to_config = ((EXT_SYS_WLANSYSCOEX_CH_NO_WINDOW_LOOKUP_44 -
|
||||
EXT_SYS_WLANSYSCOEX_CH_NO_WINDOW_LOOKUP_0) >> 2) + 1;
|
||||
|
||||
if (wlan_band == NRF_WIFI_PTA_WLAN_OP_BAND_2_4_GHZ) {
|
||||
/* WLAN operating in 2.4GHz */
|
||||
if (separate_antennas) {
|
||||
/* separate antennas configuration */
|
||||
if (is_sr_protocol_ble) {
|
||||
config_buffer_ptr = config_buffer_SEA_ble;
|
||||
} else {
|
||||
config_buffer_ptr = config_buffer_SEA_non_ble;
|
||||
}
|
||||
} else {
|
||||
/* Shared antenna configuration */
|
||||
config_buffer_ptr = config_buffer_SHA;
|
||||
}
|
||||
} else if (wlan_band == NRF_WIFI_PTA_WLAN_OP_BAND_5_GHZ) {
|
||||
/* WLAN operating in 5GHz */
|
||||
config_buffer_ptr = config_buffer_5G;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
params.message_id = HW_CONFIGURATION;
|
||||
params.num_reg_to_config = num_reg_to_config;
|
||||
params.hw_to_config = COEX_HARDWARE;
|
||||
params.hw_block_base_addr = CH_BASE_ADDRESS;
|
||||
|
||||
for (index = 0; index < num_reg_to_config; index++) {
|
||||
params.configbuf[index] = (start_offset << COEX_REG_CFG_OFFSET_SHIFT) |
|
||||
(*(config_buffer_ptr+index));
|
||||
start_offset++;
|
||||
}
|
||||
|
||||
cmd_len = (COEX_CONFIG_FIXED_PARAMS + num_reg_to_config) * sizeof(uint32_t);
|
||||
status = nrf_wifi_fmac_conf_srcoex(rpu_ctx->rpu_ctx,
|
||||
(void *)(¶ms), cmd_len);
|
||||
if (status != NRF_WIFI_STATUS_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_NRF70_SR_COEX_RF_SWITCH
|
||||
int nrf_wifi_config_sr_switch(bool separate_antennas)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!device_is_ready(sr_rf_switch_spec.port)) {
|
||||
LOG_ERR("Unable to open GPIO device");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = gpio_pin_configure_dt(&sr_rf_switch_spec, GPIO_OUTPUT);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Unable to configure GPIO device");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (separate_antennas) {
|
||||
gpio_pin_set_dt(&sr_rf_switch_spec, 0x0);
|
||||
LOG_INF("GPIO P1.10 set to 0");
|
||||
} else {
|
||||
gpio_pin_set_dt(&sr_rf_switch_spec, 0x1);
|
||||
LOG_INF("GPIO P1.10 set to 1");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_NRF70_SR_COEX_RF_SWITCH */
|
||||
|
||||
int nrf_wifi_coex_hw_reset(void)
|
||||
{
|
||||
enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
|
||||
struct coex_ch_configuration params = { 0 };
|
||||
uint32_t num_reg_to_config = 1;
|
||||
uint32_t start_offset = 0;
|
||||
uint32_t index = 0;
|
||||
uint32_t coex_hw_reset = 1;
|
||||
uint32_t cmd_len;
|
||||
|
||||
/* reset CH */
|
||||
params.message_id = HW_CONFIGURATION;
|
||||
params.num_reg_to_config = num_reg_to_config;
|
||||
params.hw_to_config = COEX_HARDWARE;
|
||||
params.hw_block_base_addr = CH_BASE_ADDRESS;
|
||||
|
||||
start_offset = ((EXT_SYS_WLANSYSCOEX_CH_CONTROL - EXT_SYS_WLANSYSCOEX_CH_CONTROL) >> 2);
|
||||
params.configbuf[index] = (start_offset << COEX_REG_CFG_OFFSET_SHIFT) |
|
||||
(coex_hw_reset << EXT_SYS_WLANSYSCOEX_RESET_SHIFT);
|
||||
|
||||
cmd_len = (COEX_CONFIG_FIXED_PARAMS + num_reg_to_config) * sizeof(uint32_t);
|
||||
|
||||
status = nrf_wifi_fmac_conf_srcoex(rpu_ctx->rpu_ctx,
|
||||
(void *)(¶ms), cmd_len);
|
||||
|
||||
if (status != NRF_WIFI_STATUS_SUCCESS) {
|
||||
LOG_ERR("CH reset configuration failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NRF70_SR_COEX_RF_SWITCH
|
||||
int sr_gpio_config(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!device_is_ready(sr_rf_switch_spec.port)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = gpio_pin_configure_dt(&sr_rf_switch_spec, GPIO_OUTPUT);
|
||||
if (ret) {
|
||||
LOG_ERR("SR GPIO configuration failed %d", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sr_gpio_remove(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpio_pin_configure_dt(&sr_rf_switch_spec, GPIO_DISCONNECTED);
|
||||
if (ret) {
|
||||
LOG_ERR("SR GPIO remove failed %d", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sr_ant_switch(unsigned int ant_switch)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpio_pin_set_dt(&sr_rf_switch_spec, ant_switch & 0x1);
|
||||
if (ret) {
|
||||
LOG_ERR("SR GPIO set failed %d", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_NRF70_SR_COEX_RF_SWITCH */
|
933
drivers/wifi/nrfwifi/src/fmac_main.c
Normal file
933
drivers/wifi/nrfwifi/src/fmac_main.c
Normal file
|
@ -0,0 +1,933 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief File containing FMAC interface specific definitions for the
|
||||
* Zephyr OS layer of the Wi-Fi driver.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#ifdef CONFIG_NET_L2_ETHERNET
|
||||
#include <zephyr/net/ethernet.h>
|
||||
#endif
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/net/wifi_mgmt.h>
|
||||
#include <zephyr/net/conn_mgr_connectivity.h>
|
||||
#include <zephyr/net/conn_mgr_connectivity_impl.h>
|
||||
|
||||
|
||||
#include <util.h>
|
||||
#include <fmac_api.h>
|
||||
#include "fmac_util.h"
|
||||
#include <fmac_main.h>
|
||||
|
||||
#ifndef CONFIG_NRF70_RADIO_TEST
|
||||
#ifdef CONFIG_NRF70_STA_MODE
|
||||
#include <zephyr/net/wifi_nm.h>
|
||||
#include <wifi_mgmt_scan.h>
|
||||
#include <wifi_mgmt.h>
|
||||
#include <wpa_supp_if.h>
|
||||
#else
|
||||
#include <wifi_mgmt.h>
|
||||
#include <wifi_mgmt_scan.h>
|
||||
#endif /* CONFIG_NRF70_STA_MODE */
|
||||
#include <zephyr/net/conn_mgr_connectivity.h>
|
||||
|
||||
#endif /* !CONFIG_NRF70_RADIO_TEST */
|
||||
|
||||
#define DT_DRV_COMPAT nordic_wlan
|
||||
LOG_MODULE_DECLARE(wifi_nrf, CONFIG_WIFI_NRF70_LOG_LEVEL);
|
||||
|
||||
struct nrf_wifi_drv_priv_zep rpu_drv_priv_zep;
|
||||
|
||||
/* 3 bytes for addreess, 3 bytes for length */
|
||||
#define MAX_PKT_RAM_TX_ALIGN_OVERHEAD 6
|
||||
#ifndef CONFIG_NRF70_RADIO_TEST
|
||||
#ifdef CONFIG_NRF70_DATA_TX
|
||||
|
||||
#define MAX_RX_QUEUES 3
|
||||
|
||||
#define MAX_TX_FRAME_SIZE \
|
||||
(CONFIG_NRF_WIFI_IFACE_MTU + NRF_WIFI_FMAC_ETH_HDR_LEN + TX_BUF_HEADROOM)
|
||||
#define TOTAL_TX_SIZE \
|
||||
(CONFIG_NRF70_MAX_TX_TOKENS * CONFIG_NRF70_TX_MAX_DATA_SIZE)
|
||||
#define TOTAL_RX_SIZE \
|
||||
(CONFIG_NRF70_RX_NUM_BUFS * CONFIG_NRF70_RX_MAX_DATA_SIZE)
|
||||
|
||||
BUILD_ASSERT(CONFIG_NRF70_MAX_TX_TOKENS >= 1,
|
||||
"At least one TX token is required");
|
||||
BUILD_ASSERT(CONFIG_NRF70_MAX_TX_AGGREGATION <= 15,
|
||||
"Max TX aggregation is 15");
|
||||
BUILD_ASSERT(CONFIG_NRF70_RX_NUM_BUFS >= 1,
|
||||
"At least one RX buffer is required");
|
||||
BUILD_ASSERT(RPU_PKTRAM_SIZE - TOTAL_RX_SIZE >= TOTAL_TX_SIZE,
|
||||
"Packet RAM overflow: not enough memory for TX");
|
||||
|
||||
BUILD_ASSERT(CONFIG_NRF70_TX_MAX_DATA_SIZE >= MAX_TX_FRAME_SIZE,
|
||||
"TX buffer size must be at least as big as the MTU and headroom");
|
||||
|
||||
static const unsigned char aggregation = 1;
|
||||
static const unsigned char wmm = 1;
|
||||
static const unsigned char max_num_tx_agg_sessions = 4;
|
||||
static const unsigned char max_num_rx_agg_sessions = 8;
|
||||
static const unsigned char reorder_buf_size = 16;
|
||||
static const unsigned char max_rxampdu_size = MAX_RX_AMPDU_SIZE_64KB;
|
||||
|
||||
static const unsigned char max_tx_aggregation = CONFIG_NRF70_MAX_TX_AGGREGATION;
|
||||
|
||||
static const unsigned int rx1_num_bufs = CONFIG_NRF70_RX_NUM_BUFS / MAX_RX_QUEUES;
|
||||
static const unsigned int rx2_num_bufs = CONFIG_NRF70_RX_NUM_BUFS / MAX_RX_QUEUES;
|
||||
static const unsigned int rx3_num_bufs = CONFIG_NRF70_RX_NUM_BUFS / MAX_RX_QUEUES;
|
||||
|
||||
static const unsigned int rx1_buf_sz = CONFIG_NRF70_RX_MAX_DATA_SIZE;
|
||||
static const unsigned int rx2_buf_sz = CONFIG_NRF70_RX_MAX_DATA_SIZE;
|
||||
static const unsigned int rx3_buf_sz = CONFIG_NRF70_RX_MAX_DATA_SIZE;
|
||||
|
||||
static const unsigned char rate_protection_type;
|
||||
#else
|
||||
/* Reduce buffers to Scan only operation */
|
||||
static const unsigned int rx1_num_bufs = 2;
|
||||
static const unsigned int rx2_num_bufs = 2;
|
||||
static const unsigned int rx3_num_bufs = 2;
|
||||
|
||||
static const unsigned int rx1_buf_sz = 1000;
|
||||
static const unsigned int rx2_buf_sz = 1000;
|
||||
static const unsigned int rx3_buf_sz = 1000;
|
||||
#endif
|
||||
|
||||
struct nrf_wifi_drv_priv_zep rpu_drv_priv_zep;
|
||||
static K_MUTEX_DEFINE(reg_lock);
|
||||
|
||||
const char *nrf_wifi_get_drv_version(void)
|
||||
{
|
||||
return NRF70_DRIVER_VERSION;
|
||||
}
|
||||
|
||||
/* If the interface is not Wi-Fi then errors are expected, so, fail silently */
|
||||
struct nrf_wifi_vif_ctx_zep *nrf_wifi_get_vif_ctx(struct net_if *iface)
|
||||
{
|
||||
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
|
||||
struct nrf_wifi_ctx_zep *rpu_ctx = &rpu_drv_priv_zep.rpu_ctx_zep;
|
||||
|
||||
if (!iface || !rpu_ctx || !rpu_ctx->rpu_ctx) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(rpu_ctx->vif_ctx_zep); i++) {
|
||||
if (rpu_ctx->vif_ctx_zep[i].zep_net_if_ctx == iface) {
|
||||
vif_ctx_zep = &rpu_ctx->vif_ctx_zep[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return vif_ctx_zep;
|
||||
}
|
||||
|
||||
void nrf_wifi_event_proc_scan_start_zep(void *if_priv,
|
||||
struct nrf_wifi_umac_event_trigger_scan *scan_start_event,
|
||||
unsigned int event_len)
|
||||
{
|
||||
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
|
||||
|
||||
vif_ctx_zep = if_priv;
|
||||
|
||||
if (vif_ctx_zep->scan_type == SCAN_DISPLAY) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NRF70_STA_MODE
|
||||
nrf_wifi_wpa_supp_event_proc_scan_start(if_priv);
|
||||
#endif /* CONFIG_NRF70_STA_MODE */
|
||||
}
|
||||
|
||||
|
||||
void nrf_wifi_event_proc_scan_done_zep(void *vif_ctx,
|
||||
struct nrf_wifi_umac_event_trigger_scan *scan_done_event,
|
||||
unsigned int event_len)
|
||||
{
|
||||
enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
|
||||
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
|
||||
|
||||
vif_ctx_zep = vif_ctx;
|
||||
|
||||
if (!vif_ctx_zep) {
|
||||
LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (vif_ctx_zep->scan_type) {
|
||||
#ifdef CONFIG_NET_L2_WIFI_MGMT
|
||||
case SCAN_DISPLAY:
|
||||
status = nrf_wifi_disp_scan_res_get_zep(vif_ctx_zep);
|
||||
if (status != NRF_WIFI_STATUS_SUCCESS) {
|
||||
LOG_ERR("%s: nrf_wifi_disp_scan_res_get_zep failed", __func__);
|
||||
return;
|
||||
}
|
||||
vif_ctx_zep->scan_in_progress = false;
|
||||
break;
|
||||
#endif /* CONFIG_NET_L2_WIFI_MGMT */
|
||||
#ifdef CONFIG_NRF70_STA_MODE
|
||||
case SCAN_CONNECT:
|
||||
nrf_wifi_wpa_supp_event_proc_scan_done(vif_ctx_zep,
|
||||
scan_done_event,
|
||||
event_len,
|
||||
0);
|
||||
break;
|
||||
#endif /* CONFIG_NRF70_STA_MODE */
|
||||
default:
|
||||
LOG_ERR("%s: Scan type = %d not supported yet", __func__, vif_ctx_zep->scan_type);
|
||||
return;
|
||||
}
|
||||
|
||||
status = NRF_WIFI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void nrf_wifi_scan_timeout_work(struct k_work *work)
|
||||
{
|
||||
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
|
||||
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
|
||||
struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
|
||||
|
||||
vif_ctx_zep = CONTAINER_OF(work, struct nrf_wifi_vif_ctx_zep, scan_timeout_work.work);
|
||||
|
||||
if (!vif_ctx_zep->scan_in_progress) {
|
||||
LOG_INF("%s: Scan not in progress", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
|
||||
fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
|
||||
|
||||
#ifdef CONFIG_NET_L2_WIFI_MGMT
|
||||
if (vif_ctx_zep->disp_scan_cb) {
|
||||
vif_ctx_zep->disp_scan_cb(vif_ctx_zep->zep_net_if_ctx, -ETIMEDOUT, NULL);
|
||||
vif_ctx_zep->disp_scan_cb = NULL;
|
||||
} else
|
||||
#endif /* CONFIG_NET_L2_WIFI_MGMT */
|
||||
{
|
||||
#ifdef CONFIG_NRF70_STA_MODE
|
||||
/* WPA supplicant scan */
|
||||
union wpa_event_data event;
|
||||
struct scan_info *info = NULL;
|
||||
|
||||
memset(&event, 0, sizeof(event));
|
||||
|
||||
info = &event.scan_info;
|
||||
|
||||
info->aborted = 0;
|
||||
info->external_scan = 0;
|
||||
info->nl_scan_event = 1;
|
||||
|
||||
if (vif_ctx_zep->supp_drv_if_ctx &&
|
||||
vif_ctx_zep->supp_callbk_fns.scan_done) {
|
||||
vif_ctx_zep->supp_callbk_fns.scan_done(vif_ctx_zep->supp_drv_if_ctx,
|
||||
&event);
|
||||
}
|
||||
#endif /* CONFIG_NRF70_STA_MODE */
|
||||
}
|
||||
|
||||
vif_ctx_zep->scan_in_progress = false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NRF70_STA_MODE
|
||||
static void nrf_wifi_process_rssi_from_rx(void *vif_ctx,
|
||||
signed short signal)
|
||||
{
|
||||
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = vif_ctx;
|
||||
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
|
||||
struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
|
||||
|
||||
vif_ctx_zep = vif_ctx;
|
||||
|
||||
if (!vif_ctx_zep) {
|
||||
LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
|
||||
|
||||
if (!rpu_ctx_zep) {
|
||||
LOG_ERR("%s: rpu_ctx_zep is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
|
||||
|
||||
vif_ctx_zep->rssi = MBM_TO_DBM(signal);
|
||||
vif_ctx_zep->rssi_record_timestamp_us =
|
||||
nrf_wifi_osal_time_get_curr_us(fmac_dev_ctx->fpriv->opriv);
|
||||
}
|
||||
#endif /* CONFIG_NRF70_STA_MODE */
|
||||
|
||||
|
||||
void nrf_wifi_event_get_reg_zep(void *vif_ctx,
|
||||
struct nrf_wifi_reg *get_reg_event,
|
||||
unsigned int event_len)
|
||||
{
|
||||
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
|
||||
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
|
||||
struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
|
||||
|
||||
LOG_DBG("%s: alpha2 = %c%c", __func__,
|
||||
get_reg_event->nrf_wifi_alpha2[0],
|
||||
get_reg_event->nrf_wifi_alpha2[1]);
|
||||
vif_ctx_zep = vif_ctx;
|
||||
|
||||
if (!vif_ctx_zep) {
|
||||
LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
|
||||
fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
|
||||
|
||||
if (fmac_dev_ctx->alpha2_valid) {
|
||||
LOG_ERR("%s: Unsolicited regulatory get!", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&fmac_dev_ctx->alpha2,
|
||||
&get_reg_event->nrf_wifi_alpha2,
|
||||
sizeof(get_reg_event->nrf_wifi_alpha2));
|
||||
|
||||
fmac_dev_ctx->reg_chan_count = get_reg_event->num_channels;
|
||||
memcpy(fmac_dev_ctx->reg_chan_info,
|
||||
&get_reg_event->chn_info,
|
||||
fmac_dev_ctx->reg_chan_count *
|
||||
sizeof(struct nrf_wifi_get_reg_chn_info));
|
||||
|
||||
fmac_dev_ctx->alpha2_valid = true;
|
||||
}
|
||||
|
||||
int nrf_wifi_reg_domain(const struct device *dev, struct wifi_reg_domain *reg_domain)
|
||||
{
|
||||
enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
|
||||
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
|
||||
struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
|
||||
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
|
||||
struct nrf_wifi_fmac_reg_info reg_domain_info = {0};
|
||||
struct wifi_reg_chan_info *chan_info = NULL;
|
||||
struct nrf_wifi_get_reg_chn_info *reg_domain_chan_info = NULL;
|
||||
int ret = -1;
|
||||
int chan_idx = 0;
|
||||
|
||||
k_mutex_lock(®_lock, K_FOREVER);
|
||||
|
||||
if (!dev || !reg_domain) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
vif_ctx_zep = dev->data;
|
||||
|
||||
if (!vif_ctx_zep) {
|
||||
LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
|
||||
|
||||
if (!rpu_ctx_zep) {
|
||||
LOG_ERR("%s: rpu_ctx_zep is NULL", __func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
|
||||
if (!fmac_dev_ctx) {
|
||||
LOG_ERR("%s: fmac_dev_ctx is NULL", __func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (reg_domain->oper == WIFI_MGMT_SET) {
|
||||
#ifndef CONFIG_NRF70_RADIO_TEST
|
||||
#ifdef CONFIG_NRF70_STA_MODE
|
||||
/* Need to check if WPA supplicant is initialized or not.
|
||||
* Must be checked when CONFIG_WIFI_NM_WPA_SUPPLICANT is enabled.
|
||||
* Not applicable for RADIO_TEST or when
|
||||
* CONFIG_WIFI_NM_WPA_SUPPLICANT is not enabled.
|
||||
*/
|
||||
/* It is possbile that during supplicant initialization driver may
|
||||
* get the command. lock will try to ensure that supplicant
|
||||
* initialization is complete.
|
||||
*/
|
||||
k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
|
||||
if ((!vif_ctx_zep->supp_drv_if_ctx) ||
|
||||
(!wifi_nm_get_instance_iface(vif_ctx_zep->zep_net_if_ctx))) {
|
||||
LOG_ERR("%s: WPA supplicant initialization not complete yet", __func__);
|
||||
k_mutex_unlock(&vif_ctx_zep->vif_lock);
|
||||
goto err;
|
||||
}
|
||||
k_mutex_unlock(&vif_ctx_zep->vif_lock);
|
||||
#endif /* CONFIG_NRF70_STA_MODE */
|
||||
#endif /* !CONFIG_NRF70_RADIO_TEST */
|
||||
memcpy(reg_domain_info.alpha2, reg_domain->country_code, WIFI_COUNTRY_CODE_LEN);
|
||||
|
||||
reg_domain_info.force = reg_domain->force;
|
||||
|
||||
status = nrf_wifi_fmac_set_reg(fmac_dev_ctx, ®_domain_info);
|
||||
if (status != NRF_WIFI_STATUS_SUCCESS) {
|
||||
LOG_ERR("%s: Failed to set regulatory domain", __func__);
|
||||
goto err;
|
||||
}
|
||||
} else if (reg_domain->oper == WIFI_MGMT_GET) {
|
||||
|
||||
if (!reg_domain->chan_info) {
|
||||
LOG_ERR("%s: Invalid regulatory info (NULL)\n", __func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
status = nrf_wifi_fmac_get_reg(fmac_dev_ctx, ®_domain_info);
|
||||
if (status != NRF_WIFI_STATUS_SUCCESS) {
|
||||
LOG_ERR("%s: Failed to get regulatory domain", __func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy(reg_domain->country_code, reg_domain_info.alpha2, WIFI_COUNTRY_CODE_LEN);
|
||||
reg_domain->num_channels = reg_domain_info.reg_chan_count;
|
||||
|
||||
for (chan_idx = 0; chan_idx < reg_domain_info.reg_chan_count; chan_idx++) {
|
||||
chan_info = &(reg_domain->chan_info[chan_idx]);
|
||||
reg_domain_chan_info = &(reg_domain_info.reg_chan_info[chan_idx]);
|
||||
chan_info->center_frequency = reg_domain_chan_info->center_frequency;
|
||||
chan_info->dfs = !!reg_domain_chan_info->dfs;
|
||||
chan_info->max_power = reg_domain_chan_info->max_power;
|
||||
chan_info->passive_only = !!reg_domain_chan_info->passive_channel;
|
||||
chan_info->supported = !!reg_domain_chan_info->supported;
|
||||
}
|
||||
} else {
|
||||
LOG_ERR("%s: Invalid operation: %d", __func__, reg_domain->oper);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
err:
|
||||
k_mutex_unlock(®_lock);
|
||||
return ret;
|
||||
}
|
||||
#ifdef CONFIG_NRF70_STA_MODE
|
||||
void nrf_wifi_event_proc_cookie_rsp(void *vif_ctx,
|
||||
struct nrf_wifi_umac_event_cookie_rsp *cookie_rsp_event,
|
||||
unsigned int event_len)
|
||||
{
|
||||
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
|
||||
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
|
||||
struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
|
||||
|
||||
vif_ctx_zep = vif_ctx;
|
||||
|
||||
if (!vif_ctx_zep) {
|
||||
LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
|
||||
fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
|
||||
|
||||
LOG_DBG("%s: cookie_rsp_event->cookie = %llx", __func__, cookie_rsp_event->cookie);
|
||||
LOG_DBG("%s: host_cookie = %llx", __func__, cookie_rsp_event->host_cookie);
|
||||
LOG_DBG("%s: mac_addr = %x:%x:%x:%x:%x:%x", __func__,
|
||||
cookie_rsp_event->mac_addr[0],
|
||||
cookie_rsp_event->mac_addr[1],
|
||||
cookie_rsp_event->mac_addr[2],
|
||||
cookie_rsp_event->mac_addr[3],
|
||||
cookie_rsp_event->mac_addr[4],
|
||||
cookie_rsp_event->mac_addr[5]);
|
||||
|
||||
vif_ctx_zep->cookie_resp_received = true;
|
||||
/* TODO: When supp_callbk_fns.mgmt_tx_status is implemented, add logic
|
||||
* here to use the cookie and host_cookie to map requests to responses.
|
||||
*/
|
||||
}
|
||||
#endif /* CONFIG_NRF70_STA_MODE */
|
||||
|
||||
void reg_change_callbk_fn(void *vif_ctx,
|
||||
struct nrf_wifi_event_regulatory_change *reg_change_event,
|
||||
unsigned int event_len)
|
||||
{
|
||||
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
|
||||
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
|
||||
struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
|
||||
|
||||
vif_ctx_zep = vif_ctx;
|
||||
|
||||
if (!vif_ctx_zep) {
|
||||
LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
|
||||
if (!rpu_ctx_zep) {
|
||||
LOG_ERR("%s: rpu_ctx_zep is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
|
||||
if (!fmac_dev_ctx) {
|
||||
LOG_ERR("%s: fmac_dev_ctx is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
fmac_dev_ctx->reg_change = k_malloc(sizeof(struct nrf_wifi_event_regulatory_change));
|
||||
if (!fmac_dev_ctx->reg_change) {
|
||||
LOG_ERR("%s: Failed to allocate memory for reg_change", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(fmac_dev_ctx->reg_change,
|
||||
reg_change_event,
|
||||
sizeof(struct nrf_wifi_event_regulatory_change));
|
||||
fmac_dev_ctx->reg_set_status = true;
|
||||
}
|
||||
#endif /* !CONFIG_NRF70_RADIO_TEST */
|
||||
|
||||
/* DTS uses 1dBm as the unit for TX power, while the RPU uses 0.25dBm */
|
||||
#define MAX_TX_PWR(label) DT_PROP(DT_NODELABEL(nrf70), label) * 4
|
||||
|
||||
void configure_tx_pwr_settings(struct nrf_wifi_tx_pwr_ctrl_params *tx_pwr_ctrl_params,
|
||||
struct nrf_wifi_tx_pwr_ceil_params *tx_pwr_ceil_params)
|
||||
{
|
||||
tx_pwr_ctrl_params->ant_gain_2g = CONFIG_NRF70_ANT_GAIN_2G;
|
||||
tx_pwr_ctrl_params->ant_gain_5g_band1 = CONFIG_NRF70_ANT_GAIN_5G_BAND1;
|
||||
tx_pwr_ctrl_params->ant_gain_5g_band2 = CONFIG_NRF70_ANT_GAIN_5G_BAND2;
|
||||
tx_pwr_ctrl_params->ant_gain_5g_band3 = CONFIG_NRF70_ANT_GAIN_5G_BAND3;
|
||||
tx_pwr_ctrl_params->band_edge_2g_lo_dss = CONFIG_NRF70_BAND_2G_LOWER_EDGE_BACKOFF_DSSS;
|
||||
tx_pwr_ctrl_params->band_edge_2g_lo_ht = CONFIG_NRF70_BAND_2G_LOWER_EDGE_BACKOFF_HT;
|
||||
tx_pwr_ctrl_params->band_edge_2g_lo_he = CONFIG_NRF70_BAND_2G_LOWER_EDGE_BACKOFF_HE;
|
||||
tx_pwr_ctrl_params->band_edge_2g_hi_dsss = CONFIG_NRF70_BAND_2G_UPPER_EDGE_BACKOFF_DSSS;
|
||||
tx_pwr_ctrl_params->band_edge_2g_hi_ht = CONFIG_NRF70_BAND_2G_UPPER_EDGE_BACKOFF_HT;
|
||||
tx_pwr_ctrl_params->band_edge_2g_hi_he = CONFIG_NRF70_BAND_2G_UPPER_EDGE_BACKOFF_HE;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_1_lo_ht =
|
||||
CONFIG_NRF70_BAND_UNII_1_LOWER_EDGE_BACKOFF_HT;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_1_lo_he =
|
||||
CONFIG_NRF70_BAND_UNII_1_LOWER_EDGE_BACKOFF_HE;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_1_hi_ht =
|
||||
CONFIG_NRF70_BAND_UNII_1_UPPER_EDGE_BACKOFF_HT;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_1_hi_he =
|
||||
CONFIG_NRF70_BAND_UNII_1_UPPER_EDGE_BACKOFF_HE;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_2a_lo_ht =
|
||||
CONFIG_NRF70_BAND_UNII_2A_LOWER_EDGE_BACKOFF_HT;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_2a_lo_he =
|
||||
CONFIG_NRF70_BAND_UNII_2A_LOWER_EDGE_BACKOFF_HE;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_2a_hi_ht =
|
||||
CONFIG_NRF70_BAND_UNII_2A_UPPER_EDGE_BACKOFF_HT;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_2a_hi_he =
|
||||
CONFIG_NRF70_BAND_UNII_2A_UPPER_EDGE_BACKOFF_HE;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_2c_lo_ht =
|
||||
CONFIG_NRF70_BAND_UNII_2C_LOWER_EDGE_BACKOFF_HT;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_2c_lo_he =
|
||||
CONFIG_NRF70_BAND_UNII_2C_LOWER_EDGE_BACKOFF_HE;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_2c_hi_ht =
|
||||
CONFIG_NRF70_BAND_UNII_2C_UPPER_EDGE_BACKOFF_HT;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_2c_hi_he =
|
||||
CONFIG_NRF70_BAND_UNII_2C_UPPER_EDGE_BACKOFF_HE;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_3_lo_ht =
|
||||
CONFIG_NRF70_BAND_UNII_3_LOWER_EDGE_BACKOFF_HT;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_3_lo_he =
|
||||
CONFIG_NRF70_BAND_UNII_3_LOWER_EDGE_BACKOFF_HE;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_3_hi_ht =
|
||||
CONFIG_NRF70_BAND_UNII_3_UPPER_EDGE_BACKOFF_HT;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_3_hi_he =
|
||||
CONFIG_NRF70_BAND_UNII_3_UPPER_EDGE_BACKOFF_HE;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_4_lo_ht =
|
||||
CONFIG_NRF70_BAND_UNII_4_LOWER_EDGE_BACKOFF_HT;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_4_lo_he =
|
||||
CONFIG_NRF70_BAND_UNII_4_LOWER_EDGE_BACKOFF_HE;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_4_hi_ht =
|
||||
CONFIG_NRF70_BAND_UNII_4_UPPER_EDGE_BACKOFF_HT;
|
||||
tx_pwr_ctrl_params->band_edge_5g_unii_4_hi_he =
|
||||
CONFIG_NRF70_BAND_UNII_4_UPPER_EDGE_BACKOFF_HE;
|
||||
|
||||
|
||||
tx_pwr_ceil_params->max_pwr_2g_dsss = MAX_TX_PWR(wifi_max_tx_pwr_2g_dsss);
|
||||
tx_pwr_ceil_params->max_pwr_2g_mcs7 = MAX_TX_PWR(wifi_max_tx_pwr_2g_mcs7);
|
||||
tx_pwr_ceil_params->max_pwr_2g_mcs0 = MAX_TX_PWR(wifi_max_tx_pwr_2g_mcs0);
|
||||
#ifndef CONFIG_NRF70_2_4G_ONLY
|
||||
tx_pwr_ceil_params->max_pwr_5g_low_mcs7 = MAX_TX_PWR(wifi_max_tx_pwr_5g_low_mcs7);
|
||||
tx_pwr_ceil_params->max_pwr_5g_mid_mcs7 = MAX_TX_PWR(wifi_max_tx_pwr_5g_mid_mcs7);
|
||||
tx_pwr_ceil_params->max_pwr_5g_high_mcs7 = MAX_TX_PWR(wifi_max_tx_pwr_5g_high_mcs7);
|
||||
tx_pwr_ceil_params->max_pwr_5g_low_mcs0 = MAX_TX_PWR(wifi_max_tx_pwr_5g_low_mcs0);
|
||||
tx_pwr_ceil_params->max_pwr_5g_mid_mcs0 = MAX_TX_PWR(wifi_max_tx_pwr_5g_mid_mcs0);
|
||||
tx_pwr_ceil_params->max_pwr_5g_high_mcs0 = MAX_TX_PWR(wifi_max_tx_pwr_5g_high_mcs0);
|
||||
#endif /* CONFIG_NRF70_2_4G_ONLY */
|
||||
}
|
||||
|
||||
void configure_board_dep_params(struct nrf_wifi_board_params *board_params)
|
||||
{
|
||||
board_params->pcb_loss_2g = CONFIG_NRF70_PCB_LOSS_2G;
|
||||
#ifndef CONFIG_NRF70_2_4G_ONLY
|
||||
board_params->pcb_loss_5g_band1 = CONFIG_NRF70_PCB_LOSS_5G_BAND1;
|
||||
board_params->pcb_loss_5g_band2 = CONFIG_NRF70_PCB_LOSS_5G_BAND2;
|
||||
board_params->pcb_loss_5g_band3 = CONFIG_NRF70_PCB_LOSS_5G_BAND3;
|
||||
#endif /* CONFIG_NRF70_2_4G_ONLY */
|
||||
}
|
||||
|
||||
enum nrf_wifi_status nrf_wifi_fmac_dev_add_zep(struct nrf_wifi_drv_priv_zep *drv_priv_zep)
|
||||
{
|
||||
enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
|
||||
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
|
||||
void *rpu_ctx = NULL;
|
||||
enum op_band op_band = CONFIG_NRF_WIFI_OP_BAND;
|
||||
#ifdef CONFIG_NRF_WIFI_LOW_POWER
|
||||
int sleep_type = -1;
|
||||
|
||||
#ifndef CONFIG_NRF70_RADIO_TEST
|
||||
sleep_type = HW_SLEEP_ENABLE;
|
||||
#else
|
||||
sleep_type = SLEEP_DISABLE;
|
||||
#endif /* CONFIG_NRF70_RADIO_TEST */
|
||||
#endif /* CONFIG_NRF_WIFI_LOW_POWER */
|
||||
struct nrf_wifi_tx_pwr_ctrl_params tx_pwr_ctrl_params;
|
||||
struct nrf_wifi_tx_pwr_ceil_params tx_pwr_ceil_params;
|
||||
struct nrf_wifi_board_params board_params;
|
||||
|
||||
unsigned int fw_ver = 0;
|
||||
|
||||
rpu_ctx_zep = &drv_priv_zep->rpu_ctx_zep;
|
||||
|
||||
rpu_ctx_zep->drv_priv_zep = drv_priv_zep;
|
||||
|
||||
rpu_ctx = nrf_wifi_fmac_dev_add(drv_priv_zep->fmac_priv, rpu_ctx_zep);
|
||||
|
||||
if (!rpu_ctx) {
|
||||
LOG_ERR("%s: nrf_wifi_fmac_dev_add failed", __func__);
|
||||
rpu_ctx_zep = NULL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
rpu_ctx_zep->rpu_ctx = rpu_ctx;
|
||||
|
||||
status = nrf_wifi_fw_load(rpu_ctx);
|
||||
if (status != NRF_WIFI_STATUS_SUCCESS) {
|
||||
LOG_ERR("%s: nrf_wifi_fw_load failed", __func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
status = nrf_wifi_fmac_ver_get(rpu_ctx,
|
||||
&fw_ver);
|
||||
|
||||
if (status != NRF_WIFI_STATUS_SUCCESS) {
|
||||
LOG_ERR("%s: FW version read failed", __func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
LOG_DBG("Firmware (v%d.%d.%d.%d) booted successfully",
|
||||
NRF_WIFI_UMAC_VER(fw_ver),
|
||||
NRF_WIFI_UMAC_VER_MAJ(fw_ver),
|
||||
NRF_WIFI_UMAC_VER_MIN(fw_ver),
|
||||
NRF_WIFI_UMAC_VER_EXTRA(fw_ver));
|
||||
|
||||
configure_tx_pwr_settings(&tx_pwr_ctrl_params,
|
||||
&tx_pwr_ceil_params);
|
||||
|
||||
configure_board_dep_params(&board_params);
|
||||
|
||||
#ifdef CONFIG_NRF70_RADIO_TEST
|
||||
status = nrf_wifi_fmac_dev_init_rt(rpu_ctx_zep->rpu_ctx,
|
||||
#ifdef CONFIG_NRF_WIFI_LOW_POWER
|
||||
sleep_type,
|
||||
#endif /* CONFIG_NRF_WIFI_LOW_POWER */
|
||||
NRF_WIFI_DEF_PHY_CALIB,
|
||||
op_band,
|
||||
IS_ENABLED(CONFIG_NRF_WIFI_BEAMFORMING),
|
||||
&tx_pwr_ctrl_params,
|
||||
&tx_pwr_ceil_params,
|
||||
&board_params);
|
||||
#else
|
||||
status = nrf_wifi_fmac_dev_init(rpu_ctx_zep->rpu_ctx,
|
||||
#ifdef CONFIG_NRF_WIFI_LOW_POWER
|
||||
sleep_type,
|
||||
#endif /* CONFIG_NRF_WIFI_LOW_POWER */
|
||||
NRF_WIFI_DEF_PHY_CALIB,
|
||||
op_band,
|
||||
IS_ENABLED(CONFIG_NRF_WIFI_BEAMFORMING),
|
||||
&tx_pwr_ctrl_params,
|
||||
&tx_pwr_ceil_params,
|
||||
&board_params);
|
||||
#endif /* CONFIG_NRF70_RADIO_TEST */
|
||||
|
||||
|
||||
if (status != NRF_WIFI_STATUS_SUCCESS) {
|
||||
LOG_ERR("%s: nrf_wifi_fmac_dev_init failed", __func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
k_mutex_init(&rpu_ctx_zep->rpu_lock);
|
||||
|
||||
return status;
|
||||
err:
|
||||
if (rpu_ctx) {
|
||||
#ifdef CONFIG_NRF70_RADIO_TEST
|
||||
nrf_wifi_fmac_dev_rem_rt(rpu_ctx);
|
||||
#else
|
||||
nrf_wifi_fmac_dev_rem(rpu_ctx);
|
||||
#endif /* CONFIG_NRF70_RADIO_TEST */
|
||||
rpu_ctx_zep->rpu_ctx = NULL;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
enum nrf_wifi_status nrf_wifi_fmac_dev_rem_zep(struct nrf_wifi_drv_priv_zep *drv_priv_zep)
|
||||
{
|
||||
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
|
||||
|
||||
rpu_ctx_zep = &drv_priv_zep->rpu_ctx_zep;
|
||||
#ifdef CONFIG_NRF70_RADIO_TEST
|
||||
nrf_wifi_fmac_dev_deinit_rt(rpu_ctx_zep->rpu_ctx);
|
||||
nrf_wifi_fmac_dev_rem_rt(rpu_ctx_zep->rpu_ctx);
|
||||
#else
|
||||
nrf_wifi_fmac_dev_deinit(rpu_ctx_zep->rpu_ctx);
|
||||
nrf_wifi_fmac_dev_rem(rpu_ctx_zep->rpu_ctx);
|
||||
#endif /* CONFIG_NRF70_RADIO_TEST */
|
||||
|
||||
k_free(rpu_ctx_zep->extended_capa);
|
||||
rpu_ctx_zep->extended_capa = NULL;
|
||||
k_free(rpu_ctx_zep->extended_capa_mask);
|
||||
rpu_ctx_zep->extended_capa_mask = NULL;
|
||||
|
||||
rpu_ctx_zep->rpu_ctx = NULL;
|
||||
LOG_DBG("%s: FMAC device removed", __func__);
|
||||
|
||||
return NRF_WIFI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static int nrf_wifi_drv_main_zep(const struct device *dev)
|
||||
{
|
||||
#ifndef CONFIG_NRF70_RADIO_TEST
|
||||
struct nrf_wifi_fmac_callbk_fns callbk_fns = { 0 };
|
||||
struct nrf_wifi_data_config_params data_config = { 0 };
|
||||
struct rx_buf_pool_params rx_buf_pools[MAX_NUM_OF_RX_QUEUES];
|
||||
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = dev->data;
|
||||
|
||||
vif_ctx_zep->rpu_ctx_zep = &rpu_drv_priv_zep.rpu_ctx_zep;
|
||||
|
||||
#ifdef CONFIG_NRF70_DATA_TX
|
||||
data_config.aggregation = aggregation;
|
||||
data_config.wmm = wmm;
|
||||
data_config.max_num_tx_agg_sessions = max_num_tx_agg_sessions;
|
||||
data_config.max_num_rx_agg_sessions = max_num_rx_agg_sessions;
|
||||
data_config.max_tx_aggregation = max_tx_aggregation;
|
||||
data_config.reorder_buf_size = reorder_buf_size;
|
||||
data_config.max_rxampdu_size = max_rxampdu_size;
|
||||
data_config.rate_protection_type = rate_protection_type;
|
||||
callbk_fns.if_carr_state_chg_callbk_fn = nrf_wifi_if_carr_state_chg;
|
||||
callbk_fns.rx_frm_callbk_fn = nrf_wifi_if_rx_frm;
|
||||
#if defined(CONFIG_NRF70_RAW_DATA_RX) || defined(CONFIG_NRF70_PROMISC_DATA_RX)
|
||||
callbk_fns.rx_sniffer_frm_callbk_fn = nrf_wifi_if_sniffer_rx_frm;
|
||||
#endif /* CONFIG_NRF70_RAW_DATA_RX || CONFIG_NRF70_PROMISC_DATA_RX */
|
||||
#endif
|
||||
rx_buf_pools[0].num_bufs = rx1_num_bufs;
|
||||
rx_buf_pools[1].num_bufs = rx2_num_bufs;
|
||||
rx_buf_pools[2].num_bufs = rx3_num_bufs;
|
||||
rx_buf_pools[0].buf_sz = rx1_buf_sz;
|
||||
rx_buf_pools[1].buf_sz = rx2_buf_sz;
|
||||
rx_buf_pools[2].buf_sz = rx3_buf_sz;
|
||||
|
||||
#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY
|
||||
callbk_fns.rpu_recovery_callbk_fn = nrf_wifi_rpu_recovery_cb;
|
||||
#endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */
|
||||
callbk_fns.scan_start_callbk_fn = nrf_wifi_event_proc_scan_start_zep;
|
||||
callbk_fns.scan_done_callbk_fn = nrf_wifi_event_proc_scan_done_zep;
|
||||
callbk_fns.reg_change_callbk_fn = reg_change_callbk_fn;
|
||||
#ifdef CONFIG_NET_L2_WIFI_MGMT
|
||||
callbk_fns.disp_scan_res_callbk_fn = nrf_wifi_event_proc_disp_scan_res_zep;
|
||||
#endif /* CONFIG_NET_L2_WIFI_MGMT */
|
||||
#ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS
|
||||
callbk_fns.rx_bcn_prb_resp_callbk_fn = nrf_wifi_rx_bcn_prb_resp_frm;
|
||||
#endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */
|
||||
#if defined(CONFIG_NRF70_SYSTEM_MODE) || defined(CONFIG_NRF70_SYSTEM_WITH_RAW_MODES)
|
||||
callbk_fns.set_if_callbk_fn = nrf_wifi_set_iface_event_handler;
|
||||
#endif /* CONFIG_NRF70_SYSTEM_MODE */
|
||||
#ifdef CONFIG_NRF70_STA_MODE
|
||||
callbk_fns.twt_config_callbk_fn = nrf_wifi_event_proc_twt_setup_zep;
|
||||
callbk_fns.twt_teardown_callbk_fn = nrf_wifi_event_proc_twt_teardown_zep;
|
||||
callbk_fns.twt_sleep_callbk_fn = nrf_wifi_event_proc_twt_sleep_zep;
|
||||
callbk_fns.event_get_reg = nrf_wifi_event_get_reg_zep;
|
||||
callbk_fns.event_get_ps_info = nrf_wifi_event_proc_get_power_save_info;
|
||||
callbk_fns.cookie_rsp_callbk_fn = nrf_wifi_event_proc_cookie_rsp;
|
||||
callbk_fns.process_rssi_from_rx = nrf_wifi_process_rssi_from_rx;
|
||||
callbk_fns.scan_res_callbk_fn = nrf_wifi_wpa_supp_event_proc_scan_res;
|
||||
callbk_fns.auth_resp_callbk_fn = nrf_wifi_wpa_supp_event_proc_auth_resp;
|
||||
callbk_fns.assoc_resp_callbk_fn = nrf_wifi_wpa_supp_event_proc_assoc_resp;
|
||||
callbk_fns.deauth_callbk_fn = nrf_wifi_wpa_supp_event_proc_deauth;
|
||||
callbk_fns.disassoc_callbk_fn = nrf_wifi_wpa_supp_event_proc_disassoc;
|
||||
callbk_fns.get_station_callbk_fn = nrf_wifi_wpa_supp_event_proc_get_sta;
|
||||
callbk_fns.get_interface_callbk_fn = nrf_wifi_wpa_supp_event_proc_get_if;
|
||||
callbk_fns.mgmt_tx_status = nrf_wifi_wpa_supp_event_mgmt_tx_status;
|
||||
callbk_fns.unprot_mlme_mgmt_rx_callbk_fn = nrf_wifi_wpa_supp_event_proc_unprot_mgmt;
|
||||
callbk_fns.event_get_wiphy = nrf_wifi_wpa_supp_event_get_wiphy;
|
||||
callbk_fns.mgmt_rx_callbk_fn = nrf_wifi_wpa_supp_event_mgmt_rx_callbk_fn;
|
||||
callbk_fns.get_conn_info_callbk_fn = nrf_wifi_supp_event_proc_get_conn_info;
|
||||
#endif /* CONFIG_NRF70_STA_MODE */
|
||||
|
||||
rpu_drv_priv_zep.fmac_priv = nrf_wifi_fmac_init(&data_config,
|
||||
rx_buf_pools,
|
||||
&callbk_fns);
|
||||
#else /* !CONFIG_NRF70_RADIO_TEST */
|
||||
enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
|
||||
|
||||
rpu_drv_priv_zep.fmac_priv = nrf_wifi_fmac_init_rt();
|
||||
#endif /* CONFIG_NRF70_RADIO_TEST */
|
||||
|
||||
if (rpu_drv_priv_zep.fmac_priv == NULL) {
|
||||
LOG_ERR("%s: nrf_wifi_fmac_init failed",
|
||||
__func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NRF70_DATA_TX
|
||||
struct nrf_wifi_fmac_priv_def *def_priv = NULL;
|
||||
|
||||
def_priv = wifi_fmac_priv(rpu_drv_priv_zep.fmac_priv);
|
||||
def_priv->max_ampdu_len_per_token =
|
||||
(RPU_PKTRAM_SIZE - (CONFIG_NRF70_RX_NUM_BUFS * CONFIG_NRF70_RX_MAX_DATA_SIZE)) /
|
||||
CONFIG_NRF70_MAX_TX_TOKENS;
|
||||
/* Align to 4-byte */
|
||||
def_priv->max_ampdu_len_per_token &= ~0x3;
|
||||
|
||||
/* Alignment overhead for size based coalesce */
|
||||
def_priv->avail_ampdu_len_per_token =
|
||||
def_priv->max_ampdu_len_per_token -
|
||||
(MAX_PKT_RAM_TX_ALIGN_OVERHEAD * max_tx_aggregation);
|
||||
#endif /* CONFIG_NRF70_DATA_TX */
|
||||
|
||||
#ifdef CONFIG_NRF70_RADIO_TEST
|
||||
status = nrf_wifi_fmac_dev_add_zep(&rpu_drv_priv_zep);
|
||||
if (status != NRF_WIFI_STATUS_SUCCESS) {
|
||||
LOG_ERR("%s: nrf_wifi_fmac_dev_add_zep failed", __func__);
|
||||
goto fmac_deinit;
|
||||
}
|
||||
#else
|
||||
k_work_init_delayable(&vif_ctx_zep->scan_timeout_work,
|
||||
nrf_wifi_scan_timeout_work);
|
||||
#endif /* CONFIG_NRF70_RADIO_TEST */
|
||||
|
||||
return 0;
|
||||
#ifdef CONFIG_NRF70_RADIO_TEST
|
||||
fmac_deinit:
|
||||
nrf_wifi_fmac_deinit_rt(rpu_drv_priv_zep.fmac_priv);
|
||||
#endif /* CONFIG_NRF70_RADIO_TEST */
|
||||
err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_NRF70_RADIO_TEST
|
||||
#ifdef CONFIG_NET_L2_WIFI_MGMT
|
||||
static struct wifi_mgmt_ops nrf_wifi_mgmt_ops = {
|
||||
.scan = nrf_wifi_disp_scan_zep,
|
||||
#ifdef CONFIG_NET_STATISTICS_WIFI
|
||||
.get_stats = nrf_wifi_stats_get,
|
||||
#endif /* CONFIG_NET_STATISTICS_WIFI */
|
||||
#ifdef CONFIG_NRF70_STA_MODE
|
||||
.set_power_save = nrf_wifi_set_power_save,
|
||||
.set_twt = nrf_wifi_set_twt,
|
||||
.reg_domain = nrf_wifi_reg_domain,
|
||||
.get_power_save_config = nrf_wifi_get_power_save_config,
|
||||
.set_rts_threshold = nrf_wifi_set_rts_threshold,
|
||||
#endif /* CONFIG_NRF70_STA_MODE */
|
||||
#ifdef CONFIG_NRF70_SYSTEM_WITH_RAW_MODES
|
||||
.mode = nrf_wifi_mode,
|
||||
#endif
|
||||
#if defined(CONFIG_NRF70_RAW_DATA_TX) || defined(CONFIG_NRF70_RAW_DATA_RX)
|
||||
.channel = nrf_wifi_channel,
|
||||
#endif /* CONFIG_NRF70_RAW_DATA_TX || CONFIG_NRF70_RAW_DATA_RX */
|
||||
#if defined(CONFIG_NRF70_RAW_DATA_RX) || defined(CONFIG_NRF70_PROMISC_DATA_RX)
|
||||
.filter = nrf_wifi_filter,
|
||||
#endif /* CONFIG_NRF70_RAW_DATA_RX || CONFIG_NRF70_PROMISC_DATA_RX */
|
||||
};
|
||||
#endif /* CONFIG_NET_L2_WIFI_MGMT */
|
||||
|
||||
|
||||
|
||||
#ifdef CONFIG_NRF70_STA_MODE
|
||||
static struct zep_wpa_supp_dev_ops wpa_supp_ops = {
|
||||
.init = nrf_wifi_wpa_supp_dev_init,
|
||||
.deinit = nrf_wifi_wpa_supp_dev_deinit,
|
||||
.scan2 = nrf_wifi_wpa_supp_scan2,
|
||||
.scan_abort = nrf_wifi_wpa_supp_scan_abort,
|
||||
.get_scan_results2 = nrf_wifi_wpa_supp_scan_results_get,
|
||||
.deauthenticate = nrf_wifi_wpa_supp_deauthenticate,
|
||||
.authenticate = nrf_wifi_wpa_supp_authenticate,
|
||||
.associate = nrf_wifi_wpa_supp_associate,
|
||||
.set_supp_port = nrf_wifi_wpa_set_supp_port,
|
||||
.set_key = nrf_wifi_wpa_supp_set_key,
|
||||
.signal_poll = nrf_wifi_wpa_supp_signal_poll,
|
||||
.send_mlme = nrf_wifi_nl80211_send_mlme,
|
||||
.get_wiphy = nrf_wifi_supp_get_wiphy,
|
||||
.register_frame = nrf_wifi_supp_register_frame,
|
||||
.get_capa = nrf_wifi_supp_get_capa,
|
||||
.get_conn_info = nrf_wifi_supp_get_conn_info,
|
||||
#ifdef CONFIG_NRF70_AP_MODE
|
||||
.init_ap = nrf_wifi_wpa_supp_init_ap,
|
||||
.start_ap = nrf_wifi_wpa_supp_start_ap,
|
||||
.change_beacon = nrf_wifi_wpa_supp_change_beacon,
|
||||
.stop_ap = nrf_wifi_wpa_supp_stop_ap,
|
||||
.deinit_ap = nrf_wifi_wpa_supp_deinit_ap,
|
||||
.sta_add = nrf_wifi_wpa_supp_sta_add,
|
||||
.sta_remove = nrf_wifi_wpa_supp_sta_remove,
|
||||
.register_mgmt_frame = nrf_wifi_supp_register_mgmt_frame,
|
||||
.sta_set_flags = nrf_wifi_wpa_supp_sta_set_flags,
|
||||
.get_inact_sec = nrf_wifi_wpa_supp_sta_get_inact_sec,
|
||||
#endif /* CONFIG_NRF70_AP_MODE */
|
||||
};
|
||||
#endif /* CONFIG_NRF70_STA_MODE */
|
||||
#endif /* !CONFIG_NRF70_RADIO_TEST */
|
||||
|
||||
|
||||
#ifdef CONFIG_NET_L2_ETHERNET
|
||||
static const struct net_wifi_mgmt_offload wifi_offload_ops = {
|
||||
.wifi_iface.iface_api.init = nrf_wifi_if_init_zep,
|
||||
.wifi_iface.start = nrf_wifi_if_start_zep,
|
||||
.wifi_iface.stop = nrf_wifi_if_stop_zep,
|
||||
.wifi_iface.set_config = nrf_wifi_if_set_config_zep,
|
||||
.wifi_iface.get_config = nrf_wifi_if_get_config_zep,
|
||||
.wifi_iface.get_capabilities = nrf_wifi_if_caps_get,
|
||||
.wifi_iface.send = nrf_wifi_if_send,
|
||||
#ifdef CONFIG_NET_STATISTICS_ETHERNET
|
||||
.wifi_iface.get_stats = nrf_wifi_eth_stats_get,
|
||||
#endif /* CONFIG_NET_STATISTICS_ETHERNET */
|
||||
#ifdef CONFIG_NET_L2_WIFI_MGMT
|
||||
.wifi_mgmt_api = &nrf_wifi_mgmt_ops,
|
||||
#endif /* CONFIG_NET_L2_WIFI_MGMT */
|
||||
#ifdef CONFIG_NRF70_STA_MODE
|
||||
.wifi_drv_ops = &wpa_supp_ops,
|
||||
#endif /* CONFIG_NRF70_STA_MODE */
|
||||
};
|
||||
#endif /* CONFIG_NET_L2_ETHERNET */
|
||||
|
||||
|
||||
|
||||
#ifdef CONFIG_NET_L2_ETHERNET
|
||||
ETH_NET_DEVICE_DT_INST_DEFINE(0,
|
||||
nrf_wifi_drv_main_zep, /* init_fn */
|
||||
NULL, /* pm_action_cb */
|
||||
&rpu_drv_priv_zep.rpu_ctx_zep.vif_ctx_zep[0], /* data */
|
||||
#ifdef CONFIG_NRF70_STA_MODE
|
||||
&wpa_supp_ops, /* cfg */
|
||||
#else /* CONFIG_NRF70_STA_MODE */
|
||||
NULL, /* cfg */
|
||||
#endif /* !CONFIG_NRF70_STA_MODE */
|
||||
CONFIG_WIFI_INIT_PRIORITY, /* prio */
|
||||
&wifi_offload_ops, /* api */
|
||||
CONFIG_NRF_WIFI_IFACE_MTU); /*mtu */
|
||||
#else
|
||||
DEVICE_DT_INST_DEFINE(0,
|
||||
nrf_wifi_drv_main_zep, /* init_fn */
|
||||
NULL, /* pm_action_cb */
|
||||
#ifndef CONFIG_NRF70_RADIO_TEST
|
||||
&rpu_drv_priv_zep, /* data */
|
||||
#else /* !CONFIG_NRF70_RADIO_TEST */
|
||||
NULL,
|
||||
#endif /* CONFIG_NRF70_RADIO_TEST */
|
||||
NULL, /* cfg */
|
||||
POST_KERNEL,
|
||||
CONFIG_WIFI_INIT_PRIORITY, /* prio */
|
||||
NULL); /* api */
|
||||
#endif /* CONFIG_NRF70_STA_MODE */
|
||||
|
||||
#ifdef CONFIG_NET_CONNECTION_MANAGER_CONNECTIVITY_WIFI_MGMT
|
||||
CONNECTIVITY_WIFI_MGMT_BIND(Z_DEVICE_DT_DEV_ID(DT_DRV_INST(0)), L2_CONN_WLAN0);
|
||||
#endif /* CONFIG_NET_CONNECTION_MANAGER_CONNECTIVITY_WIFI_MGMT */
|
85
drivers/wifi/nrfwifi/src/fw_load.c
Normal file
85
drivers/wifi/nrfwifi/src/fw_load.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief File containing FW load functions for Zephyr.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/device.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_DECLARE(wifi_nrf, CONFIG_WIFI_NRF70_LOG_LEVEL);
|
||||
|
||||
#include <fmac_main.h>
|
||||
|
||||
#ifdef CONFIG_NRF_WIFI_PATCHES_BUILTIN
|
||||
/* INCBIN macro Taken from https://gist.github.com/mmozeiko/ed9655cf50341553d282 */
|
||||
#define STR2(x) #x
|
||||
#define STR(x) STR2(x)
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define USTR(x) "_" STR(x)
|
||||
#else
|
||||
#define USTR(x) STR(x)
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define INCBIN_SECTION ".rdata, \"dr\""
|
||||
#elif defined __APPLE__
|
||||
#define INCBIN_SECTION "__TEXT,__const"
|
||||
#else
|
||||
#define INCBIN_SECTION ".rodata.*"
|
||||
#endif
|
||||
|
||||
/* this aligns start address to 16 and terminates byte array with explicit 0
|
||||
* which is not really needed, feel free to change it to whatever you want/need
|
||||
*/
|
||||
#define INCBIN(prefix, name, file) \
|
||||
__asm__(".section " INCBIN_SECTION "\n" \
|
||||
".global " USTR(prefix) "_" STR(name) "_start\n" \
|
||||
".balign 16\n" \
|
||||
USTR(prefix) "_" STR(name) "_start:\n" \
|
||||
".incbin \"" file "\"\n" \
|
||||
\
|
||||
".global " STR(prefix) "_" STR(name) "_end\n" \
|
||||
".balign 1\n" \
|
||||
USTR(prefix) "_" STR(name) "_end:\n" \
|
||||
".byte 0\n" \
|
||||
); \
|
||||
extern __aligned(16) const char prefix ## _ ## name ## _start[]; \
|
||||
extern const char prefix ## _ ## name ## _end[];
|
||||
|
||||
INCBIN(_bin, nrf70_fw, STR(CONFIG_NRF_WIFI_FW_BIN));
|
||||
#endif /* CONFIG_NRF_WIFI_PATCHES_BUILTIN */
|
||||
|
||||
enum nrf_wifi_status nrf_wifi_fw_load(void *rpu_ctx)
|
||||
{
|
||||
enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
|
||||
struct nrf_wifi_fmac_fw_info fw_info = { 0 };
|
||||
uint8_t *fw_start;
|
||||
uint8_t *fw_end;
|
||||
|
||||
fw_start = (uint8_t *)_bin_nrf70_fw_start;
|
||||
fw_end = (uint8_t *)_bin_nrf70_fw_end;
|
||||
|
||||
status = nrf_wifi_fmac_fw_parse(rpu_ctx, fw_start, fw_end - fw_start,
|
||||
&fw_info);
|
||||
if (status != NRF_WIFI_STATUS_SUCCESS) {
|
||||
LOG_ERR("%s: nrf_wifi_fmac_fw_parse failed", __func__);
|
||||
return status;
|
||||
}
|
||||
/* Load the FW patches to the RPU */
|
||||
status = nrf_wifi_fmac_fw_load(rpu_ctx, &fw_info);
|
||||
|
||||
if (status != NRF_WIFI_STATUS_SUCCESS) {
|
||||
LOG_ERR("%s: nrf_wifi_fmac_fw_load failed", __func__);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
1145
drivers/wifi/nrfwifi/src/net_if.c
Normal file
1145
drivers/wifi/nrfwifi/src/net_if.c
Normal file
File diff suppressed because it is too large
Load diff
23
drivers/wifi/nrfwifi/src/qspi/inc/ficr_prog.h
Normal file
23
drivers/wifi/nrfwifi/src/qspi/inc/ficr_prog.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Header containing address/offets and functions for writing
|
||||
* the FICR fields of the OTP memory on nRF7002 device
|
||||
*/
|
||||
|
||||
#ifndef __OTP_PROG_H_
|
||||
#define __OTP_PROG_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int write_otp_memory(unsigned int otp_addr, unsigned int *write_val);
|
||||
int read_otp_memory(unsigned int otp_addr, unsigned int *read_val, int len);
|
||||
unsigned int check_protection(unsigned int *buff, unsigned int off1, unsigned int off2,
|
||||
unsigned int off3, unsigned int off4);
|
||||
|
||||
#endif /* __OTP_PROG_H_ */
|
116
drivers/wifi/nrfwifi/src/qspi/inc/qspi_if.h
Normal file
116
drivers/wifi/nrfwifi/src/qspi/inc/qspi_if.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Header containing QSPI device interface specific declarations for the
|
||||
* Zephyr OS layer of the Wi-Fi driver.
|
||||
*/
|
||||
|
||||
#ifndef __QSPI_IF_H__
|
||||
#define __QSPI_IF_H__
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#ifdef CONFIG_NRF70_ON_QSPI
|
||||
#include <nrfx_qspi.h>
|
||||
#endif
|
||||
|
||||
#define RPU_WAKEUP_NOW BIT(0) /* WAKEUP RPU - RW */
|
||||
#define RPU_AWAKE_BIT BIT(1) /* RPU AWAKE FROM SLEEP - RO */
|
||||
#define RPU_READY_BIT BIT(2) /* RPU IS READY - RO*/
|
||||
|
||||
struct qspi_config {
|
||||
#ifdef CONFIG_NRF70_ON_QSPI
|
||||
nrf_qspi_addrmode_t addrmode;
|
||||
nrf_qspi_readoc_t readoc;
|
||||
nrf_qspi_writeoc_t writeoc;
|
||||
nrf_qspi_frequency_t sckfreq;
|
||||
#endif
|
||||
unsigned char RDC4IO;
|
||||
bool easydma;
|
||||
bool single_op;
|
||||
bool quad_spi;
|
||||
bool encryption;
|
||||
bool CMD_CNONCE;
|
||||
bool enc_enabled;
|
||||
struct k_sem lock;
|
||||
unsigned int addrmask;
|
||||
unsigned char qspi_slave_latency;
|
||||
#if defined(CONFIG_NRF70_ON_QSPI) && (NRF_QSPI_HAS_XIP_ENC || NRF_QSPI_HAS_DMA_ENC)
|
||||
nrf_qspi_encryption_t p_cfg;
|
||||
#endif /*CONFIG_NRF70_ON_QSPI && (NRF_QSPI_HAS_XIP_ENC || NRF_QSPI_HAS_DMA_ENC)*/
|
||||
int test_hlread;
|
||||
char *test_name;
|
||||
int test_start;
|
||||
int test_end;
|
||||
int test_iterations;
|
||||
int test_timediff_read;
|
||||
int test_timediff_write;
|
||||
int test_status;
|
||||
int test_iteration;
|
||||
};
|
||||
struct qspi_dev {
|
||||
int (*deinit)(void);
|
||||
void *config;
|
||||
int (*init)(struct qspi_config *config);
|
||||
int (*write)(unsigned int addr, const void *data, int len);
|
||||
int (*read)(unsigned int addr, void *data, int len);
|
||||
int (*hl_read)(unsigned int addr, void *data, int len);
|
||||
void (*hard_reset)(void);
|
||||
};
|
||||
|
||||
int qspi_cmd_wakeup_rpu(const struct device *dev, uint8_t data);
|
||||
|
||||
int qspi_init(struct qspi_config *config);
|
||||
|
||||
int qspi_write(unsigned int addr, const void *data, int len);
|
||||
|
||||
int qspi_read(unsigned int addr, void *data, int len);
|
||||
|
||||
int qspi_hl_read(unsigned int addr, void *data, int len);
|
||||
|
||||
int qspi_deinit(void);
|
||||
|
||||
void gpio_free_irq(int pin, struct gpio_callback *button_cb_data);
|
||||
|
||||
int gpio_request_irq(int pin, struct gpio_callback *button_cb_data, void (*irq_handler)());
|
||||
|
||||
struct qspi_config *qspi_defconfig(void);
|
||||
|
||||
struct qspi_dev *qspi_dev(void);
|
||||
struct qspi_config *qspi_get_config(void);
|
||||
|
||||
int qspi_cmd_sleep_rpu(const struct device *dev);
|
||||
|
||||
void hard_reset(void);
|
||||
void get_sleep_stats(uint32_t addr, uint32_t *buff, uint32_t wrd_len);
|
||||
|
||||
extern struct device qspi_perip;
|
||||
|
||||
int qspi_validate_rpu_wake_writecmd(const struct device *dev);
|
||||
int qspi_cmd_wakeup_rpu(const struct device *dev, uint8_t data);
|
||||
int qspi_wait_while_rpu_awake(const struct device *dev);
|
||||
|
||||
int qspi_RDSR1(const struct device *dev, uint8_t *rdsr1);
|
||||
int qspi_RDSR2(const struct device *dev, uint8_t *rdsr2);
|
||||
int qspi_WRSR2(const struct device *dev, const uint8_t wrsr2);
|
||||
|
||||
#ifdef CONFIG_NRF_WIFI_LOW_POWER
|
||||
int func_rpu_sleep(void);
|
||||
int func_rpu_wake(void);
|
||||
int func_rpu_sleep_status(void);
|
||||
#endif /* CONFIG_NRF_WIFI_LOW_POWER */
|
||||
|
||||
#define QSPI_KEY_LEN_BYTES 16
|
||||
|
||||
/*! \brief Enable encryption
|
||||
*
|
||||
* \param key Pointer to the 128-bit key
|
||||
* \return 0 on success, negative errno code on failure.
|
||||
*/
|
||||
int qspi_enable_encryption(uint8_t *key);
|
||||
|
||||
#endif /* __QSPI_IF_H__ */
|
61
drivers/wifi/nrfwifi/src/qspi/inc/rpu_hw_if.h
Normal file
61
drivers/wifi/nrfwifi/src/qspi/inc/rpu_hw_if.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Header containing common functions for RPU hardware interaction
|
||||
* using QSPI and SPI that can be invoked by shell or the driver.
|
||||
*/
|
||||
|
||||
#ifndef __RPU_HW_IF_H_
|
||||
#define __RPU_HW_IF_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
|
||||
enum {
|
||||
SYSBUS = 0,
|
||||
EXT_SYS_BUS,
|
||||
PBUS,
|
||||
PKTRAM,
|
||||
GRAM,
|
||||
LMAC_ROM,
|
||||
LMAC_RET_RAM,
|
||||
LMAC_SRC_RAM,
|
||||
UMAC_ROM,
|
||||
UMAC_RET_RAM,
|
||||
UMAC_SRC_RAM,
|
||||
NUM_MEM_BLOCKS
|
||||
};
|
||||
|
||||
extern char blk_name[][15];
|
||||
extern uint32_t rpu_7002_memmap[][3];
|
||||
|
||||
int rpu_read(unsigned int addr, void *data, int len);
|
||||
int rpu_write(unsigned int addr, const void *data, int len);
|
||||
|
||||
int rpu_sleep(void);
|
||||
int rpu_wakeup(void);
|
||||
int rpu_sleep_status(void);
|
||||
void rpu_get_sleep_stats(uint32_t addr, uint32_t *buff, uint32_t wrd_len);
|
||||
int rpu_irq_config(struct gpio_callback *irq_callback_data, void (*irq_handler)());
|
||||
int rpu_irq_remove(struct gpio_callback *irq_callback_data);
|
||||
|
||||
int rpu_wrsr2(uint8_t data);
|
||||
int rpu_rdsr2(void);
|
||||
int rpu_rdsr1(void);
|
||||
int rpu_clks_on(void);
|
||||
|
||||
int rpu_init(void);
|
||||
int rpu_enable(void);
|
||||
int rpu_disable(void);
|
||||
|
||||
#ifdef CONFIG_NRF70_SR_COEX_RF_SWITCH
|
||||
int sr_ant_switch(unsigned int ant_switch);
|
||||
int sr_gpio_remove(void);
|
||||
int sr_gpio_config(void);
|
||||
#endif /* CONFIG_NRF70_SR_COEX_RF_SWITCH */
|
||||
#endif /* __RPU_HW_IF_H_ */
|
36
drivers/wifi/nrfwifi/src/qspi/inc/spi_if.h
Normal file
36
drivers/wifi/nrfwifi/src/qspi/inc/spi_if.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Header containing SPI device interface specific declarations for the
|
||||
* Zephyr OS layer of the Wi-Fi driver.
|
||||
*/
|
||||
|
||||
/* SPIM driver config */
|
||||
|
||||
int spim_init(struct qspi_config *config);
|
||||
|
||||
int spim_deinit(void);
|
||||
|
||||
int spim_write(unsigned int addr, const void *data, int len);
|
||||
|
||||
int spim_read(unsigned int addr, void *data, int len);
|
||||
|
||||
int spim_hl_read(unsigned int addr, void *data, int len);
|
||||
|
||||
int spim_cmd_rpu_wakeup_fn(uint32_t data);
|
||||
|
||||
int spim_wait_while_rpu_awake(void);
|
||||
|
||||
int spi_validate_rpu_wake_writecmd(void);
|
||||
|
||||
int spim_cmd_sleep_rpu_fn(void);
|
||||
|
||||
int spim_RDSR1(const struct device *dev, uint8_t *rdsr1);
|
||||
|
||||
int spim_RDSR2(const struct device *dev, uint8_t *rdsr2);
|
||||
|
||||
int spim_WRSR2(const struct device *dev, const uint8_t wrsr2);
|
49
drivers/wifi/nrfwifi/src/qspi/inc/spi_nor.h
Normal file
49
drivers/wifi/nrfwifi/src/qspi/inc/spi_nor.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Header containing SPI device specific declarations for the
|
||||
* Zephyr OS layer of the Wi-Fi driver.
|
||||
*/
|
||||
|
||||
#ifndef __SPI_NOR_H__
|
||||
#define __SPI_NOR_H__
|
||||
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
#define SPI_NOR_MAX_ID_LEN 3
|
||||
|
||||
/* Status register bits */
|
||||
#define SPI_NOR_WIP_BIT BIT(0) /* Write in progress */
|
||||
#define SPI_NOR_WEL_BIT BIT(1) /* Write enable latch */
|
||||
|
||||
/* Flash opcodes */
|
||||
#define SPI_NOR_CMD_WRSR 0x01 /* Write status register */
|
||||
#define SPI_NOR_CMD_RDSR 0x05 /* Read status register */
|
||||
#define SPI_NOR_CMD_READ 0x03 /* Read data */
|
||||
#define SPI_NOR_CMD_WREN 0x06 /* Write enable */
|
||||
#define SPI_NOR_CMD_WRDI 0x04 /* Write disable */
|
||||
#define SPI_NOR_CMD_PP 0x02 /* Page program */
|
||||
#define SPI_NOR_CMD_SE 0x20 /* Sector erase */
|
||||
#define SPI_NOR_CMD_BE_32K 0x52 /* Block erase 32KB */
|
||||
#define SPI_NOR_CMD_BE 0xD8 /* Block erase */
|
||||
#define SPI_NOR_CMD_CE 0xC7 /* Chip erase */
|
||||
#define SPI_NOR_CMD_RDID 0x9F /* Read JEDEC ID */
|
||||
#define SPI_NOR_CMD_ULBPR 0x98 /* Global Block Protection Unlock */
|
||||
#define SPI_NOR_CMD_4BA 0xB7 /* Enter 4-Byte Address Mode */
|
||||
#define SPI_NOR_CMD_DPD 0xB9 /* Deep Power Down */
|
||||
#define SPI_NOR_CMD_RDPD 0xAB /* Release from Deep Power Down */
|
||||
|
||||
/* Page, sector, and block size are standard, not configurable. */
|
||||
#define SPI_NOR_PAGE_SIZE 0x0100U
|
||||
#define SPI_NOR_SECTOR_SIZE 0x1000U
|
||||
#define SPI_NOR_BLOCK_SIZE 0x10000U
|
||||
|
||||
/* Test whether offset is aligned to a given number of bits. */
|
||||
#define SPI_NOR_IS_ALIGNED(_ofs, _bits) (((_ofs)&BIT_MASK(_bits)) == 0)
|
||||
#define SPI_NOR_IS_SECTOR_ALIGNED(_ofs) SPI_NOR_IS_ALIGNED(_ofs, 12)
|
||||
|
||||
#endif /*__SPI_NOR_H__*/
|
86
drivers/wifi/nrfwifi/src/qspi/src/device.c
Normal file
86
drivers/wifi/nrfwifi/src/qspi/src/device.c
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief File containing QSPI device specific definitions for the
|
||||
* Zephyr OS layer of the Wi-Fi driver.
|
||||
*/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/printk.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "qspi_if.h"
|
||||
#include "spi_if.h"
|
||||
|
||||
static struct qspi_config config;
|
||||
|
||||
#if defined(CONFIG_NRF70_ON_QSPI)
|
||||
static struct qspi_dev qspi = {
|
||||
.init = qspi_init,
|
||||
.deinit = qspi_deinit,
|
||||
.read = qspi_read,
|
||||
.write = qspi_write,
|
||||
.hl_read = qspi_hl_read
|
||||
};
|
||||
#else
|
||||
static struct qspi_dev spim = {
|
||||
.init = spim_init,
|
||||
.deinit = spim_deinit,
|
||||
.read = spim_read,
|
||||
.write = spim_write,
|
||||
.hl_read = spim_hl_read
|
||||
};
|
||||
#endif
|
||||
|
||||
struct qspi_config *qspi_defconfig(void)
|
||||
{
|
||||
memset(&config, 0, sizeof(struct qspi_config));
|
||||
#if defined(CONFIG_NRF70_ON_QSPI)
|
||||
config.addrmode = NRF_QSPI_ADDRMODE_24BIT;
|
||||
config.RDC4IO = 0xA0;
|
||||
config.easydma = true;
|
||||
config.quad_spi = true;
|
||||
#endif
|
||||
config.addrmask = 0x800000; /* set bit23 (incr. addr mode) */
|
||||
|
||||
config.test_name = "QSPI TEST";
|
||||
config.test_hlread = false;
|
||||
config.test_iteration = 0;
|
||||
|
||||
config.qspi_slave_latency = 0;
|
||||
|
||||
config.encryption = config.CMD_CNONCE = false;
|
||||
|
||||
#if defined(CONFIG_NRF70_ON_QSPI) && (NRF_QSPI_HAS_XIP_ENC || NRF_QSPI_HAS_DMA_ENC)
|
||||
|
||||
/*For #Bit 6 Enable below: i.e ALL Ones for QSPI Key*/
|
||||
memset(&config.p_cfg.key, 0xff, sizeof(config.p_cfg.key));
|
||||
|
||||
config.p_cfg.nonce[0] = 0x16181648;
|
||||
config.p_cfg.nonce[1] = 0x0;
|
||||
config.p_cfg.nonce[2] = 0x1;
|
||||
|
||||
#endif /*CONFIG_NRF70_ON_QSPI && (NRF_QSPI_HAS_XIP_ENC || NRF_QSPI_HAS_DMA_ENC)*/
|
||||
|
||||
return &config;
|
||||
}
|
||||
|
||||
struct qspi_config *qspi_get_config(void)
|
||||
{
|
||||
return &config;
|
||||
}
|
||||
|
||||
struct qspi_dev *qspi_dev(void)
|
||||
{
|
||||
#if CONFIG_NRF70_ON_QSPI
|
||||
return &qspi;
|
||||
#else
|
||||
return &spim;
|
||||
#endif
|
||||
}
|
379
drivers/wifi/nrfwifi/src/qspi/src/ficr_prog.c
Normal file
379
drivers/wifi/nrfwifi/src/qspi/src/ficr_prog.c
Normal file
|
@ -0,0 +1,379 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* @file
|
||||
* @brief NRF Wi-Fi radio FICR programming functions
|
||||
*/
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include "rpu_if.h"
|
||||
#include "rpu_hw_if.h"
|
||||
#include "ficr_prog.h"
|
||||
|
||||
|
||||
LOG_MODULE_DECLARE(otp_prog, CONFIG_WIFI_NRF70_BUS_LOG_LEVEL);
|
||||
|
||||
static void write_word(unsigned int addr, unsigned int data)
|
||||
{
|
||||
rpu_write(addr, &data, 4);
|
||||
}
|
||||
|
||||
static void read_word(unsigned int addr, unsigned int *data)
|
||||
{
|
||||
rpu_read(addr, data, 4);
|
||||
}
|
||||
|
||||
unsigned int check_protection(unsigned int *buff, unsigned int off1, unsigned int off2,
|
||||
unsigned int off3, unsigned int off4)
|
||||
{
|
||||
if ((buff[off1] == OTP_PROGRAMMED) &&
|
||||
(buff[off2] == OTP_PROGRAMMED) &&
|
||||
(buff[off3] == OTP_PROGRAMMED) &&
|
||||
(buff[off4] == OTP_PROGRAMMED))
|
||||
return OTP_PROGRAMMED;
|
||||
else if ((buff[off1] == OTP_FRESH_FROM_FAB) &&
|
||||
(buff[off2] == OTP_FRESH_FROM_FAB) &&
|
||||
(buff[off3] == OTP_FRESH_FROM_FAB) &&
|
||||
(buff[off4] == OTP_FRESH_FROM_FAB))
|
||||
return OTP_FRESH_FROM_FAB;
|
||||
else if ((buff[off1] == OTP_ENABLE_PATTERN) &&
|
||||
(buff[off2] == OTP_ENABLE_PATTERN) &&
|
||||
(buff[off3] == OTP_ENABLE_PATTERN) &&
|
||||
(buff[off4] == OTP_ENABLE_PATTERN))
|
||||
return OTP_ENABLE_PATTERN;
|
||||
else
|
||||
return OTP_INVALID;
|
||||
}
|
||||
|
||||
|
||||
static void set_otp_timing_reg_40mhz(void)
|
||||
{
|
||||
write_word(OTP_TIMING_REG1_ADDR, OTP_TIMING_REG1_VAL);
|
||||
write_word(OTP_TIMING_REG2_ADDR, OTP_TIMING_REG2_VAL);
|
||||
}
|
||||
|
||||
static int poll_otp_ready(void)
|
||||
{
|
||||
int otp_mem_status = 0;
|
||||
int poll = 0;
|
||||
|
||||
while (poll != 100) {
|
||||
read_word(OTP_POLL_ADDR, &otp_mem_status);
|
||||
|
||||
if ((otp_mem_status & OTP_READY) == OTP_READY) {
|
||||
return 0;
|
||||
}
|
||||
poll++;
|
||||
}
|
||||
LOG_ERR("OTP is not ready");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
|
||||
static int req_otp_standby_mode(void)
|
||||
{
|
||||
write_word(OTP_RWSBMODE_ADDR, 0x0);
|
||||
return poll_otp_ready();
|
||||
}
|
||||
|
||||
|
||||
static int otp_wr_voltage_2V5(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = req_otp_standby_mode();
|
||||
|
||||
if (err) {
|
||||
LOG_ERR("Failed Setting OTP voltage IOVDD to 2.5V");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
write_word(OTP_VOLTCTRL_ADDR, OTP_VOLTCTRL_2V5);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int poll_otp_read_valid(void)
|
||||
{
|
||||
int otp_mem_status = 0;
|
||||
int poll = 0;
|
||||
|
||||
while (poll < 100) {
|
||||
read_word(OTP_POLL_ADDR, &otp_mem_status);
|
||||
|
||||
if ((otp_mem_status & OTP_READ_VALID) == OTP_READ_VALID) {
|
||||
return 0;
|
||||
}
|
||||
poll++;
|
||||
}
|
||||
LOG_ERR("%s: OTP read failed", __func__);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
static int poll_otp_wrdone(void)
|
||||
{
|
||||
int otp_mem_status = 0;
|
||||
int poll = 0;
|
||||
|
||||
while (poll < 100) {
|
||||
read_word(OTP_POLL_ADDR, &otp_mem_status);
|
||||
|
||||
if ((otp_mem_status & OTP_WR_DONE) == OTP_WR_DONE) {
|
||||
return 0;
|
||||
}
|
||||
poll++;
|
||||
}
|
||||
LOG_ERR("%s: OTP write done failed", __func__);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
static int req_otp_read_mode(void)
|
||||
{
|
||||
write_word(OTP_RWSBMODE_ADDR, OTP_READ_MODE);
|
||||
return poll_otp_ready();
|
||||
}
|
||||
|
||||
|
||||
static int req_otp_byte_write_mode(void)
|
||||
{
|
||||
write_word(OTP_RWSBMODE_ADDR, OTP_BYTE_WRITE_MODE);
|
||||
return poll_otp_ready();
|
||||
}
|
||||
|
||||
static unsigned int read_otp_location(unsigned int offset, unsigned int *read_val)
|
||||
{
|
||||
int err;
|
||||
|
||||
write_word(OTP_RDENABLE_ADDR, offset);
|
||||
err = poll_otp_read_valid();
|
||||
if (err) {
|
||||
LOG_ERR("OTP read failed");
|
||||
return err;
|
||||
}
|
||||
read_word(OTP_READREG_ADDR, read_val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_otp_location(unsigned int otp_location_offset, unsigned int otp_data)
|
||||
{
|
||||
write_word(OTP_WRENABLE_ADDR, otp_location_offset);
|
||||
write_word(OTP_WRITEREG_ADDR, otp_data);
|
||||
|
||||
return poll_otp_wrdone();
|
||||
}
|
||||
|
||||
|
||||
static int otp_rd_voltage_1V8(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = req_otp_standby_mode();
|
||||
if (err) {
|
||||
LOG_ERR("error in %s", __func__);
|
||||
return err;
|
||||
}
|
||||
write_word(OTP_VOLTCTRL_ADDR, OTP_VOLTCTRL_1V8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int update_mac_addr(unsigned int index, unsigned int *write_val)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
ret = write_otp_location(MAC0_ADDR + 2 * index + i, write_val[i]);
|
||||
if (ret == -ENOEXEC) {
|
||||
LOG_ERR("FICR: Failed to update MAC ADDR%d", index);
|
||||
break;
|
||||
}
|
||||
LOG_INF("mac addr %d : Reg%d (0x%x) = 0x%04x",
|
||||
index, (i+1), (MAC0_ADDR + i) << 2, write_val[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int write_otp_memory(unsigned int otp_addr, unsigned int *write_val)
|
||||
{
|
||||
int err = 0;
|
||||
int mask_val;
|
||||
int ret = 0;
|
||||
int retrim_loc = 0;
|
||||
|
||||
err = poll_otp_ready();
|
||||
if (err) {
|
||||
LOG_ERR("err in otp ready poll");
|
||||
return err;
|
||||
}
|
||||
|
||||
set_otp_timing_reg_40mhz();
|
||||
|
||||
err = otp_wr_voltage_2V5();
|
||||
if (err) {
|
||||
LOG_ERR("error in write_voltage 2V5");
|
||||
goto _exit_otp_write;
|
||||
}
|
||||
|
||||
err = req_otp_byte_write_mode();
|
||||
if (err) {
|
||||
LOG_ERR("error in OTP byte write mode");
|
||||
goto _exit_otp_write;
|
||||
}
|
||||
|
||||
switch (otp_addr) {
|
||||
case REGION_PROTECT:
|
||||
write_otp_location(REGION_PROTECT, write_val[0]);
|
||||
write_otp_location(REGION_PROTECT+1, write_val[0]);
|
||||
write_otp_location(REGION_PROTECT+2, write_val[0]);
|
||||
write_otp_location(REGION_PROTECT+3, write_val[0]);
|
||||
|
||||
LOG_INF("Written REGION_PROTECT0 (0x%x) : 0x%04x",
|
||||
(REGION_PROTECT << 2), write_val[0]);
|
||||
LOG_INF("Written REGION_PROTECT1 (0x%x) : 0x%04x",
|
||||
(REGION_PROTECT+1) << 2, write_val[0]);
|
||||
LOG_INF("Written REGION_PROTECT2 (0x%x) : 0x%04x",
|
||||
(REGION_PROTECT+2) << 2, write_val[0]);
|
||||
LOG_INF("Written REGION_PROTECT3 (0x%x) : 0x%04x",
|
||||
(REGION_PROTECT+3) << 2, write_val[0]);
|
||||
break;
|
||||
case QSPI_KEY:
|
||||
mask_val = QSPI_KEY_FLAG_MASK;
|
||||
for (int i = 0; i < QSPI_KEY_LENGTH_BYTES / 4; i++) {
|
||||
ret = write_otp_location(QSPI_KEY + i, write_val[i]);
|
||||
if (ret == -ENOEXEC) {
|
||||
LOG_ERR("FICR: Failed to write QSPI key offset-%d", QSPI_KEY + i);
|
||||
goto _exit_otp_write;
|
||||
}
|
||||
LOG_INF("Written QSPI_KEY0 (0x%x) : 0x%04x",
|
||||
(QSPI_KEY + i) << 2, write_val[i]);
|
||||
}
|
||||
write_otp_location(REGION_DEFAULTS, mask_val);
|
||||
LOG_INF("Written REGION_DEFAULTS (0x%x) : 0x%04x",
|
||||
(REGION_DEFAULTS) << 2, mask_val);
|
||||
break;
|
||||
case MAC0_ADDR:
|
||||
mask_val = MAC0_ADDR_FLAG_MASK;
|
||||
ret = update_mac_addr(0, write_val);
|
||||
if (ret == -ENOEXEC) {
|
||||
goto _exit_otp_write;
|
||||
}
|
||||
|
||||
write_otp_location(REGION_DEFAULTS, mask_val);
|
||||
LOG_INF("Written MAC address 0");
|
||||
LOG_INF("Written REGION_DEFAULTS (0x%x) : 0x%04x",
|
||||
(REGION_DEFAULTS) << 2, mask_val);
|
||||
break;
|
||||
case MAC1_ADDR:
|
||||
mask_val = MAC1_ADDR_FLAG_MASK;
|
||||
ret = update_mac_addr(1, write_val);
|
||||
if (ret == -ENOEXEC) {
|
||||
goto _exit_otp_write;
|
||||
}
|
||||
write_otp_location(REGION_DEFAULTS, mask_val);
|
||||
LOG_INF("Written MAC address 1");
|
||||
LOG_INF("Written REGION_DEFAULTS (0x%x) : 0x%04x",
|
||||
(REGION_DEFAULTS) << 2, mask_val);
|
||||
break;
|
||||
case CALIB_XO:
|
||||
mask_val = CALIB_XO_FLAG_MASK;
|
||||
ret = write_otp_location(CALIB_XO, write_val[0]);
|
||||
|
||||
if (ret == -ENOEXEC) {
|
||||
LOG_ERR("XO_Update Exception");
|
||||
goto _exit_otp_write;
|
||||
} else {
|
||||
write_otp_location(REGION_DEFAULTS, mask_val);
|
||||
|
||||
LOG_INF("Written CALIB_XO (0x%x) to 0x%04x",
|
||||
CALIB_XO << 2, write_val[0]);
|
||||
LOG_INF("Written REGION_DEFAULTS (0x%x) : 0x%04x",
|
||||
(REGION_DEFAULTS) << 2, mask_val);
|
||||
}
|
||||
break;
|
||||
case PRODRETEST_PROGVERSION:
|
||||
ret = write_otp_location(PRODRETEST_PROGVERSION, *write_val);
|
||||
|
||||
if (ret == -ENOEXEC) {
|
||||
LOG_ERR("PRODRETEST.PROGVERSION_Update Exception");
|
||||
goto _exit_otp_write;
|
||||
} else {
|
||||
LOG_INF("Written PRODRETEST.PROGVERSION 0x%04x", *write_val);
|
||||
}
|
||||
break;
|
||||
case PRODRETEST_TRIM0:
|
||||
case PRODRETEST_TRIM1:
|
||||
case PRODRETEST_TRIM2:
|
||||
case PRODRETEST_TRIM3:
|
||||
case PRODRETEST_TRIM4:
|
||||
case PRODRETEST_TRIM5:
|
||||
case PRODRETEST_TRIM6:
|
||||
case PRODRETEST_TRIM7:
|
||||
case PRODRETEST_TRIM8:
|
||||
case PRODRETEST_TRIM9:
|
||||
case PRODRETEST_TRIM10:
|
||||
case PRODRETEST_TRIM11:
|
||||
case PRODRETEST_TRIM12:
|
||||
case PRODRETEST_TRIM13:
|
||||
case PRODRETEST_TRIM14:
|
||||
retrim_loc = otp_addr - PRODRETEST_TRIM0;
|
||||
ret = write_otp_location(otp_addr, *write_val);
|
||||
|
||||
if (ret == -ENOEXEC) {
|
||||
LOG_ERR("PRODRETEST.TRIM_Update Exception");
|
||||
goto _exit_otp_write;
|
||||
} else {
|
||||
LOG_INF("Written PRODRETEST.TRIM%d 0x%04x",
|
||||
retrim_loc, *write_val);
|
||||
}
|
||||
break;
|
||||
case REGION_DEFAULTS:
|
||||
write_otp_location(REGION_DEFAULTS, write_val[0]);
|
||||
|
||||
LOG_INF("Written REGION_DEFAULTS (0x%x) to 0x%04x",
|
||||
REGION_DEFAULTS << 2, write_val[0]);
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("unknown field received: %d", otp_addr);
|
||||
|
||||
}
|
||||
return ret;
|
||||
|
||||
_exit_otp_write:
|
||||
err = req_otp_standby_mode();
|
||||
err |= otp_rd_voltage_1V8();
|
||||
return err;
|
||||
}
|
||||
|
||||
int read_otp_memory(unsigned int otp_addr, unsigned int *read_val, int len)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = poll_otp_ready();
|
||||
if (err) {
|
||||
LOG_ERR("err in otp ready poll");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
set_otp_timing_reg_40mhz();
|
||||
|
||||
err = otp_rd_voltage_1V8();
|
||||
if (err) {
|
||||
LOG_ERR("error in read_voltage 1V8");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
err = req_otp_read_mode();
|
||||
if (err) {
|
||||
LOG_ERR("error in req_otp_read_mode()");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
read_otp_location(otp_addr + i, &read_val[i]);
|
||||
}
|
||||
|
||||
return req_otp_standby_mode();
|
||||
}
|
1327
drivers/wifi/nrfwifi/src/qspi/src/qspi_if.c
Normal file
1327
drivers/wifi/nrfwifi/src/qspi/src/qspi_if.c
Normal file
File diff suppressed because it is too large
Load diff
489
drivers/wifi/nrfwifi/src/qspi/src/rpu_hw_if.c
Normal file
489
drivers/wifi/nrfwifi/src/qspi/src/rpu_hw_if.c
Normal file
|
@ -0,0 +1,489 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief File containing common functions for RPU hardware interaction
|
||||
* using QSPI and SPI that can be invoked by shell or the driver.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/printk.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
#include <zephyr/dt-bindings/gpio/nordic-nrf-gpio.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "rpu_hw_if.h"
|
||||
#include "qspi_if.h"
|
||||
#include "spi_if.h"
|
||||
|
||||
LOG_MODULE_REGISTER(wifi_nrf_bus, CONFIG_WIFI_NRF70_BUS_LOG_LEVEL);
|
||||
|
||||
#define NRF7002_NODE DT_NODELABEL(nrf70)
|
||||
|
||||
static const struct gpio_dt_spec host_irq_spec =
|
||||
GPIO_DT_SPEC_GET(NRF7002_NODE, host_irq_gpios);
|
||||
|
||||
static const struct gpio_dt_spec iovdd_ctrl_spec =
|
||||
GPIO_DT_SPEC_GET(NRF7002_NODE, iovdd_ctrl_gpios);
|
||||
|
||||
static const struct gpio_dt_spec bucken_spec =
|
||||
GPIO_DT_SPEC_GET(NRF7002_NODE, bucken_gpios);
|
||||
|
||||
char blk_name[][15] = { "SysBus", "ExtSysBus", "PBus", "PKTRAM",
|
||||
"GRAM", "LMAC_ROM", "LMAC_RET_RAM", "LMAC_SRC_RAM",
|
||||
"UMAC_ROM", "UMAC_RET_RAM", "UMAC_SRC_RAM" };
|
||||
|
||||
uint32_t rpu_7002_memmap[][3] = {
|
||||
{ 0x000000, 0x008FFF, 1 },
|
||||
{ 0x009000, 0x03FFFF, 2 },
|
||||
{ 0x040000, 0x07FFFF, 1 },
|
||||
{ 0x0C0000, 0x0F0FFF, 0 },
|
||||
{ 0x080000, 0x092000, 1 },
|
||||
{ 0x100000, 0x134000, 1 },
|
||||
{ 0x140000, 0x14C000, 1 },
|
||||
{ 0x180000, 0x190000, 1 },
|
||||
{ 0x200000, 0x261800, 1 },
|
||||
{ 0x280000, 0x2A4000, 1 },
|
||||
{ 0x300000, 0x338000, 1 }
|
||||
};
|
||||
|
||||
static const struct qspi_dev *qdev;
|
||||
static struct qspi_config *cfg;
|
||||
|
||||
static int validate_addr_blk(uint32_t start_addr,
|
||||
uint32_t end_addr,
|
||||
uint32_t block_no,
|
||||
bool *hl_flag,
|
||||
int *selected_blk)
|
||||
{
|
||||
uint32_t *block_map = rpu_7002_memmap[block_no];
|
||||
|
||||
if (((start_addr >= block_map[0]) && (start_addr <= block_map[1])) &&
|
||||
((end_addr >= block_map[0]) && (end_addr <= block_map[1]))) {
|
||||
if (block_no == PKTRAM) {
|
||||
*hl_flag = 0;
|
||||
}
|
||||
*selected_blk = block_no;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int rpu_validate_addr(uint32_t start_addr, uint32_t len, bool *hl_flag)
|
||||
{
|
||||
int ret = 0, i;
|
||||
uint32_t end_addr;
|
||||
int selected_blk;
|
||||
|
||||
end_addr = start_addr + len - 1;
|
||||
|
||||
*hl_flag = 1;
|
||||
|
||||
for (i = 0; i < NUM_MEM_BLOCKS; i++) {
|
||||
ret = validate_addr_blk(start_addr, end_addr, i, hl_flag, &selected_blk);
|
||||
if (!ret) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
LOG_ERR("Address validation failed - pls check memmory map and re-try");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((selected_blk == LMAC_ROM) || (selected_blk == UMAC_ROM)) {
|
||||
LOG_ERR("Error: Cannot write to ROM blocks");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cfg->qspi_slave_latency = (*hl_flag) ? rpu_7002_memmap[selected_blk][2] : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rpu_irq_config(struct gpio_callback *irq_callback_data, void (*irq_handler)())
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!device_is_ready(host_irq_spec.port)) {
|
||||
LOG_ERR("Host IRQ GPIO %s is not ready", host_irq_spec.port->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = gpio_pin_configure_dt(&host_irq_spec, GPIO_INPUT);
|
||||
if (ret) {
|
||||
LOG_ERR("Failed to configure host_irq pin %d", host_irq_spec.pin);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = gpio_pin_interrupt_configure_dt(&host_irq_spec,
|
||||
GPIO_INT_EDGE_TO_ACTIVE);
|
||||
if (ret) {
|
||||
LOG_ERR("Failed to configure interrupt on host_irq pin %d",
|
||||
host_irq_spec.pin);
|
||||
goto out;
|
||||
}
|
||||
|
||||
gpio_init_callback(irq_callback_data,
|
||||
irq_handler,
|
||||
BIT(host_irq_spec.pin));
|
||||
|
||||
ret = gpio_add_callback(host_irq_spec.port, irq_callback_data);
|
||||
if (ret) {
|
||||
LOG_ERR("Failed to add callback on host_irq pin %d",
|
||||
host_irq_spec.pin);
|
||||
goto out;
|
||||
}
|
||||
|
||||
LOG_DBG("Finished Interrupt config\n");
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rpu_irq_remove(struct gpio_callback *irq_callback_data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpio_pin_configure_dt(&host_irq_spec, GPIO_DISCONNECTED);
|
||||
if (ret) {
|
||||
LOG_ERR("Failed to remove host_irq pin %d", host_irq_spec.pin);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = gpio_remove_callback(host_irq_spec.port, irq_callback_data);
|
||||
if (ret) {
|
||||
LOG_ERR("Failed to remove callback on host_irq pin %d",
|
||||
host_irq_spec.pin);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rpu_gpio_config(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!device_is_ready(iovdd_ctrl_spec.port)) {
|
||||
LOG_ERR("IOVDD GPIO %s is not ready", iovdd_ctrl_spec.port->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!device_is_ready(bucken_spec.port)) {
|
||||
LOG_ERR("BUCKEN GPIO %s is not ready", bucken_spec.port->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = gpio_pin_configure_dt(&bucken_spec, (GPIO_OUTPUT | NRF_GPIO_DRIVE_H0H1));
|
||||
if (ret) {
|
||||
LOG_ERR("BUCKEN GPIO configuration failed...");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpio_pin_configure_dt(&iovdd_ctrl_spec, GPIO_OUTPUT);
|
||||
if (ret) {
|
||||
LOG_ERR("IOVDD GPIO configuration failed...");
|
||||
gpio_pin_configure_dt(&bucken_spec, GPIO_DISCONNECTED);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LOG_DBG("GPIO configuration done...\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rpu_gpio_remove(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpio_pin_configure_dt(&bucken_spec, GPIO_DISCONNECTED);
|
||||
if (ret) {
|
||||
LOG_ERR("BUCKEN GPIO remove failed...");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpio_pin_configure_dt(&iovdd_ctrl_spec, GPIO_DISCONNECTED);
|
||||
if (ret) {
|
||||
LOG_ERR("IOVDD GPIO remove failed...");
|
||||
return ret;
|
||||
}
|
||||
|
||||
LOG_DBG("GPIO remove done...\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rpu_pwron(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpio_pin_set_dt(&bucken_spec, 1);
|
||||
if (ret) {
|
||||
LOG_ERR("BUCKEN GPIO set failed...");
|
||||
return ret;
|
||||
}
|
||||
/* Settling time is 50us (H0) or 100us (L0) */
|
||||
k_msleep(1);
|
||||
|
||||
ret = gpio_pin_set_dt(&iovdd_ctrl_spec, 1);
|
||||
if (ret) {
|
||||
LOG_ERR("IOVDD GPIO set failed...");
|
||||
gpio_pin_set_dt(&bucken_spec, 0);
|
||||
return ret;
|
||||
}
|
||||
/* Settling time for iovdd nRF7002 DK/EK - switch (TCK106AG): ~600us */
|
||||
k_msleep(1);
|
||||
|
||||
if (IS_ENABLED(CONFIG_NRF_WIFI_COMBINED_BUCKEN_IOVDD_GPIO)) {
|
||||
/* When a single GPIO is used, we need a total wait time after bucken assertion
|
||||
* to be 6ms (1ms + 1ms + 4ms).
|
||||
*/
|
||||
k_msleep(4);
|
||||
}
|
||||
|
||||
LOG_DBG("Bucken = %d, IOVDD = %d", gpio_pin_get_dt(&bucken_spec),
|
||||
gpio_pin_get_dt(&iovdd_ctrl_spec));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rpu_pwroff(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpio_pin_set_dt(&bucken_spec, 0); /* BUCKEN = 0 */
|
||||
if (ret) {
|
||||
LOG_ERR("BUCKEN GPIO set failed...");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpio_pin_set_dt(&iovdd_ctrl_spec, 0); /* IOVDD CNTRL = 0 */
|
||||
if (ret) {
|
||||
LOG_ERR("IOVDD GPIO set failed...");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rpu_read(unsigned int addr, void *data, int len)
|
||||
{
|
||||
bool hl_flag;
|
||||
|
||||
if (rpu_validate_addr(addr, len, &hl_flag)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hl_flag)
|
||||
return qdev->hl_read(addr, data, len);
|
||||
else
|
||||
return qdev->read(addr, data, len);
|
||||
}
|
||||
|
||||
int rpu_write(unsigned int addr, const void *data, int len)
|
||||
{
|
||||
bool hl_flag;
|
||||
|
||||
if (rpu_validate_addr(addr, len, &hl_flag)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return qdev->write(addr, data, len);
|
||||
}
|
||||
|
||||
int rpu_sleep(void)
|
||||
{
|
||||
#if CONFIG_NRF70_ON_QSPI
|
||||
return qspi_cmd_sleep_rpu(&qspi_perip);
|
||||
#else
|
||||
return spim_cmd_sleep_rpu_fn();
|
||||
#endif
|
||||
}
|
||||
|
||||
int rpu_wakeup(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rpu_wrsr2(1);
|
||||
if (ret) {
|
||||
LOG_ERR("Error: WRSR2 failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rpu_rdsr2();
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Error: RDSR2 failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rpu_rdsr1();
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Error: RDSR1 failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rpu_sleep_status(void)
|
||||
{
|
||||
return rpu_rdsr1();
|
||||
}
|
||||
|
||||
void rpu_get_sleep_stats(uint32_t addr, uint32_t *buff, uint32_t wrd_len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rpu_wakeup();
|
||||
if (ret) {
|
||||
LOG_ERR("Error: RPU wakeup failed");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = rpu_read(addr, buff, wrd_len * 4);
|
||||
if (ret) {
|
||||
LOG_ERR("Error: RPU read failed");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = rpu_sleep();
|
||||
if (ret) {
|
||||
LOG_ERR("Error: RPU sleep failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int rpu_wrsr2(uint8_t data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if CONFIG_NRF70_ON_QSPI
|
||||
ret = qspi_cmd_wakeup_rpu(&qspi_perip, data);
|
||||
#else
|
||||
ret = spim_cmd_rpu_wakeup_fn(data);
|
||||
#endif
|
||||
|
||||
LOG_DBG("Written 0x%x to WRSR2", data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rpu_rdsr2(void)
|
||||
{
|
||||
#if CONFIG_NRF70_ON_QSPI
|
||||
return qspi_validate_rpu_wake_writecmd(&qspi_perip);
|
||||
#else
|
||||
return spi_validate_rpu_wake_writecmd();
|
||||
#endif
|
||||
}
|
||||
|
||||
int rpu_rdsr1(void)
|
||||
{
|
||||
#if CONFIG_NRF70_ON_QSPI
|
||||
return qspi_wait_while_rpu_awake(&qspi_perip);
|
||||
#else
|
||||
return spim_wait_while_rpu_awake();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int rpu_clks_on(void)
|
||||
{
|
||||
uint32_t rpu_clks = 0x100;
|
||||
/* Enable RPU Clocks */
|
||||
qdev->write(0x048C20, &rpu_clks, 4);
|
||||
LOG_DBG("RPU Clocks ON...");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rpu_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
qdev = qspi_dev();
|
||||
cfg = qspi_get_config();
|
||||
|
||||
ret = rpu_gpio_config();
|
||||
if (ret) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NRF70_SR_COEX_RF_SWITCH
|
||||
ret = sr_gpio_config();
|
||||
if (ret) {
|
||||
goto remove_rpu_gpio;
|
||||
}
|
||||
#endif
|
||||
ret = rpu_pwron();
|
||||
if (ret) {
|
||||
#ifdef CONFIG_NRF70_SR_COEX_RF_SWITCH
|
||||
goto remove_sr_gpio;
|
||||
#else
|
||||
goto remove_rpu_gpio;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_NRF70_SR_COEX_RF_SWITCH
|
||||
remove_sr_gpio:
|
||||
sr_gpio_remove();
|
||||
#endif
|
||||
remove_rpu_gpio:
|
||||
rpu_gpio_remove();
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rpu_enable(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rpu_wakeup();
|
||||
if (ret) {
|
||||
goto rpu_pwroff;
|
||||
}
|
||||
|
||||
ret = rpu_clks_on();
|
||||
if (ret) {
|
||||
goto rpu_pwroff;
|
||||
}
|
||||
|
||||
return 0;
|
||||
rpu_pwroff:
|
||||
rpu_pwroff();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rpu_disable(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rpu_pwroff();
|
||||
if (ret) {
|
||||
goto out;
|
||||
}
|
||||
ret = rpu_gpio_remove();
|
||||
if (ret) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NRF70_SR_COEX_RF_SWITCH
|
||||
ret = sr_gpio_remove();
|
||||
if (ret) {
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
qdev = NULL;
|
||||
cfg = NULL;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
343
drivers/wifi/nrfwifi/src/qspi/src/spi_if.c
Normal file
343
drivers/wifi/nrfwifi/src/qspi/src/spi_if.c
Normal file
|
@ -0,0 +1,343 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief File containing SPI device interface specific definitions for the
|
||||
* Zephyr OS layer of the Wi-Fi driver.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <zephyr/drivers/spi.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "qspi_if.h"
|
||||
#include "spi_if.h"
|
||||
|
||||
LOG_MODULE_DECLARE(wifi_nrf_bus, CONFIG_WIFI_NRF70_BUS_LOG_LEVEL);
|
||||
|
||||
#define NRF7002_NODE DT_NODELABEL(nrf70)
|
||||
|
||||
static struct qspi_config *spim_config;
|
||||
|
||||
static const struct spi_dt_spec spi_spec =
|
||||
SPI_DT_SPEC_GET(NRF7002_NODE, SPI_WORD_SET(8) | SPI_TRANSFER_MSB, 0);
|
||||
|
||||
static int spim_xfer_tx(unsigned int addr, void *data, unsigned int len)
|
||||
{
|
||||
int err;
|
||||
uint8_t hdr[4] = {
|
||||
0x02, /* PP opcode */
|
||||
(((addr >> 16) & 0xFF) | 0x80),
|
||||
(addr >> 8) & 0xFF,
|
||||
(addr & 0xFF)
|
||||
};
|
||||
|
||||
const struct spi_buf tx_buf[] = {
|
||||
{.buf = hdr, .len = sizeof(hdr) },
|
||||
{.buf = data, .len = len },
|
||||
};
|
||||
const struct spi_buf_set tx = { .buffers = tx_buf, .count = 2 };
|
||||
|
||||
|
||||
err = spi_transceive_dt(&spi_spec, &tx, NULL);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int spim_xfer_rx(unsigned int addr, void *data, unsigned int len, unsigned int discard_bytes)
|
||||
{
|
||||
uint8_t hdr[] = {
|
||||
0x0b, /* FASTREAD opcode */
|
||||
(addr >> 16) & 0xFF,
|
||||
(addr >> 8) & 0xFF,
|
||||
addr & 0xFF,
|
||||
0 /* dummy byte */
|
||||
};
|
||||
|
||||
const struct spi_buf tx_buf[] = {
|
||||
{.buf = hdr, .len = sizeof(hdr) },
|
||||
{.buf = NULL, .len = len },
|
||||
};
|
||||
|
||||
const struct spi_buf_set tx = { .buffers = tx_buf, .count = 2 };
|
||||
|
||||
const struct spi_buf rx_buf[] = {
|
||||
{.buf = NULL, .len = sizeof(hdr) + discard_bytes},
|
||||
{.buf = data, .len = len },
|
||||
};
|
||||
|
||||
const struct spi_buf_set rx = { .buffers = rx_buf, .count = 2 };
|
||||
|
||||
return spi_transceive_dt(&spi_spec, &tx, &rx);
|
||||
}
|
||||
|
||||
int spim_read_reg(uint32_t reg_addr, uint8_t *reg_value)
|
||||
{
|
||||
int err;
|
||||
uint8_t tx_buffer[6] = { reg_addr };
|
||||
|
||||
const struct spi_buf tx_buf = {
|
||||
.buf = tx_buffer,
|
||||
.len = sizeof(tx_buffer)
|
||||
};
|
||||
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = &tx_buf,
|
||||
.count = 1
|
||||
};
|
||||
|
||||
uint8_t sr[6];
|
||||
|
||||
struct spi_buf rx_buf = {
|
||||
.buf = &sr,
|
||||
.len = sizeof(sr),
|
||||
};
|
||||
const struct spi_buf_set rx = { .buffers = &rx_buf, .count = 1 };
|
||||
|
||||
err = spi_transceive_dt(&spi_spec, &tx, &rx);
|
||||
|
||||
LOG_DBG("err: %d -> %x %x %x %x %x %x", err, sr[0], sr[1], sr[2], sr[3], sr[4], sr[5]);
|
||||
|
||||
if (err == 0)
|
||||
*reg_value = sr[1];
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int spim_write_reg(uint32_t reg_addr, const uint8_t reg_value)
|
||||
{
|
||||
int err;
|
||||
uint8_t tx_buffer[] = { reg_addr, reg_value };
|
||||
|
||||
const struct spi_buf tx_buf = { .buf = tx_buffer, .len = sizeof(tx_buffer) };
|
||||
const struct spi_buf_set tx = { .buffers = &tx_buf, .count = 1 };
|
||||
|
||||
err = spi_transceive_dt(&spi_spec, &tx, NULL);
|
||||
|
||||
if (err) {
|
||||
LOG_ERR("SPI error: %d", err);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int spim_RDSR1(const struct device *dev, uint8_t *rdsr1)
|
||||
{
|
||||
uint8_t val = 0;
|
||||
|
||||
return spim_read_reg(0x1F, &val);
|
||||
}
|
||||
|
||||
int spim_RDSR2(const struct device *dev, uint8_t *rdsr1)
|
||||
{
|
||||
uint8_t val = 0;
|
||||
|
||||
return spim_read_reg(0x2F, &val);
|
||||
}
|
||||
|
||||
int spim_WRSR2(const struct device *dev, const uint8_t wrsr2)
|
||||
{
|
||||
return spim_write_reg(0x3F, wrsr2);
|
||||
}
|
||||
|
||||
int _spim_wait_while_rpu_awake(void)
|
||||
{
|
||||
int ret;
|
||||
uint8_t val = 0;
|
||||
|
||||
for (int ii = 0; ii < 10; ii++) {
|
||||
|
||||
ret = spim_read_reg(0x1F, &val);
|
||||
|
||||
LOG_DBG("RDSR1 = 0x%x", val);
|
||||
|
||||
if (!ret && (val & RPU_AWAKE_BIT)) {
|
||||
break;
|
||||
}
|
||||
|
||||
k_msleep(1);
|
||||
}
|
||||
|
||||
if (ret || !(val & RPU_AWAKE_BIT)) {
|
||||
LOG_ERR("RPU is not awake even after 10ms");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Wait until RDSR2 confirms RPU_WAKEUP_NOW write is successful */
|
||||
int spim_wait_while_rpu_wake_write(void)
|
||||
{
|
||||
int ret;
|
||||
uint8_t val = 0;
|
||||
|
||||
for (int ii = 0; ii < 10; ii++) {
|
||||
|
||||
ret = spim_read_reg(0x2F, &val);
|
||||
|
||||
LOG_DBG("RDSR2 = 0x%x", val);
|
||||
|
||||
if (!ret && (val & RPU_WAKEUP_NOW)) {
|
||||
break;
|
||||
}
|
||||
|
||||
k_msleep(1);
|
||||
}
|
||||
|
||||
if (ret || !(val & RPU_WAKEUP_NOW)) {
|
||||
LOG_ERR("RPU wakeup write ACK failed even after 10ms");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int spim_cmd_rpu_wakeup(uint32_t data)
|
||||
{
|
||||
return spim_write_reg(0x3F, data);
|
||||
}
|
||||
|
||||
unsigned int spim_cmd_sleep_rpu(void)
|
||||
{
|
||||
int err;
|
||||
uint8_t tx_buffer[] = { 0x3f, 0x0 };
|
||||
|
||||
const struct spi_buf tx_buf = { .buf = tx_buffer, .len = sizeof(tx_buffer) };
|
||||
const struct spi_buf_set tx = { .buffers = &tx_buf, .count = 1 };
|
||||
|
||||
err = spi_transceive_dt(&spi_spec, &tx, NULL);
|
||||
|
||||
if (err) {
|
||||
LOG_ERR("SPI error: %d", err);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spim_init(struct qspi_config *config)
|
||||
{
|
||||
if (!spi_is_ready_dt(&spi_spec)) {
|
||||
LOG_ERR("Device %s is not ready", spi_spec.bus->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
spim_config = config;
|
||||
|
||||
k_sem_init(&spim_config->lock, 1, 1);
|
||||
|
||||
if (spi_spec.config.frequency >= MHZ(16)) {
|
||||
spim_config->qspi_slave_latency = 1;
|
||||
}
|
||||
|
||||
LOG_INF("SPIM %s: freq = %d MHz", spi_spec.bus->name,
|
||||
spi_spec.config.frequency / MHZ(1));
|
||||
LOG_INF("SPIM %s: latency = %d", spi_spec.bus->name, spim_config->qspi_slave_latency);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spim_deinit(void)
|
||||
{
|
||||
LOG_DBG("TODO : %s", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spim_addr_check(unsigned int addr, const void *data, unsigned int len)
|
||||
{
|
||||
if ((addr % 4 != 0) || (((unsigned int)data) % 4 != 0) || (len % 4 != 0)) {
|
||||
LOG_ERR("%s : Unaligned address %x %x %d %x %x", __func__, addr,
|
||||
(unsigned int)data, (addr % 4 != 0), (((unsigned int)data) % 4 != 0),
|
||||
(len % 4 != 0));
|
||||
}
|
||||
}
|
||||
|
||||
int spim_write(unsigned int addr, const void *data, int len)
|
||||
{
|
||||
int status;
|
||||
|
||||
spim_addr_check(addr, data, len);
|
||||
|
||||
addr |= spim_config->addrmask;
|
||||
|
||||
k_sem_take(&spim_config->lock, K_FOREVER);
|
||||
|
||||
status = spim_xfer_tx(addr, (void *)data, len);
|
||||
|
||||
k_sem_give(&spim_config->lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int spim_read(unsigned int addr, void *data, int len)
|
||||
{
|
||||
int status;
|
||||
|
||||
spim_addr_check(addr, data, len);
|
||||
|
||||
addr |= spim_config->addrmask;
|
||||
|
||||
k_sem_take(&spim_config->lock, K_FOREVER);
|
||||
|
||||
status = spim_xfer_rx(addr, data, len, 0);
|
||||
|
||||
k_sem_give(&spim_config->lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int spim_hl_readw(unsigned int addr, void *data)
|
||||
{
|
||||
int status = -1;
|
||||
|
||||
k_sem_take(&spim_config->lock, K_FOREVER);
|
||||
|
||||
status = spim_xfer_rx(addr, data, 4, 4 * spim_config->qspi_slave_latency);
|
||||
|
||||
k_sem_give(&spim_config->lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int spim_hl_read(unsigned int addr, void *data, int len)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
spim_addr_check(addr, data, len);
|
||||
|
||||
while (count < (len / 4)) {
|
||||
spim_hl_readw(addr + (4 * count), (char *)data + (4 * count));
|
||||
count++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------added for wifi utils -------------------------------- */
|
||||
|
||||
int spim_cmd_rpu_wakeup_fn(uint32_t data)
|
||||
{
|
||||
return spim_cmd_rpu_wakeup(data);
|
||||
}
|
||||
|
||||
int spim_cmd_sleep_rpu_fn(void)
|
||||
{
|
||||
return spim_cmd_sleep_rpu();
|
||||
}
|
||||
|
||||
int spim_wait_while_rpu_awake(void)
|
||||
{
|
||||
return _spim_wait_while_rpu_awake();
|
||||
}
|
||||
|
||||
int spi_validate_rpu_wake_writecmd(void)
|
||||
{
|
||||
return spim_wait_while_rpu_wake_write();
|
||||
}
|
969
drivers/wifi/nrfwifi/src/shim.c
Normal file
969
drivers/wifi/nrfwifi/src/shim.c
Normal file
|
@ -0,0 +1,969 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Header containing OS specific definitions for the
|
||||
* Zephyr OS layer of the Wi-Fi driver.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/printk.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/sys/__assert.h>
|
||||
|
||||
#include "rpu_hw_if.h"
|
||||
#include "shim.h"
|
||||
#include "work.h"
|
||||
#include "timer.h"
|
||||
#include "osal_ops.h"
|
||||
#include "qspi_if.h"
|
||||
|
||||
LOG_MODULE_REGISTER(wifi_nrf, CONFIG_WIFI_NRF70_LOG_LEVEL);
|
||||
|
||||
struct zep_shim_intr_priv *intr_priv;
|
||||
|
||||
static void *zep_shim_mem_alloc(size_t size)
|
||||
{
|
||||
size_t size_aligned = ROUND_UP(size, 4);
|
||||
|
||||
return k_malloc(size_aligned);
|
||||
}
|
||||
|
||||
static void *zep_shim_mem_zalloc(size_t size)
|
||||
{
|
||||
size_t size_aligned = ROUND_UP(size, 4);
|
||||
|
||||
return k_calloc(size_aligned, sizeof(char));
|
||||
}
|
||||
|
||||
static void *zep_shim_mem_cpy(void *dest, const void *src, size_t count)
|
||||
{
|
||||
return memcpy(dest, src, count);
|
||||
}
|
||||
|
||||
static void *zep_shim_mem_set(void *start, int val, size_t size)
|
||||
{
|
||||
return memset(start, val, size);
|
||||
}
|
||||
|
||||
static int zep_shim_mem_cmp(const void *addr1,
|
||||
const void *addr2,
|
||||
size_t size)
|
||||
{
|
||||
return memcmp(addr1, addr2, size);
|
||||
}
|
||||
|
||||
static unsigned int zep_shim_qspi_read_reg32(void *priv, unsigned long addr)
|
||||
{
|
||||
unsigned int val;
|
||||
struct zep_shim_bus_qspi_priv *qspi_priv = priv;
|
||||
struct qspi_dev *dev;
|
||||
|
||||
dev = qspi_priv->qspi_dev;
|
||||
|
||||
if (addr < 0x0C0000) {
|
||||
dev->hl_read(addr, &val, 4);
|
||||
} else {
|
||||
dev->read(addr, &val, 4);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void zep_shim_qspi_write_reg32(void *priv, unsigned long addr, unsigned int val)
|
||||
{
|
||||
struct zep_shim_bus_qspi_priv *qspi_priv = priv;
|
||||
struct qspi_dev *dev;
|
||||
|
||||
dev = qspi_priv->qspi_dev;
|
||||
|
||||
dev->write(addr, &val, 4);
|
||||
}
|
||||
|
||||
static void zep_shim_qspi_cpy_from(void *priv, void *dest, unsigned long addr, size_t count)
|
||||
{
|
||||
struct zep_shim_bus_qspi_priv *qspi_priv = priv;
|
||||
struct qspi_dev *dev;
|
||||
size_t count_aligned = ROUND_UP(count, 4);
|
||||
|
||||
dev = qspi_priv->qspi_dev;
|
||||
|
||||
if (addr < 0x0C0000) {
|
||||
dev->hl_read(addr, dest, count_aligned);
|
||||
} else {
|
||||
dev->read(addr, dest, count_aligned);
|
||||
}
|
||||
}
|
||||
|
||||
static void zep_shim_qspi_cpy_to(void *priv, unsigned long addr, const void *src, size_t count)
|
||||
{
|
||||
struct zep_shim_bus_qspi_priv *qspi_priv = priv;
|
||||
struct qspi_dev *dev;
|
||||
size_t count_aligned = ROUND_UP(count, 4);
|
||||
|
||||
dev = qspi_priv->qspi_dev;
|
||||
|
||||
dev->write(addr, src, count_aligned);
|
||||
}
|
||||
|
||||
static void *zep_shim_spinlock_alloc(void)
|
||||
{
|
||||
struct k_sem *lock = NULL;
|
||||
|
||||
lock = k_malloc(sizeof(*lock));
|
||||
|
||||
if (!lock) {
|
||||
LOG_ERR("%s: Unable to allocate memory for spinlock", __func__);
|
||||
}
|
||||
|
||||
return lock;
|
||||
}
|
||||
|
||||
static void zep_shim_spinlock_free(void *lock)
|
||||
{
|
||||
k_free(lock);
|
||||
}
|
||||
|
||||
static void zep_shim_spinlock_init(void *lock)
|
||||
{
|
||||
k_sem_init(lock, 1, 1);
|
||||
}
|
||||
|
||||
static void zep_shim_spinlock_take(void *lock)
|
||||
{
|
||||
k_sem_take(lock, K_FOREVER);
|
||||
}
|
||||
|
||||
static void zep_shim_spinlock_rel(void *lock)
|
||||
{
|
||||
k_sem_give(lock);
|
||||
}
|
||||
|
||||
static void zep_shim_spinlock_irq_take(void *lock, unsigned long *flags)
|
||||
{
|
||||
k_sem_take(lock, K_FOREVER);
|
||||
}
|
||||
|
||||
static void zep_shim_spinlock_irq_rel(void *lock, unsigned long *flags)
|
||||
{
|
||||
k_sem_give(lock);
|
||||
}
|
||||
|
||||
static int zep_shim_pr_dbg(const char *fmt, va_list args)
|
||||
{
|
||||
static char buf[80];
|
||||
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
|
||||
LOG_DBG("%s", buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zep_shim_pr_info(const char *fmt, va_list args)
|
||||
{
|
||||
static char buf[80];
|
||||
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
|
||||
LOG_INF("%s", buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zep_shim_pr_err(const char *fmt, va_list args)
|
||||
{
|
||||
static char buf[256];
|
||||
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
|
||||
LOG_ERR("%s", buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nwb {
|
||||
unsigned char *data;
|
||||
unsigned char *tail;
|
||||
int len;
|
||||
int headroom;
|
||||
void *next;
|
||||
void *priv;
|
||||
int iftype;
|
||||
void *ifaddr;
|
||||
void *dev;
|
||||
int hostbuffer;
|
||||
void *cleanup_ctx;
|
||||
void (*cleanup_cb)();
|
||||
unsigned char priority;
|
||||
bool chksum_done;
|
||||
};
|
||||
|
||||
static void *zep_shim_nbuf_alloc(unsigned int size)
|
||||
{
|
||||
struct nwb *nbuff;
|
||||
|
||||
nbuff = (struct nwb *)k_calloc(sizeof(struct nwb), sizeof(char));
|
||||
|
||||
if (!nbuff)
|
||||
return NULL;
|
||||
|
||||
nbuff->priv = k_calloc(size, sizeof(char));
|
||||
|
||||
if (!nbuff->priv) {
|
||||
k_free(nbuff);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nbuff->data = (unsigned char *)nbuff->priv;
|
||||
nbuff->tail = nbuff->data;
|
||||
nbuff->len = 0;
|
||||
nbuff->headroom = 0;
|
||||
nbuff->next = NULL;
|
||||
|
||||
return nbuff;
|
||||
}
|
||||
|
||||
static void zep_shim_nbuf_free(void *nbuf)
|
||||
{
|
||||
k_free(((struct nwb *)nbuf)->priv);
|
||||
k_free(nbuf);
|
||||
}
|
||||
|
||||
static void zep_shim_nbuf_headroom_res(void *nbuf, unsigned int size)
|
||||
{
|
||||
struct nwb *nwb = (struct nwb *)nbuf;
|
||||
|
||||
nwb->data += size;
|
||||
nwb->tail += size;
|
||||
nwb->headroom += size;
|
||||
}
|
||||
|
||||
static unsigned int zep_shim_nbuf_headroom_get(void *nbuf)
|
||||
{
|
||||
return ((struct nwb *)nbuf)->headroom;
|
||||
}
|
||||
|
||||
static unsigned int zep_shim_nbuf_data_size(void *nbuf)
|
||||
{
|
||||
return ((struct nwb *)nbuf)->len;
|
||||
}
|
||||
|
||||
static void *zep_shim_nbuf_data_get(void *nbuf)
|
||||
{
|
||||
return ((struct nwb *)nbuf)->data;
|
||||
}
|
||||
|
||||
static void *zep_shim_nbuf_data_put(void *nbuf, unsigned int size)
|
||||
{
|
||||
struct nwb *nwb = (struct nwb *)nbuf;
|
||||
unsigned char *data = nwb->tail;
|
||||
|
||||
nwb->tail += size;
|
||||
nwb->len += size;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void *zep_shim_nbuf_data_push(void *nbuf, unsigned int size)
|
||||
{
|
||||
struct nwb *nwb = (struct nwb *)nbuf;
|
||||
|
||||
nwb->data -= size;
|
||||
nwb->headroom -= size;
|
||||
nwb->len += size;
|
||||
|
||||
return nwb->data;
|
||||
}
|
||||
|
||||
static void *zep_shim_nbuf_data_pull(void *nbuf, unsigned int size)
|
||||
{
|
||||
struct nwb *nwb = (struct nwb *)nbuf;
|
||||
|
||||
nwb->data += size;
|
||||
nwb->headroom += size;
|
||||
nwb->len -= size;
|
||||
|
||||
return nwb->data;
|
||||
}
|
||||
|
||||
static unsigned char zep_shim_nbuf_get_priority(void *nbuf)
|
||||
{
|
||||
struct nwb *nwb = (struct nwb *)nbuf;
|
||||
|
||||
return nwb->priority;
|
||||
}
|
||||
|
||||
static unsigned char zep_shim_nbuf_get_chksum_done(void *nbuf)
|
||||
{
|
||||
struct nwb *nwb = (struct nwb *)nbuf;
|
||||
|
||||
return nwb->chksum_done;
|
||||
}
|
||||
|
||||
static void zep_shim_nbuf_set_chksum_done(void *nbuf, unsigned char chksum_done)
|
||||
{
|
||||
struct nwb *nwb = (struct nwb *)nbuf;
|
||||
|
||||
nwb->chksum_done = (bool)chksum_done;
|
||||
}
|
||||
|
||||
#include <zephyr/net/ethernet.h>
|
||||
#include <zephyr/net/net_core.h>
|
||||
|
||||
void *net_pkt_to_nbuf(struct net_pkt *pkt)
|
||||
{
|
||||
struct nwb *nbuff;
|
||||
unsigned char *data;
|
||||
unsigned int len;
|
||||
|
||||
len = net_pkt_get_len(pkt);
|
||||
|
||||
nbuff = zep_shim_nbuf_alloc(len + 100);
|
||||
|
||||
if (!nbuff) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zep_shim_nbuf_headroom_res(nbuff, 100);
|
||||
|
||||
data = zep_shim_nbuf_data_put(nbuff, len);
|
||||
|
||||
net_pkt_read(pkt, data, len);
|
||||
|
||||
nbuff->priority = net_pkt_priority(pkt);
|
||||
nbuff->chksum_done = (bool)net_pkt_is_chksum_done(pkt);
|
||||
|
||||
return nbuff;
|
||||
}
|
||||
|
||||
void *net_pkt_from_nbuf(void *iface, void *frm)
|
||||
{
|
||||
struct net_pkt *pkt = NULL;
|
||||
unsigned char *data;
|
||||
unsigned int len;
|
||||
struct nwb *nwb = frm;
|
||||
|
||||
if (!nwb) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = zep_shim_nbuf_data_size(nwb);
|
||||
|
||||
data = zep_shim_nbuf_data_get(nwb);
|
||||
|
||||
pkt = net_pkt_rx_alloc_with_buffer(iface, len, AF_UNSPEC, 0, K_MSEC(100));
|
||||
|
||||
if (!pkt) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (net_pkt_write(pkt, data, len)) {
|
||||
net_pkt_unref(pkt);
|
||||
pkt = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
zep_shim_nbuf_free(nwb);
|
||||
return pkt;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NRF70_RAW_DATA_RX) || defined(CONFIG_NRF70_PROMISC_DATA_RX)
|
||||
void *net_raw_pkt_from_nbuf(void *iface, void *frm,
|
||||
unsigned short raw_hdr_len,
|
||||
void *raw_rx_hdr,
|
||||
bool pkt_free)
|
||||
{
|
||||
struct net_pkt *pkt = NULL;
|
||||
unsigned char *nwb_data;
|
||||
unsigned char *data = NULL;
|
||||
unsigned int nwb_len;
|
||||
unsigned int total_len;
|
||||
struct nwb *nwb = frm;
|
||||
|
||||
if (!nwb) {
|
||||
LOG_ERR("%s: Received network buffer is NULL", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nwb_len = zep_shim_nbuf_data_size(nwb);
|
||||
nwb_data = zep_shim_nbuf_data_get(nwb);
|
||||
total_len = raw_hdr_len + nwb_len;
|
||||
|
||||
data = (unsigned char *)k_malloc(total_len);
|
||||
if (!data) {
|
||||
LOG_ERR("%s: Unable to allocate memory for sniffer data packet", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
pkt = net_pkt_rx_alloc_with_buffer(iface, total_len, AF_PACKET, ETH_P_ALL, K_MSEC(100));
|
||||
if (!pkt) {
|
||||
LOG_ERR("%s: Unable to allocate net packet buffer", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(data, raw_rx_hdr, raw_hdr_len);
|
||||
memcpy((data+raw_hdr_len), nwb_data, nwb_len);
|
||||
|
||||
if (net_pkt_write(pkt, data, total_len)) {
|
||||
net_pkt_unref(pkt);
|
||||
pkt = NULL;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
if (data != NULL) {
|
||||
k_free(data);
|
||||
}
|
||||
|
||||
if (pkt_free) {
|
||||
zep_shim_nbuf_free(nwb);
|
||||
}
|
||||
|
||||
return pkt;
|
||||
}
|
||||
#endif /* CONFIG_NRF70_RAW_DATA_RX || CONFIG_NRF70_PROMISC_DATA_RX */
|
||||
|
||||
static void *zep_shim_llist_node_alloc(void)
|
||||
{
|
||||
struct zep_shim_llist_node *llist_node = NULL;
|
||||
|
||||
llist_node = k_calloc(sizeof(*llist_node), sizeof(char));
|
||||
|
||||
if (!llist_node) {
|
||||
LOG_ERR("%s: Unable to allocate memory for linked list node", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sys_dnode_init(&llist_node->head);
|
||||
|
||||
return llist_node;
|
||||
}
|
||||
|
||||
static void zep_shim_llist_node_free(void *llist_node)
|
||||
{
|
||||
k_free(llist_node);
|
||||
}
|
||||
|
||||
static void *zep_shim_llist_node_data_get(void *llist_node)
|
||||
{
|
||||
struct zep_shim_llist_node *zep_llist_node = NULL;
|
||||
|
||||
zep_llist_node = (struct zep_shim_llist_node *)llist_node;
|
||||
|
||||
return zep_llist_node->data;
|
||||
}
|
||||
|
||||
static void zep_shim_llist_node_data_set(void *llist_node, void *data)
|
||||
{
|
||||
struct zep_shim_llist_node *zep_llist_node = NULL;
|
||||
|
||||
zep_llist_node = (struct zep_shim_llist_node *)llist_node;
|
||||
|
||||
zep_llist_node->data = data;
|
||||
}
|
||||
|
||||
static void *zep_shim_llist_alloc(void)
|
||||
{
|
||||
struct zep_shim_llist *llist = NULL;
|
||||
|
||||
llist = k_calloc(sizeof(*llist), sizeof(char));
|
||||
|
||||
if (!llist) {
|
||||
LOG_ERR("%s: Unable to allocate memory for linked list", __func__);
|
||||
}
|
||||
|
||||
return llist;
|
||||
}
|
||||
|
||||
static void zep_shim_llist_free(void *llist)
|
||||
{
|
||||
k_free(llist);
|
||||
}
|
||||
|
||||
static void zep_shim_llist_init(void *llist)
|
||||
{
|
||||
struct zep_shim_llist *zep_llist = NULL;
|
||||
|
||||
zep_llist = (struct zep_shim_llist *)llist;
|
||||
|
||||
sys_dlist_init(&zep_llist->head);
|
||||
}
|
||||
|
||||
static void zep_shim_llist_add_node_tail(void *llist, void *llist_node)
|
||||
{
|
||||
struct zep_shim_llist *zep_llist = NULL;
|
||||
struct zep_shim_llist_node *zep_node = NULL;
|
||||
|
||||
zep_llist = (struct zep_shim_llist *)llist;
|
||||
zep_node = (struct zep_shim_llist_node *)llist_node;
|
||||
|
||||
sys_dlist_append(&zep_llist->head, &zep_node->head);
|
||||
|
||||
zep_llist->len += 1;
|
||||
}
|
||||
|
||||
static void zep_shim_llist_add_node_head(void *llist, void *llist_node)
|
||||
{
|
||||
struct zep_shim_llist *zep_llist = NULL;
|
||||
struct zep_shim_llist_node *zep_node = NULL;
|
||||
|
||||
zep_llist = (struct zep_shim_llist *)llist;
|
||||
zep_node = (struct zep_shim_llist_node *)llist_node;
|
||||
|
||||
sys_dlist_prepend(&zep_llist->head, &zep_node->head);
|
||||
|
||||
zep_llist->len += 1;
|
||||
}
|
||||
|
||||
static void *zep_shim_llist_get_node_head(void *llist)
|
||||
{
|
||||
struct zep_shim_llist_node *zep_head_node = NULL;
|
||||
struct zep_shim_llist *zep_llist = NULL;
|
||||
|
||||
zep_llist = (struct zep_shim_llist *)llist;
|
||||
|
||||
if (!zep_llist->len) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zep_head_node = (struct zep_shim_llist_node *)sys_dlist_peek_head(&zep_llist->head);
|
||||
|
||||
return zep_head_node;
|
||||
}
|
||||
|
||||
static void *zep_shim_llist_get_node_nxt(void *llist, void *llist_node)
|
||||
{
|
||||
struct zep_shim_llist_node *zep_node = NULL;
|
||||
struct zep_shim_llist_node *zep_nxt_node = NULL;
|
||||
struct zep_shim_llist *zep_llist = NULL;
|
||||
|
||||
zep_llist = (struct zep_shim_llist *)llist;
|
||||
zep_node = (struct zep_shim_llist_node *)llist_node;
|
||||
|
||||
zep_nxt_node = (struct zep_shim_llist_node *)sys_dlist_peek_next(&zep_llist->head,
|
||||
&zep_node->head);
|
||||
|
||||
return zep_nxt_node;
|
||||
}
|
||||
|
||||
static void zep_shim_llist_del_node(void *llist, void *llist_node)
|
||||
{
|
||||
struct zep_shim_llist_node *zep_node = NULL;
|
||||
struct zep_shim_llist *zep_llist = NULL;
|
||||
|
||||
zep_llist = (struct zep_shim_llist *)llist;
|
||||
zep_node = (struct zep_shim_llist_node *)llist_node;
|
||||
|
||||
sys_dlist_remove(&zep_node->head);
|
||||
|
||||
zep_llist->len -= 1;
|
||||
}
|
||||
|
||||
static unsigned int zep_shim_llist_len(void *llist)
|
||||
{
|
||||
struct zep_shim_llist *zep_llist = NULL;
|
||||
|
||||
zep_llist = (struct zep_shim_llist *)llist;
|
||||
|
||||
return zep_llist->len;
|
||||
}
|
||||
|
||||
static void *zep_shim_work_alloc(int type)
|
||||
{
|
||||
return work_alloc(type);
|
||||
}
|
||||
|
||||
static void zep_shim_work_free(void *item)
|
||||
{
|
||||
return work_free(item);
|
||||
}
|
||||
|
||||
static void zep_shim_work_init(void *item, void (*callback)(unsigned long data),
|
||||
unsigned long data)
|
||||
{
|
||||
work_init(item, callback, data);
|
||||
}
|
||||
|
||||
static void zep_shim_work_schedule(void *item)
|
||||
{
|
||||
work_schedule(item);
|
||||
}
|
||||
|
||||
static void zep_shim_work_kill(void *item)
|
||||
{
|
||||
work_kill(item);
|
||||
}
|
||||
|
||||
static unsigned long zep_shim_time_get_curr_us(void)
|
||||
{
|
||||
return k_uptime_get() * USEC_PER_MSEC;
|
||||
}
|
||||
|
||||
static unsigned int zep_shim_time_elapsed_us(unsigned long start_time_us)
|
||||
{
|
||||
unsigned long curr_time_us = 0;
|
||||
|
||||
curr_time_us = zep_shim_time_get_curr_us();
|
||||
|
||||
return curr_time_us - start_time_us;
|
||||
}
|
||||
|
||||
static enum nrf_wifi_status zep_shim_bus_qspi_dev_init(void *os_qspi_dev_ctx)
|
||||
{
|
||||
ARG_UNUSED(os_qspi_dev_ctx);
|
||||
|
||||
return NRF_WIFI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void zep_shim_bus_qspi_dev_deinit(void *priv)
|
||||
{
|
||||
struct zep_shim_bus_qspi_priv *qspi_priv = priv;
|
||||
volatile struct qspi_dev *dev = qspi_priv->qspi_dev;
|
||||
|
||||
dev->deinit();
|
||||
}
|
||||
|
||||
static void *zep_shim_bus_qspi_dev_add(void *os_qspi_priv, void *osal_qspi_dev_ctx)
|
||||
{
|
||||
struct zep_shim_bus_qspi_priv *zep_qspi_priv = os_qspi_priv;
|
||||
struct qspi_dev *dev = qspi_dev();
|
||||
int ret;
|
||||
enum nrf_wifi_status status;
|
||||
|
||||
ret = rpu_init();
|
||||
if (ret) {
|
||||
LOG_ERR("%s: RPU init failed with error %d", __func__, ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = dev->init(qspi_defconfig());
|
||||
if (status != NRF_WIFI_STATUS_SUCCESS) {
|
||||
LOG_ERR("%s: QSPI device init failed", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = rpu_enable();
|
||||
if (ret) {
|
||||
LOG_ERR("%s: RPU enable failed with error %d", __func__, ret);
|
||||
return NULL;
|
||||
}
|
||||
zep_qspi_priv->qspi_dev = dev;
|
||||
zep_qspi_priv->dev_added = true;
|
||||
|
||||
return zep_qspi_priv;
|
||||
}
|
||||
|
||||
static void zep_shim_bus_qspi_dev_rem(void *priv)
|
||||
{
|
||||
struct zep_shim_bus_qspi_priv *qspi_priv = priv;
|
||||
struct qspi_dev *dev = qspi_priv->qspi_dev;
|
||||
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
/* TODO: Make qspi_dev a dynamic instance and remove it here */
|
||||
rpu_disable();
|
||||
}
|
||||
|
||||
static void *zep_shim_bus_qspi_init(void)
|
||||
{
|
||||
struct zep_shim_bus_qspi_priv *qspi_priv = NULL;
|
||||
|
||||
qspi_priv = k_calloc(sizeof(*qspi_priv), sizeof(char));
|
||||
|
||||
if (!qspi_priv) {
|
||||
LOG_ERR("%s: Unable to allocate memory for qspi_priv", __func__);
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
return qspi_priv;
|
||||
}
|
||||
|
||||
static void zep_shim_bus_qspi_deinit(void *os_qspi_priv)
|
||||
{
|
||||
struct zep_shim_bus_qspi_priv *qspi_priv = NULL;
|
||||
|
||||
qspi_priv = os_qspi_priv;
|
||||
|
||||
k_free(qspi_priv);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NRF_WIFI_LOW_POWER
|
||||
static int zep_shim_bus_qspi_ps_sleep(void *os_qspi_priv)
|
||||
{
|
||||
rpu_sleep();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zep_shim_bus_qspi_ps_wake(void *os_qspi_priv)
|
||||
{
|
||||
rpu_wakeup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zep_shim_bus_qspi_ps_status(void *os_qspi_priv)
|
||||
{
|
||||
return rpu_sleep_status();
|
||||
}
|
||||
#endif /* CONFIG_NRF_WIFI_LOW_POWER */
|
||||
|
||||
static void zep_shim_bus_qspi_dev_host_map_get(void *os_qspi_dev_ctx,
|
||||
struct nrf_wifi_osal_host_map *host_map)
|
||||
{
|
||||
if (!os_qspi_dev_ctx || !host_map) {
|
||||
LOG_ERR("%s: Invalid parameters", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
host_map->addr = 0;
|
||||
}
|
||||
|
||||
static void irq_work_handler(struct k_work *work)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = intr_priv->callbk_fn(intr_priv->callbk_data);
|
||||
|
||||
if (ret) {
|
||||
LOG_ERR("%s: Interrupt callback failed", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern struct k_work_q zep_wifi_intr_q;
|
||||
|
||||
static void zep_shim_irq_handler(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
|
||||
{
|
||||
ARG_UNUSED(cb);
|
||||
ARG_UNUSED(pins);
|
||||
|
||||
k_work_schedule_for_queue(&zep_wifi_intr_q, &intr_priv->work, K_NO_WAIT);
|
||||
}
|
||||
|
||||
static enum nrf_wifi_status zep_shim_bus_qspi_intr_reg(void *os_dev_ctx, void *callbk_data,
|
||||
int (*callbk_fn)(void *callbk_data))
|
||||
{
|
||||
enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
|
||||
int ret = -1;
|
||||
|
||||
ARG_UNUSED(os_dev_ctx);
|
||||
|
||||
intr_priv = k_calloc(sizeof(*intr_priv), sizeof(char));
|
||||
|
||||
if (!intr_priv) {
|
||||
LOG_ERR("%s: Unable to allocate memory for intr_priv", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
intr_priv->callbk_data = callbk_data;
|
||||
intr_priv->callbk_fn = callbk_fn;
|
||||
|
||||
k_work_init_delayable(&intr_priv->work, irq_work_handler);
|
||||
|
||||
ret = rpu_irq_config(&intr_priv->gpio_cb_data, zep_shim_irq_handler);
|
||||
|
||||
if (ret) {
|
||||
LOG_ERR("%s: request_irq failed", __func__);
|
||||
k_free(intr_priv);
|
||||
intr_priv = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = NRF_WIFI_STATUS_SUCCESS;
|
||||
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
static void zep_shim_bus_qspi_intr_unreg(void *os_qspi_dev_ctx)
|
||||
{
|
||||
struct k_work_sync sync;
|
||||
int ret;
|
||||
|
||||
ARG_UNUSED(os_qspi_dev_ctx);
|
||||
|
||||
ret = rpu_irq_remove(&intr_priv->gpio_cb_data);
|
||||
if (ret) {
|
||||
LOG_ERR("%s: rpu_irq_remove failed", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
k_work_cancel_delayable_sync(&intr_priv->work, &sync);
|
||||
|
||||
k_free(intr_priv);
|
||||
intr_priv = NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NRF_WIFI_LOW_POWER
|
||||
static void *zep_shim_timer_alloc(void)
|
||||
{
|
||||
struct timer_list *timer = NULL;
|
||||
|
||||
timer = k_malloc(sizeof(*timer));
|
||||
|
||||
if (!timer)
|
||||
LOG_ERR("%s: Unable to allocate memory for work", __func__);
|
||||
|
||||
return timer;
|
||||
}
|
||||
|
||||
static void zep_shim_timer_init(void *timer, void (*callback)(unsigned long), unsigned long data)
|
||||
{
|
||||
((struct timer_list *)timer)->function = callback;
|
||||
((struct timer_list *)timer)->data = data;
|
||||
|
||||
init_timer(timer);
|
||||
}
|
||||
|
||||
static void zep_shim_timer_free(void *timer)
|
||||
{
|
||||
k_free(timer);
|
||||
}
|
||||
|
||||
static void zep_shim_timer_schedule(void *timer, unsigned long duration)
|
||||
{
|
||||
mod_timer(timer, duration);
|
||||
}
|
||||
|
||||
static void zep_shim_timer_kill(void *timer)
|
||||
{
|
||||
del_timer_sync(timer);
|
||||
}
|
||||
#endif /* CONFIG_NRF_WIFI_LOW_POWER */
|
||||
|
||||
static void zep_shim_assert(int test_val, int val, enum nrf_wifi_assert_op_type op, char *msg)
|
||||
{
|
||||
switch (op) {
|
||||
case NRF_WIFI_ASSERT_EQUAL_TO:
|
||||
NET_ASSERT(test_val == val, "%s", msg);
|
||||
break;
|
||||
case NRF_WIFI_ASSERT_NOT_EQUAL_TO:
|
||||
NET_ASSERT(test_val != val, "%s", msg);
|
||||
break;
|
||||
case NRF_WIFI_ASSERT_LESS_THAN:
|
||||
NET_ASSERT(test_val < val, "%s", msg);
|
||||
break;
|
||||
case NRF_WIFI_ASSERT_LESS_THAN_EQUAL_TO:
|
||||
NET_ASSERT(test_val <= val, "%s", msg);
|
||||
break;
|
||||
case NRF_WIFI_ASSERT_GREATER_THAN:
|
||||
NET_ASSERT(test_val > val, "%s", msg);
|
||||
break;
|
||||
case NRF_WIFI_ASSERT_GREATER_THAN_EQUAL_TO:
|
||||
NET_ASSERT(test_val >= val, "%s", msg);
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("%s: Invalid assertion operation", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int zep_shim_strlen(const void *str)
|
||||
{
|
||||
return strlen(str);
|
||||
}
|
||||
|
||||
static const struct nrf_wifi_osal_ops nrf_wifi_os_zep_ops = {
|
||||
.mem_alloc = zep_shim_mem_alloc,
|
||||
.mem_zalloc = zep_shim_mem_zalloc,
|
||||
.mem_free = k_free,
|
||||
.mem_cpy = zep_shim_mem_cpy,
|
||||
.mem_set = zep_shim_mem_set,
|
||||
.mem_cmp = zep_shim_mem_cmp,
|
||||
|
||||
.qspi_read_reg32 = zep_shim_qspi_read_reg32,
|
||||
.qspi_write_reg32 = zep_shim_qspi_write_reg32,
|
||||
.qspi_cpy_from = zep_shim_qspi_cpy_from,
|
||||
.qspi_cpy_to = zep_shim_qspi_cpy_to,
|
||||
|
||||
.spinlock_alloc = zep_shim_spinlock_alloc,
|
||||
.spinlock_free = zep_shim_spinlock_free,
|
||||
.spinlock_init = zep_shim_spinlock_init,
|
||||
.spinlock_take = zep_shim_spinlock_take,
|
||||
.spinlock_rel = zep_shim_spinlock_rel,
|
||||
|
||||
.spinlock_irq_take = zep_shim_spinlock_irq_take,
|
||||
.spinlock_irq_rel = zep_shim_spinlock_irq_rel,
|
||||
|
||||
.log_dbg = zep_shim_pr_dbg,
|
||||
.log_info = zep_shim_pr_info,
|
||||
.log_err = zep_shim_pr_err,
|
||||
|
||||
.llist_node_alloc = zep_shim_llist_node_alloc,
|
||||
.llist_node_free = zep_shim_llist_node_free,
|
||||
.llist_node_data_get = zep_shim_llist_node_data_get,
|
||||
.llist_node_data_set = zep_shim_llist_node_data_set,
|
||||
|
||||
.llist_alloc = zep_shim_llist_alloc,
|
||||
.llist_free = zep_shim_llist_free,
|
||||
.llist_init = zep_shim_llist_init,
|
||||
.llist_add_node_tail = zep_shim_llist_add_node_tail,
|
||||
.llist_add_node_head = zep_shim_llist_add_node_head,
|
||||
.llist_get_node_head = zep_shim_llist_get_node_head,
|
||||
.llist_get_node_nxt = zep_shim_llist_get_node_nxt,
|
||||
.llist_del_node = zep_shim_llist_del_node,
|
||||
.llist_len = zep_shim_llist_len,
|
||||
|
||||
.nbuf_alloc = zep_shim_nbuf_alloc,
|
||||
.nbuf_free = zep_shim_nbuf_free,
|
||||
.nbuf_headroom_res = zep_shim_nbuf_headroom_res,
|
||||
.nbuf_headroom_get = zep_shim_nbuf_headroom_get,
|
||||
.nbuf_data_size = zep_shim_nbuf_data_size,
|
||||
.nbuf_data_get = zep_shim_nbuf_data_get,
|
||||
.nbuf_data_put = zep_shim_nbuf_data_put,
|
||||
.nbuf_data_push = zep_shim_nbuf_data_push,
|
||||
.nbuf_data_pull = zep_shim_nbuf_data_pull,
|
||||
.nbuf_get_priority = zep_shim_nbuf_get_priority,
|
||||
.nbuf_get_chksum_done = zep_shim_nbuf_get_chksum_done,
|
||||
.nbuf_set_chksum_done = zep_shim_nbuf_set_chksum_done,
|
||||
|
||||
.tasklet_alloc = zep_shim_work_alloc,
|
||||
.tasklet_free = zep_shim_work_free,
|
||||
.tasklet_init = zep_shim_work_init,
|
||||
.tasklet_schedule = zep_shim_work_schedule,
|
||||
.tasklet_kill = zep_shim_work_kill,
|
||||
|
||||
.sleep_ms = k_msleep,
|
||||
.delay_us = k_usleep,
|
||||
.time_get_curr_us = zep_shim_time_get_curr_us,
|
||||
.time_elapsed_us = zep_shim_time_elapsed_us,
|
||||
|
||||
.bus_qspi_init = zep_shim_bus_qspi_init,
|
||||
.bus_qspi_deinit = zep_shim_bus_qspi_deinit,
|
||||
.bus_qspi_dev_add = zep_shim_bus_qspi_dev_add,
|
||||
.bus_qspi_dev_rem = zep_shim_bus_qspi_dev_rem,
|
||||
.bus_qspi_dev_init = zep_shim_bus_qspi_dev_init,
|
||||
.bus_qspi_dev_deinit = zep_shim_bus_qspi_dev_deinit,
|
||||
.bus_qspi_dev_intr_reg = zep_shim_bus_qspi_intr_reg,
|
||||
.bus_qspi_dev_intr_unreg = zep_shim_bus_qspi_intr_unreg,
|
||||
.bus_qspi_dev_host_map_get = zep_shim_bus_qspi_dev_host_map_get,
|
||||
|
||||
#ifdef CONFIG_NRF_WIFI_LOW_POWER
|
||||
.timer_alloc = zep_shim_timer_alloc,
|
||||
.timer_init = zep_shim_timer_init,
|
||||
.timer_free = zep_shim_timer_free,
|
||||
.timer_schedule = zep_shim_timer_schedule,
|
||||
.timer_kill = zep_shim_timer_kill,
|
||||
|
||||
.bus_qspi_ps_sleep = zep_shim_bus_qspi_ps_sleep,
|
||||
.bus_qspi_ps_wake = zep_shim_bus_qspi_ps_wake,
|
||||
.bus_qspi_ps_status = zep_shim_bus_qspi_ps_status,
|
||||
#endif /* CONFIG_NRF_WIFI_LOW_POWER */
|
||||
|
||||
.assert = zep_shim_assert,
|
||||
.strlen = zep_shim_strlen,
|
||||
};
|
||||
|
||||
const struct nrf_wifi_osal_ops *get_os_ops(void)
|
||||
{
|
||||
return &nrf_wifi_os_zep_ops;
|
||||
}
|
68
drivers/wifi/nrfwifi/src/shim.h
Normal file
68
drivers/wifi/nrfwifi/src/shim.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Header containing OS interface specific declarations for the
|
||||
* Zephyr OS layer of the Wi-Fi driver.
|
||||
*/
|
||||
|
||||
#ifndef __SHIM_H__
|
||||
#define __SHIM_H__
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/net/net_pkt.h>
|
||||
|
||||
/**
|
||||
* struct zep_shim_bus_qspi_priv - Structure to hold context information for the Linux OS
|
||||
* shim.
|
||||
* @opriv: Pointer to OSAL context.
|
||||
* @pcie_callbk_data: Callback data to be passed to the PCIe callback functions.
|
||||
* @pcie_prb_callbk: The callback function to be called when a PCIe device
|
||||
* has been probed.
|
||||
* @pcie_rem_callbk: The callback function to be called when a PCIe device
|
||||
* has been removed.
|
||||
*
|
||||
* This structure maintains the context information necessary for the operation
|
||||
* of the Linux shim. Some of the elements of the structure need to be
|
||||
* initialized during the initialization of the Linux shim while others need to
|
||||
* be kept updated over the duration of the Linux shim operation.
|
||||
*/
|
||||
struct zep_shim_bus_qspi_priv {
|
||||
void *qspi_dev;
|
||||
|
||||
bool dev_added;
|
||||
bool dev_init;
|
||||
};
|
||||
|
||||
struct zep_shim_intr_priv {
|
||||
struct gpio_callback gpio_cb_data;
|
||||
void *callbk_data;
|
||||
int (*callbk_fn)(void *callbk_data);
|
||||
struct k_work_delayable work;
|
||||
};
|
||||
|
||||
struct zep_shim_llist_node {
|
||||
sys_dnode_t head;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct zep_shim_llist {
|
||||
sys_dlist_t head;
|
||||
unsigned int len;
|
||||
};
|
||||
|
||||
void *net_pkt_to_nbuf(struct net_pkt *pkt);
|
||||
void *net_pkt_from_nbuf(void *iface, void *frm);
|
||||
#if defined(CONFIG_NRF70_RAW_DATA_RX) || defined(CONFIG_NRF70_PROMISC_DATA_RX)
|
||||
void *net_raw_pkt_from_nbuf(void *iface,
|
||||
void *frm,
|
||||
unsigned short raw_hdr_len,
|
||||
void *raw_rx_hdr,
|
||||
bool pkt_free);
|
||||
#endif /* CONFIG_NRF70_RAW_DATA_RX || CONFIG_NRF70_PROMISC_DATA_RX */
|
||||
|
||||
#endif /* __SHIM_H__ */
|
43
drivers/wifi/nrfwifi/src/timer.c
Normal file
43
drivers/wifi/nrfwifi/src/timer.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief File containing timer specific definitons for the
|
||||
* Zephyr OS layer of the Wi-Fi driver.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/printk.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
|
||||
#include "timer.h"
|
||||
|
||||
static void timer_expiry_function(struct k_work *work)
|
||||
{
|
||||
struct timer_list *timer;
|
||||
|
||||
timer = (struct timer_list *)CONTAINER_OF(work, struct timer_list, work.work);
|
||||
|
||||
timer->function(timer->data);
|
||||
}
|
||||
|
||||
void init_timer(struct timer_list *timer)
|
||||
{
|
||||
k_work_init_delayable(&timer->work, timer_expiry_function);
|
||||
}
|
||||
|
||||
void mod_timer(struct timer_list *timer, int msec)
|
||||
{
|
||||
k_work_schedule(&timer->work, K_MSEC(msec));
|
||||
}
|
||||
|
||||
void del_timer_sync(struct timer_list *timer)
|
||||
{
|
||||
k_work_cancel_delayable(&timer->work);
|
||||
}
|
26
drivers/wifi/nrfwifi/src/timer.h
Normal file
26
drivers/wifi/nrfwifi/src/timer.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Header containing timer specific declarations for the
|
||||
* Zephyr OS layer of the Wi-Fi driver.
|
||||
*/
|
||||
#ifndef __TIMER_H__
|
||||
#define __TIMER_H__
|
||||
|
||||
struct timer_list {
|
||||
void (*function)(unsigned long data);
|
||||
unsigned long data;
|
||||
struct k_work_delayable work;
|
||||
};
|
||||
|
||||
void init_timer(struct timer_list *timer);
|
||||
|
||||
void mod_timer(struct timer_list *timer, int msec);
|
||||
|
||||
void del_timer_sync(struct timer_list *timer);
|
||||
|
||||
#endif /* __TIMER_H__ */
|
1021
drivers/wifi/nrfwifi/src/wifi_mgmt.c
Normal file
1021
drivers/wifi/nrfwifi/src/wifi_mgmt.c
Normal file
File diff suppressed because it is too large
Load diff
447
drivers/wifi/nrfwifi/src/wifi_mgmt_scan.c
Normal file
447
drivers/wifi/nrfwifi/src/wifi_mgmt_scan.c
Normal file
|
@ -0,0 +1,447 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief File containing display scan specific definitions for the
|
||||
* Zephyr OS layer of the Wi-Fi driver.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "fmac_api.h"
|
||||
#include "fmac_tx.h"
|
||||
#include "fmac_main.h"
|
||||
#include "wifi_mgmt_scan.h"
|
||||
|
||||
LOG_MODULE_DECLARE(wifi_nrf, CONFIG_WIFI_NRF70_LOG_LEVEL);
|
||||
|
||||
extern struct nrf_wifi_drv_priv_zep rpu_drv_priv_zep;
|
||||
|
||||
static enum nrf_wifi_band nrf_wifi_map_zep_band_to_rpu(enum wifi_frequency_bands zep_band)
|
||||
{
|
||||
switch (zep_band) {
|
||||
case WIFI_FREQ_BAND_2_4_GHZ:
|
||||
return NRF_WIFI_BAND_2GHZ;
|
||||
case WIFI_FREQ_BAND_5_GHZ:
|
||||
return NRF_WIFI_BAND_5GHZ;
|
||||
default:
|
||||
return NRF_WIFI_BAND_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
int nrf_wifi_disp_scan_zep(const struct device *dev, struct wifi_scan_params *params,
|
||||
scan_result_cb_t cb)
|
||||
{
|
||||
enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
|
||||
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
|
||||
struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
|
||||
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
|
||||
struct nrf_wifi_umac_scan_info *scan_info = NULL;
|
||||
enum nrf_wifi_band band = NRF_WIFI_BAND_INVALID;
|
||||
uint8_t band_flags = 0xFF;
|
||||
uint8_t i = 0;
|
||||
uint8_t j = 0;
|
||||
uint8_t k = 0;
|
||||
uint16_t num_scan_channels = 0;
|
||||
int ret = -1;
|
||||
|
||||
vif_ctx_zep = dev->data;
|
||||
|
||||
if (!vif_ctx_zep) {
|
||||
LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (vif_ctx_zep->if_op_state != NRF_WIFI_FMAC_IF_OP_STATE_UP) {
|
||||
LOG_ERR("%s: Interface not UP", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
|
||||
if (!rpu_ctx_zep) {
|
||||
LOG_ERR("%s: rpu_ctx_zep is NULL", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
|
||||
if (!rpu_ctx_zep->rpu_ctx) {
|
||||
LOG_DBG("%s: RPU context not initialized", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
|
||||
|
||||
|
||||
if (vif_ctx_zep->scan_in_progress) {
|
||||
LOG_INF("%s: Scan already in progress", __func__);
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (params) {
|
||||
band_flags &= (~(1 << WIFI_FREQ_BAND_2_4_GHZ));
|
||||
|
||||
#ifndef CONFIG_NRF70_2_4G_ONLY
|
||||
band_flags &= (~(1 << WIFI_FREQ_BAND_5_GHZ));
|
||||
#endif /* CONFIG_NRF70_2_4G_ONLY */
|
||||
|
||||
if (params->bands & band_flags) {
|
||||
LOG_ERR("%s: Unsupported band(s) (0x%X)", __func__, params->bands);
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (j = 0; j < CONFIG_WIFI_MGMT_SCAN_CHAN_MAX_MANUAL; j++) {
|
||||
if (!params->band_chan[j].channel) {
|
||||
break;
|
||||
}
|
||||
|
||||
num_scan_channels++;
|
||||
}
|
||||
}
|
||||
|
||||
vif_ctx_zep->disp_scan_cb = cb;
|
||||
|
||||
scan_info = k_calloc(sizeof(*scan_info) +
|
||||
(num_scan_channels *
|
||||
sizeof(scan_info->scan_params.center_frequency[0])),
|
||||
sizeof(char));
|
||||
|
||||
if (!scan_info) {
|
||||
LOG_ERR("%s: Unable to allocate memory for scan_info (size: %d bytes)",
|
||||
__func__,
|
||||
sizeof(*scan_info) + (num_scan_channels *
|
||||
sizeof(scan_info->scan_params.center_frequency[0])));
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(scan_info, 0, sizeof(*scan_info) + (num_scan_channels *
|
||||
sizeof(scan_info->scan_params.center_frequency[0])));
|
||||
|
||||
static uint8_t skip_local_admin_mac = IS_ENABLED(CONFIG_WIFI_NRF70_SKIP_LOCAL_ADMIN_MAC);
|
||||
|
||||
scan_info->scan_params.skip_local_admin_macs = skip_local_admin_mac;
|
||||
|
||||
scan_info->scan_reason = SCAN_DISPLAY;
|
||||
|
||||
if (params) {
|
||||
if (params->scan_type == WIFI_SCAN_TYPE_PASSIVE) {
|
||||
scan_info->scan_params.passive_scan = 1;
|
||||
}
|
||||
|
||||
scan_info->scan_params.bands = params->bands;
|
||||
|
||||
if (params->dwell_time_active < 0) {
|
||||
LOG_ERR("%s: Invalid dwell_time_active %d", __func__,
|
||||
params->dwell_time_active);
|
||||
goto out;
|
||||
} else {
|
||||
scan_info->scan_params.dwell_time_active = params->dwell_time_active;
|
||||
}
|
||||
|
||||
if (params->dwell_time_passive < 0) {
|
||||
LOG_ERR("%s: Invalid dwell_time_passive %d", __func__,
|
||||
params->dwell_time_passive);
|
||||
goto out;
|
||||
} else {
|
||||
scan_info->scan_params.dwell_time_passive = params->dwell_time_passive;
|
||||
}
|
||||
|
||||
if ((params->max_bss_cnt < 0) ||
|
||||
(params->max_bss_cnt > WIFI_MGMT_SCAN_MAX_BSS_CNT)) {
|
||||
LOG_ERR("%s: Invalid max_bss_cnt %d", __func__,
|
||||
params->max_bss_cnt);
|
||||
goto out;
|
||||
} else {
|
||||
vif_ctx_zep->max_bss_cnt = params->max_bss_cnt;
|
||||
}
|
||||
|
||||
for (i = 0; i < NRF_WIFI_SCAN_MAX_NUM_SSIDS; i++) {
|
||||
if (!(params->ssids[i]) || !strlen(params->ssids[i])) {
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(scan_info->scan_params.scan_ssids[i].nrf_wifi_ssid,
|
||||
params->ssids[i],
|
||||
sizeof(scan_info->scan_params.scan_ssids[i].nrf_wifi_ssid));
|
||||
|
||||
scan_info->scan_params.scan_ssids[i].nrf_wifi_ssid_len =
|
||||
strlen(scan_info->scan_params.scan_ssids[i].nrf_wifi_ssid);
|
||||
|
||||
scan_info->scan_params.num_scan_ssids++;
|
||||
}
|
||||
|
||||
for (i = 0; i < CONFIG_WIFI_MGMT_SCAN_CHAN_MAX_MANUAL; i++) {
|
||||
if (!params->band_chan[i].channel) {
|
||||
break;
|
||||
}
|
||||
|
||||
band = nrf_wifi_map_zep_band_to_rpu(params->band_chan[i].band);
|
||||
|
||||
if (band == NRF_WIFI_BAND_INVALID) {
|
||||
LOG_ERR("%s: Unsupported band %d", __func__,
|
||||
params->band_chan[i].band);
|
||||
goto out;
|
||||
}
|
||||
|
||||
scan_info->scan_params.center_frequency[k++] = nrf_wifi_utils_chan_to_freq(
|
||||
fmac_dev_ctx->fpriv->opriv, band, params->band_chan[i].channel);
|
||||
|
||||
if (scan_info->scan_params.center_frequency[k - 1] == -1) {
|
||||
LOG_ERR("%s: Invalid channel %d", __func__,
|
||||
params->band_chan[i].channel);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
scan_info->scan_params.num_scan_channels = k;
|
||||
}
|
||||
|
||||
vif_ctx_zep->scan_res_cnt = 0;
|
||||
|
||||
status = nrf_wifi_fmac_scan(rpu_ctx_zep->rpu_ctx, vif_ctx_zep->vif_idx, scan_info);
|
||||
|
||||
if (status != NRF_WIFI_STATUS_SUCCESS) {
|
||||
LOG_ERR("%s: nrf_wifi_fmac_scan failed", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
vif_ctx_zep->scan_type = SCAN_DISPLAY;
|
||||
vif_ctx_zep->scan_in_progress = true;
|
||||
|
||||
k_work_schedule(&vif_ctx_zep->scan_timeout_work,
|
||||
K_SECONDS(CONFIG_WIFI_NRF70_SCAN_TIMEOUT_S));
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
if (scan_info) {
|
||||
k_free(scan_info);
|
||||
}
|
||||
k_mutex_unlock(&vif_ctx_zep->vif_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum nrf_wifi_status nrf_wifi_disp_scan_res_get_zep(struct nrf_wifi_vif_ctx_zep *vif_ctx_zep)
|
||||
{
|
||||
enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
|
||||
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
|
||||
|
||||
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
|
||||
if (!rpu_ctx_zep) {
|
||||
LOG_ERR("%s: rpu_ctx_zep is NULL", __func__);
|
||||
return NRF_WIFI_STATUS_FAIL;
|
||||
}
|
||||
|
||||
k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
|
||||
if (!rpu_ctx_zep->rpu_ctx) {
|
||||
LOG_DBG("%s: RPU context not initialized", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = nrf_wifi_fmac_scan_res_get(rpu_ctx_zep->rpu_ctx,
|
||||
vif_ctx_zep->vif_idx,
|
||||
SCAN_DISPLAY);
|
||||
|
||||
if (status != NRF_WIFI_STATUS_SUCCESS) {
|
||||
LOG_ERR("%s: nrf_wifi_fmac_scan failed", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = NRF_WIFI_STATUS_SUCCESS;
|
||||
out:
|
||||
k_mutex_unlock(&vif_ctx_zep->vif_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
static inline enum wifi_mfp_options drv_to_wifi_mgmt_mfp(unsigned char mfp_flag)
|
||||
{
|
||||
if (!mfp_flag)
|
||||
return WIFI_MFP_DISABLE;
|
||||
if (mfp_flag & NRF_WIFI_MFP_REQUIRED)
|
||||
return WIFI_MFP_REQUIRED;
|
||||
if (mfp_flag & NRF_WIFI_MFP_CAPABLE)
|
||||
return WIFI_MFP_OPTIONAL;
|
||||
|
||||
return WIFI_MFP_UNKNOWN;
|
||||
}
|
||||
static inline enum wifi_security_type drv_to_wifi_mgmt(int drv_security_type)
|
||||
{
|
||||
switch (drv_security_type) {
|
||||
case NRF_WIFI_OPEN:
|
||||
return WIFI_SECURITY_TYPE_NONE;
|
||||
case NRF_WIFI_WEP:
|
||||
return WIFI_SECURITY_TYPE_WEP;
|
||||
case NRF_WIFI_WPA:
|
||||
return WIFI_SECURITY_TYPE_WPA_PSK;
|
||||
case NRF_WIFI_WPA2:
|
||||
return WIFI_SECURITY_TYPE_PSK;
|
||||
case NRF_WIFI_WPA2_256:
|
||||
return WIFI_SECURITY_TYPE_PSK_SHA256;
|
||||
case NRF_WIFI_WPA3:
|
||||
return WIFI_SECURITY_TYPE_SAE;
|
||||
case NRF_WIFI_WAPI:
|
||||
return WIFI_SECURITY_TYPE_WAPI;
|
||||
case NRF_WIFI_EAP:
|
||||
return WIFI_SECURITY_TYPE_EAP;
|
||||
default:
|
||||
return WIFI_SECURITY_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
void nrf_wifi_event_proc_disp_scan_res_zep(void *vif_ctx,
|
||||
struct nrf_wifi_umac_event_new_scan_display_results *scan_res,
|
||||
unsigned int event_len,
|
||||
bool more_res)
|
||||
{
|
||||
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
|
||||
struct umac_display_results *r = NULL;
|
||||
struct wifi_scan_result res;
|
||||
uint16_t max_bss_cnt = 0;
|
||||
unsigned int i = 0;
|
||||
scan_result_cb_t cb = NULL;
|
||||
|
||||
vif_ctx_zep = vif_ctx;
|
||||
|
||||
cb = (scan_result_cb_t)vif_ctx_zep->disp_scan_cb;
|
||||
|
||||
/* Delayed event (after scan timeout) or rogue event after scan done */
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
max_bss_cnt = vif_ctx_zep->max_bss_cnt ?
|
||||
vif_ctx_zep->max_bss_cnt : CONFIG_NRF_WIFI_SCAN_MAX_BSS_CNT;
|
||||
|
||||
for (i = 0; i < scan_res->event_bss_count; i++) {
|
||||
/* Limit the scan results to the configured maximum */
|
||||
if ((max_bss_cnt > 0) &&
|
||||
(vif_ctx_zep->scan_res_cnt >= max_bss_cnt)) {
|
||||
break;
|
||||
}
|
||||
|
||||
memset(&res, 0x0, sizeof(res));
|
||||
|
||||
r = &scan_res->display_results[i];
|
||||
|
||||
res.ssid_length = MIN(sizeof(res.ssid), r->ssid.nrf_wifi_ssid_len);
|
||||
|
||||
res.band = r->nwk_band;
|
||||
|
||||
res.channel = r->nwk_channel;
|
||||
|
||||
res.security = drv_to_wifi_mgmt(r->security_type);
|
||||
|
||||
res.mfp = drv_to_wifi_mgmt_mfp(r->mfp_flag);
|
||||
|
||||
memcpy(res.ssid,
|
||||
r->ssid.nrf_wifi_ssid,
|
||||
res.ssid_length);
|
||||
|
||||
memcpy(res.mac, r->mac_addr, NRF_WIFI_ETH_ADDR_LEN);
|
||||
res.mac_length = NRF_WIFI_ETH_ADDR_LEN;
|
||||
|
||||
if (r->signal.signal_type == NRF_WIFI_SIGNAL_TYPE_MBM) {
|
||||
int val = (r->signal.signal.mbm_signal);
|
||||
|
||||
res.rssi = (val / 100);
|
||||
} else if (r->signal.signal_type == NRF_WIFI_SIGNAL_TYPE_UNSPEC) {
|
||||
res.rssi = (r->signal.signal.unspec_signal);
|
||||
}
|
||||
|
||||
vif_ctx_zep->disp_scan_cb(vif_ctx_zep->zep_net_if_ctx,
|
||||
0,
|
||||
&res);
|
||||
|
||||
vif_ctx_zep->scan_res_cnt++;
|
||||
|
||||
/* NET_MGMT dropping events if too many are queued */
|
||||
k_yield();
|
||||
}
|
||||
|
||||
if (more_res == false) {
|
||||
vif_ctx_zep->disp_scan_cb(vif_ctx_zep->zep_net_if_ctx, 0, NULL);
|
||||
vif_ctx_zep->scan_in_progress = false;
|
||||
vif_ctx_zep->disp_scan_cb = NULL;
|
||||
k_work_cancel_delayable(&vif_ctx_zep->scan_timeout_work);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS
|
||||
void nrf_wifi_rx_bcn_prb_resp_frm(void *vif_ctx,
|
||||
void *nwb,
|
||||
unsigned short frequency,
|
||||
signed short signal)
|
||||
{
|
||||
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = vif_ctx;
|
||||
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
|
||||
struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
|
||||
struct wifi_raw_scan_result bcn_prb_resp_info;
|
||||
int frame_length = 0;
|
||||
int val = signal;
|
||||
|
||||
vif_ctx_zep = vif_ctx;
|
||||
|
||||
if (!vif_ctx_zep) {
|
||||
LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!vif_ctx_zep->scan_in_progress) {
|
||||
/*LOG_INF("%s: Scan not in progress : raw scan data not available", __func__);*/
|
||||
return;
|
||||
}
|
||||
|
||||
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
|
||||
|
||||
if (!rpu_ctx_zep) {
|
||||
LOG_ERR("%s: rpu_ctx_zep is NULL", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
|
||||
if (!rpu_ctx_zep->rpu_ctx) {
|
||||
LOG_DBG("%s: RPU context not initialized", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
|
||||
|
||||
frame_length = nrf_wifi_osal_nbuf_data_size(fmac_dev_ctx->fpriv->opriv,
|
||||
nwb);
|
||||
|
||||
if (frame_length > CONFIG_WIFI_MGMT_RAW_SCAN_RESULT_LENGTH) {
|
||||
nrf_wifi_osal_mem_cpy(fmac_dev_ctx->fpriv->opriv,
|
||||
&bcn_prb_resp_info.data,
|
||||
nrf_wifi_osal_nbuf_data_get(
|
||||
fmac_dev_ctx->fpriv->opriv,
|
||||
nwb),
|
||||
CONFIG_WIFI_MGMT_RAW_SCAN_RESULT_LENGTH);
|
||||
|
||||
} else {
|
||||
nrf_wifi_osal_mem_cpy(fmac_dev_ctx->fpriv->opriv,
|
||||
&bcn_prb_resp_info.data,
|
||||
nrf_wifi_osal_nbuf_data_get(
|
||||
fmac_dev_ctx->fpriv->opriv,
|
||||
nwb),
|
||||
frame_length);
|
||||
}
|
||||
|
||||
bcn_prb_resp_info.rssi = MBM_TO_DBM(val);
|
||||
bcn_prb_resp_info.frequency = frequency;
|
||||
bcn_prb_resp_info.frame_length = frame_length;
|
||||
|
||||
wifi_mgmt_raise_raw_scan_result_event(vif_ctx_zep->zep_net_if_ctx,
|
||||
&bcn_prb_resp_info);
|
||||
|
||||
out:
|
||||
k_mutex_unlock(&vif_ctx_zep->vif_lock);
|
||||
}
|
||||
#endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */
|
1005
drivers/wifi/nrfwifi/src/wifi_util.c
Normal file
1005
drivers/wifi/nrfwifi/src/wifi_util.c
Normal file
File diff suppressed because it is too large
Load diff
24
drivers/wifi/nrfwifi/src/wifi_util.h
Normal file
24
drivers/wifi/nrfwifi/src/wifi_util.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* @file
|
||||
* @brief nRF Wi-Fi radio-test mode shell module
|
||||
*/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <zephyr/shell/shell.h>
|
||||
#include <zephyr/init.h>
|
||||
#include <ctype.h>
|
||||
#include <host_rpu_sys_if.h>
|
||||
#include <fmac_structs.h>
|
||||
#include <queue.h>
|
||||
|
||||
struct nrf_wifi_ctx_zep_rt {
|
||||
struct nrf_wifi_fmac_priv *fmac_priv;
|
||||
struct rpu_conf_params conf_params;
|
||||
};
|
158
drivers/wifi/nrfwifi/src/work.c
Normal file
158
drivers/wifi/nrfwifi/src/work.c
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief File containing work specific definitions for the
|
||||
* Zephyr OS layer of the Wi-Fi driver.
|
||||
*/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/init.h>
|
||||
#include <zephyr/sys/printk.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "work.h"
|
||||
|
||||
LOG_MODULE_DECLARE(wifi_nrf, CONFIG_WIFI_NRF70_LOG_LEVEL);
|
||||
|
||||
K_THREAD_STACK_DEFINE(bh_wq_stack_area, CONFIG_NRF70_BH_WQ_STACK_SIZE);
|
||||
struct k_work_q zep_wifi_bh_q;
|
||||
|
||||
K_THREAD_STACK_DEFINE(irq_wq_stack_area, CONFIG_NRF70_IRQ_WQ_STACK_SIZE);
|
||||
struct k_work_q zep_wifi_intr_q;
|
||||
|
||||
#ifdef CONFIG_NRF70_TX_DONE_WQ_ENABLED
|
||||
K_THREAD_STACK_DEFINE(tx_done_wq_stack_area, CONFIG_NRF70_TX_DONE_WQ_STACK_SIZE);
|
||||
struct k_work_q zep_wifi_tx_done_q;
|
||||
#endif /* CONFIG_NRF70_TX_DONE_WQ_ENABLED */
|
||||
|
||||
#ifdef CONFIG_NRF70_RX_WQ_ENABLED
|
||||
K_THREAD_STACK_DEFINE(rx_wq_stack_area, CONFIG_NRF70_RX_WQ_STACK_SIZE);
|
||||
struct k_work_q zep_wifi_rx_q;
|
||||
#endif /* CONFIG_NRF70_RX_WQ_ENABLED */
|
||||
|
||||
struct zep_work_item zep_work_item[CONFIG_NRF70_WORKQ_MAX_ITEMS];
|
||||
|
||||
int get_free_work_item_index(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONFIG_NRF70_WORKQ_MAX_ITEMS; i++) {
|
||||
if (zep_work_item[i].in_use)
|
||||
continue;
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void workqueue_callback(struct k_work *work)
|
||||
{
|
||||
struct zep_work_item *item = CONTAINER_OF(work, struct zep_work_item, work);
|
||||
|
||||
item->callback(item->data);
|
||||
}
|
||||
|
||||
struct zep_work_item *work_alloc(enum zep_work_type type)
|
||||
{
|
||||
int free_work_index = get_free_work_item_index();
|
||||
|
||||
if (free_work_index < 0) {
|
||||
LOG_ERR("%s: Reached maximum work items", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zep_work_item[free_work_index].in_use = true;
|
||||
zep_work_item[free_work_index].type = type;
|
||||
|
||||
return &zep_work_item[free_work_index];
|
||||
}
|
||||
|
||||
static int workqueue_init(void)
|
||||
{
|
||||
k_work_queue_init(&zep_wifi_bh_q);
|
||||
|
||||
k_work_queue_start(&zep_wifi_bh_q,
|
||||
bh_wq_stack_area,
|
||||
K_THREAD_STACK_SIZEOF(bh_wq_stack_area),
|
||||
CONFIG_NRF70_BH_WQ_PRIORITY,
|
||||
NULL);
|
||||
|
||||
k_thread_name_set(&zep_wifi_bh_q.thread, "nrf70_bh_wq");
|
||||
|
||||
k_work_queue_init(&zep_wifi_intr_q);
|
||||
|
||||
k_work_queue_start(&zep_wifi_intr_q,
|
||||
irq_wq_stack_area,
|
||||
K_THREAD_STACK_SIZEOF(irq_wq_stack_area),
|
||||
CONFIG_NRF70_IRQ_WQ_PRIORITY,
|
||||
NULL);
|
||||
|
||||
k_thread_name_set(&zep_wifi_intr_q.thread, "nrf70_intr_wq");
|
||||
#ifdef CONFIG_NRF70_TX_DONE_WQ_ENABLED
|
||||
k_work_queue_init(&zep_wifi_tx_done_q);
|
||||
|
||||
k_work_queue_start(&zep_wifi_tx_done_q,
|
||||
tx_done_wq_stack_area,
|
||||
K_THREAD_STACK_SIZEOF(tx_done_wq_stack_area),
|
||||
CONFIG_NRF70_TX_DONE_WQ_PRIORITY,
|
||||
NULL);
|
||||
|
||||
k_thread_name_set(&zep_wifi_tx_done_q.thread, "nrf70_tx_done_wq");
|
||||
#endif /* CONFIG_NRF70_TX_DONE_WQ_ENABLED */
|
||||
|
||||
#ifdef CONFIG_NRF70_RX_WQ_ENABLED
|
||||
k_work_queue_init(&zep_wifi_rx_q);
|
||||
|
||||
k_work_queue_start(&zep_wifi_rx_q,
|
||||
rx_wq_stack_area,
|
||||
K_THREAD_STACK_SIZEOF(rx_wq_stack_area),
|
||||
CONFIG_NRF70_RX_WQ_PRIORITY,
|
||||
NULL);
|
||||
|
||||
k_thread_name_set(&zep_wifi_rx_q.thread, "nrf70_rx_wq");
|
||||
#endif /* CONFIG_NRF70_RX_WQ_ENABLED */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void work_init(struct zep_work_item *item, void (*callback)(unsigned long),
|
||||
unsigned long data)
|
||||
{
|
||||
item->callback = callback;
|
||||
item->data = data;
|
||||
|
||||
k_work_init(&item->work, workqueue_callback);
|
||||
}
|
||||
|
||||
void work_schedule(struct zep_work_item *item)
|
||||
{
|
||||
if (item->type == ZEP_WORK_TYPE_IRQ)
|
||||
k_work_submit_to_queue(&zep_wifi_intr_q, &item->work);
|
||||
else if (item->type == ZEP_WORK_TYPE_BH)
|
||||
k_work_submit_to_queue(&zep_wifi_bh_q, &item->work);
|
||||
#ifdef CONFIG_NRF70_TX_DONE_WQ_ENABLED
|
||||
else if (item->type == ZEP_WORK_TYPE_TX_DONE)
|
||||
k_work_submit_to_queue(&zep_wifi_tx_done_q, &item->work);
|
||||
#endif /* CONFIG_NRF70_TX_DONE_WQ_ENABLED */
|
||||
#ifdef CONFIG_NRF70_RX_WQ_ENABLED
|
||||
else if (item->type == ZEP_WORK_TYPE_RX)
|
||||
k_work_submit_to_queue(&zep_wifi_rx_q, &item->work);
|
||||
#endif /* CONFIG_NRF70_RX_WQ_ENABLED */
|
||||
}
|
||||
|
||||
void work_kill(struct zep_work_item *item)
|
||||
{
|
||||
/* TODO: Based on context, use _sync version */
|
||||
k_work_cancel(&item->work);
|
||||
}
|
||||
|
||||
void work_free(struct zep_work_item *item)
|
||||
{
|
||||
item->in_use = 0;
|
||||
}
|
||||
|
||||
SYS_INIT(workqueue_init, POST_KERNEL, 0);
|
44
drivers/wifi/nrfwifi/src/work.h
Normal file
44
drivers/wifi/nrfwifi/src/work.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Header containing work specific declarations for the
|
||||
* Zephyr OS layer of the Wi-Fi driver.
|
||||
*/
|
||||
|
||||
#ifndef __WORK_H__
|
||||
#define __WORK_H__
|
||||
|
||||
|
||||
extern struct k_work_q zep_wifi_bh_q;
|
||||
|
||||
enum zep_work_type {
|
||||
ZEP_WORK_TYPE_BH,
|
||||
ZEP_WORK_TYPE_IRQ,
|
||||
ZEP_WORK_TYPE_TX_DONE,
|
||||
ZEP_WORK_TYPE_RX,
|
||||
};
|
||||
|
||||
struct zep_work_item {
|
||||
bool in_use;
|
||||
struct k_work work;
|
||||
unsigned long data;
|
||||
void (*callback)(unsigned long data);
|
||||
enum zep_work_type type;
|
||||
};
|
||||
|
||||
struct zep_work_item *work_alloc(enum zep_work_type);
|
||||
|
||||
void work_init(struct zep_work_item *work, void (*callback)(unsigned long callbk_data),
|
||||
unsigned long data);
|
||||
|
||||
void work_schedule(struct zep_work_item *work);
|
||||
|
||||
void work_kill(struct zep_work_item *work);
|
||||
|
||||
void work_free(struct zep_work_item *work);
|
||||
|
||||
#endif /* __WORK_H__ */
|
2761
drivers/wifi/nrfwifi/src/wpa_supp_if.c
Normal file
2761
drivers/wifi/nrfwifi/src/wpa_supp_if.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -907,6 +907,7 @@ flagged.
|
|||
"MYFEATURE",
|
||||
"MY_DRIVER_0",
|
||||
"NORMAL_SLEEP", # #defined by RV32M1 in ext/
|
||||
"NRF_WIFI_FW_BIN", # Directly passed from CMakeLists.txt
|
||||
"OPT",
|
||||
"OPT_0",
|
||||
"PEDO_THS_MIN",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue