mirror of
https://github.com/RinCat/RTL88x2BU-Linux-Driver.git
synced 2024-12-26 10:01:33 +00:00
893 lines
24 KiB
C
893 lines
24 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright(c) 2016 - 2018 Realtek Corporation. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of version 2 of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
******************************************************************************/
|
|
|
|
#include "halmac_sdio_88xx.h"
|
|
#include "halmac_88xx_cfg.h"
|
|
|
|
#if HALMAC_88XX_SUPPORT
|
|
|
|
/* define the SDIO Bus CLK threshold */
|
|
/* for avoiding CMD53 fails that result from SDIO CLK sync to ana_clk fail */
|
|
#define SDIO_CLK_HIGH_SPEED_TH 50 /* 50MHz */
|
|
#define SDIO_CLK_SPEED_MAX 208 /* 208MHz */
|
|
|
|
/*only for r_indir_sdio_88xx !!, Soar 20171222*/
|
|
static u8
|
|
r_indir_cmd52_88xx(struct halmac_adapter *adapter, u32 offset);
|
|
|
|
/*only for r_indir_sdio_88xx !!, Soar 20171222*/
|
|
static u32
|
|
r_indir_cmd53_88xx(struct halmac_adapter *adapter, u32 offset);
|
|
|
|
/*only for r_indir_sdio_88xx !!, Soar 20171222*/
|
|
static u32
|
|
r8_indir_sdio_88xx(struct halmac_adapter *adapter, u32 adr);
|
|
|
|
/*only for r_indir_sdio_88xx !!, Soar 20171222*/
|
|
static u32
|
|
r16_indir_sdio_88xx(struct halmac_adapter *adapter, u32 adr);
|
|
|
|
/*only for r_indir_sdio_88xx !!, Soar 20171222*/
|
|
static u32
|
|
r32_indir_sdio_88xx(struct halmac_adapter *adapter, u32 adr);
|
|
|
|
/*only for w_indir_sdio_88xx !!, Soar 20171222*/
|
|
static enum halmac_ret_status
|
|
w_indir_cmd52_88xx(struct halmac_adapter *adapter, u32 adr, u32 val,
|
|
enum halmac_io_size size);
|
|
|
|
/*only for w_indir_sdio_88xx !!, Soar 20171222*/
|
|
static enum halmac_ret_status
|
|
w_indir_cmd53_88xx(struct halmac_adapter *adapter, u32 adr, u32 val,
|
|
enum halmac_io_size size);
|
|
|
|
/*only for w_indir_sdio_88xx !!, Soar 20171222*/
|
|
static enum halmac_ret_status
|
|
w8_indir_sdio_88xx(struct halmac_adapter *adapter, u32 adr, u32 val);
|
|
|
|
/*only for w_indir_sdio_88xx !!, Soar 20171222*/
|
|
static enum halmac_ret_status
|
|
w16_indir_sdio_88xx(struct halmac_adapter *adapter, u32 adr, u32 val);
|
|
|
|
/*only for w_indir_sdio_88xx !!, Soar 20171222*/
|
|
static enum halmac_ret_status
|
|
w32_indir_sdio_88xx(struct halmac_adapter *adapter, u32 adr, u32 val);
|
|
|
|
/**
|
|
* init_sdio_cfg_88xx() - init SDIO
|
|
* @adapter : the adapter of halmac
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
init_sdio_cfg_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
u32 value32;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
if (adapter->intf != HALMAC_INTERFACE_SDIO)
|
|
return HALMAC_RET_WRONG_INTF;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
HALMAC_REG_R32(REG_SDIO_FREE_TXPG);
|
|
|
|
value32 = HALMAC_REG_R32(REG_SDIO_TX_CTRL) & 0xFFFF;
|
|
value32 &= ~(BIT_CMD_ERR_STOP_INT_EN | BIT_EN_MASK_TIMER |
|
|
BIT_EN_RXDMA_MASK_INT);
|
|
HALMAC_REG_W32(REG_SDIO_TX_CTRL, value32);
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* deinit_sdio_cfg_88xx() - deinit SDIO
|
|
* @adapter : the adapter of halmac
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
deinit_sdio_cfg_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
if (adapter->intf != HALMAC_INTERFACE_SDIO)
|
|
return HALMAC_RET_WRONG_INTF;
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* cfg_sdio_rx_agg_88xx() - config rx aggregation
|
|
* @adapter : the adapter of halmac
|
|
* @halmac_rx_agg_mode
|
|
* Author : KaiYuan Chang/Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
cfg_sdio_rx_agg_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_rxagg_cfg *cfg)
|
|
{
|
|
u8 value8;
|
|
u8 size;
|
|
u8 timeout;
|
|
u8 agg_enable;
|
|
u32 value32;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
agg_enable = HALMAC_REG_R8(REG_TXDMA_PQ_MAP);
|
|
|
|
switch (cfg->mode) {
|
|
case HALMAC_RX_AGG_MODE_NONE:
|
|
agg_enable &= ~(BIT_RXDMA_AGG_EN);
|
|
break;
|
|
case HALMAC_RX_AGG_MODE_DMA:
|
|
case HALMAC_RX_AGG_MODE_USB:
|
|
agg_enable |= BIT_RXDMA_AGG_EN;
|
|
break;
|
|
default:
|
|
PLTFM_MSG_ERR("[ERR]unsupported mode\n");
|
|
agg_enable &= ~BIT_RXDMA_AGG_EN;
|
|
break;
|
|
}
|
|
|
|
if (cfg->threshold.drv_define == _FALSE) {
|
|
size = 0xFF;
|
|
timeout = 0x01;
|
|
} else {
|
|
size = cfg->threshold.size;
|
|
timeout = cfg->threshold.timeout;
|
|
}
|
|
|
|
value32 = HALMAC_REG_R32(REG_RXDMA_AGG_PG_TH);
|
|
if (cfg->threshold.size_limit_en == _FALSE)
|
|
HALMAC_REG_W32(REG_RXDMA_AGG_PG_TH, value32 & ~BIT_EN_PRE_CALC);
|
|
else
|
|
HALMAC_REG_W32(REG_RXDMA_AGG_PG_TH, value32 | BIT_EN_PRE_CALC);
|
|
|
|
HALMAC_REG_W8(REG_TXDMA_PQ_MAP, agg_enable);
|
|
HALMAC_REG_W16(REG_RXDMA_AGG_PG_TH,
|
|
(u16)(size | (timeout << BIT_SHIFT_DMA_AGG_TO_V1)));
|
|
|
|
value8 = HALMAC_REG_R8(REG_RXDMA_MODE);
|
|
if (0 != (agg_enable & BIT_RXDMA_AGG_EN))
|
|
HALMAC_REG_W8(REG_RXDMA_MODE, value8 | BIT_DMA_MODE);
|
|
else
|
|
HALMAC_REG_W8(REG_RXDMA_MODE, value8 & ~(BIT_DMA_MODE));
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* sdio_reg_rn_88xx() - read n byte register
|
|
* @adapter : the adapter of halmac
|
|
* @offset : register offset
|
|
* @halmac_size : register value size
|
|
* @value : register value
|
|
* Author : Soar
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
sdio_reg_rn_88xx(struct halmac_adapter *adapter, u32 offset, u32 size,
|
|
u8 *value)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
if (0 == (offset & 0xFFFF0000)) {
|
|
PLTFM_MSG_ERR("[ERR]offset 0x%x\n", offset);
|
|
return HALMAC_RET_FAIL;
|
|
}
|
|
|
|
status = cnv_to_sdio_bus_offset_88xx(adapter, &offset);
|
|
if (status != HALMAC_RET_SUCCESS) {
|
|
PLTFM_MSG_ERR("[ERR]convert offset\n");
|
|
return status;
|
|
}
|
|
|
|
if (adapter->halmac_state.mac_pwr == HALMAC_MAC_POWER_OFF) {
|
|
PLTFM_MSG_ERR("[ERR]power off\n");
|
|
return HALMAC_RET_FAIL;
|
|
}
|
|
|
|
PLTFM_SDIO_CMD53_RN(offset, size, value);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* cfg_txagg_sdio_align_88xx() -config sdio bus tx agg alignment
|
|
* @adapter : the adapter of halmac
|
|
* @enable : function enable(1)/disable(0)
|
|
* @align_size : sdio bus tx agg alignment size (2^n, n = 3~11)
|
|
* Author : Soar Tu
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
cfg_txagg_sdio_align_88xx(struct halmac_adapter *adapter, u8 enable,
|
|
u16 align_size)
|
|
{
|
|
u8 i;
|
|
u8 flag = 0;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (adapter->chip_id == HALMAC_CHIP_ID_8822B)
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
|
|
if ((align_size & 0xF000) != 0) {
|
|
PLTFM_MSG_ERR("[ERR]out of range\n");
|
|
return HALMAC_RET_FAIL;
|
|
}
|
|
|
|
for (i = 3; i <= 11; i++) {
|
|
if (align_size == 1 << i) {
|
|
flag = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (flag == 0) {
|
|
PLTFM_MSG_ERR("[ERR]not 2^3 ~ 2^11\n");
|
|
return HALMAC_RET_FAIL;
|
|
}
|
|
|
|
adapter->hw_cfg_info.tx_align_size = align_size;
|
|
|
|
if (enable)
|
|
HALMAC_REG_W16(REG_RQPN_CTRL_2, 0x8000 | align_size);
|
|
else
|
|
HALMAC_REG_W16(REG_RQPN_CTRL_2, align_size);
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* sdio_indirect_reg_r32_88xx() - read MAC reg by SDIO reg
|
|
* @adapter : the adapter of halmac
|
|
* @offset : register offset
|
|
* Author : Soar
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
u32
|
|
sdio_indirect_reg_r32_88xx(struct halmac_adapter *adapter, u32 offset)
|
|
{
|
|
return r_indir_sdio_88xx(adapter, offset, HALMAC_IO_DWORD);
|
|
}
|
|
|
|
/**
|
|
* set_sdio_bulkout_num_88xx() - inform bulk-out num
|
|
* @adapter : the adapter of halmac
|
|
* @bulkout_num : usb bulk-out number
|
|
* Author : KaiYuan Chang
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
set_sdio_bulkout_num_88xx(struct halmac_adapter *adapter, u8 num)
|
|
{
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
}
|
|
|
|
/**
|
|
* get_sdio_bulkout_id_88xx() - get bulk out id for the TX packet
|
|
* @adapter : the adapter of halmac
|
|
* @halmac_buf : tx packet, include txdesc
|
|
* @halmac_size : tx packet size
|
|
* @bulkout_id : usb bulk-out id
|
|
* Author : KaiYuan Chang
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
get_sdio_bulkout_id_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size,
|
|
u8 *id)
|
|
{
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
}
|
|
|
|
/**
|
|
* sdio_cmd53_4byte_88xx() - cmd53 only for 4byte len register IO
|
|
* @adapter : the adapter of halmac
|
|
* @enable : 1->CMD53 only use in 4byte reg, 0 : No limitation
|
|
* Author : Ivan Lin/KaiYuan Chang
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
sdio_cmd53_4byte_88xx(struct halmac_adapter *adapter,
|
|
enum halmac_sdio_cmd53_4byte_mode mode)
|
|
{
|
|
if (adapter->intf != HALMAC_INTERFACE_SDIO)
|
|
return HALMAC_RET_WRONG_INTF;
|
|
|
|
if (adapter->api_registry.sdio_cmd53_4byte_en == 0)
|
|
return HALMAC_RET_NOT_SUPPORT;
|
|
|
|
adapter->sdio_cmd53_4byte = mode;
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* sdio_hw_info_88xx() - info sdio hw info
|
|
* @adapter : the adapter of halmac
|
|
* @HALMAC_SDIO_CMD53_4BYTE_MODE :
|
|
* clock_speed : sdio bus clock. Unit -> MHz
|
|
* spec_ver : sdio spec version
|
|
* Author : Ivan Lin
|
|
* Return : enum halmac_ret_status
|
|
* More details of status code can be found in prototype document
|
|
*/
|
|
enum halmac_ret_status
|
|
sdio_hw_info_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_sdio_hw_info *info)
|
|
{
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (adapter->intf != HALMAC_INTERFACE_SDIO)
|
|
return HALMAC_RET_WRONG_INTF;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]SDIO clock:%d, spec:%d\n",
|
|
info->clock_speed, info->spec_ver);
|
|
|
|
if (info->clock_speed > SDIO_CLK_SPEED_MAX)
|
|
return HALMAC_RET_SDIO_CLOCK_ERR;
|
|
|
|
if (info->clock_speed > SDIO_CLK_HIGH_SPEED_TH)
|
|
adapter->sdio_hw_info.io_hi_speed_flag = 1;
|
|
|
|
adapter->sdio_hw_info.io_indir_flag = info->io_indir_flag;
|
|
if (info->clock_speed > SDIO_CLK_HIGH_SPEED_TH &&
|
|
adapter->sdio_hw_info.io_indir_flag == 0)
|
|
PLTFM_MSG_WARN("[WARN]SDIO clock:%d, indir access is better\n",
|
|
info->clock_speed);
|
|
|
|
adapter->sdio_hw_info.clock_speed = info->clock_speed;
|
|
adapter->sdio_hw_info.spec_ver = info->spec_ver;
|
|
adapter->sdio_hw_info.block_size = info->block_size;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
void
|
|
cfg_sdio_tx_page_threshold_88xx(struct halmac_adapter *adapter,
|
|
struct halmac_tx_page_threshold_info *info)
|
|
{
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
u32 threshold = info->threshold;
|
|
|
|
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
|
|
|
|
if (info->enable == 1) {
|
|
threshold = BIT(31) | threshold;
|
|
PLTFM_MSG_TRACE("[TRACE]enable\n");
|
|
} else {
|
|
threshold = ~(BIT(31)) & threshold;
|
|
PLTFM_MSG_TRACE("[TRACE]disable\n");
|
|
}
|
|
|
|
switch (info->dma_queue_sel) {
|
|
case HALMAC_MAP2_HQ:
|
|
HALMAC_REG_W32(REG_TQPNT1, threshold);
|
|
break;
|
|
case HALMAC_MAP2_NQ:
|
|
HALMAC_REG_W32(REG_TQPNT2, threshold);
|
|
break;
|
|
case HALMAC_MAP2_LQ:
|
|
HALMAC_REG_W32(REG_TQPNT3, threshold);
|
|
break;
|
|
case HALMAC_MAP2_EXQ:
|
|
HALMAC_REG_W32(REG_TQPNT4, threshold);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
cnv_to_sdio_bus_offset_88xx(struct halmac_adapter *adapter, u32 *offset)
|
|
{
|
|
switch ((*offset) & 0xFFFF0000) {
|
|
case WLAN_IOREG_OFFSET:
|
|
*offset &= HALMAC_WLAN_MAC_REG_MSK;
|
|
*offset |= HALMAC_SDIO_CMD_ADDR_MAC_REG << 13;
|
|
break;
|
|
case SDIO_LOCAL_OFFSET:
|
|
*offset &= HALMAC_SDIO_LOCAL_MSK;
|
|
*offset |= HALMAC_SDIO_CMD_ADDR_SDIO_REG << 13;
|
|
break;
|
|
default:
|
|
*offset = 0xFFFFFFFF;
|
|
PLTFM_MSG_ERR("[ERR]base address!!\n");
|
|
return HALMAC_RET_CONVERT_SDIO_OFFSET_FAIL;
|
|
}
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
leave_sdio_suspend_88xx(struct halmac_adapter *adapter)
|
|
{
|
|
u8 value8;
|
|
u32 cnt;
|
|
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
|
|
|
|
value8 = HALMAC_REG_R8(REG_SDIO_HSUS_CTRL);
|
|
HALMAC_REG_W8(REG_SDIO_HSUS_CTRL, value8 & ~(BIT(0)));
|
|
|
|
cnt = 10000;
|
|
while (!(HALMAC_REG_R8(REG_SDIO_HSUS_CTRL) & 0x02)) {
|
|
cnt--;
|
|
if (cnt == 0)
|
|
return HALMAC_RET_SDIO_LEAVE_SUSPEND_FAIL;
|
|
}
|
|
|
|
value8 = HALMAC_REG_R8(REG_HCI_OPT_CTRL + 2);
|
|
if (adapter->sdio_hw_info.spec_ver == HALMAC_SDIO_SPEC_VER_3_00)
|
|
HALMAC_REG_W8(REG_HCI_OPT_CTRL + 2, value8 | BIT(2));
|
|
else
|
|
HALMAC_REG_W8(REG_HCI_OPT_CTRL + 2, value8 & ~(BIT(2)));
|
|
|
|
return HALMAC_RET_SUCCESS;
|
|
}
|
|
|
|
/*only for r_indir_sdio_88xx !!, Soar 20171222*/
|
|
static u8
|
|
r_indir_cmd52_88xx(struct halmac_adapter *adapter, u32 offset)
|
|
{
|
|
u8 value8, tmp, cnt = 50;
|
|
u32 reg_cfg = REG_SDIO_INDIRECT_REG_CFG;
|
|
u32 reg_data = REG_SDIO_INDIRECT_REG_DATA;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
status = cnv_to_sdio_bus_offset_88xx(adapter, ®_cfg);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
status = cnv_to_sdio_bus_offset_88xx(adapter, ®_data);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
|
|
PLTFM_SDIO_CMD52_W(reg_cfg, (u8)offset);
|
|
PLTFM_SDIO_CMD52_W(reg_cfg + 1, (u8)(offset >> 8));
|
|
PLTFM_SDIO_CMD52_W(reg_cfg + 2, (u8)(BIT(3) | BIT(4)));
|
|
|
|
do {
|
|
tmp = PLTFM_SDIO_CMD52_R(reg_cfg + 2);
|
|
cnt--;
|
|
} while (((tmp & BIT(4)) == 0) && (cnt > 0));
|
|
|
|
if (((cnt & BIT(4)) == 0) && cnt == 0)
|
|
PLTFM_MSG_ERR("[ERR]sdio indirect CMD52 read\n");
|
|
|
|
value8 = PLTFM_SDIO_CMD52_R(reg_data);
|
|
|
|
return value8;
|
|
}
|
|
|
|
/*only for r_indir_sdio_88xx !!, Soar 20171222*/
|
|
static u32
|
|
r_indir_cmd53_88xx(struct halmac_adapter *adapter, u32 offset)
|
|
{
|
|
u8 tmp, cnt = 50;
|
|
u32 reg_cfg = REG_SDIO_INDIRECT_REG_CFG;
|
|
u32 reg_data = REG_SDIO_INDIRECT_REG_DATA;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
union {
|
|
u32 dword;
|
|
u8 byte[4];
|
|
} value32 = { 0x00000000 };
|
|
|
|
status = cnv_to_sdio_bus_offset_88xx(adapter, ®_cfg);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
status = cnv_to_sdio_bus_offset_88xx(adapter, ®_data);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
|
|
PLTFM_SDIO_CMD53_W32(reg_cfg, offset | BIT(19) | BIT(20));
|
|
|
|
do {
|
|
tmp = PLTFM_SDIO_CMD52_R(reg_cfg + 2);
|
|
cnt--;
|
|
} while (((tmp & BIT(4)) == 0) && (cnt > 0));
|
|
|
|
if (((cnt & BIT(4)) == 0) && cnt == 0)
|
|
PLTFM_MSG_ERR("[ERR]sdio indirect CMD53 read\n");
|
|
|
|
value32.dword = PLTFM_SDIO_CMD53_R32(reg_data);
|
|
|
|
return value32.dword;
|
|
}
|
|
|
|
/*only for r_indir_sdio_88xx !!, Soar 20171222*/
|
|
static u32
|
|
r8_indir_sdio_88xx(struct halmac_adapter *adapter, u32 adr)
|
|
{
|
|
union {
|
|
u32 dword;
|
|
u8 byte[4];
|
|
} val = { 0x00000000 };
|
|
|
|
if (adapter->pwr_off_flow_flag == 1 ||
|
|
adapter->halmac_state.mac_pwr == HALMAC_MAC_POWER_OFF) {
|
|
val.byte[0] = r_indir_cmd52_88xx(adapter, adr);
|
|
val.dword = rtk_le32_to_cpu(val.dword);
|
|
} else {
|
|
val.dword = r_indir_cmd53_88xx(adapter, adr);
|
|
}
|
|
|
|
return val.dword;
|
|
}
|
|
|
|
/*only for r_indir_sdio_88xx !!, Soar 20171222*/
|
|
static u32
|
|
r16_indir_sdio_88xx(struct halmac_adapter *adapter, u32 adr)
|
|
{
|
|
u32 reg_data = REG_SDIO_INDIRECT_REG_DATA;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
union {
|
|
u32 dword;
|
|
u8 byte[4];
|
|
} val = { 0x00000000 };
|
|
|
|
status = cnv_to_sdio_bus_offset_88xx(adapter, ®_data);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
|
|
if (adapter->halmac_state.mac_pwr == HALMAC_MAC_POWER_OFF) {
|
|
if (0 != (adr & (2 - 1))) {
|
|
val.byte[0] = r_indir_cmd52_88xx(adapter, adr);
|
|
val.byte[1] = r_indir_cmd52_88xx(adapter, adr + 1);
|
|
} else {
|
|
val.byte[0] = r_indir_cmd52_88xx(adapter, adr);
|
|
val.byte[1] = PLTFM_SDIO_CMD52_R(reg_data + 1);
|
|
}
|
|
val.dword = rtk_le32_to_cpu(val.dword);
|
|
} else {
|
|
if (0 != (adr & (2 - 1))) {
|
|
val.byte[0] = (u8)r_indir_cmd53_88xx(adapter, adr);
|
|
val.byte[1] = (u8)r_indir_cmd53_88xx(adapter, adr + 1);
|
|
val.dword = rtk_le32_to_cpu(val.dword);
|
|
} else {
|
|
val.dword = r_indir_cmd53_88xx(adapter, adr);
|
|
}
|
|
}
|
|
return val.dword;
|
|
}
|
|
|
|
/*only for r_indir_sdio_88xx !!, Soar 20171222*/
|
|
static u32
|
|
r32_indir_sdio_88xx(struct halmac_adapter *adapter, u32 adr)
|
|
{
|
|
u32 reg_data = REG_SDIO_INDIRECT_REG_DATA;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
union {
|
|
u32 dword;
|
|
u8 byte[4];
|
|
} val = { 0x00000000 };
|
|
|
|
status = cnv_to_sdio_bus_offset_88xx(adapter, ®_data);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
|
|
if (adapter->halmac_state.mac_pwr == HALMAC_MAC_POWER_OFF) {
|
|
if (0 != (adr & (4 - 1))) {
|
|
val.byte[0] = r_indir_cmd52_88xx(adapter, adr);
|
|
val.byte[1] = r_indir_cmd52_88xx(adapter, adr + 1);
|
|
val.byte[2] = r_indir_cmd52_88xx(adapter, adr + 2);
|
|
val.byte[3] = r_indir_cmd52_88xx(adapter, adr + 3);
|
|
} else {
|
|
val.byte[0] = r_indir_cmd52_88xx(adapter, adr);
|
|
val.byte[1] = PLTFM_SDIO_CMD52_R(reg_data + 1);
|
|
val.byte[2] = PLTFM_SDIO_CMD52_R(reg_data + 2);
|
|
val.byte[3] = PLTFM_SDIO_CMD52_R(reg_data + 3);
|
|
}
|
|
val.dword = rtk_le32_to_cpu(val.dword);
|
|
} else {
|
|
if (0 != (adr & (4 - 1))) {
|
|
val.byte[0] = (u8)r_indir_cmd53_88xx(adapter, adr);
|
|
val.byte[1] = (u8)r_indir_cmd53_88xx(adapter, adr + 1);
|
|
val.byte[2] = (u8)r_indir_cmd53_88xx(adapter, adr + 2);
|
|
val.byte[3] = (u8)r_indir_cmd53_88xx(adapter, adr + 3);
|
|
val.dword = rtk_le32_to_cpu(val.dword);
|
|
} else {
|
|
val.dword = r_indir_cmd53_88xx(adapter, adr);
|
|
}
|
|
}
|
|
return val.dword;
|
|
}
|
|
|
|
u32
|
|
r_indir_sdio_88xx(struct halmac_adapter *adapter, u32 adr,
|
|
enum halmac_io_size size)
|
|
{
|
|
u32 reg_data = REG_SDIO_INDIRECT_REG_DATA;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
union {
|
|
u32 dword;
|
|
u8 byte[4];
|
|
} val = { 0x00000000 };
|
|
|
|
status = cnv_to_sdio_bus_offset_88xx(adapter, ®_data);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
|
|
PLTFM_MUTEX_LOCK(&adapter->sdio_indir_mutex);
|
|
|
|
switch (size) {
|
|
case HALMAC_IO_BYTE:
|
|
val.dword = r8_indir_sdio_88xx(adapter, adr);
|
|
break;
|
|
case HALMAC_IO_WORD:
|
|
val.dword = r16_indir_sdio_88xx(adapter, adr);
|
|
break;
|
|
case HALMAC_IO_DWORD:
|
|
val.dword = r32_indir_sdio_88xx(adapter, adr);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
PLTFM_MUTEX_UNLOCK(&adapter->sdio_indir_mutex);
|
|
|
|
return val.dword;
|
|
}
|
|
|
|
/*only for w_indir_sdio_88xx !!, Soar 20171222*/
|
|
static enum halmac_ret_status
|
|
w_indir_cmd52_88xx(struct halmac_adapter *adapter, u32 adr, u32 val,
|
|
enum halmac_io_size size)
|
|
{
|
|
u8 tmp, cnt = 50;
|
|
u32 reg_cfg = REG_SDIO_INDIRECT_REG_CFG;
|
|
u32 reg_data = REG_SDIO_INDIRECT_REG_DATA;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
status = cnv_to_sdio_bus_offset_88xx(adapter, ®_cfg);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
status = cnv_to_sdio_bus_offset_88xx(adapter, ®_data);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
|
|
PLTFM_SDIO_CMD52_W(reg_cfg, (u8)adr);
|
|
PLTFM_SDIO_CMD52_W(reg_cfg + 1, (u8)(adr >> 8));
|
|
switch (size) {
|
|
case HALMAC_IO_BYTE:
|
|
PLTFM_SDIO_CMD52_W(reg_data, (u8)val);
|
|
PLTFM_SDIO_CMD52_W(reg_cfg + 2, (u8)(BIT(2) | BIT(4)));
|
|
break;
|
|
case HALMAC_IO_WORD:
|
|
PLTFM_SDIO_CMD52_W(reg_data, (u8)val);
|
|
PLTFM_SDIO_CMD52_W(reg_data + 1, (u8)(val >> 8));
|
|
PLTFM_SDIO_CMD52_W(reg_cfg + 2,
|
|
(u8)(BIT(0) | BIT(2) | BIT(4)));
|
|
break;
|
|
case HALMAC_IO_DWORD:
|
|
PLTFM_SDIO_CMD52_W(reg_data, (u8)val);
|
|
PLTFM_SDIO_CMD52_W(reg_data + 1, (u8)(val >> 8));
|
|
PLTFM_SDIO_CMD52_W(reg_data + 2, (u8)(val >> 16));
|
|
PLTFM_SDIO_CMD52_W(reg_data + 3, (u8)(val >> 24));
|
|
PLTFM_SDIO_CMD52_W(reg_cfg + 2,
|
|
(u8)(BIT(1) | BIT(2) | BIT(4)));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
do {
|
|
tmp = PLTFM_SDIO_CMD52_R(reg_cfg + 2);
|
|
cnt--;
|
|
} while (((tmp & BIT(4)) == 0) && (cnt > 0));
|
|
|
|
if (((cnt & BIT(4)) == 0) && cnt == 0)
|
|
PLTFM_MSG_ERR("[ERR]sdio indirect CMD52 write\n");
|
|
|
|
return status;
|
|
}
|
|
|
|
/*only for w_indir_sdio_88xx !!, Soar 20171222*/
|
|
static enum halmac_ret_status
|
|
w_indir_cmd53_88xx(struct halmac_adapter *adapter, u32 adr, u32 val,
|
|
enum halmac_io_size size)
|
|
{
|
|
u8 tmp, cnt = 50;
|
|
u32 reg_cfg = REG_SDIO_INDIRECT_REG_CFG;
|
|
u32 reg_data = REG_SDIO_INDIRECT_REG_DATA;
|
|
u32 value32 = 0;
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
status = cnv_to_sdio_bus_offset_88xx(adapter, ®_cfg);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
status = cnv_to_sdio_bus_offset_88xx(adapter, ®_data);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
|
|
switch (size) {
|
|
case HALMAC_IO_BYTE:
|
|
value32 = adr | BIT(18) | BIT(20);
|
|
break;
|
|
case HALMAC_IO_WORD:
|
|
value32 = adr | BIT(16) | BIT(18) | BIT(20);
|
|
break;
|
|
case HALMAC_IO_DWORD:
|
|
value32 = adr | BIT(17) | BIT(18) | BIT(20);
|
|
break;
|
|
default:
|
|
return HALMAC_RET_FAIL;
|
|
}
|
|
|
|
PLTFM_SDIO_CMD53_W32(reg_data, val);
|
|
PLTFM_SDIO_CMD53_W32(reg_cfg, value32);
|
|
|
|
do {
|
|
tmp = PLTFM_SDIO_CMD52_R(reg_cfg + 2);
|
|
cnt--;
|
|
} while (((tmp & BIT(4)) == 0) && (cnt > 0));
|
|
|
|
if (((cnt & BIT(4)) == 0) && cnt == 0)
|
|
PLTFM_MSG_ERR("[ERR]sdio indirect CMD53 read\n");
|
|
|
|
return status;
|
|
}
|
|
|
|
/*only for w_indir_sdio_88xx !!, Soar 20171222*/
|
|
static enum halmac_ret_status
|
|
w8_indir_sdio_88xx(struct halmac_adapter *adapter, u32 adr, u32 val)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
if (adapter->pwr_off_flow_flag == 1 ||
|
|
adapter->halmac_state.mac_pwr == HALMAC_MAC_POWER_OFF)
|
|
status = w_indir_cmd52_88xx(adapter, adr, val, HALMAC_IO_BYTE);
|
|
else
|
|
status = w_indir_cmd53_88xx(adapter, adr, val, HALMAC_IO_BYTE);
|
|
return status;
|
|
}
|
|
|
|
/*only for w_indir_sdio_88xx !!, Soar 20171222*/
|
|
static enum halmac_ret_status
|
|
w16_indir_sdio_88xx(struct halmac_adapter *adapter, u32 adr, u32 val)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
if (adapter->halmac_state.mac_pwr == HALMAC_MAC_POWER_OFF) {
|
|
if (0 != (adr & (2 - 1))) {
|
|
status = w_indir_cmd52_88xx(adapter, adr, val,
|
|
HALMAC_IO_BYTE);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
status = w_indir_cmd52_88xx(adapter, adr + 1, val >> 8,
|
|
HALMAC_IO_BYTE);
|
|
} else {
|
|
status = w_indir_cmd52_88xx(adapter, adr, val,
|
|
HALMAC_IO_WORD);
|
|
}
|
|
} else {
|
|
if (0 != (adr & (2 - 1))) {
|
|
status = w_indir_cmd53_88xx(adapter, adr, val,
|
|
HALMAC_IO_BYTE);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
status = w_indir_cmd53_88xx(adapter, adr + 1, val >> 8,
|
|
HALMAC_IO_BYTE);
|
|
} else {
|
|
status = w_indir_cmd53_88xx(adapter, adr, val,
|
|
HALMAC_IO_WORD);
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/*only for w_indir_sdio_88xx !!, Soar 20171222*/
|
|
static enum halmac_ret_status
|
|
w32_indir_sdio_88xx(struct halmac_adapter *adapter, u32 adr, u32 val)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
if (adapter->halmac_state.mac_pwr == HALMAC_MAC_POWER_OFF) {
|
|
if (0 != (adr & (4 - 1))) {
|
|
status = w_indir_cmd52_88xx(adapter, adr, val,
|
|
HALMAC_IO_BYTE);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
status = w_indir_cmd52_88xx(adapter, adr + 1, val >> 8,
|
|
HALMAC_IO_BYTE);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
status = w_indir_cmd52_88xx(adapter, adr + 2, val >> 16,
|
|
HALMAC_IO_BYTE);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
status = w_indir_cmd52_88xx(adapter, adr + 3, val >> 24,
|
|
HALMAC_IO_BYTE);
|
|
} else {
|
|
status = w_indir_cmd52_88xx(adapter, adr, val,
|
|
HALMAC_IO_DWORD);
|
|
}
|
|
} else {
|
|
if (0 != (adr & (4 - 1))) {
|
|
status = w_indir_cmd53_88xx(adapter, adr, val,
|
|
HALMAC_IO_BYTE);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
status = w_indir_cmd53_88xx(adapter, adr + 1, val >> 8,
|
|
HALMAC_IO_BYTE);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
status = w_indir_cmd53_88xx(adapter, adr + 2, val >> 16,
|
|
HALMAC_IO_BYTE);
|
|
if (status != HALMAC_RET_SUCCESS)
|
|
return status;
|
|
status = w_indir_cmd53_88xx(adapter, adr + 3, val >> 24,
|
|
HALMAC_IO_BYTE);
|
|
} else {
|
|
status = w_indir_cmd53_88xx(adapter, adr, val,
|
|
HALMAC_IO_DWORD);
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
enum halmac_ret_status
|
|
w_indir_sdio_88xx(struct halmac_adapter *adapter, u32 adr, u32 val,
|
|
enum halmac_io_size size)
|
|
{
|
|
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
|
|
|
|
PLTFM_MUTEX_LOCK(&adapter->sdio_indir_mutex);
|
|
|
|
switch (size) {
|
|
case HALMAC_IO_BYTE:
|
|
status = w8_indir_sdio_88xx(adapter, adr, val);
|
|
break;
|
|
case HALMAC_IO_WORD:
|
|
status = w16_indir_sdio_88xx(adapter, adr, val);
|
|
break;
|
|
case HALMAC_IO_DWORD:
|
|
status = w32_indir_sdio_88xx(adapter, adr, val);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
PLTFM_MUTEX_UNLOCK(&adapter->sdio_indir_mutex);
|
|
|
|
return status;
|
|
}
|
|
|
|
#endif /* HALMAC_88XX_SUPPORT */
|