The shim files should be part of the Zephyr module directory within Zephyr, as they are coupled with the module implementation which os OS agnostic. Signed-off-by: Chaitanya Tata <Chaitanya.Tata@nordicsemi.no>
998 lines
21 KiB
C
998 lines
21 KiB
C
/*
|
|
* 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_mutex *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_mutex_init(lock);
|
|
}
|
|
|
|
static void zep_shim_spinlock_take(void *lock)
|
|
{
|
|
k_mutex_lock(lock, K_FOREVER);
|
|
}
|
|
|
|
static void zep_shim_spinlock_rel(void *lock)
|
|
{
|
|
k_mutex_unlock(lock);
|
|
}
|
|
|
|
static void zep_shim_spinlock_irq_take(void *lock, unsigned long *flags)
|
|
{
|
|
ARG_UNUSED(flags);
|
|
k_mutex_lock(lock, K_FOREVER);
|
|
}
|
|
|
|
static void zep_shim_spinlock_irq_rel(void *lock, unsigned long *flags)
|
|
{
|
|
ARG_UNUSED(flags);
|
|
k_mutex_unlock(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)
|
|
{
|
|
if (!nbuf) {
|
|
return;
|
|
}
|
|
|
|
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)
|
|
{
|
|
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 unsigned long zep_shim_time_get_curr_ms(void)
|
|
{
|
|
return k_uptime_get();
|
|
}
|
|
|
|
static unsigned int zep_shim_time_elapsed_ms(unsigned long start_time_ms)
|
|
{
|
|
unsigned long curr_time_ms = 0;
|
|
|
|
curr_time_ms = zep_shim_time_get_curr_ms();
|
|
|
|
return curr_time_ms - start_time_ms;
|
|
}
|
|
|
|
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;
|
|
|
|
if (!intr_priv || !intr_priv->callbk_fn || !intr_priv->callbk_data) {
|
|
LOG_ERR("%s: Invalid intr_priv handler", __func__);
|
|
return;
|
|
}
|
|
|
|
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);
|
|
|
|
if (!(intr_priv && intr_priv->callbk_fn && intr_priv->callbk_data)) {
|
|
LOG_ERR("%s: Invalid intr_priv", __func__);
|
|
return;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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,
|
|
.time_get_curr_ms = zep_shim_time_get_curr_ms,
|
|
.time_elapsed_ms = zep_shim_time_elapsed_ms,
|
|
|
|
.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,
|
|
};
|