mirror of
https://gitee.com/Vancouver2017/luban-lite.git
synced 2025-12-24 21:18:54 +00:00
917 lines
23 KiB
C
917 lines
23 KiB
C
/**************************************************************************************************************
|
|
* altobeam RTOS wifi hmac source code
|
|
*
|
|
* Copyright (c) 2018, altobeam.inc All rights reserved.
|
|
*
|
|
* The source code contains proprietary information of AltoBeam, and shall not be distributed,
|
|
* copied, reproduced, or disclosed in whole or in part without prior written permission of AltoBeam.
|
|
*****************************************************************************************************************/
|
|
#include "atbm_hal.h"
|
|
#include "atbm_sdio.h"
|
|
#include "atbm_sdio_hwio.h"
|
|
|
|
int atbm_reg_read_8(struct atbmwifi_common *hw_priv,
|
|
atbm_uint16 addr, atbm_uint8 *val)
|
|
{
|
|
atbm_uint32 bigVal;
|
|
int ret;
|
|
ret = atbm_reg_read_dpll(hw_priv, addr, &bigVal, sizeof(bigVal));
|
|
*val = (atbm_uint8)bigVal;
|
|
return ret;
|
|
}
|
|
|
|
int atbm_reg_write_8(struct atbmwifi_common *hw_priv,
|
|
atbm_uint16 addr, atbm_uint8 val)
|
|
{
|
|
atbm_uint32 bigVal = (atbm_uint32)val;
|
|
return atbm_reg_write_dpll(hw_priv, addr, &bigVal, sizeof(bigVal));
|
|
}
|
|
|
|
int atbm_reg_read_16(struct atbmwifi_common *hw_priv,
|
|
atbm_uint16 addr, atbm_uint16 *val)
|
|
{
|
|
atbm_uint32 bigVal;
|
|
int ret;
|
|
ret = atbm_reg_read(hw_priv, addr, &bigVal, sizeof(bigVal));
|
|
*val = (atbm_uint16)bigVal;
|
|
return ret;
|
|
}
|
|
|
|
int atbm_reg_write_16(struct atbmwifi_common *hw_priv,
|
|
atbm_uint16 addr, atbm_uint16 val)
|
|
{
|
|
atbm_uint32 bigVal = (atbm_uint32)val;
|
|
return atbm_reg_write(hw_priv, addr, &bigVal, sizeof(bigVal));
|
|
}
|
|
|
|
int atbm_reg_read_32(struct atbmwifi_common *hw_priv,
|
|
atbm_uint16 addr, atbm_uint32 *val)
|
|
{
|
|
return atbm_reg_read(hw_priv, addr, val, sizeof(int));
|
|
}
|
|
|
|
int atbm_reg_write_32(struct atbmwifi_common *hw_priv,
|
|
atbm_uint16 addr, atbm_uint32 val)
|
|
{
|
|
return atbm_reg_write(hw_priv, addr, &val, sizeof(int));
|
|
}
|
|
|
|
int atbm_apb_read(struct atbmwifi_common *hw_priv, atbm_uint32 addr,
|
|
atbm_void *buf, atbm_uint32 buf_len)
|
|
{
|
|
return atbm_indirect_read(hw_priv, addr, buf, buf_len,
|
|
ATBM_HIFREG_CONFIG_PFETCH_BIT, ATBM_HIFREG_SRAM_DPORT_REG_ID);
|
|
}
|
|
|
|
int atbm_ahb_read(struct atbmwifi_common *hw_priv, atbm_uint32 addr,
|
|
atbm_void *buf, atbm_size_t buf_len)
|
|
{
|
|
return atbm_indirect_read(hw_priv, addr, buf, buf_len,
|
|
ATBM_HIFREG_CONFIG_AHB_PFETCH_BIT, ATBM_HIFREG_AHB_DPORT_REG_ID);
|
|
}
|
|
|
|
int atbm_apb_read_32(struct atbmwifi_common *hw_priv,
|
|
atbm_uint32 addr, atbm_uint32 *val)
|
|
{
|
|
return atbm_apb_read(hw_priv, addr, val, sizeof(int));
|
|
}
|
|
|
|
int atbm_apb_write_32(struct atbmwifi_common *hw_priv,
|
|
atbm_uint32 addr, atbm_uint32 val)
|
|
{
|
|
return atbm_apb_write(hw_priv, addr, &val, sizeof(val));
|
|
}
|
|
|
|
int atbm_ahb_read_32(struct atbmwifi_common *hw_priv,
|
|
atbm_uint32 addr, atbm_uint32 *val)
|
|
{
|
|
return atbm_ahb_read(hw_priv, addr, val, sizeof(int));
|
|
}
|
|
|
|
int atbm_ahb_write_32(struct atbmwifi_common *hw_priv,
|
|
atbm_uint32 addr, atbm_uint32 val)
|
|
{
|
|
int ret = atbm_ahb_write(hw_priv, addr, &val, sizeof(val));
|
|
if((addr&WRITE_32K_ADDR_MSK)==WRITE_32K_ADDR)
|
|
{
|
|
atbm_mdelay(10);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static int __atbm_reg_read(struct atbmwifi_common *hw_priv, atbm_uint16 addr,
|
|
atbm_void *buf, atbm_uint32 buf_len)
|
|
{
|
|
atbm_uint16 addr_sdio;
|
|
atbm_uint32 sdio_reg_addr_17bit ;
|
|
|
|
/* Check if buffer is aligned to 4 byte boundary */
|
|
if (ATBM_WARN_ON(((unsigned long)buf & 3) && (buf_len > 4))) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: buffer is not aligned.\n", __FUNCTION__);
|
|
return -ATBM_EINVAL;
|
|
}
|
|
|
|
/* Convert to SDIO Register Address */
|
|
addr_sdio = SPI_REG_ADDR_TO_SDIO(addr);
|
|
sdio_reg_addr_17bit = SDIO_ADDR17BIT(0, 0, 0, addr_sdio);
|
|
|
|
ATBM_BUG_ON(!hw_priv->sbus_ops);
|
|
return hw_priv->sbus_ops->sbus_read_sync(hw_priv->sbus_priv,
|
|
sdio_reg_addr_17bit,
|
|
buf, buf_len);
|
|
}
|
|
|
|
static int __atbm_reg_write(struct atbmwifi_common *hw_priv, atbm_uint16 addr,
|
|
const atbm_void *buf, atbm_uint32 buf_len)
|
|
{
|
|
atbm_uint16 addr_sdio;
|
|
atbm_uint32 sdio_reg_addr_17bit ;
|
|
|
|
|
|
/* Convert to SDIO Register Address */
|
|
addr_sdio = SPI_REG_ADDR_TO_SDIO(addr);
|
|
sdio_reg_addr_17bit = SDIO_ADDR17BIT(0, 0, 0, addr_sdio);
|
|
|
|
ATBM_BUG_ON(!hw_priv->sbus_ops);
|
|
return hw_priv->sbus_ops->sbus_write_sync(hw_priv->sbus_priv,
|
|
sdio_reg_addr_17bit,
|
|
buf, buf_len);
|
|
}
|
|
|
|
static int __atbm_data_read(struct atbmwifi_common *hw_priv, atbm_uint16 addr,
|
|
atbm_void *buf, atbm_uint32 buf_len, int buf_id)
|
|
{
|
|
atbm_uint16 addr_sdio;
|
|
atbm_uint32 sdio_reg_addr_17bit ;
|
|
|
|
/* Check if buffer is aligned to 4 byte boundary */
|
|
if (ATBM_WARN_ON(((unsigned long)buf & 3) && (buf_len > 4))) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: buffer is not aligned.\n", __FUNCTION__);
|
|
return -ATBM_EINVAL;
|
|
}
|
|
|
|
/* Convert to SDIO Register Address */
|
|
addr_sdio = SPI_REG_ADDR_TO_SDIO(addr);
|
|
sdio_reg_addr_17bit = SDIO_ADDR17BIT(buf_id, 0, 0, addr_sdio);
|
|
|
|
ATBM_BUG_ON(!hw_priv->sbus_ops);
|
|
return hw_priv->sbus_ops->sbus_memcpy_fromio(hw_priv->sbus_priv,
|
|
sdio_reg_addr_17bit,
|
|
buf, buf_len);
|
|
}
|
|
|
|
static int __atbm_data_write(struct atbmwifi_common *hw_priv, atbm_uint16 addr,
|
|
const atbm_void *buf, atbm_uint32 buf_len, int buf_id)
|
|
{
|
|
atbm_uint16 addr_sdio;
|
|
atbm_uint32 sdio_reg_addr_17bit ;
|
|
|
|
|
|
/* Convert to SDIO Register Address */
|
|
addr_sdio = SPI_REG_ADDR_TO_SDIO(addr);
|
|
sdio_reg_addr_17bit = SDIO_ADDR17BIT(buf_id, 0, 0, addr_sdio);
|
|
|
|
ATBM_BUG_ON(!hw_priv->sbus_ops);
|
|
return hw_priv->sbus_ops->sbus_memcpy_toio(hw_priv->sbus_priv,
|
|
sdio_reg_addr_17bit,
|
|
buf, buf_len);
|
|
}
|
|
|
|
static int __atbm_reg_read_32(struct atbmwifi_common *hw_priv,
|
|
atbm_uint16 addr, atbm_uint32 *val)
|
|
{
|
|
return __atbm_reg_read(hw_priv, addr, val, sizeof(val));
|
|
}
|
|
|
|
static int __atbm_reg_write_32(struct atbmwifi_common *hw_priv,
|
|
atbm_uint16 addr, atbm_uint32 val)
|
|
{
|
|
return __atbm_reg_write(hw_priv, addr, &val, sizeof(val));
|
|
}
|
|
|
|
int __atbm_reg_write_dpll(struct atbmwifi_common *hw_priv, atbm_uint16 addr,
|
|
const atbm_void *buf, atbm_uint32 buf_len,int buf_id)
|
|
{
|
|
atbm_uint16 addr_sdio;
|
|
atbm_uint32 sdio_reg_addr_17bit ;
|
|
|
|
/* Check if buffer is aligned to 4 byte boundary */
|
|
if (ATBM_WARN_ON(((unsigned long)buf & 3) && (buf_len > 4))) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: buffer is not aligned.\n", __FUNCTION__);
|
|
return -ATBM_EINVAL;
|
|
}
|
|
|
|
/* Convert to SDIO Register Address */
|
|
addr_sdio = addr;//SPI_REG_ADDR_TO_SDIO(addr);
|
|
sdio_reg_addr_17bit = SDIO_ADDR17BIT(buf_id, 0, 0, addr_sdio);
|
|
|
|
ATBM_BUG_ON(!hw_priv->sbus_ops);
|
|
return hw_priv->sbus_ops->sbus_write_sync(hw_priv->sbus_priv,
|
|
sdio_reg_addr_17bit,
|
|
buf, buf_len);
|
|
|
|
}
|
|
int __atbm_reg_read_dpll(struct atbmwifi_common *hw_priv, atbm_uint16 addr,
|
|
const atbm_void *buf, atbm_uint32 buf_len,int buf_id)
|
|
{
|
|
atbm_uint16 addr_sdio;
|
|
atbm_uint32 sdio_reg_addr_17bit ;
|
|
|
|
//wifi_printk(WIFI_IF, "%x,addr,func=s\n",addr,__FUNCTION__);
|
|
|
|
/* Convert to SDIO Register Address */
|
|
addr_sdio = addr;//SPI_REG_ADDR_TO_SDIO(addr);
|
|
sdio_reg_addr_17bit = SDIO_ADDR17BIT(buf_id, 0, 0, addr_sdio);
|
|
//wifi_printk(WIFI_IF, "%x,sdio_reg_addr_17bit,func=%s\n",sdio_reg_addr_17bit,__FUNCTION__);
|
|
|
|
ATBM_BUG_ON(!hw_priv->sbus_ops);
|
|
return hw_priv->sbus_ops->sbus_read_sync(hw_priv->sbus_priv,
|
|
sdio_reg_addr_17bit,
|
|
(atbm_void*)buf, buf_len);
|
|
|
|
|
|
}
|
|
int atbm_reg_read_dpll(struct atbmwifi_common *hw_priv, atbm_uint16 addr, atbm_void *buf,
|
|
atbm_uint32 buf_len)
|
|
{
|
|
int ret;
|
|
ATBM_BUG_ON(!hw_priv->sbus_ops);
|
|
hw_priv->sbus_ops->lock(hw_priv->sbus_priv);
|
|
ret = __atbm_reg_read_dpll(hw_priv, addr, buf, buf_len, 0);
|
|
hw_priv->sbus_ops->unlock(hw_priv->sbus_priv);
|
|
return ret;
|
|
}
|
|
|
|
int atbm_reg_write_dpll(struct atbmwifi_common *hw_priv, atbm_uint16 addr, const atbm_void *buf,
|
|
atbm_uint32 buf_len)
|
|
{
|
|
int ret;
|
|
ATBM_BUG_ON(!hw_priv->sbus_ops);
|
|
hw_priv->sbus_ops->lock(hw_priv->sbus_priv);
|
|
ret = __atbm_reg_write_dpll(hw_priv, addr, buf, buf_len, 0);
|
|
hw_priv->sbus_ops->unlock(hw_priv->sbus_priv);
|
|
return ret;
|
|
}
|
|
|
|
|
|
int atbm_reg_read(struct atbmwifi_common *hw_priv, atbm_uint16 addr, atbm_void *buf,
|
|
atbm_uint32 buf_len)
|
|
{
|
|
int ret;
|
|
ATBM_BUG_ON(!hw_priv->sbus_ops);
|
|
hw_priv->sbus_ops->lock(hw_priv->sbus_priv);
|
|
ret = __atbm_reg_read(hw_priv, addr, buf, buf_len);
|
|
hw_priv->sbus_ops->unlock(hw_priv->sbus_priv);
|
|
return ret;
|
|
}
|
|
|
|
int atbm_reg_write(struct atbmwifi_common *hw_priv, atbm_uint16 addr, const atbm_void *buf,
|
|
atbm_uint32 buf_len)
|
|
{
|
|
int ret;
|
|
ATBM_BUG_ON(!hw_priv->sbus_ops);
|
|
hw_priv->sbus_ops->lock(hw_priv->sbus_priv);
|
|
ret = __atbm_reg_write(hw_priv, addr, buf, buf_len);
|
|
hw_priv->sbus_ops->unlock(hw_priv->sbus_priv);
|
|
return ret;
|
|
}
|
|
|
|
int atbm_data_read(struct atbmwifi_common *hw_priv, atbm_void *buf, atbm_uint32 buf_len)
|
|
{
|
|
int ret, retry = 1;
|
|
ATBM_BUG_ON(!hw_priv->sbus_ops);
|
|
hw_priv->sbus_ops->lock(hw_priv->sbus_priv);
|
|
{
|
|
int buf_id_rx = hw_priv->buf_id_rx;
|
|
while (retry <= MAX_RETRY) {
|
|
ret = __atbm_data_read(hw_priv,
|
|
ATBM_HIFREG_IN_OUT_QUEUE_REG_ID, buf,
|
|
buf_len, buf_id_rx + 1);
|
|
if (!ret) {
|
|
buf_id_rx = (buf_id_rx + 1) & 3;
|
|
hw_priv->buf_id_rx = buf_id_rx;
|
|
break;
|
|
} else {
|
|
retry++;
|
|
atbm_mdelay(1);
|
|
wifi_printk(WIFI_IF, "%s,error :[%d]\n",
|
|
__FUNCTION__, ret);
|
|
}
|
|
}
|
|
}
|
|
hw_priv->sbus_ops->unlock(hw_priv->sbus_priv);
|
|
return ret;
|
|
}
|
|
|
|
//sdio
|
|
int atbm_data_write(struct atbmwifi_common *hw_priv, const atbm_void *buf,
|
|
atbm_size_t buf_len)
|
|
{
|
|
int ret, retry = 1;
|
|
int buf_id_tx;
|
|
|
|
ATBM_BUG_ON(!hw_priv->sbus_ops);
|
|
hw_priv->sbus_ops->lock(hw_priv->sbus_priv);
|
|
buf_id_tx = hw_priv->buf_id_tx;
|
|
while (retry <= MAX_RETRY) {
|
|
ret = __atbm_data_write(hw_priv,
|
|
ATBM_HIFREG_IN_OUT_QUEUE_REG_ID, buf,
|
|
buf_len, buf_id_tx);
|
|
|
|
if (!ret) {
|
|
// buf_id_tx = ((buf_id_tx + 1) >= hw_priv->wsm_caps_numInpChBufs)? 0: (buf_id_tx + 1) ;
|
|
buf_id_tx = (buf_id_tx+hw_priv->buf_id_offset)&(0x3f);
|
|
hw_priv->buf_id_tx = buf_id_tx;
|
|
break;
|
|
} else {
|
|
retry++;
|
|
atbm_mdelay(1);
|
|
wifi_printk(WIFI_IF, "%s,%d,error :[%d]\n",
|
|
__FUNCTION__, __LINE__, ret);
|
|
}
|
|
}
|
|
hw_priv->sbus_ops->unlock(hw_priv->sbus_priv);
|
|
return ret;
|
|
}
|
|
|
|
|
|
//usb
|
|
int atbm_indirect_read(struct atbmwifi_common *hw_priv, atbm_uint32 addr, atbm_void *buf,
|
|
atbm_uint32 buf_len, atbm_uint32 prefetch, atbm_uint16 port_addr)
|
|
{
|
|
atbm_uint32 val32 = 0;
|
|
int i, ret;
|
|
|
|
if ((buf_len / 2) >= 0x1000) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: Can't read more than 0xfff words.\n",
|
|
__FUNCTION__);
|
|
ATBM_WARN_ON_FUNC(1);
|
|
return -ATBM_EINVAL;
|
|
goto out;
|
|
}
|
|
|
|
hw_priv->sbus_ops->lock(hw_priv->sbus_priv);
|
|
/* Write address */
|
|
ret = __atbm_reg_write_32(hw_priv, ATBM_HIFREG_SRAM_BASE_ADDR_REG_ID,
|
|
addr);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: Can't write address register.\n",
|
|
__FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
/* Read CONFIG Register Value - We will read 32 bits */
|
|
ret = __atbm_reg_read_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID, &val32);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: Can't read config register.\n",
|
|
__FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
/* Set PREFETCH bit */
|
|
ret = __atbm_reg_write_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID,
|
|
val32 | prefetch);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: Can't write prefetch bit.\n",
|
|
__FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
/* Check for PRE-FETCH bit to be cleared */
|
|
for (i = 0; i < 20; i++) {
|
|
ret = __atbm_reg_read_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID,
|
|
&val32);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: Can't check prefetch bit.\n",
|
|
__FUNCTION__);
|
|
goto out;
|
|
}
|
|
if (!(val32 & prefetch))
|
|
break;
|
|
|
|
atbm_mdelay(i);
|
|
}
|
|
|
|
if (val32 & prefetch) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: Prefetch bit is not cleared.\n",
|
|
__FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
/* Read data port */
|
|
ret = __atbm_reg_read(hw_priv, port_addr, buf, buf_len);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: Can't read data port.\n",
|
|
__FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
hw_priv->sbus_ops->unlock(hw_priv->sbus_priv);
|
|
return ret;
|
|
}
|
|
|
|
int atbm_apb_write(struct atbmwifi_common *hw_priv, atbm_uint32 addr, const atbm_void *buf,
|
|
atbm_uint32 buf_len)
|
|
{
|
|
int ret;
|
|
|
|
if ((buf_len / 2) >= 0x1000) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: Can't wrire more than 0xfff words.\n",
|
|
__FUNCTION__);
|
|
ATBM_WARN_ON_FUNC(1);
|
|
return -ATBM_EINVAL;
|
|
}
|
|
|
|
hw_priv->sbus_ops->lock(hw_priv->sbus_priv);
|
|
|
|
/* Write address */
|
|
ret = __atbm_reg_write_32(hw_priv, ATBM_HIFREG_SRAM_BASE_ADDR_REG_ID,
|
|
addr);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: Can't write address register.\n",
|
|
__FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
/* Write data port */
|
|
ret = __atbm_reg_write(hw_priv, ATBM_HIFREG_SRAM_DPORT_REG_ID,
|
|
buf, buf_len);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF, "%s: Can't write data port.\n",
|
|
__FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
hw_priv->sbus_ops->unlock(hw_priv->sbus_priv);
|
|
return ret;
|
|
}
|
|
int atbm_fw_write(struct atbmwifi_common *priv, atbm_uint32 addr, const atbm_void *buf,
|
|
atbm_uint32 buf_len)
|
|
{
|
|
return atbm_ahb_write(priv, addr, buf, buf_len);
|
|
}
|
|
|
|
|
|
int atbm_ahb_write(struct atbmwifi_common *priv, atbm_uint32 addr, const atbm_void *buf,
|
|
atbm_uint32 buf_len)
|
|
{
|
|
int ret;
|
|
if (buf_len >= 512) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: Can't wrire more than 0xfff words.\n",
|
|
__FUNCTION__);
|
|
ATBM_WARN_ON_FUNC(1);
|
|
return -ATBM_EINVAL;
|
|
}
|
|
|
|
priv->sbus_ops->lock(priv->sbus_priv);
|
|
|
|
/* Write address */
|
|
ret = __atbm_reg_write_32(priv, ATBM_HIFREG_SRAM_BASE_ADDR_REG_ID, addr);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: Can't write address register.\n",
|
|
__FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
/* Write data port */
|
|
ret = __atbm_reg_write(priv, ATBM_HIFREG_AHB_DPORT_REG_ID,
|
|
buf, buf_len);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF, "%s: Can't write data port.\n",
|
|
__FUNCTION__);
|
|
goto out;
|
|
}
|
|
out:
|
|
priv->sbus_ops->unlock(priv->sbus_priv);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int atbm_direct_read_reg_32(struct atbmwifi_common *hw_priv, atbm_uint32 addr, atbm_uint32 *val)
|
|
{
|
|
int ret;
|
|
atbm_uint32 val32;
|
|
atbm_uint32 orig_config_data = 0;
|
|
|
|
/* Checking for access mode */
|
|
ret = atbm_reg_read_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID, &val32);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: can't read " \
|
|
"config register.\n", __FUNCTION__);
|
|
goto out1;
|
|
}
|
|
orig_config_data = val32;
|
|
val32 |= ATBM_HIFREG_CONFIG_ACCESS_MODE_BIT;
|
|
ret = atbm_reg_write_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID,val32);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: can't write " \
|
|
"config register.\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
ret = atbm_ahb_read_32(hw_priv,addr,val);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: can't write " \
|
|
"config register.\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
ret = atbm_reg_write_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID,orig_config_data);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: enable_irq: can't write " \
|
|
"config register.\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
out1:
|
|
return ret;
|
|
}
|
|
|
|
|
|
int atbm_direct_write_reg_32(struct atbmwifi_common *hw_priv, atbm_uint32 addr, atbm_uint32 val)
|
|
{
|
|
int ret;
|
|
atbm_uint32 val32;
|
|
atbm_uint32 orig_config_data = 0;
|
|
|
|
/* Checking for access mode */
|
|
ret = atbm_reg_read_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID, &val32);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: can't read " \
|
|
"config register.\n", __FUNCTION__);
|
|
goto out1;
|
|
}
|
|
orig_config_data = val32;
|
|
val32 |= ATBM_HIFREG_CONFIG_ACCESS_MODE_BIT;
|
|
ret = atbm_reg_write_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID,val32);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: can't write " \
|
|
"config register.\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
ret = atbm_ahb_write_32(hw_priv,addr,val);
|
|
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: can't write " \
|
|
"config register.\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
ret = atbm_reg_write_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID,orig_config_data);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF,
|
|
"%s: enable_irq: can't write " \
|
|
"config register.\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
out1:
|
|
return ret;
|
|
}
|
|
int __atbm_irq_enable(struct atbmwifi_common *priv, int enable)
|
|
{
|
|
atbm_uint32 val32;
|
|
int ret;
|
|
|
|
ret = __atbm_reg_read_32(priv, ATBM_HIFREG_CONFIG_REG_ID, &val32);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF,"Can't read config register.\n");
|
|
return ret;
|
|
}
|
|
|
|
if (enable){
|
|
if(val32 & ATBM_HIFREG_CONF_IRQ_RDY_ENABLE)
|
|
return ret;
|
|
val32 |= ATBM_HIFREG_CONF_IRQ_RDY_ENABLE;
|
|
|
|
}
|
|
else {
|
|
if((val32 & ATBM_HIFREG_CONF_IRQ_RDY_ENABLE)==0)
|
|
return ret;
|
|
val32 &= ~ATBM_HIFREG_CONF_IRQ_RDY_ENABLE;
|
|
}
|
|
ret = __atbm_reg_write_32(priv, ATBM_HIFREG_CONFIG_REG_ID, val32);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_IF,"Can't write config register.\n");
|
|
return ret;
|
|
}
|
|
return 0;
|
|
}
|
|
int atbm_reg_read_unlock(struct atbmwifi_common *hw_priv, atbm_uint16 addr, atbm_void *buf,
|
|
atbm_uint32 buf_len)
|
|
{
|
|
int ret;
|
|
int retry=0;
|
|
ATBM_BUG_ON(!hw_priv->sbus_ops);
|
|
while (retry <= 3) {
|
|
ret = __atbm_reg_read(hw_priv, addr, buf, buf_len);
|
|
if(ret){
|
|
wifi_printk(WIFI_ALWAYS,"%s\n",__func__);
|
|
retry++;
|
|
}else{
|
|
break;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int atbm_reg_write_unlock(struct atbmwifi_common *hw_priv, atbm_uint16 addr, const atbm_void *buf,
|
|
atbm_uint32 buf_len)
|
|
{
|
|
int ret;
|
|
int retry=0;
|
|
ATBM_BUG_ON(!hw_priv->sbus_ops);
|
|
while (retry <= 3) {
|
|
ret = __atbm_reg_write(hw_priv, addr, buf, buf_len);
|
|
if(ret){
|
|
wifi_printk(WIFI_ALWAYS,"%s\n",__func__);
|
|
retry++;
|
|
}else{
|
|
break;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
int atbm_direct_write_unlock(struct atbmwifi_common *hw_priv, atbm_uint32 addr, atbm_uint32 val)
|
|
{
|
|
int ret;
|
|
atbm_uint32 val32;
|
|
atbm_uint32 orig_config_data = 0;
|
|
|
|
/* Checking for access mode */
|
|
ret = atbm_reg_read_unlock_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID, &val32);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_ALWAYS,
|
|
"%s: can't read " \
|
|
"config register.\n", __func__);
|
|
goto out1;
|
|
}
|
|
orig_config_data = val32;
|
|
val32 |= ATBM_HIFREG_CONFIG_ACCESS_MODE_BIT;
|
|
ret = atbm_reg_write_unlock_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID,val32);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_ALWAYS,
|
|
"%s: can't write " \
|
|
"config register.\n", __func__);
|
|
goto out;
|
|
}
|
|
ret = atbm_ahb_write_unlock_32(hw_priv,addr,val);
|
|
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_ALWAYS,
|
|
"%s: can't write " \
|
|
"config register.\n", __func__);
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
ret = atbm_reg_write_unlock_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID,orig_config_data);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_ALWAYS,
|
|
"%s: enable_irq: can't write " \
|
|
"config register.\n", __func__);
|
|
goto out;
|
|
}
|
|
out1:
|
|
return ret;
|
|
}
|
|
int atbm_direct_read_unlock(struct atbmwifi_common *hw_priv, atbm_uint32 addr, atbm_uint32 *val)
|
|
{
|
|
int ret;
|
|
atbm_uint32 val32;
|
|
atbm_uint32 orig_config_data = 0;
|
|
|
|
/* Checking for access mode */
|
|
ret = atbm_reg_read_unlock_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID, &val32);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_ALWAYS,
|
|
"%s: can't read " \
|
|
"config register.\n", __func__);
|
|
goto out1;
|
|
}
|
|
orig_config_data = val32;
|
|
val32 |= ATBM_HIFREG_CONFIG_ACCESS_MODE_BIT;
|
|
ret = atbm_reg_write_unlock_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID,val32);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_ALWAYS,
|
|
"%s: can't write " \
|
|
"config register.\n", __func__);
|
|
goto out;
|
|
}
|
|
ret = atbm_ahb_read_unlock_32(hw_priv,addr,val);
|
|
//printk("val=%x\n",val);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_ALWAYS,
|
|
"%s: can't write " \
|
|
"config register.\n", __func__);
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
ret = atbm_reg_write_unlock_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID,orig_config_data);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_ALWAYS,
|
|
"%s: enable_irq: can't write " \
|
|
"config register.\n", __func__);
|
|
goto out;
|
|
}
|
|
out1:
|
|
return ret;
|
|
}
|
|
int atbm_ahb_write_unlock(struct atbmwifi_common *priv, atbm_uint32 addr, const void *buf,
|
|
atbm_uint32 buf_len)
|
|
{
|
|
int ret;
|
|
int retry=0;
|
|
//printk(KERN_ERR "%s: addr %x\n",__func__,addr);
|
|
if (buf_len >= 512) {
|
|
wifi_printk(WIFI_ALWAYS,
|
|
"%s: Can't wrire more than 0xfff words.\n",
|
|
__func__);
|
|
ATBM_WARN_ON_FUNC(1);
|
|
wifi_printk(WIFI_ALWAYS, "%s:EXIT (1) \n",__func__);
|
|
return -1;
|
|
}
|
|
/* Write address */
|
|
while(retry<=3){
|
|
ret = __atbm_reg_write_32(priv, ATBM_HIFREG_SRAM_BASE_ADDR_REG_ID, addr);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_ALWAYS,
|
|
"%s: Can't write address register.\n",
|
|
__func__);
|
|
retry++;
|
|
}else{
|
|
break;
|
|
}
|
|
}
|
|
retry=0;
|
|
/* Write data port */
|
|
while(retry<=3){
|
|
ret = __atbm_reg_write(priv, ATBM_HIFREG_AHB_DPORT_REG_ID,
|
|
buf, buf_len);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_ALWAYS, "%s: Can't write data port.\n",
|
|
__func__);
|
|
retry++;
|
|
}else{
|
|
break;
|
|
}
|
|
}
|
|
//out:
|
|
return ret;
|
|
}
|
|
int atbm_indirect_read_unlock(struct atbmwifi_common *hw_priv, atbm_uint32 addr, void *buf,
|
|
atbm_uint32 buf_len, atbm_uint32 prefetch, atbm_uint16 port_addr)
|
|
{
|
|
atbm_uint32 val32 = 0;
|
|
int i, ret;
|
|
int retry=0;
|
|
if ((buf_len / 2) >= 0x1000) {
|
|
wifi_printk(WIFI_ALWAYS,
|
|
"%s: Can't read more than 0xfff words.\n",
|
|
__func__);
|
|
ATBM_WARN_ON_FUNC(1);
|
|
return -1;
|
|
goto out;
|
|
}
|
|
/* Write address */
|
|
|
|
while(retry<=3){
|
|
ret = __atbm_reg_write_32(hw_priv, ATBM_HIFREG_SRAM_BASE_ADDR_REG_ID,
|
|
addr);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_ALWAYS,
|
|
"%s: Can't write address register.\n",
|
|
__func__);
|
|
retry++;
|
|
}else{
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Read CONFIG Register Value - We will read 32 bits */
|
|
retry=0;
|
|
while(retry<=3){
|
|
ret = __atbm_reg_read_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID, &val32);
|
|
if (ret <0) {
|
|
wifi_printk(WIFI_ALWAYS,
|
|
"%s: Can't read config register.\n",
|
|
__func__);
|
|
retry++;
|
|
}else{
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Set PREFETCH bit */
|
|
retry=0;
|
|
while(retry<=3){
|
|
ret = __atbm_reg_write_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID,
|
|
val32 | prefetch);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_ALWAYS,
|
|
"%s: Can't write prefetch bit.\n",
|
|
__func__);
|
|
retry++;
|
|
}else{
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Check for PRE-FETCH bit to be cleared */
|
|
for (i = 0; i < 20; i++) {
|
|
ret = __atbm_reg_read_32(hw_priv, ATBM_HIFREG_CONFIG_REG_ID,
|
|
&val32);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_ALWAYS,
|
|
"%s: Can't check prefetch bit.\n",
|
|
__func__);
|
|
atbm_mdelay(i);
|
|
continue;
|
|
}
|
|
if (!(val32 & prefetch))
|
|
break;
|
|
|
|
atbm_mdelay(i);
|
|
}
|
|
|
|
if (val32 & prefetch) {
|
|
wifi_printk(WIFI_ALWAYS,
|
|
"%s: Prefetch bit is not cleared.\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
/* Read data port */
|
|
retry=0;
|
|
while(retry<=3){
|
|
ret = __atbm_reg_read(hw_priv, port_addr, buf, buf_len);
|
|
if (ret < 0) {
|
|
wifi_printk(WIFI_ALWAYS,
|
|
"%s: Can't read data port.\n",
|
|
__func__);
|
|
retry++;
|
|
}else{
|
|
break;
|
|
}
|
|
}
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
#if (PROJ_TYPE>=ARES_B)
|
|
//just ARESB have this function
|
|
//used this function to clear sdio rtl bug register
|
|
// if not do this sdio direct mode (wr/read reigster) will not work
|
|
int atbm_data_force_write(struct atbmwifi_common *hw_priv, const void *buf,
|
|
int buf_len)
|
|
{
|
|
int ret, retry = 1;
|
|
int buf_id_tx;
|
|
ATBM_BUG_ON(!hw_priv->sbus_ops);
|
|
hw_priv->sbus_ops->lock(hw_priv->sbus_priv);
|
|
buf_id_tx = ((hw_priv->buf_id_tx-1)&0x3f)+64;
|
|
wifi_printk(WIFI_ALWAYS,"buf_id_tx =%d %s\n",buf_id_tx,__func__);
|
|
while (retry <= MAX_RETRY) {
|
|
ret = __atbm_data_write(hw_priv,
|
|
ATBM_HIFREG_IN_OUT_QUEUE_REG_ID, buf,
|
|
buf_len, buf_id_tx);
|
|
|
|
if (!ret) {
|
|
buf_id_tx = ((buf_id_tx + hw_priv->buf_id_offset)&0x3f);
|
|
hw_priv->buf_id_tx = buf_id_tx;
|
|
break;
|
|
} else {
|
|
retry++;
|
|
atbm_mdelay(1000);
|
|
|
|
}
|
|
}
|
|
hw_priv->sbus_ops->unlock(hw_priv->sbus_priv);
|
|
return ret;
|
|
}
|
|
#endif //#if (PROJ_TYPE>=ARES_B)
|
|
|