android13/external/wifi_driver/aic8800/aic8800_fdrv/sdio_host.c

138 lines
4.4 KiB
C

/**
* sdio_host.c
*
* SDIO host function declarations
*
* Copyright (C) AICSemi 2018-2020
*/
#include "sdio_host.h"
//#include "ipc_compat.h"
#include "rwnx_tx.h"
#include "rwnx_platform.h"
#include "aicwf_debug.h"
/**
****************************************************************************************
*/
void aicwf_sdio_host_init(struct sdio_host_env_tag *env,
void *cb,
void *shared_env_ptr,
void *pthis)
{
// Reset the environments
// Reset the Host environment
memset(env, 0, sizeof(struct sdio_host_env_tag));
// Save the pointer to the register base
env->pthis = pthis;
}
/**
****************************************************************************************
*/
volatile struct txdesc_host *aicwf_sdio_host_txdesc_get(struct sdio_host_env_tag *env, const int queue_idx)
{
// struct ipc_shared_env_tag *shared_env_ptr = env->shared;
volatile struct txdesc_host *txdesc_free = NULL;
uint32_t used_idx = env->txdesc_used_idx[queue_idx];
uint32_t free_idx = env->txdesc_free_idx[queue_idx];
// ASSERT_ERR(queue_idx < SDIO_TXQUEUE_CNT);
// ASSERT_ERR((free_idx - used_idx) <= SDIO_TXDESC_CNT);
// Check if a free descriptor is available
if (free_idx != (used_idx + SDIO_TXDESC_CNT)) {
// Get the pointer to the first free descriptor
// txdesc_free = shared_env_ptr->txdesc[queue_idx] + (free_idx % IPC_TXDESC_CNT);
} else {
txdesc_free = NULL;
}
return txdesc_free;
}
/**
****************************************************************************************
*/
void aicwf_sdio_host_txdesc_push(struct sdio_host_env_tag *env, const int queue_idx, const uint64_t host_id)
{
//printk("push, %d, %d, 0x%llx \r\n", queue_idx, env->txdesc_free_idx[queue_idx], host_id);
// Save the host id in the environment
env->tx_host_id[queue_idx][env->txdesc_free_idx[queue_idx] % SDIO_TXDESC_CNT] = host_id;
// Increment the index
env->txdesc_free_idx[queue_idx]++;
if (env->txdesc_free_idx[queue_idx] == 0x80000000)
env->txdesc_free_idx[queue_idx] = 0;
}
/**
****************************************************************************************
*/
void aicwf_sdio_host_tx_cfm_handler(struct sdio_host_env_tag *env, u32 *data)
{
u32 queue_idx = 0;// data[0];
//struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)env->pthis;
struct sk_buff *skb = NULL;
struct rwnx_txhdr *txhdr;
// TX confirmation descriptors have been received
// REG_SW_SET_PROFILING(env->pthis, SW_PROF_IRQ_E2A_TXCFM);
//while (1)
{
// Get the used index and increase it. We do the increase before knowing if the
// current buffer is confirmed because the callback function may call the
// ipc_host_txdesc_get() in case flow control was enabled and the index has to be
// already at the good value to ensure that the test of FIFO full is correct
//uint32_t used_idx = env->txdesc_used_idx[queue_idx]++;
uint32_t used_idx = data[1];
unsigned long host_id = env->tx_host_id[queue_idx][used_idx % SDIO_TXDESC_CNT];
// Reset the host id in the array
env->tx_host_id[queue_idx][used_idx % SDIO_TXDESC_CNT] = 0;
// call the external function to indicate that a TX packet is freed
if (host_id == 0) {
// No more confirmations, so put back the used index at its initial value
env->txdesc_used_idx[queue_idx] = used_idx;
AICWFDBG(LOGERROR, "ERROR:No more confirmations\r\n");
//break;
}
// set the cfm status
skb = (struct sk_buff *)host_id;
txhdr = (struct rwnx_txhdr *)skb->data;
txhdr->hw_hdr.cfm.status = (union rwnx_hw_txstatus)data[0];
AICWFDBG(LOGINFO, "sdio_host_tx_cfm_handler:used_idx=%d, 0x%p, status=%x\r\n", used_idx, env->pthis, txhdr->hw_hdr.cfm.status.value);
//if (env->cb.send_data_cfm(env->pthis, host_id) != 0)
if (rwnx_txdatacfm(env->pthis, (void *)host_id) != 0) {
// No more confirmations, so put back the used index at its initial value
env->txdesc_used_idx[queue_idx] = used_idx;
env->tx_host_id[queue_idx][used_idx % SDIO_TXDESC_CNT] = host_id;
// and exit the loop
AICWFDBG(LOGERROR, "ERROR:rwnx_txdatacfm,\r\n");
// break;
}
}
}
int aicwf_rwnx_sdio_platform_init(struct aic_sdio_dev *sdiodev)
{
struct rwnx_plat *rwnx_plat = NULL;
void *drvdata;
int ret = -ENODEV;
rwnx_plat = kzalloc(sizeof(struct rwnx_plat), GFP_KERNEL);
if (!rwnx_plat) {
return -ENOMEM;
}
rwnx_plat->sdiodev = sdiodev;
ret = rwnx_platform_init(rwnx_plat, &drvdata);
return ret;
}