Files
luban-lite/bsp/peripheral/wireless/atbm603x/hal/sdio/atbm_sdio_hwio.c
刘可亮 8bca5e8332 v1.0.4
2024-04-03 16:40:57 +08:00

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)