From 3953bb9ce343586e3036821bb93d46954b42ea71 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Sun, 22 Dec 2024 00:43:04 +0530 Subject: [PATCH] nrf_wifi: Add nRF71 support nRF7120 PDK support that uses IPC as comms b/w APP and Wi-Fi domains. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf_wifi/CMakeLists.txt | 8 +- drivers/wifi/nrf_wifi/Kconfig.nrfwifi | 10 +- drivers/wifi/nrf_wifi/src/fmac_main.c | 4 + drivers/wifi/nrf_wifi/src/fw_load.c | 3 +- drivers/wifi/nrf_wifi/src/net_if.c | 10 + modules/nrf_wifi/bus/CMakeLists.txt | 19 +- modules/nrf_wifi/bus/Kconfig | 10 + modules/nrf_wifi/bus/device.c | 28 ++- modules/nrf_wifi/bus/ipc_if.c | 135 +++++++++++++ modules/nrf_wifi/bus/ipc_if.h | 48 +++++ modules/nrf_wifi/bus/ipc_service.c | 206 ++++++++++++++++++++ modules/nrf_wifi/bus/ipc_service.h | 260 ++++++++++++++++++++++++++ modules/nrf_wifi/bus/spsc_qm.c | 84 +++++++++ modules/nrf_wifi/bus/spsc_qm.h | 79 ++++++++ modules/nrf_wifi/os/CMakeLists.txt | 8 + modules/nrf_wifi/os/shim.c | 84 ++++++++- 16 files changed, 979 insertions(+), 17 deletions(-) create mode 100644 modules/nrf_wifi/bus/ipc_if.c create mode 100644 modules/nrf_wifi/bus/ipc_if.h create mode 100644 modules/nrf_wifi/bus/ipc_service.c create mode 100644 modules/nrf_wifi/bus/ipc_service.h create mode 100644 modules/nrf_wifi/bus/spsc_qm.c create mode 100644 modules/nrf_wifi/bus/spsc_qm.h diff --git a/drivers/wifi/nrf_wifi/CMakeLists.txt b/drivers/wifi/nrf_wifi/CMakeLists.txt index d59a6ef6e9f..383d58490c5 100644 --- a/drivers/wifi/nrf_wifi/CMakeLists.txt +++ b/drivers/wifi/nrf_wifi/CMakeLists.txt @@ -27,9 +27,11 @@ zephyr_library_sources_ifndef(CONFIG_NRF70_OFFLOADED_RAW_TX src/fmac_main.c ) -zephyr_library_sources_ifdef(CONFIG_NRF_WIFI_PATCHES_BUILTIN - src/fw_load.c -) +if(NOT CONFIG_NRF71_ON_IPC) + zephyr_library_sources_ifdef(CONFIG_NRF_WIFI_PATCHES_BUILTIN + src/fw_load.c + ) +endif() if(NOT CONFIG_NRF70_RADIO_TEST AND NOT CONFIG_NRF70_OFFLOADED_RAW_TX) zephyr_library_sources( diff --git a/drivers/wifi/nrf_wifi/Kconfig.nrfwifi b/drivers/wifi/nrf_wifi/Kconfig.nrfwifi index a8bd7e83fa8..130e49d0901 100644 --- a/drivers/wifi/nrf_wifi/Kconfig.nrfwifi +++ b/drivers/wifi/nrf_wifi/Kconfig.nrfwifi @@ -5,6 +5,9 @@ # SPDX-License-Identifier: Apache-2.0 # +# TODO: Use DTS generated Kconfig once the board support is added +DT_COMPAT_NORDIC_WIFI71 := nordic,wifi71 + menuconfig WIFI_NRF70 bool "nRF70 driver" select NET_L2_WIFI_MGMT if NETWORKING @@ -16,7 +19,8 @@ menuconfig WIFI_NRF70 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 + DT_HAS_NORDIC_NRF7000_SPI_ENABLED || DT_HAS_NORDIC_NRF7000_QSPI_ENABLED || \ + $(dt_compat_enabled,$(DT_COMPAT_NORDIC_WIFI71)) help Nordic Wi-Fi Driver @@ -24,7 +28,7 @@ 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 + default y if DT_HAS_NORDIC_NRF7002_SPI_ENABLED || DT_HAS_NORDIC_NRF7002_QSPI_ENABLED || $(dt_compat_enabled,$(DT_COMPAT_NORDIC_WIFI71)) config WIFI_NRF7001 bool @@ -151,6 +155,7 @@ endchoice config NRF_WIFI_LOW_POWER bool "Low power mode in nRF Wi-Fi chipsets" depends on !NRF70_RADIO_TEST && !NRF70_AP_MODE + depends on !NRF71_ON_IPC default y config NRF70_TCP_IP_CHECKSUM_OFFLOAD @@ -202,6 +207,7 @@ config NRF70_SR_COEX_RF_SWITCH config NRF70_SR_COEX_SLEEP_CTRL_GPIO_CTRL bool "Configuration of GPIO control for coexistence" + depends on !NRF71_ON_IPC default y config NRF70_SR_COEX_SWCTRL1_OUTPUT diff --git a/drivers/wifi/nrf_wifi/src/fmac_main.c b/drivers/wifi/nrf_wifi/src/fmac_main.c index 0559ca48f7c..b218bc13add 100644 --- a/drivers/wifi/nrf_wifi/src/fmac_main.c +++ b/drivers/wifi/nrf_wifi/src/fmac_main.c @@ -485,8 +485,12 @@ void reg_change_callbk_fn(void *vif_ctx, } #endif /* !CONFIG_NRF70_RADIO_TEST */ +#ifdef CONFIG_NRF71_ON_IPC +#define MAX_TX_PWR(label) DT_PROP(DT_NODELABEL(wifi), label) * 4 +#else /* 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 +#endif /* CONFIG_NRF71_ON_IPC */ 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) diff --git a/drivers/wifi/nrf_wifi/src/fw_load.c b/drivers/wifi/nrf_wifi/src/fw_load.c index 9204d295d30..f09643a585a 100644 --- a/drivers/wifi/nrf_wifi/src/fw_load.c +++ b/drivers/wifi/nrf_wifi/src/fw_load.c @@ -31,12 +31,13 @@ enum nrf_wifi_status nrf_wifi_fw_load(void *rpu_ctx) LOG_ERR("%s: nrf_wifi_fmac_fw_parse failed", __func__); return status; } +#ifndef CONFIG_NRF71_ON_IPC /* 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__); } - +#endif /* !CONFIG_NRF71_ON_IPC */ return status; } diff --git a/drivers/wifi/nrf_wifi/src/net_if.c b/drivers/wifi/nrf_wifi/src/net_if.c index 0a4c189e689..aff943127a5 100644 --- a/drivers/wifi/nrf_wifi/src/net_if.c +++ b/drivers/wifi/nrf_wifi/src/net_if.c @@ -575,6 +575,7 @@ enum nrf_wifi_status nrf_wifi_get_mac_addr(struct nrf_wifi_vif_ctx_zep *vif_ctx_ random_mac_addr, WIFI_MAC_ADDR_LEN); #elif CONFIG_WIFI_OTP_MAC_ADDRESS +#ifndef CONFIG_NRF71_ON_IPC status = nrf_wifi_fmac_otp_mac_addr_get(fmac_dev_ctx, vif_ctx_zep->vif_idx, vif_ctx_zep->mac_addr.addr); @@ -583,6 +584,15 @@ enum nrf_wifi_status nrf_wifi_get_mac_addr(struct nrf_wifi_vif_ctx_zep *vif_ctx_ __func__); goto unlock; } +#else + /* Set dummy MAC address */ + vif_ctx_zep->mac_addr.addr[0] = 0x00; + vif_ctx_zep->mac_addr.addr[1] = 0x00; + vif_ctx_zep->mac_addr.addr[2] = 0x5E; + vif_ctx_zep->mac_addr.addr[3] = 0x00; + vif_ctx_zep->mac_addr.addr[4] = 0x10; + vif_ctx_zep->mac_addr.addr[5] = 0x00; +#endif /* !CONFIG_NRF71_ON_IPC */ #endif if (!nrf_wifi_utils_is_mac_addr_valid(vif_ctx_zep->mac_addr.addr)) { diff --git a/modules/nrf_wifi/bus/CMakeLists.txt b/modules/nrf_wifi/bus/CMakeLists.txt index c36fec9d737..829b48d1aab 100644 --- a/modules/nrf_wifi/bus/CMakeLists.txt +++ b/modules/nrf_wifi/bus/CMakeLists.txt @@ -26,8 +26,18 @@ if (CONFIG_NRF70_BUSLIB) inc ${NRF_WIFI_DIR}/os_if/inc ) + zephyr_library_include_directories_ifdef(CONFIG_NRF71_ON_IPC + ${NRF_WIFI_DIR}/bus_if/bal/inc + # QSPI is common to (Q)SPI and IPC + ${NRF_WIFI_DIR}/bus_if/bus/qspi/inc + ${NRF_WIFI_DIR}/fw_if/umac_if/inc/fw + ${NRF_WIFI_DIR}/hw_if/hal/inc + ) + + zephyr_library_compile_definitions_ifdef(CONFIG_NRF71_ON_IPC + NRF71_ON_IPC + ) zephyr_library_sources( - rpu_hw_if.c device.c ) if(NOT CONFIG_WIFI_NRF70) @@ -36,9 +46,16 @@ if (CONFIG_NRF70_BUSLIB) ) endif() zephyr_library_sources_ifdef(CONFIG_NRF70_ON_QSPI + rpu_hw_if.c qspi_if.c ) zephyr_library_sources_ifdef(CONFIG_NRF70_ON_SPI + rpu_hw_if.c spi_if.c ) + zephyr_library_sources_ifdef(CONFIG_NRF71_ON_IPC + ipc_if.c + ipc_service.c + spsc_qm.c + ) endif() diff --git a/modules/nrf_wifi/bus/Kconfig b/modules/nrf_wifi/bus/Kconfig index 152904e86b7..fe6b0f34553 100644 --- a/modules/nrf_wifi/bus/Kconfig +++ b/modules/nrf_wifi/bus/Kconfig @@ -10,6 +10,7 @@ DT_COMPAT_NORDIC_NRF7001_QSPI := nordic,nrf7001-qspi DT_COMPAT_NORDIC_NRF7001_SPI := nordic,nrf7001-spi DT_COMPAT_NORDIC_NRF7000_QSPI := nordic,nrf7000-qspi DT_COMPAT_NORDIC_NRF7000_SPI := nordic,nrf7000-spi +DT_COMPAT_NORDIC_WIFI71 := nordic,wifi71 menuconfig NRF70_BUSLIB bool "NRF70 Bus Library" @@ -30,6 +31,15 @@ config NRF70_ON_SPI $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF7000_SPI)) select SPI +config NRF71_ON_IPC + def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_WIFI71)) + select MBOX + select IPC_SERVICE + select SPSC_PBUF + help + nRF71 is a Wi-Fi and BLE combo SoC and uses IPC as a communication + between APP and Wi-Fi cores. + module = WIFI_NRF70_BUSLIB module-dep = LOG module-str = Log level for Wi-Fi nRF70 bus library diff --git a/modules/nrf_wifi/bus/device.c b/modules/nrf_wifi/bus/device.c index 8cf0b77cd67..611af2489c8 100644 --- a/modules/nrf_wifi/bus/device.c +++ b/modules/nrf_wifi/bus/device.c @@ -12,15 +12,26 @@ #include #include #include -#include #include #include +#if defined(CONFIG_NRF71_ON_IPC) +#include "ipc_if.h" +#else +#include #include "spi_if.h" - static struct qspi_config config; +#endif -#if defined(CONFIG_NRF70_ON_QSPI) +#if defined(CONFIG_NRF71_ON_IPC) +static struct rpu_dev ipc = { + .init = ipc_init, + .deinit = ipc_deinit, + .send = ipc_send, + .recv = ipc_recv, + .register_rx_cb = ipc_register_rx_cb, +}; +#elif defined(CONFIG_NRF70_ON_QSPI) static struct qspi_dev qspi = {.init = qspi_init, .deinit = qspi_deinit, .read = qspi_read, @@ -34,6 +45,7 @@ static struct qspi_dev spim = {.init = spim_init, .hl_read = spim_hl_read}; #endif +#ifndef CONFIG_NRF71_ON_IPC struct qspi_config *qspi_defconfig(void) { memset(&config, 0, sizeof(struct qspi_config)); @@ -71,12 +83,20 @@ struct qspi_config *qspi_get_config(void) { return &config; } +#endif +#ifndef CONFIG_NRF71_ON_IPC struct qspi_dev *qspi_dev(void) { -#if CONFIG_NRF70_ON_QSPI +#if defined(CONFIG_NRF70_ON_QSPI) return &qspi; #else return &spim; #endif } +#else +struct rpu_dev *rpu_dev(void) +{ + return &ipc; +} +#endif /*! CONFIG_NRF71_ON_IPC */ diff --git a/modules/nrf_wifi/bus/ipc_if.c b/modules/nrf_wifi/bus/ipc_if.c new file mode 100644 index 00000000000..cd2365a9af0 --- /dev/null +++ b/modules/nrf_wifi/bus/ipc_if.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief File containing API definitions for the + * IPC bus layer of the nRF71 Wi-Fi driver. + */ +#include +#include + +LOG_MODULE_DECLARE(wifi_nrf_bus, CONFIG_WIFI_NRF70_BUSLIB_LOG_LEVEL); + +#include "ipc_if.h" +#include "bal_structs.h" +#include "qspi.h" +#include "common/hal_structs_common.h" + +/* Define addresses to use for the free queues */ +#define EVENT_FREEQ_ADDR 0x200C2000 +#define CMD_FREEQ_ADDR 0x200C3000 + +#define NUM_INSTANCES 3 +#define NUM_ENDPOINTS 1 + +struct device *ipc_instances[NUM_INSTANCES]; +struct ipc_ept ept[NUM_ENDPOINTS]; +struct ipc_ept_cfg ept_cfg[NUM_ENDPOINTS]; + +static wifi_ipc_t wifi_event; +static wifi_ipc_t wifi_cmd; +static wifi_ipc_t wifi_tx; + +static int (*callback_func)(void *data); + +static void event_recv(void *data, void *priv) +{ + struct nrf_wifi_bus_qspi_dev_ctx *dev_ctx = NULL; + struct nrf_wifi_bal_dev_ctx *bal_dev_ctx = NULL; + struct nrf_wifi_hal_dev_ctx *hal_dev_ctx = NULL; + + dev_ctx = (struct nrf_wifi_bus_qspi_dev_ctx *)priv; + bal_dev_ctx = (struct nrf_wifi_bal_dev_ctx *)dev_ctx->bal_dev_ctx; + hal_dev_ctx = (struct nrf_wifi_hal_dev_ctx *)bal_dev_ctx->hal_dev_ctx; + LOG_DBG("Event IPC received"); + + hal_dev_ctx->ipc_msg = data; + callback_func(priv); + LOG_DBG("Event IPC callback completed"); +} + +int ipc_init(void) +{ + wifi_ipc_host_event_init(&wifi_event, EVENT_FREEQ_ADDR); + LOG_DBG("Event IPC initialized"); + wifi_ipc_host_cmd_init(&wifi_cmd, CMD_FREEQ_ADDR); + LOG_DBG("Command IPC initialized"); + return 0; +} + +int ipc_deinit(void) +{ + return 0; +} + +int ipc_recv(ipc_ctx_t ctx, void *data, int len) +{ + return 0; +} + +int ipc_send(ipc_ctx_t ctx, const void *data, int len) +{ + + int ret = 0; + + switch (ctx.inst) { + case IPC_INSTANCE_CMD_CTRL: + /* IPC service on RPU may not have been established. Keep trying. */ + do { + ret = wifi_ipc_host_cmd_send_memcpy(&wifi_cmd, data, len); + } while (ret == WIFI_IPC_STATUS_BUSYQ_NOTREADY); + + /* Critical error during IPC service transfer. Should never happen. */ + if (ret == WIFI_IPC_STATUS_BUSYQ_CRITICAL_ERR) { + LOG_ERR("Critical error during IPC CMD busyq transfer"); + return -1; + } + break; + case IPC_INSTANCE_CMD_TX: + /* IPC service on RPU may not have been established. Keep trying. */ + do { + ret = wifi_ipc_host_tx_send(&wifi_tx, data); + } while (ret == WIFI_IPC_STATUS_BUSYQ_NOTREADY); + + /* Critical error during IPC service transfer. Should never happen. */ + if (ret == WIFI_IPC_STATUS_BUSYQ_CRITICAL_ERR) { + LOG_ERR("Critical error during IPC TX busyq transfer"); + return -1; + } + break; + case IPC_INSTANCE_RX: + break; + default: + break; + } + + LOG_DBG("IPC send completed: %d", ret); + + return ret; +} + +int ipc_register_rx_cb(int (*rx_handler)(void *priv), void *data) +{ + int ret; + + callback_func = rx_handler; + + ret = wifi_ipc_bind_ipc_service_tx_rx(&wifi_cmd, &wifi_event, + DEVICE_DT_GET(DT_NODELABEL(ipc0)), event_recv, data); + if (ret != WIFI_IPC_STATUS_OK) { + LOG_ERR("Failed to bind IPC service: %d", ret); + return -1; + } + + ret = wifi_ipc_bind_ipc_service(&wifi_tx, DEVICE_DT_GET(DT_NODELABEL(ipc1)), event_recv, + data); + if (ret != WIFI_IPC_STATUS_OK) { + LOG_ERR("Failed to bind IPC service: %d", ret); + return -1; + } + + return 0; +} diff --git a/modules/nrf_wifi/bus/ipc_if.h b/modules/nrf_wifi/bus/ipc_if.h new file mode 100644 index 00000000000..5dbc2edf4f4 --- /dev/null +++ b/modules/nrf_wifi/bus/ipc_if.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __IPC_IF_H__ +#define __IPC_IF_H__ + +#include +#include "ipc_service.h" + +typedef enum { + IPC_INSTANCE_CMD_CTRL = 0, + IPC_INSTANCE_CMD_TX, + IPC_INSTANCE_EVT, + IPC_INSTANCE_RX +} ipc_instances_nrf71_t; + +typedef enum { + IPC_EPT_UMAC = 0, + IPC_EPT_LMAC +} ipc_epts_nrf71_t; + +typedef struct ipc_ctx { + ipc_instances_nrf71_t inst; + ipc_epts_nrf71_t ept; +} ipc_ctx_t; + +struct rpu_dev { + int (*init)(); + int (*deinit)(void); + int (*send)(ipc_ctx_t ctx, const void *data, int len); + int (*recv)(ipc_ctx_t ctx, void *data, int len); + int (*register_rx_cb)(int (*rx_handler)(void *priv), void *data); +}; + +struct rpu_dev *rpu_dev(void); + +int ipc_init(void); +int ipc_deinit(void); +int ipc_send(ipc_ctx_t ctx, const void *data, int len); +/* Blocking Receive */ +int ipc_recv(ipc_ctx_t ctx, void *data, int len); +/* Non-blocking Receive (global, not per instance) */ +int ipc_register_rx_cb(int (*rx_handler)(void *priv), void *data); + +#endif /* __IPC_IF_H__ */ diff --git a/modules/nrf_wifi/bus/ipc_service.c b/modules/nrf_wifi/bus/ipc_service.c new file mode 100644 index 00000000000..e1e6b3cf4fb --- /dev/null +++ b/modules/nrf_wifi/bus/ipc_service.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief File containing API definitions for the + * IPC service layer of the nrf71 Wi-Fi driver. + */ +#include +#include + +LOG_MODULE_REGISTER(wifi_nrf_bus, CONFIG_WIFI_NRF70_BUSLIB_LOG_LEVEL); + +#include "ipc_service.h" + +static void wifi_ipc_ep_bound(void *priv) +{ + wifi_ipc_t *context = (wifi_ipc_t *)priv; + + context->busy_q.ipc_ready = true; +} + +static void wifi_ipc_recv_callback(const void *data, size_t len, void *priv) +{ + (void)len; + uint32_t global_addr = *((uint32_t *)data); + + wifi_ipc_t *context = (wifi_ipc_t *)priv; + + context->busy_q.recv_cb((void *)global_addr, context->busy_q.priv); + + if (context->free_q != NULL) { + while (!spsc32_push(context->free_q, global_addr)) { + }; + } +} + +static void wifi_ipc_busyq_init(wifi_ipc_busyq_t *busyq, const ipc_device_wrapper_t *ipc_inst, + void *rx_cb, void *priv) +{ + busyq->ipc_inst = ipc_inst; + busyq->ipc_ep_cfg.cb.bound = wifi_ipc_ep_bound; + busyq->ipc_ep_cfg.cb.received = wifi_ipc_recv_callback; + busyq->recv_cb = rx_cb; + busyq->ipc_ready = false; + busyq->priv = priv; +} + +/** + * Register the IPC service on the busy_queue + */ +static wifi_ipc_status_t wifi_ipc_busyq_register(wifi_ipc_t *context) +{ + int ret; + const struct device *ipc_instance = GET_IPC_INSTANCE(context->busy_q.ipc_inst); + + ret = ipc_service_open_instance(ipc_instance); + if (ret < 0) { + return WIFI_IPC_STATUS_INIT_ERR; + } + + context->busy_q.ipc_ep_cfg.name = "ep"; + context->busy_q.ipc_ep_cfg.priv = context; + + ret = ipc_service_register_endpoint(ipc_instance, &context->busy_q.ipc_ep, + &context->busy_q.ipc_ep_cfg); + if (ret < 0 && ret != -EALREADY) { + return WIFI_IPC_STATUS_INIT_ERR; + } + + LOG_INF("IPC busy queue registered"); + + return WIFI_IPC_STATUS_OK; +} + +wifi_ipc_status_t wifi_ipc_bind_ipc_service(wifi_ipc_t *context, + const ipc_device_wrapper_t *ipc_inst, + void (*rx_cb)(void *data, void *priv), void *priv) +{ + wifi_ipc_busyq_init(&context->busy_q, ipc_inst, rx_cb, priv); + return wifi_ipc_busyq_register(context); +} + +wifi_ipc_status_t wifi_ipc_bind_ipc_service_tx_rx(wifi_ipc_t *tx, wifi_ipc_t *rx, + const ipc_device_wrapper_t *ipc_inst, + void (*rx_cb)(void *data, void *priv), void *priv) +{ + wifi_ipc_busyq_init(&rx->busy_q, ipc_inst, rx_cb, priv); + + /** + * When initialising an IPC service, both TX and RX mailboxes need to be + * registered at the same time using a single function call. Both tx and + * rx need to refer to the same IPC instance. + */ + tx->linked_ipc = &rx->busy_q; + + return wifi_ipc_busyq_register(rx); +} + +wifi_ipc_status_t wifi_ipc_freeq_get(wifi_ipc_t *context, uint32_t *data) +{ + if (context->free_q == NULL) { + LOG_ERR("Free queue is not initialised"); + return WIFI_IPC_STATUS_FREEQ_UNINIT_ERR; + } + + if (spsc32_is_empty(context->free_q)) { + LOG_DBG("Free queue is empty"); + return WIFI_IPC_STATUS_FREEQ_EMPTY; + } + + if (!spsc32_read_head(context->free_q, data)) { + LOG_DBG("Free queue is empty"); + return WIFI_IPC_STATUS_FREEQ_EMPTY; + } + + return WIFI_IPC_STATUS_OK; +} + +wifi_ipc_status_t wifi_ipc_freeq_send(wifi_ipc_t *context, uint32_t data) +{ + return (spsc32_push(context->free_q, data) == true ? WIFI_IPC_STATUS_OK + : WIFI_IPC_STATUS_FREEQ_FULL); +} + +wifi_ipc_status_t wifi_ipc_busyq_send(wifi_ipc_t *context, uint32_t *data) +{ + /* Get correct linked endpoint */ + wifi_ipc_busyq_t *busyq = + context->linked_ipc ? context->linked_ipc : &context->busy_q; + + if (!busyq->ipc_ready) { + LOG_ERR("IPC service is not ready"); + return WIFI_IPC_STATUS_BUSYQ_NOTREADY; + } + + int ret = ipc_service_send(&busyq->ipc_ep, data, sizeof(*data)); + + if (ret == -ENOMEM) { + LOG_ERR("No space in the buffer"); + /* No space in the buffer */ + return WIFI_IPC_STATUS_BUSYQ_FULL; + } else if (ret < 0) { + LOG_ERR("Critical IPC failure: %d", ret); + /* Critical IPC failure */ + return WIFI_IPC_STATUS_BUSYQ_CRITICAL_ERR; + } + + if (context->free_q != NULL) { + /* Free up global address pointer from the free queue */ + uint32_t data_out; + + return (spsc32_pop(context->free_q, &data_out) == true + ? (*data == data_out ? WIFI_IPC_STATUS_OK + : WIFI_IPC_STATUS_FREEQ_INVALID) + : WIFI_IPC_STATUS_FREEQ_EMPTY); + } + + return WIFI_IPC_STATUS_OK; +} + +wifi_ipc_status_t wifi_ipc_host_cmd_init(wifi_ipc_t *context, uint32_t addr_freeq) +{ + context->free_q = (void *)addr_freeq; + return WIFI_IPC_STATUS_OK; +} + +wifi_ipc_status_t wifi_ipc_host_event_init(wifi_ipc_t *context, uint32_t addr_freeq) +{ + context->free_q = (void *)addr_freeq; + return WIFI_IPC_STATUS_OK; +} + +wifi_ipc_status_t wifi_ipc_host_cmd_get(wifi_ipc_t *context, uint32_t *data) +{ + return wifi_ipc_freeq_get(context, data); +} + +wifi_ipc_status_t wifi_ipc_host_cmd_send(wifi_ipc_t *context, uint32_t *data) +{ + return wifi_ipc_busyq_send(context, data); +} + +wifi_ipc_status_t wifi_ipc_host_cmd_send_memcpy(wifi_ipc_t *context, const void *msg, + size_t len) +{ + int ret; + uint32_t gdram_addr; + + ret = wifi_ipc_host_cmd_get(context, &gdram_addr); + if (ret != WIFI_IPC_STATUS_OK) { + LOG_ERR("Failed to get command location from free queue: %d", ret); + return ret; + } + + memcpy((void *)gdram_addr, msg, len); + + return wifi_ipc_host_cmd_send(context, &gdram_addr); +} + +wifi_ipc_status_t wifi_ipc_host_tx_send(wifi_ipc_t *context, const void *msg) +{ + return wifi_ipc_host_cmd_send(context, (uint32_t *)&msg); +} diff --git a/modules/nrf_wifi/bus/ipc_service.h b/modules/nrf_wifi/bus/ipc_service.h new file mode 100644 index 00000000000..3d355e0c23a --- /dev/null +++ b/modules/nrf_wifi/bus/ipc_service.h @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef IPC_SERVICE_H +#define IPC_SERVICE_H + +#include +#include +#include "spsc_qm.h" + +#define GET_IPC_INSTANCE(dev) (dev) +typedef struct device ipc_device_wrapper_t; + +#include +#include + +/* + * Must be large enough to contain the internal struct (spsc_pbuf struct) and + * at least two bytes of data (one is reserved for written message length) + */ +#define _MIN_SPSC_SIZE (sizeof(spsc_queue_t) + sizeof(uint32_t)) +/* + * TODO: Unsure why some additional bytes are needed for overhead. + */ +#define WIFI_IPC_GET_SPSC_SIZE(x) (_MIN_SPSC_SIZE + 12 + (x)) + +/* 4 x cmd location 32-bit pointers of 400 bytes each */ +#define WIFI_IPC_CMD_SIZE 400 +#define WIFI_IPC_CMD_NUM 4 +#define WIFI_IPC_CMD_SPSC_SIZE WIFI_IPC_GET_SPSC_SIZE(WIFI_IPC_CMD_NUM * sizeof(uint32_t)) + +/* 7 x event location 32-bit pointers of 1000 bytes each */ +#define WIFI_IPC_EVENT_SIZE 1000 +#define WIFI_IPC_EVENT_NUM 7 +#define WIFI_IPC_EVENT_SPSC_SIZE WIFI_IPC_GET_SPSC_SIZE(WIFI_IPC_EVENT_NUM * sizeof(uint32_t)) + +/** + * @enum wifi_ipc_status_t + * @brief Status codes for the Wi-Fi IPC service. + * + * This enumeration defines various status codes that represent + * the state or result of operations in the Wi-Fi IPC service. + */ +typedef enum { + /** Status indicating the operation completed successfully. */ + WIFI_IPC_STATUS_OK = 0, + + /** Error indicating failure to register IPC service for the Busy queue. */ + WIFI_IPC_STATUS_INIT_ERR, + + /** Error indicating that the Free queue has not been initialized. */ + WIFI_IPC_STATUS_FREEQ_UNINIT_ERR, + + /** Status indicating that the Free queue is empty. */ + WIFI_IPC_STATUS_FREEQ_EMPTY, + + /** Error indicating that the value passed to wifi_ipc_busyq_send() + * does not match the value from the Free queue. + */ + WIFI_IPC_STATUS_FREEQ_INVALID, + + /** Status indicating that the Free queue is full. */ + WIFI_IPC_STATUS_FREEQ_FULL, + + /** Error indicating that the IPC service for the Busy queue connection + * has not been established. + */ + WIFI_IPC_STATUS_BUSYQ_NOTREADY, + + /** Status indicating that the Busy queue is full. */ + WIFI_IPC_STATUS_BUSYQ_FULL, + + /** Critical error indicating an IPC transfer failure. This should never happen. */ + WIFI_IPC_STATUS_BUSYQ_CRITICAL_ERR, +} wifi_ipc_status_t; + +/** + * Structure to hold context information for busy queue. + */ +typedef struct { + const ipc_device_wrapper_t *ipc_inst; + struct ipc_ept ipc_ep; + struct ipc_ept_cfg ipc_ep_cfg; + void (*recv_cb)(const void *data, const void *priv); + const void *priv; + volatile bool ipc_ready; +} wifi_ipc_busyq_t; + +/** + * Top-level structure to hold context information for sending data between RPU + * and the Host. + */ +typedef struct { + spsc_queue_t *free_q; + + wifi_ipc_busyq_t busy_q; + wifi_ipc_busyq_t *linked_ipc; +} wifi_ipc_t; + +/** + * Performs memory-to-memory copy via MVDMA. + * + * Enters low power state by issuing wait-for-interrupt (WFI) while waiting for + * MVDMA event to complete. + * + * @param[in] p_dest : Pointer to destination memory to be copied to. + * @param[in] p_src : Pointer to source memory to be copied from. + * @param[in] len : Number of bytes to be copied. + */ +void wifi_ipc_mvdma_copy(void *p_dest, const void *p_src, size_t len); + +/** + * Bind either TX or RX context to one IPC service. This utilises the half-duplex + * capability of the IPC service. + * + * @param[in] p_context : Pointer to wifi_ipc_t struct. + * @param[in] ipc_inst : Pointer to the IPC instance. + * @param[in] rx_cb : If binding RX context, this is the callback function. + * Leave NULL if binding to a TX. + * @param[in] priv : If binding RX context, this is the private data to be passed + * along with the callback function. + * Leave NULL if binding to a TX. + * @return : wifi_ipc_status_ok if successful, otherwise wifi_ipc_status_init_err. + */ +wifi_ipc_status_t wifi_ipc_bind_ipc_service(wifi_ipc_t *p_context, + const ipc_device_wrapper_t *ipc_inst, + void (*rx_cb)(void *data, void *priv), void *priv); + +/** + * Bind both TX and RX contexts to a single IPC service. This utilises the + * full-duplex capability of the IPC service. + * + * @param[in] p_tx : Pointer to wifi_ipc_t struct to bind IPC TX mailbox to. + * @param[in] p_rx : Pointer to wifi_ipc_t struct to bind IPC RX mailbox to. + * @param[in] ipc_inst : Pointer to the IPC instance. + * @param[in] rx_cb : Callback function to bind to data in received from RX mailbox. + * @param[in] priv : Private data to the callback function. + * @return : wifi_ipc_status_ok if successful, otherwise wifi_ipc_status_init_err. + */ +wifi_ipc_status_t wifi_ipc_bind_ipc_service_tx_rx(wifi_ipc_t *p_tx, wifi_ipc_t *p_rx, + const ipc_device_wrapper_t *ipc_inst, + void (*rx_cb)(void *data, void *priv), + void *priv); + +/** + * Get data from the free queue. + * + * @param[in] p_context : Pointer to wifi_ipc_t struct. + * @param[out] data : Pointer to the data to read to. + * @return : wifi_ipc_status_ok if successful, otherwise wifi_ipc_status_freeq_empty. + */ +wifi_ipc_status_t wifi_ipc_freeq_get(wifi_ipc_t *p_context, uint32_t *data); + +/** + * Send data to the free queue. + * + * @param[in] p_context : Pointer to wifi_ipc_t struct. + * @param[in] data : 32-bit data to send. + * @return : wifi_ipc_status_ok if successful, otherwise wifi_ipc_status_freeq_full. + */ +wifi_ipc_status_t wifi_ipc_freeq_send(wifi_ipc_t *p_context, uint32_t data); + +/** + * Send data to the busy queue over IPC service, and pop the same data from the + * free queue. + * + * @param[in] p_context : Pointer to wifi_ipc_t struct. + * @param[in] data : Pointer to the data to send to. + * @return : wifi_ipc_status_ok if successful, otherwise one of the following: + * - wifi_ipc_status_busyq_notready + * - wifi_ipc_status_busyq_full + * - wifi_ipc_status_busyq_critical_err + * - wifi_ipc_status_freeq_invalid + * - wifi_ipc_status_freeq_empty + */ +wifi_ipc_status_t wifi_ipc_busyq_send(wifi_ipc_t *p_context, uint32_t *data); + +/** + * Prepares and initialises the Host for sending a command to RPU. + * + * The free queue points to the already allocated free queue from the RPU. + * + * The busy queue using IPC service must be initialised using @see wifi_ipc_bind_ipc_service() + * or @see wifi_ipc_bind_ipc_service_tx_rx(). + * + * @param[in] p_context : Pointer to wifi_ipc_t struct. + * @param[in] addr_freeq : Address of the allocated free queue. + * @return : wifi_ipc_status_ok if successful. + */ +wifi_ipc_status_t wifi_ipc_host_cmd_init(wifi_ipc_t *p_context, uint32_t addr_freeq); + +/** + * Prepares and initialises the Host for receiving an event from RPU. + * + * The free queue points to the already allocated free queue from the RPU. + * + * The busy queue using IPC service must be initialised using @see wifi_ipc_bind_ipc_service() + * or @see wifi_ipc_bind_ipc_service_tx_rx(). + * + * @param[in] p_context : Pointer to wifi_ipc_t struct. + * @param[in] addr_freeq : Address of the allocated SPSC free queue. + * @return : wifi_ipc_status_ok if successful. + */ +wifi_ipc_status_t wifi_ipc_host_event_init(wifi_ipc_t *p_context, uint32_t addr_freeq); + +/** + * Get a command location from the free queue. + * + * @param[in] p_context : Pointer to wifi_ipc_t struct. + * @param[out] p_data : Pointer to data to write event location to. + * @return : wifi_ipc_status_ok if successful, otherwise wifi_ipc_status_freeq_empty. + */ +wifi_ipc_status_t wifi_ipc_host_cmd_get(wifi_ipc_t *p_context, uint32_t *p_data); + +/** + * Send an event location pointer to the Host and frees up the event location + * pointer from the free queue. + * + * @param[in] p_context : Pointer to wifi_ipc_t struct. + * @param[in] p_data : Pointer to command location to be sent. + * @return : wifi_ipc_status_ok if successful, otherwise one of the following + * - wifi_ipc_status_busyq_notready + * - wifi_ipc_status_busyq_full + * - wifi_ipc_status_busyq_critical_err + * - wifi_ipc_status_freeq_invalid + * - wifi_ipc_status_freeq_empty + */ +wifi_ipc_status_t wifi_ipc_host_cmd_send(wifi_ipc_t *p_context, uint32_t *p_data); + +/** + * Send a command from the Host to RPU using standard memcpy. + * + * 1. Retrieves an address pointer of Packet RAM from the free queue. + * 2. Copies local message to the retrieved address pointer via memcpy. + * 3. Sends the address pointer to the busy queue via IPC service. + * 4. Upon successful transmission, removes the address pointer the free queue. + * + * @param[in] p_context : Pointer to wifi_ipc_t struct. + * @param[in] p_msg : Pointer the local message to be copied to Packet RAM via memcpy. + * @param[in] len : Length of the local message in bytes. + * @return : wifi_ipc_status_ok if send is successful, otherwise one of + * status code from wifi_ipc_status_t will be returned. + */ +wifi_ipc_status_t wifi_ipc_host_cmd_send_memcpy(wifi_ipc_t *p_context, const void *p_msg, + size_t len); + +/** + * Send a tx data pointer from the Host to RPU and raises RPU interrupt. + * + * @param[in] p_context : Pointer to wifi_ipc_t struct. + * @param[in] p_msg : Pointer to message. + * @return : wifi_ipc_status_ok if send is successful, otherwise one of + * status code from wifi_ipc_status_t will be returned. + */ +wifi_ipc_status_t wifi_ipc_host_tx_send(wifi_ipc_t *p_context, const void *p_msg); + +#endif /* IPC_SERVICE_H */ diff --git a/modules/nrf_wifi/bus/spsc_qm.c b/modules/nrf_wifi/bus/spsc_qm.c new file mode 100644 index 00000000000..01da1b5e897 --- /dev/null +++ b/modules/nrf_wifi/bus/spsc_qm.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief File containing API definitions for the + * SPSC queue management layer of the nRF71 Wi-Fi driver. + */ +#include +#include + +LOG_MODULE_DECLARE(wifi_nrf_bus, CONFIG_WIFI_NRF70_BUSLIB_LOG_LEVEL); + +#include "spsc_qm.h" + +spsc_queue_t *spsc32_init(uint32_t address, size_t size) +{ + return spsc_pbuf_init((void *)address, size, 0); +} + +bool spsc32_push(spsc_queue_t *queue, uint32_t value) +{ + char *pbuf; + uint8_t len = sizeof(uint32_t); + + if (spsc_pbuf_alloc(queue, len, &pbuf) != len) { + LOG_ERR("%s: Failed to allocate buffer", __func__); + return false; + } + + memcpy(pbuf, &value, len); + spsc_pbuf_commit(queue, len); + + return true; +} + +bool spsc32_pop(spsc_queue_t *queue, uint32_t *out_value) +{ + char *buf; + uint16_t plen = spsc_pbuf_claim(queue, &buf); + + if (plen == 0) { + LOG_ERR("%s: Failed to claim buffer", __func__); + return false; + } + + spsc_pbuf_free(queue, plen); + + *out_value = *((uint32_t *)buf); + + return true; +} + +bool spsc32_read_head(spsc_queue_t *queue, uint32_t *out_value) +{ + char *buf; + uint16_t plen = spsc_pbuf_claim(queue, &buf); + + if (plen == 0) { + LOG_ERR("%s: Failed to claim buffer", __func__); + return false; + } + + *out_value = *((uint32_t *)buf); + + return true; +} + +bool spsc32_is_empty(spsc_queue_t *queue) +{ + char *buf; + + return spsc_pbuf_claim(queue, &buf) == 0; +} + +bool spsc32_is_full(spsc_queue_t *queue) +{ + char *pbuf; + uint8_t len = sizeof(uint32_t); + + return spsc_pbuf_alloc(queue, len, &pbuf) != len; +} diff --git a/modules/nrf_wifi/bus/spsc_qm.h b/modules/nrf_wifi/bus/spsc_qm.h new file mode 100644 index 00000000000..063cb470b52 --- /dev/null +++ b/modules/nrf_wifi/bus/spsc_qm.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief File containing API definitions for the + * SPSC queue management layer of the nRF71 Wi-Fi driver. + + * SPSC Queue Manager API for handling 32-bit values. + * + * The Queue Manager API for Single-Producer, Single-Consumer (SPSC) queue. This + * API allows queues to be allocated, pushed and popped. + */ + +#ifndef SPSC_QM_H +#define SPSC_QM_H + +#include + +#include +#include + +typedef struct spsc_pbuf spsc_queue_t; + +/** + * Initialise and allocate SPSC queue. + * + * @param[in] address : Address to allocate. + * @param[in] size : Size in bytes to allocate. + * @return : SPSC packet queue. + */ +spsc_queue_t *spsc32_init(uint32_t address, size_t size); + +/** + * Push a value onto the tail of a queue. + * + * @param[in] pb : Pointer to SPSC packet queue. + * @param[in] value : The value to push to the queue. + * @return : true if push is successful, false otherwise. + */ +bool spsc32_push(spsc_queue_t *pb, uint32_t value); + +/** + * Pop a value from the head of a queue and return it. + * + * @param[in] pb : Pointer to SPSC packet queue. + * @param[out] out_value : Pointer to the value to pop to. + * @return : true if pop is successful, false otherwise. + */ +bool spsc32_pop(spsc_queue_t *pb, uint32_t *out_value); + +/** + * Return a value at the head of a queue without popping it. + * + * @param[in] pb : Pointer to SPSC packet queue. + * @param[out] out_value : Pointer to value to read from the head of the queue. + * @return : true if read is successful, false otherwise. + */ +bool spsc32_read_head(spsc_queue_t *pb, uint32_t *out_value); + +/** + * Test whether a queue is empty. + * + * @param[in] pb : Pointer to SPSC packet queue. + * @return : true if the queue is empty, false otherwise. + */ +bool spsc32_is_empty(spsc_queue_t *pb); + +/** + * Test whether a queue is full. + * + * @param[in] pb : Pointer to SPSC packet queue. + * @return : true if the queue is full, false otherwise. + */ +bool spsc32_is_full(spsc_queue_t *pb); + +#endif /* SPSC_QM_H */ diff --git a/modules/nrf_wifi/os/CMakeLists.txt b/modules/nrf_wifi/os/CMakeLists.txt index e4f9cf2a0b6..ce1c9a850c8 100644 --- a/modules/nrf_wifi/os/CMakeLists.txt +++ b/modules/nrf_wifi/os/CMakeLists.txt @@ -15,5 +15,13 @@ zephyr_library_sources( timer.c work.c ) +zephyr_include_directories_ifdef(CONFIG_NRF71_ON_IPC + ${CMAKE_CURRENT_LIST_DIR}/../bus/ + ${CMAKE_CURRENT_LIST_DIR}/../hw_if/hal/inc +) + +zephyr_library_compile_definitions_ifdef(CONFIG_NRF71_ON_IPC + NRF71_ON_IPC +) zephyr_library_link_libraries(nrf-wifi-osal) diff --git a/modules/nrf_wifi/os/shim.c b/modules/nrf_wifi/os/shim.c index 997704b01bb..b892d50df7f 100644 --- a/modules/nrf_wifi/os/shim.c +++ b/modules/nrf_wifi/os/shim.c @@ -18,14 +18,19 @@ #include #include #include +#ifdef CONFIG_NRF71_ON_IPC +#include "ipc_if.h" +#else #include #include +#endif /* CONFIG_NRF71_ON_IPC */ #include #include "shim.h" #include "work.h" #include "timer.h" #include "osal_ops.h" +#include "common/hal_structs_common.h" LOG_MODULE_REGISTER(wifi_nrf, CONFIG_WIFI_NRF70_LOG_LEVEL); #if defined(CONFIG_NOCACHE_MEMORY) @@ -122,6 +127,7 @@ static int zep_shim_mem_cmp(const void *addr1, return memcmp(addr1, addr2, size); } +#ifndef CONFIG_NRF71_ON_IPC static unsigned int zep_shim_qspi_read_reg32(void *priv, unsigned long addr) { unsigned int val; @@ -174,6 +180,7 @@ static void zep_shim_qspi_cpy_to(void *priv, unsigned long addr, const void *src dev->write(addr, src, count_aligned); } +#endif /* !CONFIG_NRF71_ON_IPC */ static void *zep_shim_spinlock_alloc(void) { @@ -807,14 +814,56 @@ static enum nrf_wifi_status zep_shim_bus_qspi_dev_init(void *os_qspi_dev_ctx) static void zep_shim_bus_qspi_dev_deinit(void *priv) { struct zep_shim_bus_qspi_priv *qspi_priv = priv; +#ifndef CONFIG_NRF71_ON_IPC volatile struct qspi_dev *dev = qspi_priv->qspi_dev; - +#else + volatile struct rpu_dev *dev = qspi_priv->qspi_dev; +#endif /* !CONFIG_NRF71_ON_IPC */ dev->deinit(); } +#ifdef CONFIG_NRF71_ON_IPC +static int ipc_send_msg(unsigned int msg_type, void *msg, unsigned int len) +{ + enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; + struct rpu_dev *dev = rpu_dev(); + int ret; + ipc_ctx_t ctx; + + switch (msg_type) { + case NRF_WIFI_HAL_MSG_TYPE_CMD_CTRL: + ctx.inst = IPC_INSTANCE_CMD_CTRL; + ctx.ept = IPC_EPT_UMAC; + break; + case NRF_WIFI_HAL_MSG_TYPE_CMD_DATA_TX: + ctx.inst = IPC_INSTANCE_CMD_TX; + ctx.ept = IPC_EPT_UMAC; + break; + case NRF_WIFI_HAL_MSG_TYPE_CMD_DATA_RX: + ctx.inst = IPC_INSTANCE_RX; + ctx.ept = IPC_EPT_LMAC; + break; + default: + nrf_wifi_osal_log_err("%s: Invalid msg_type (%d)", __func__, msg_type); + goto out; + }; + + ret = dev->send(ctx, msg, len); + if (ret < 0) { + nrf_wifi_osal_log_err("%s: Sending message to RPU failed\n", __func__); + goto out; + } + + status = NRF_WIFI_STATUS_SUCCESS; +out: + return status; +} +#endif /* CONFIG_NRF71_ON_IPC */ + 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; +#ifndef CONFIG_NRF71_ON_IPC struct qspi_dev *dev = qspi_dev(); int ret; enum nrf_wifi_status status; @@ -836,6 +885,11 @@ static void *zep_shim_bus_qspi_dev_add(void *os_qspi_priv, void *osal_qspi_dev_c LOG_ERR("%s: RPU enable failed with error %d", __func__, ret); return NULL; } +#else + struct rpu_dev *dev = rpu_dev(); + + dev->init(); +#endif /* !CONFIG_NRF71_ON_IPC */ zep_qspi_priv->qspi_dev = dev; zep_qspi_priv->dev_added = true; @@ -849,8 +903,10 @@ static void zep_shim_bus_qspi_dev_rem(void *priv) ARG_UNUSED(dev); +#ifndef CONFIG_NRF71_ON_IPC /* TODO: Make qspi_dev a dynamic instance and remove it here */ rpu_disable(); +#endif /* !CONFIG_NRF71_ON_IPC */ } static void *zep_shim_bus_qspi_init(void) @@ -908,6 +964,7 @@ static void zep_shim_bus_qspi_dev_host_map_get(void *os_qspi_dev_ctx, host_map->addr = 0; } +#ifndef CONFIG_NRF71_ON_IPC static void irq_work_handler(struct k_work *work) { int ret = 0; @@ -940,6 +997,8 @@ static void zep_shim_irq_handler(const struct device *dev, struct gpio_callback k_work_schedule_for_queue(&zep_wifi_intr_q, &intr_priv->work, K_NO_WAIT); } +#endif /* !CONFIG_NRF71_ON_IPC */ + static enum nrf_wifi_status zep_shim_bus_qspi_intr_reg(void *os_dev_ctx, void *callbk_data, int (*callbk_fn)(void *callbk_data)) { @@ -948,6 +1007,14 @@ static enum nrf_wifi_status zep_shim_bus_qspi_intr_reg(void *os_dev_ctx, void *c ARG_UNUSED(os_dev_ctx); +#ifdef CONFIG_NRF71_ON_IPC + ret = ipc_register_rx_cb(callbk_fn, callbk_data); + if (ret) { + LOG_ERR("%s: ipc_register_rx_cb failed\n", __func__); + goto out; + } + status = NRF_WIFI_STATUS_SUCCESS; +#else intr_priv = zep_shim_mem_zalloc(sizeof(*intr_priv)); if (!intr_priv) { @@ -970,18 +1037,20 @@ static enum nrf_wifi_status zep_shim_bus_qspi_intr_reg(void *os_dev_ctx, void *c } status = NRF_WIFI_STATUS_SUCCESS; - +#endif /* CONFIG_NRF71_ON_IPC */ out: return status; } static void zep_shim_bus_qspi_intr_unreg(void *os_qspi_dev_ctx) { +#ifndef CONFIG_NRF71_ON_IPC struct k_work_sync sync; int ret; +#endif /* !CONFIG_NRF71_ON_IPC */ ARG_UNUSED(os_qspi_dev_ctx); - +#ifndef CONFIG_NRF71_ON_IPC ret = rpu_irq_remove(&intr_priv->gpio_cb_data); if (ret) { LOG_ERR("%s: rpu_irq_remove failed", __func__); @@ -992,6 +1061,7 @@ static void zep_shim_bus_qspi_intr_unreg(void *os_qspi_dev_ctx) zep_shim_mem_free(intr_priv); intr_priv = NULL; +#endif /*! CONFIG_NRF71_ON_IPC */ } #ifdef CONFIG_NRF_WIFI_LOW_POWER @@ -1072,12 +1142,12 @@ const struct nrf_wifi_osal_ops nrf_wifi_os_zep_ops = { .mem_cpy = zep_shim_mem_cpy, .mem_set = zep_shim_mem_set, .mem_cmp = zep_shim_mem_cmp, - +#ifndef CONFIG_NRF71_ON_IPC .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, - +#endif /* CONFIG_NRF71_ON_IPC */ .spinlock_alloc = zep_shim_spinlock_alloc, .spinlock_free = zep_shim_spinlock_free, .spinlock_init = zep_shim_spinlock_init, @@ -1157,7 +1227,9 @@ const struct nrf_wifi_osal_ops nrf_wifi_os_zep_ops = { .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, +#ifdef CONFIG_NRF71_ON_IPC + .ipc_send_msg = ipc_send_msg, +#endif /* CONFIG_NRF71_ON_IPC */ };