Commit f0eb856e authored by Larry Finger's avatar Larry Finger Committed by John W. Linville

rtlwifi: rtl8188ee: Add new driver

Signed-off-by: default avatarLarry Finger <Larry.Finger@lwfinger.net>
Cc: jcheung@suse.com
Cc: machen@suse.com
Cc: mmarek@suse.cz
Cc: page_he@realsil.com.cn
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a269913c
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __RTL92C_DEF_H__
#define __RTL92C_DEF_H__
#define HAL_RETRY_LIMIT_INFRA 48
#define HAL_RETRY_LIMIT_AP_ADHOC 7
#define RESET_DELAY_8185 20
#define RT_IBSS_INT_MASKS (IMR_BCNINT | IMR_TBDOK | IMR_TBDER)
#define RT_AC_INT_MASKS (IMR_VIDOK | IMR_VODOK | IMR_BEDOK|IMR_BKDOK)
#define NUM_OF_FIRMWARE_QUEUE 10
#define NUM_OF_PAGES_IN_FW 0x100
#define NUM_OF_PAGE_IN_FW_QUEUE_BK 0x07
#define NUM_OF_PAGE_IN_FW_QUEUE_BE 0x07
#define NUM_OF_PAGE_IN_FW_QUEUE_VI 0x07
#define NUM_OF_PAGE_IN_FW_QUEUE_VO 0x07
#define NUM_OF_PAGE_IN_FW_QUEUE_HCCA 0x0
#define NUM_OF_PAGE_IN_FW_QUEUE_CMD 0x0
#define NUM_OF_PAGE_IN_FW_QUEUE_MGNT 0x02
#define NUM_OF_PAGE_IN_FW_QUEUE_HIGH 0x02
#define NUM_OF_PAGE_IN_FW_QUEUE_BCN 0x2
#define NUM_OF_PAGE_IN_FW_QUEUE_PUB 0xA1
#define NUM_OF_PAGE_IN_FW_QUEUE_BK_DTM 0x026
#define NUM_OF_PAGE_IN_FW_QUEUE_BE_DTM 0x048
#define NUM_OF_PAGE_IN_FW_QUEUE_VI_DTM 0x048
#define NUM_OF_PAGE_IN_FW_QUEUE_VO_DTM 0x026
#define NUM_OF_PAGE_IN_FW_QUEUE_PUB_DTM 0x00
#define MAX_LINES_HWCONFIG_TXT 1000
#define MAX_BYTES_LINE_HWCONFIG_TXT 256
#define SW_THREE_WIRE 0
#define HW_THREE_WIRE 2
#define BT_DEMO_BOARD 0
#define BT_QA_BOARD 1
#define BT_FPGA 2
#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0
#define HAL_PRIME_CHNL_OFFSET_LOWER 1
#define HAL_PRIME_CHNL_OFFSET_UPPER 2
#define MAX_H2C_QUEUE_NUM 10
#define RX_MPDU_QUEUE 0
#define RX_CMD_QUEUE 1
#define RX_MAX_QUEUE 2
#define AC2QUEUEID(_AC) (_AC)
#define C2H_RX_CMD_HDR_LEN 8
#define GET_C2H_CMD_CMD_LEN(__prxhdr) \
LE_BITS_TO_4BYTE((__prxhdr), 0, 16)
#define GET_C2H_CMD_ELEMENT_ID(__prxhdr) \
LE_BITS_TO_4BYTE((__prxhdr), 16, 8)
#define GET_C2H_CMD_CMD_SEQ(__prxhdr) \
LE_BITS_TO_4BYTE((__prxhdr), 24, 7)
#define GET_C2H_CMD_CONTINUE(__prxhdr) \
LE_BITS_TO_4BYTE((__prxhdr), 31, 1)
#define GET_C2H_CMD_CONTENT(__prxhdr) \
((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN)
#define GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr) \
LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8)
#define GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr) \
LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8)
#define GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr) \
LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16)
#define GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr) \
LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5)
#define GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr) \
LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1)
#define GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr) \
LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5)
#define GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr) \
LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1)
#define GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr) \
LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4)
#define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \
LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12)
#define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3)
/* [15:12] IC version(CUT): A-cut=0, B-cut=1, C-cut=2, D-cut=3
* [7] Manufacturer: TSMC=0, UMC=1
* [6:4] RF type: 1T1R=0, 1T2R=1, 2T2R=2
* [3] Chip type: TEST=0, NORMAL=1
* [2:0] IC type: 81xxC=0, 8723=1, 92D=2
*/
#define CHIP_8723 BIT(0)
#define CHIP_92D BIT(1)
#define NORMAL_CHIP BIT(3)
#define RF_TYPE_1T1R (~(BIT(4)|BIT(5)|BIT(6)))
#define RF_TYPE_1T2R BIT(4)
#define RF_TYPE_2T2R BIT(5)
#define CHIP_VENDOR_UMC BIT(7)
#define B_CUT_VERSION BIT(12)
#define C_CUT_VERSION BIT(13)
#define D_CUT_VERSION ((BIT(12)|BIT(13)))
#define E_CUT_VERSION BIT(14)
/* MASK */
#define IC_TYPE_MASK (BIT(0)|BIT(1)|BIT(2))
#define CHIP_TYPE_MASK BIT(3)
#define RF_TYPE_MASK (BIT(4)|BIT(5)|BIT(6))
#define MANUFACTUER_MASK BIT(7)
#define ROM_VERSION_MASK (BIT(11)|BIT(10)|BIT(9)|BIT(8))
#define CUT_VERSION_MASK (BIT(15)|BIT(14)|BIT(13)|BIT(12))
/* Get element */
#define GET_CVID_IC_TYPE(version) ((version) & IC_TYPE_MASK)
#define GET_CVID_CHIP_TYPE(version) ((version) & CHIP_TYPE_MASK)
#define GET_CVID_RF_TYPE(version) ((version) & RF_TYPE_MASK)
#define GET_CVID_MANUFACTUER(version) ((version) & MANUFACTUER_MASK)
#define GET_CVID_ROM_VERSION(version) ((version) & ROM_VERSION_MASK)
#define GET_CVID_CUT_VERSION(version) ((version) & CUT_VERSION_MASK)
#define IS_81XXC(version) \
((GET_CVID_IC_TYPE(version) == 0) ? true : false)
#define IS_8723_SERIES(version) \
((GET_CVID_IC_TYPE(version) == CHIP_8723) ? true : false)
#define IS_92D(version) \
((GET_CVID_IC_TYPE(version) == CHIP_92D) ? true : false)
#define IS_NORMAL_CHIP(version) \
((GET_CVID_CHIP_TYPE(version)) ? true : false)
#define IS_NORMAL_CHIP92D(version) \
((GET_CVID_CHIP_TYPE(version)) ? true : false)
#define IS_1T1R(version) \
((GET_CVID_RF_TYPE(version)) ? false : true)
#define IS_1T2R(version) \
((GET_CVID_RF_TYPE(version) == RF_TYPE_1T2R) ? true : false)
#define IS_2T2R(version) \
((GET_CVID_RF_TYPE(version) == RF_TYPE_2T2R) ? true : false)
#define IS_CHIP_VENDOR_UMC(version) \
((GET_CVID_MANUFACTUER(version)) ? true : false)
#define IS_92C_SERIAL(version) \
((IS_81XXC(version) && IS_2T2R(version)) ? true : false)
#define IS_81xxC_VENDOR_UMC_A_CUT(version) \
(IS_81XXC(version) ? ((IS_CHIP_VENDOR_UMC(version)) ? \
((GET_CVID_CUT_VERSION(version)) ? false : true) : false) : false)
#define IS_81xxC_VENDOR_UMC_B_CUT(version) \
(IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ? \
((GET_CVID_CUT_VERSION(version) == B_CUT_VERSION) ? true \
: false) : false) : false)
enum version_8188e {
VERSION_TEST_CHIP_88E = 0x00,
VERSION_NORMAL_CHIP_88E = 0x01,
VERSION_UNKNOWN = 0xFF,
};
enum rx_packet_type {
NORMAL_RX,
TX_REPORT1,
TX_REPORT2,
HIS_REPORT,
};
enum rtl819x_loopback_e {
RTL819X_NO_LOOPBACK = 0,
RTL819X_MAC_LOOPBACK = 1,
RTL819X_DMA_LOOPBACK = 2,
RTL819X_CCK_LOOPBACK = 3,
};
enum rf_optype {
RF_OP_BY_SW_3WIRE = 0,
RF_OP_BY_FW,
RF_OP_MAX
};
enum rf_power_state {
RF_ON,
RF_OFF,
RF_SLEEP,
RF_SHUT_DOWN,
};
enum power_save_mode {
POWER_SAVE_MODE_ACTIVE,
POWER_SAVE_MODE_SAVE,
};
enum power_polocy_config {
POWERCFG_MAX_POWER_SAVINGS,
POWERCFG_GLOBAL_POWER_SAVINGS,
POWERCFG_LOCAL_POWER_SAVINGS,
POWERCFG_LENOVO,
};
enum interface_select_pci {
INTF_SEL1_MINICARD,
INTF_SEL0_PCIE,
INTF_SEL2_RSV,
INTF_SEL3_RSV,
};
enum hal_fw_c2h_cmd_id {
HAL_FW_C2H_CMD_Read_MACREG,
HAL_FW_C2H_CMD_Read_BBREG,
HAL_FW_C2H_CMD_Read_RFREG,
HAL_FW_C2H_CMD_Read_EEPROM,
HAL_FW_C2H_CMD_Read_EFUSE,
HAL_FW_C2H_CMD_Read_CAM,
HAL_FW_C2H_CMD_Get_BasicRate,
HAL_FW_C2H_CMD_Get_DataRate,
HAL_FW_C2H_CMD_Survey,
HAL_FW_C2H_CMD_SurveyDone,
HAL_FW_C2H_CMD_JoinBss,
HAL_FW_C2H_CMD_AddSTA,
HAL_FW_C2H_CMD_DelSTA,
HAL_FW_C2H_CMD_AtimDone,
HAL_FW_C2H_CMD_TX_Report,
HAL_FW_C2H_CMD_CCX_Report,
HAL_FW_C2H_CMD_DTM_Report,
HAL_FW_C2H_CMD_TX_Rate_Statistics,
HAL_FW_C2H_CMD_C2HLBK,
HAL_FW_C2H_CMD_C2HDBG,
HAL_FW_C2H_CMD_C2HFEEDBACK,
HAL_FW_C2H_CMD_MAX
};
enum wake_on_wlan_mode {
ewowlandisable,
ewakeonmagicpacketonly,
ewakeonpatternmatchonly,
ewakeonbothtypepacket
};
enum rtl_desc_qsel {
QSLT_BK = 0x2,
QSLT_BE = 0x0,
QSLT_VI = 0x5,
QSLT_VO = 0x7,
QSLT_BEACON = 0x10,
QSLT_HIGH = 0x11,
QSLT_MGNT = 0x12,
QSLT_CMD = 0x13,
};
enum rtl_desc92c_rate {
DESC92C_RATE1M = 0x00,
DESC92C_RATE2M = 0x01,
DESC92C_RATE5_5M = 0x02,
DESC92C_RATE11M = 0x03,
DESC92C_RATE6M = 0x04,
DESC92C_RATE9M = 0x05,
DESC92C_RATE12M = 0x06,
DESC92C_RATE18M = 0x07,
DESC92C_RATE24M = 0x08,
DESC92C_RATE36M = 0x09,
DESC92C_RATE48M = 0x0a,
DESC92C_RATE54M = 0x0b,
DESC92C_RATEMCS0 = 0x0c,
DESC92C_RATEMCS1 = 0x0d,
DESC92C_RATEMCS2 = 0x0e,
DESC92C_RATEMCS3 = 0x0f,
DESC92C_RATEMCS4 = 0x10,
DESC92C_RATEMCS5 = 0x11,
DESC92C_RATEMCS6 = 0x12,
DESC92C_RATEMCS7 = 0x13,
DESC92C_RATEMCS8 = 0x14,
DESC92C_RATEMCS9 = 0x15,
DESC92C_RATEMCS10 = 0x16,
DESC92C_RATEMCS11 = 0x17,
DESC92C_RATEMCS12 = 0x18,
DESC92C_RATEMCS13 = 0x19,
DESC92C_RATEMCS14 = 0x1a,
DESC92C_RATEMCS15 = 0x1b,
DESC92C_RATEMCS15_SG = 0x1c,
DESC92C_RATEMCS32 = 0x20,
};
struct phy_sts_cck_8192s_t {
u8 adc_pwdb_X[4];
u8 sq_rpt;
u8 cck_agc_rpt;
};
struct h2c_cmd_8192c {
u8 element_id;
u32 cmd_len;
u8 *p_cmdbuffer;
};
#endif
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "wifi.h"
#include "base.h"
#include "pci.h"
#include "reg.h"
#include "def.h"
#include "phy.h"
#include "dm.h"
#include "fw.h"
#include "trx.h"
static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
0x7f8001fe, /* 0, +6.0dB */
0x788001e2, /* 1, +5.5dB */
0x71c001c7, /* 2, +5.0dB */
0x6b8001ae, /* 3, +4.5dB */
0x65400195, /* 4, +4.0dB */
0x5fc0017f, /* 5, +3.5dB */
0x5a400169, /* 6, +3.0dB */
0x55400155, /* 7, +2.5dB */
0x50800142, /* 8, +2.0dB */
0x4c000130, /* 9, +1.5dB */
0x47c0011f, /* 10, +1.0dB */
0x43c0010f, /* 11, +0.5dB */
0x40000100, /* 12, +0dB */
0x3c8000f2, /* 13, -0.5dB */
0x390000e4, /* 14, -1.0dB */
0x35c000d7, /* 15, -1.5dB */
0x32c000cb, /* 16, -2.0dB */
0x300000c0, /* 17, -2.5dB */
0x2d4000b5, /* 18, -3.0dB */
0x2ac000ab, /* 19, -3.5dB */
0x288000a2, /* 20, -4.0dB */
0x26000098, /* 21, -4.5dB */
0x24000090, /* 22, -5.0dB */
0x22000088, /* 23, -5.5dB */
0x20000080, /* 24, -6.0dB */
0x1e400079, /* 25, -6.5dB */
0x1c800072, /* 26, -7.0dB */
0x1b00006c, /* 27. -7.5dB */
0x19800066, /* 28, -8.0dB */
0x18000060, /* 29, -8.5dB */
0x16c0005b, /* 30, -9.0dB */
0x15800056, /* 31, -9.5dB */
0x14400051, /* 32, -10.0dB */
0x1300004c, /* 33, -10.5dB */
0x12000048, /* 34, -11.0dB */
0x11000044, /* 35, -11.5dB */
0x10000040, /* 36, -12.0dB */
0x0f00003c, /* 37, -12.5dB */
0x0e400039, /* 38, -13.0dB */
0x0d800036, /* 39, -13.5dB */
0x0cc00033, /* 40, -14.0dB */
0x0c000030, /* 41, -14.5dB */
0x0b40002d, /* 42, -15.0dB */
};
static const u8 cck_tbl_ch1_13[CCK_TABLE_SIZE][8] = {
{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */
{0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */
{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */
{0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */
{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */
{0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */
{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */
{0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */
{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */
{0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */
{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */
{0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */
{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */
{0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */
{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */
{0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */
{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
{0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */
{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */
{0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */
{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB*/
{0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB*/
{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB*/
{0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB*/
{0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB*/
{0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB*/
{0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB*/
{0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB*/
{0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB*/
{0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB*/
{0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB*/
{0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB*/
{0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB*/
};
static const u8 cck_tbl_ch14[CCK_TABLE_SIZE][8] = {
{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */
{0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */
{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */
{0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */
{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */
{0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */
{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */
{0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */
{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */
{0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */
{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */
{0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */
{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */
{0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */
{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */
{0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */
{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
{0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */
{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */
{0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */
{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB*/
{0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB*/
{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB*/
{0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB*/
{0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB*/
{0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB*/
{0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB*/
{0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB*/
{0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB*/
{0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB*/
{0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB*/
{0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB*/
{0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB*/
};
#define CAL_SWING_OFF(_off, _dir, _size, _del) \
do { \
for (_off = 0; _off < _size; _off++) { \
if (_del < thermal_threshold[_dir][_off]) { \
if (_off != 0) \
_off--; \
break; \
} \
} \
if (_off >= _size) \
_off = _size - 1; \
} while (0)
static void rtl88e_set_iqk_matrix(struct ieee80211_hw *hw,
u8 ofdm_index, u8 rfpath,
long iqk_result_x, long iqk_result_y)
{
long ele_a = 0, ele_d, ele_c = 0, value32;
ele_d = (ofdmswing_table[ofdm_index] & 0xFFC00000)>>22;
if (iqk_result_x != 0) {
if ((iqk_result_x & 0x00000200) != 0)
iqk_result_x = iqk_result_x | 0xFFFFFC00;
ele_a = ((iqk_result_x * ele_d)>>8)&0x000003FF;
if ((iqk_result_y & 0x00000200) != 0)
iqk_result_y = iqk_result_y | 0xFFFFFC00;
ele_c = ((iqk_result_y * ele_d)>>8)&0x000003FF;
switch (rfpath) {
case RF90_PATH_A:
value32 = (ele_d << 22)|((ele_c & 0x3F)<<16) | ele_a;
rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, MASKDWORD,
value32);
value32 = (ele_c & 0x000003C0) >> 6;
rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, value32);
value32 = ((iqk_result_x * ele_d) >> 7) & 0x01;
rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(24), value32);
break;
case RF90_PATH_B:
value32 = (ele_d << 22)|((ele_c & 0x3F)<<16) | ele_a;
rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBAL,
MASKDWORD, value32);
value32 = (ele_c & 0x000003C0) >> 6;
rtl_set_bbreg(hw, ROFDM0_XDTXAFE, MASKH4BITS, value32);
value32 = ((iqk_result_x * ele_d) >> 7) & 0x01;
rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(28), value32);
break;
default:
break;
}
} else {
switch (rfpath) {
case RF90_PATH_A:
rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, MASKDWORD,
ofdmswing_table[ofdm_index]);
rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, 0x00);
rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(24), 0x00);
break;
case RF90_PATH_B:
rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBAL, MASKDWORD,
ofdmswing_table[ofdm_index]);
rtl_set_bbreg(hw, ROFDM0_XDTXAFE, MASKH4BITS, 0x00);
rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(28), 0x00);
break;
default:
break;
}
}
}
void rtl88e_dm_txpower_track_adjust(struct ieee80211_hw *hw,
u8 type, u8 *pdirection, u32 *poutwrite_val)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
u8 pwr_val = 0;
u8 cck_base = rtldm->swing_idx_cck_base;
u8 cck_val = rtldm->swing_idx_cck;
u8 ofdm_base = rtldm->swing_idx_ofdm_base;
u8 ofdm_val = rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A];
if (type == 0) {
if (ofdm_val <= ofdm_base) {
*pdirection = 1;
pwr_val = ofdm_base - ofdm_val;
} else {
*pdirection = 2;
pwr_val = ofdm_val - ofdm_base;
}
} else if (type == 1) {
if (cck_val <= cck_base) {
*pdirection = 1;
pwr_val = cck_base - cck_val;
} else {
*pdirection = 2;
pwr_val = cck_val - cck_base;
}
}
if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1))
pwr_val = TXPWRTRACK_MAX_IDX;
*poutwrite_val = pwr_val | (pwr_val << 8) | (pwr_val << 16) |
(pwr_val << 24);
}
static void rtl88e_chk_tx_track(struct ieee80211_hw *hw,
enum pwr_track_control_method method,
u8 rfpath, u8 index)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
int jj = rtldm->swing_idx_cck;
int i;
if (method == TXAGC) {
if (rtldm->swing_flag_ofdm == true ||
rtldm->swing_flag_cck == true) {
u8 chan = rtlphy->current_channel;
rtl88e_phy_set_txpower_level(hw, chan);
rtldm->swing_flag_ofdm = false;
rtldm->swing_flag_cck = false;
}
} else if (method == BBSWING) {
if (!rtldm->cck_inch14) {
for (i = 0; i < 8; i++)
rtl_write_byte(rtlpriv, 0xa22 + i,
cck_tbl_ch1_13[jj][i]);
} else {
for (i = 0; i < 8; i++)
rtl_write_byte(rtlpriv, 0xa22 + i,
cck_tbl_ch14[jj][i]);
}
if (rfpath == RF90_PATH_A) {
long x = rtlphy->iqk_matrix[index].value[0][0];
long y = rtlphy->iqk_matrix[index].value[0][1];
u8 indx = rtldm->swing_idx_ofdm[rfpath];
rtl88e_set_iqk_matrix(hw, indx, rfpath, x, y);
} else if (rfpath == RF90_PATH_B) {
u8 indx = rtldm->swing_idx_ofdm[rfpath];
long x = rtlphy->iqk_matrix[indx].value[0][4];
long y = rtlphy->iqk_matrix[indx].value[0][5];
rtl88e_set_iqk_matrix(hw, indx, rfpath, x, y);
}
} else {
return;
}
}
static void rtl88e_dm_diginit(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct dig_t *dm_dig = &rtlpriv->dm_digtable;
dm_dig->dig_enable_flag = true;
dm_dig->cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f);
dm_dig->pre_igvalue = 0;
dm_dig->cursta_cstate = DIG_STA_DISCONNECT;
dm_dig->presta_cstate = DIG_STA_DISCONNECT;
dm_dig->curmultista_cstate = DIG_MULTISTA_DISCONNECT;
dm_dig->rssi_lowthresh = DM_DIG_THRESH_LOW;
dm_dig->rssi_highthresh = DM_DIG_THRESH_HIGH;
dm_dig->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
dm_dig->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
dm_dig->rx_gain_max = DM_DIG_MAX;
dm_dig->rx_gain_min = DM_DIG_MIN;
dm_dig->back_val = DM_DIG_BACKOFF_DEFAULT;
dm_dig->back_range_max = DM_DIG_BACKOFF_MAX;
dm_dig->back_range_min = DM_DIG_BACKOFF_MIN;
dm_dig->pre_cck_cca_thres = 0xff;
dm_dig->cur_cck_cca_thres = 0x83;
dm_dig->forbidden_igi = DM_DIG_MIN;
dm_dig->large_fa_hit = 0;
dm_dig->recover_cnt = 0;
dm_dig->dig_min_0 = 0x25;
dm_dig->dig_min_1 = 0x25;
dm_dig->media_connect_0 = false;
dm_dig->media_connect_1 = false;
rtlpriv->dm.dm_initialgain_enable = true;
}
static u8 rtl88e_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct dig_t *dm_dig = &rtlpriv->dm_digtable;
long rssi_val_min = 0;
if ((dm_dig->curmultista_cstate == DIG_MULTISTA_CONNECT) &&
(dm_dig->cursta_cstate == DIG_STA_CONNECT)) {
if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0)
rssi_val_min =
(rtlpriv->dm.entry_min_undec_sm_pwdb >
rtlpriv->dm.undec_sm_pwdb) ?
rtlpriv->dm.undec_sm_pwdb :
rtlpriv->dm.entry_min_undec_sm_pwdb;
else
rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
} else if (dm_dig->cursta_cstate == DIG_STA_CONNECT ||
dm_dig->cursta_cstate == DIG_STA_BEFORE_CONNECT) {
rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
} else if (dm_dig->curmultista_cstate ==
DIG_MULTISTA_CONNECT) {
rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb;
}
return (u8)rssi_val_min;
}
static void rtl88e_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
{
u32 ret_value;
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct false_alarm_statistics *alm_cnt = &(rtlpriv->falsealm_cnt);
rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 1);
rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 1);
ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD);
alm_cnt->cnt_fast_fsync_fail = (ret_value&0xffff);
alm_cnt->cnt_sb_search_fail = ((ret_value&0xffff0000)>>16);
ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
alm_cnt->cnt_ofdm_cca = (ret_value&0xffff);
alm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
alm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
alm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
alm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
alm_cnt->cnt_ofdm_fail = alm_cnt->cnt_parity_fail +
alm_cnt->cnt_rate_illegal +
alm_cnt->cnt_crc8_fail +
alm_cnt->cnt_mcs_fail +
alm_cnt->cnt_fast_fsync_fail +
alm_cnt->cnt_sb_search_fail;
ret_value = rtl_get_bbreg(hw, REG_SC_CNT, MASKDWORD);
alm_cnt->cnt_bw_lsc = (ret_value & 0xffff);
alm_cnt->cnt_bw_usc = ((ret_value & 0xffff0000) >> 16);
rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(12), 1);
rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);
ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
alm_cnt->cnt_cck_fail = ret_value;
ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);
alm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
ret_value = rtl_get_bbreg(hw, RCCK0_CCA_CNT, MASKDWORD);
alm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) |
((ret_value&0xFF00)>>8);
alm_cnt->cnt_all = alm_cnt->cnt_fast_fsync_fail +
alm_cnt->cnt_sb_search_fail +
alm_cnt->cnt_parity_fail +
alm_cnt->cnt_rate_illegal +
alm_cnt->cnt_crc8_fail +
alm_cnt->cnt_mcs_fail +
alm_cnt->cnt_cck_fail;
alm_cnt->cnt_cca_all = alm_cnt->cnt_ofdm_cca + alm_cnt->cnt_cck_cca;
rtl_set_bbreg(hw, ROFDM0_TRSWISOLATION, BIT(31), 1);
rtl_set_bbreg(hw, ROFDM0_TRSWISOLATION, BIT(31), 0);
rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(27), 1);
rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(27), 0);
rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 0);
rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 0);
rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(13)|BIT(12), 0);
rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(13)|BIT(12), 2);
rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(15)|BIT(14), 0);
rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(15)|BIT(14), 2);
RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
"cnt_parity_fail = %d, cnt_rate_illegal = %d, "
"cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
alm_cnt->cnt_parity_fail,
alm_cnt->cnt_rate_illegal,
alm_cnt->cnt_crc8_fail, alm_cnt->cnt_mcs_fail);
RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
"cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
alm_cnt->cnt_ofdm_fail,
alm_cnt->cnt_cck_fail, alm_cnt->cnt_all);
}
static void rtl88e_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct dig_t *dm_dig = &rtlpriv->dm_digtable;
u8 cur_cck_cca_thresh;
if (dm_dig->cursta_cstate == DIG_STA_CONNECT) {
dm_dig->rssi_val_min = rtl88e_dm_initial_gain_min_pwdb(hw);
if (dm_dig->rssi_val_min > 25) {
cur_cck_cca_thresh = 0xcd;
} else if ((dm_dig->rssi_val_min <= 25) &&
(dm_dig->rssi_val_min > 10)) {
cur_cck_cca_thresh = 0x83;
} else {
if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
cur_cck_cca_thresh = 0x83;
else
cur_cck_cca_thresh = 0x40;
}
} else {
if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
cur_cck_cca_thresh = 0x83;
else
cur_cck_cca_thresh = 0x40;
}
if (dm_dig->cur_cck_cca_thres != cur_cck_cca_thresh)
rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh);
dm_dig->cur_cck_cca_thres = cur_cck_cca_thresh;
dm_dig->pre_cck_cca_thres = dm_dig->cur_cck_cca_thres;
RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
"CCK cca thresh hold =%x\n", dm_dig->cur_cck_cca_thres);
}
static void rtl88e_dm_dig(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct dig_t *dm_dig = &rtlpriv->dm_digtable;
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
u8 dig_min, dig_maxofmin;
bool bfirstconnect;
u8 dm_dig_max, dm_dig_min;
u8 current_igi = dm_dig->cur_igvalue;
if (rtlpriv->dm.dm_initialgain_enable == false)
return;
if (dm_dig->dig_enable_flag == false)
return;
if (mac->act_scanning == true)
return;
if (mac->link_state >= MAC80211_LINKED)
dm_dig->cursta_cstate = DIG_STA_CONNECT;
else
dm_dig->cursta_cstate = DIG_STA_DISCONNECT;
if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC)
dm_dig->cursta_cstate = DIG_STA_DISCONNECT;
dm_dig_max = DM_DIG_MAX;
dm_dig_min = DM_DIG_MIN;
dig_maxofmin = DM_DIG_MAX_AP;
dig_min = dm_dig->dig_min_0;
bfirstconnect = ((mac->link_state >= MAC80211_LINKED) ? true : false) &&
(dm_dig->media_connect_0 == false);
dm_dig->rssi_val_min =
rtl88e_dm_initial_gain_min_pwdb(hw);
if (mac->link_state >= MAC80211_LINKED) {
if ((dm_dig->rssi_val_min + 20) > dm_dig_max)
dm_dig->rx_gain_max = dm_dig_max;
else if ((dm_dig->rssi_val_min + 20) < dm_dig_min)
dm_dig->rx_gain_max = dm_dig_min;
else
dm_dig->rx_gain_max = dm_dig->rssi_val_min + 20;
if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) {
dig_min = dm_dig->antdiv_rssi_max;
} else {
if (dm_dig->rssi_val_min < dm_dig_min)
dig_min = dm_dig_min;
else if (dm_dig->rssi_val_min < dig_maxofmin)
dig_min = dig_maxofmin;
else
dig_min = dm_dig->rssi_val_min;
}
} else {
dm_dig->rx_gain_max = dm_dig_max;
dig_min = dm_dig_min;
RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n");
}
if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
dm_dig->large_fa_hit++;
if (dm_dig->forbidden_igi < current_igi) {
dm_dig->forbidden_igi = current_igi;
dm_dig->large_fa_hit = 1;
}
if (dm_dig->large_fa_hit >= 3) {
if ((dm_dig->forbidden_igi + 1) > dm_dig->rx_gain_max)
dm_dig->rx_gain_min = dm_dig->rx_gain_max;
else
dm_dig->rx_gain_min = dm_dig->forbidden_igi + 1;
dm_dig->recover_cnt = 3600;
}
} else {
if (dm_dig->recover_cnt != 0) {
dm_dig->recover_cnt--;
} else {
if (dm_dig->large_fa_hit == 0) {
if ((dm_dig->forbidden_igi - 1) < dig_min) {
dm_dig->forbidden_igi = dig_min;
dm_dig->rx_gain_min = dig_min;
} else {
dm_dig->forbidden_igi--;
dm_dig->rx_gain_min =
dm_dig->forbidden_igi + 1;
}
} else if (dm_dig->large_fa_hit == 3) {
dm_dig->large_fa_hit = 0;
}
}
}
if (dm_dig->cursta_cstate == DIG_STA_CONNECT) {
if (bfirstconnect) {
current_igi = dm_dig->rssi_val_min;
} else {
if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2)
current_igi += 2;
else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1)
current_igi++;
else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
current_igi--;
}
} else {
if (rtlpriv->falsealm_cnt.cnt_all > 10000)
current_igi += 2;
else if (rtlpriv->falsealm_cnt.cnt_all > 8000)
current_igi++;
else if (rtlpriv->falsealm_cnt.cnt_all < 500)
current_igi--;
}
if (current_igi > DM_DIG_FA_UPPER)
current_igi = DM_DIG_FA_UPPER;
else if (current_igi < DM_DIG_FA_LOWER)
current_igi = DM_DIG_FA_LOWER;
if (rtlpriv->falsealm_cnt.cnt_all > 10000)
current_igi = DM_DIG_FA_UPPER;
dm_dig->cur_igvalue = current_igi;
rtl88e_dm_write_dig(hw);
dm_dig->media_connect_0 = ((mac->link_state >= MAC80211_LINKED) ?
true : false);
dm_dig->dig_min_0 = dig_min;
rtl88e_dm_cck_packet_detection_thresh(hw);
}
static void rtl88e_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtlpriv->dm.dynamic_txpower_enable = false;
rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
}
static void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
long undec_sm_pwdb;
if (!rtlpriv->dm.dynamic_txpower_enable)
return;
if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
return;
}
if ((mac->link_state < MAC80211_LINKED) &&
(rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
"Not connected\n");
rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
return;
}
if (mac->link_state >= MAC80211_LINKED) {
if (mac->opmode == NL80211_IFTYPE_ADHOC) {
undec_sm_pwdb =
rtlpriv->dm.entry_min_undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"AP Client PWDB = 0x%lx\n",
undec_sm_pwdb);
} else {
undec_sm_pwdb =
rtlpriv->dm.undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"STA Default Port PWDB = 0x%lx\n",
undec_sm_pwdb);
}
} else {
undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"AP Ext Port PWDB = 0x%lx\n", undec_sm_pwdb);
}
if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"TXHIGHPWRLEVEL_LEVEL1 (TxPwr = 0x0)\n");
} else if ((undec_sm_pwdb <
(TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
(undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"TXHIGHPWRLEVEL_LEVEL1 (TxPwr = 0x10)\n");
} else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"TXHIGHPWRLEVEL_NORMAL\n");
}
if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) {
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"PHY_SetTxPowerLevel8192S() Channel = %d\n",
rtlphy->current_channel);
rtl88e_phy_set_txpower_level(hw, rtlphy->current_channel);
}
rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
}
void rtl88e_dm_write_dig(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct dig_t *dm_dig = &rtlpriv->dm_digtable;
RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
"cur_igvalue = 0x%x, "
"pre_igvalue = 0x%x, back_val = %d\n",
dm_dig->cur_igvalue, dm_dig->pre_igvalue,
dm_dig->back_val);
if (dm_dig->cur_igvalue > 0x3f)
dm_dig->cur_igvalue = 0x3f;
if (dm_dig->pre_igvalue != dm_dig->cur_igvalue) {
rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
dm_dig->cur_igvalue);
dm_dig->pre_igvalue = dm_dig->cur_igvalue;
}
}
static void rtl88e_dm_pwdb_monitor(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_sta_info *drv_priv;
static u64 last_txok;
static u64 last_rx;
long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff;
if (rtlhal->oem_id == RT_CID_819x_HP) {
u64 cur_txok_cnt = 0;
u64 cur_rxok_cnt = 0;
cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok;
cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rx;
last_txok = cur_txok_cnt;
last_rx = cur_rxok_cnt;
if (cur_rxok_cnt > (cur_txok_cnt * 6))
rtl_write_dword(rtlpriv, REG_ARFR0, 0x8f015);
else
rtl_write_dword(rtlpriv, REG_ARFR0, 0xff015);
}
/* AP & ADHOC & MESH */
spin_lock_bh(&rtlpriv->locks.entry_list_lock);
list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
if (drv_priv->rssi_stat.undec_sm_pwdb < tmp_entry_min_pwdb)
tmp_entry_min_pwdb = drv_priv->rssi_stat.undec_sm_pwdb;
if (drv_priv->rssi_stat.undec_sm_pwdb > tmp_entry_max_pwdb)
tmp_entry_max_pwdb = drv_priv->rssi_stat.undec_sm_pwdb;
}
spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
/* If associated entry is found */
if (tmp_entry_max_pwdb != 0) {
rtlpriv->dm.entry_max_undec_sm_pwdb = tmp_entry_max_pwdb;
RTPRINT(rtlpriv, FDM, DM_PWDB, "EntryMaxPWDB = 0x%lx(%ld)\n",
tmp_entry_max_pwdb, tmp_entry_max_pwdb);
} else {
rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
}
/* If associated entry is found */
if (tmp_entry_min_pwdb != 0xff) {
rtlpriv->dm.entry_min_undec_sm_pwdb = tmp_entry_min_pwdb;
RTPRINT(rtlpriv, FDM, DM_PWDB, "EntryMinPWDB = 0x%lx(%ld)\n",
tmp_entry_min_pwdb, tmp_entry_min_pwdb);
} else {
rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
}
/* Indicate Rx signal strength to FW. */
if (!rtlpriv->dm.useramask)
rtl_write_byte(rtlpriv, 0x4fe, rtlpriv->dm.undec_sm_pwdb);
}
void rtl88e_dm_init_edca_turbo(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtlpriv->dm.current_turbo_edca = false;
rtlpriv->dm.is_any_nonbepkts = false;
rtlpriv->dm.is_cur_rdlstate = false;
}
static void rtl88e_dm_check_edca_turbo(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
static u64 last_txok_cnt;
static u64 last_rxok_cnt;
static u32 last_bt_edca_ul;
static u32 last_bt_edca_dl;
u64 cur_txok_cnt = 0;
u64 cur_rxok_cnt = 0;
u32 edca_be_ul = 0x5ea42b;
u32 edca_be_dl = 0x5ea42b;
bool change_edca = false;
if ((last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul) ||
(last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl)) {
rtlpriv->dm.current_turbo_edca = false;
last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl;
}
if (rtlpcipriv->bt_coexist.bt_edca_ul != 0) {
edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
change_edca = true;
}
if (rtlpcipriv->bt_coexist.bt_edca_dl != 0) {
edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl;
change_edca = true;
}
if (mac->link_state != MAC80211_LINKED) {
rtlpriv->dm.current_turbo_edca = false;
return;
}
if ((!mac->ht_enable) && (!rtlpcipriv->bt_coexist.bt_coexistence)) {
if (!(edca_be_ul & 0xffff0000))
edca_be_ul |= 0x005e0000;
if (!(edca_be_dl & 0xffff0000))
edca_be_dl |= 0x005e0000;
}
if ((change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) &&
(!rtlpriv->dm.disable_framebursting))) {
cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
if (cur_rxok_cnt > 4 * cur_txok_cnt) {
if (!rtlpriv->dm.is_cur_rdlstate ||
!rtlpriv->dm.current_turbo_edca) {
rtl_write_dword(rtlpriv,
REG_EDCA_BE_PARAM,
edca_be_dl);
rtlpriv->dm.is_cur_rdlstate = true;
}
} else {
if (rtlpriv->dm.is_cur_rdlstate ||
!rtlpriv->dm.current_turbo_edca) {
rtl_write_dword(rtlpriv,
REG_EDCA_BE_PARAM,
edca_be_ul);
rtlpriv->dm.is_cur_rdlstate = false;
}
}
rtlpriv->dm.current_turbo_edca = true;
} else {
if (rtlpriv->dm.current_turbo_edca) {
u8 tmp = AC0_BE;
rtlpriv->cfg->ops->set_hw_reg(hw,
HW_VAR_AC_PARAM,
(u8 *)(&tmp));
rtlpriv->dm.current_turbo_edca = false;
}
}
rtlpriv->dm.is_any_nonbepkts = false;
last_txok_cnt = rtlpriv->stats.txbytesunicast;
last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
}
static void rtl88e_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
*hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
u8 thermalvalue = 0, delta, delta_lck, delta_iqk, off;
u8 th_avg_cnt = 0;
u32 thermalvalue_avg = 0;
long ele_d, temp_cck;
char ofdm_index[2], cck_index = 0, ofdm_old[2] = {0, 0}, cck_old = 0;
int i = 0;
bool is2t = false;
u8 ofdm_min_index = 6, rf = (is2t) ? 2 : 1;
u8 index_for_channel;
enum _dec_inc {dec, power_inc};
/* 0.1 the following TWO tables decide the final index of
* OFDM/CCK swing table
*/
char del_tbl_idx[2][15] = {
{0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11},
{0, 0, -1, -2, -3, -4, -4, -4, -4, -5, -7, -8, -9, -9, -10}
};
u8 thermal_threshold[2][15] = {
{0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27},
{0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 25, 25}
};
/*Initilization (7 steps in total) */
rtlpriv->dm.txpower_trackinginit = true;
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
"rtl88e_dm_txpower_tracking_callback_thermalmeter\n");
thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0xfc00);
if (!thermalvalue)
return;
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
"Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n",
thermalvalue, rtlpriv->dm.thermalvalue,
rtlefuse->eeprom_thermalmeter);
/*1. Query OFDM Default Setting: Path A*/
ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBAL, MASKDWORD) & MASKOFDM_D;
for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
ofdm_old[0] = (u8) i;
rtldm->swing_idx_ofdm_base = (u8)i;
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
"Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index = 0x%x\n",
ROFDM0_XATXIQIMBAL,
ele_d, ofdm_old[0]);
break;
}
}
if (is2t) {
ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBAL,
MASKDWORD) & MASKOFDM_D;
for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
ofdm_old[1] = (u8)i;
RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
DBG_LOUD,
"Initial pathB ele_d reg0x%x = 0x%lx, ofdm_index = 0x%x\n",
ROFDM0_XBTXIQIMBAL, ele_d,
ofdm_old[1]);
break;
}
}
}
/*2.Query CCK default setting From 0xa24*/
temp_cck = rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK;
for (i = 0; i < CCK_TABLE_LENGTH; i++) {
if (rtlpriv->dm.cck_inch14) {
if (memcmp(&temp_cck, &cck_tbl_ch14[i][2], 4) == 0) {
cck_old = (u8)i;
rtldm->swing_idx_cck_base = (u8)i;
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
"Initial reg0x%x = 0x%lx, cck_index = 0x%x, ch 14 %d\n",
RCCK0_TXFILTER2, temp_cck, cck_old,
rtlpriv->dm.cck_inch14);
break;
}
} else {
if (memcmp(&temp_cck, &cck_tbl_ch1_13[i][2], 4) == 0) {
cck_old = (u8)i;
rtldm->swing_idx_cck_base = (u8)i;
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
"Initial reg0x%x = 0x%lx, cck_index = 0x%x, ch14 %d\n",
RCCK0_TXFILTER2, temp_cck, cck_old,
rtlpriv->dm.cck_inch14);
break;
}
}
}
/*3 Initialize ThermalValues of RFCalibrateInfo*/
if (!rtldm->thermalvalue) {
rtlpriv->dm.thermalvalue = rtlefuse->eeprom_thermalmeter;
rtlpriv->dm.thermalvalue_lck = thermalvalue;
rtlpriv->dm.thermalvalue_iqk = thermalvalue;
for (i = 0; i < rf; i++)
rtlpriv->dm.ofdm_index[i] = ofdm_old[i];
rtlpriv->dm.cck_index = cck_old;
}
/*4 Calculate average thermal meter*/
rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermalvalue;
rtldm->thermalvalue_avg_index++;
if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_88E)
rtldm->thermalvalue_avg_index = 0;
for (i = 0; i < AVG_THERMAL_NUM_88E; i++) {
if (rtldm->thermalvalue_avg[i]) {
thermalvalue_avg += rtldm->thermalvalue_avg[i];
th_avg_cnt++;
}
}
if (th_avg_cnt)
thermalvalue = (u8)(thermalvalue_avg / th_avg_cnt);
/* 5 Calculate delta, delta_LCK, delta_IQK.*/
if (rtlhal->reloadtxpowerindex) {
delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
(thermalvalue - rtlefuse->eeprom_thermalmeter) :
(rtlefuse->eeprom_thermalmeter - thermalvalue);
rtlhal->reloadtxpowerindex = false;
rtlpriv->dm.done_txpower = false;
} else if (rtlpriv->dm.done_txpower) {
delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
(thermalvalue - rtlpriv->dm.thermalvalue) :
(rtlpriv->dm.thermalvalue - thermalvalue);
} else {
delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
(thermalvalue - rtlefuse->eeprom_thermalmeter) :
(rtlefuse->eeprom_thermalmeter - thermalvalue);
}
delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
(thermalvalue - rtlpriv->dm.thermalvalue_lck) :
(rtlpriv->dm.thermalvalue_lck - thermalvalue);
delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
(thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
(rtlpriv->dm.thermalvalue_iqk - thermalvalue);
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
"Readback Thermal Meter = 0x%x pre thermal meter 0x%x "
"eeprom_thermalmeter 0x%x delta 0x%x "
"delta_lck 0x%x delta_iqk 0x%x\n",
thermalvalue, rtlpriv->dm.thermalvalue,
rtlefuse->eeprom_thermalmeter, delta, delta_lck,
delta_iqk);
/* 6 If necessary, do LCK.*/
if (delta_lck >= 8) {
rtlpriv->dm.thermalvalue_lck = thermalvalue;
rtl88e_phy_lc_calibrate(hw);
}
/* 7 If necessary, move the index of swing table to adjust Tx power. */
if (delta > 0 && rtlpriv->dm.txpower_track_control) {
delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
(thermalvalue - rtlefuse->eeprom_thermalmeter) :
(rtlefuse->eeprom_thermalmeter - thermalvalue);
/* 7.1 Get the final CCK_index and OFDM_index for each
* swing table.
*/
if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
CAL_SWING_OFF(off, power_inc, IDX_MAP, delta);
for (i = 0; i < rf; i++)
ofdm_index[i] = rtldm->ofdm_index[i] +
del_tbl_idx[power_inc][off];
cck_index = rtldm->cck_index +
del_tbl_idx[power_inc][off];
} else {
CAL_SWING_OFF(off, dec, IDX_MAP, delta);
for (i = 0; i < rf; i++)
ofdm_index[i] = rtldm->ofdm_index[i] +
del_tbl_idx[dec][off];
cck_index = rtldm->cck_index + del_tbl_idx[dec][off];
}
/* 7.2 Handle boundary conditions of index.*/
for (i = 0; i < rf; i++) {
if (ofdm_index[i] > OFDM_TABLE_SIZE-1)
ofdm_index[i] = OFDM_TABLE_SIZE-1;
else if (rtldm->ofdm_index[i] < ofdm_min_index)
ofdm_index[i] = ofdm_min_index;
}
if (cck_index > CCK_TABLE_SIZE - 1)
cck_index = CCK_TABLE_SIZE - 1;
else if (cck_index < 0)
cck_index = 0;
/*7.3Configure the Swing Table to adjust Tx Power.*/
if (rtlpriv->dm.txpower_track_control) {
rtldm->done_txpower = true;
rtldm->swing_idx_ofdm[RF90_PATH_A] =
(u8)ofdm_index[RF90_PATH_A];
if (is2t)
rtldm->swing_idx_ofdm[RF90_PATH_B] =
(u8)ofdm_index[RF90_PATH_B];
rtldm->swing_idx_cck = cck_index;
if (rtldm->swing_idx_ofdm_cur !=
rtldm->swing_idx_ofdm[0]) {
rtldm->swing_idx_ofdm_cur =
rtldm->swing_idx_ofdm[0];
rtldm->swing_flag_ofdm = true;
}
if (rtldm->swing_idx_cck != rtldm->swing_idx_cck) {
rtldm->swing_idx_cck_cur = rtldm->swing_idx_cck;
rtldm->swing_flag_cck = true;
}
rtl88e_chk_tx_track(hw, TXAGC, 0, 0);
if (is2t)
rtl88e_chk_tx_track(hw, BBSWING,
RF90_PATH_B,
index_for_channel);
}
}
if (delta_iqk >= 8) {
rtlpriv->dm.thermalvalue_iqk = thermalvalue;
rtl88e_phy_iq_calibrate(hw, false);
}
if (rtldm->txpower_track_control)
rtldm->thermalvalue = thermalvalue;
rtldm->txpowercount = 0;
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n");
}
static void rtl88e_dm_init_txpower_tracking(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtlpriv->dm.txpower_tracking = true;
rtlpriv->dm.txpower_trackinginit = false;
rtlpriv->dm.txpowercount = 0;
rtlpriv->dm.txpower_track_control = true;
rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A] = 12;
rtlpriv->dm.swing_idx_ofdm_cur = 12;
rtlpriv->dm.swing_flag_ofdm = false;
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
" rtlpriv->dm.txpower_tracking = %d\n",
rtlpriv->dm.txpower_tracking);
}
void rtl88e_dm_check_txpower_tracking(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
static u8 tm_trigger;
if (!rtlpriv->dm.txpower_tracking)
return;
if (!tm_trigger) {
rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17)|BIT(16),
0x03);
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
"Trigger 88E Thermal Meter!!\n");
tm_trigger = 1;
return;
} else {
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
"Schedule TxPowerTracking !!\n");
rtl88e_dm_txpower_tracking_callback_thermalmeter(hw);
tm_trigger = 0;
}
}
void rtl88e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rate_adaptive *p_ra = &(rtlpriv->ra);
p_ra->ratr_state = DM_RATR_STA_INIT;
p_ra->pre_ratr_state = DM_RATR_STA_INIT;
if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
rtlpriv->dm.useramask = true;
else
rtlpriv->dm.useramask = false;
}
static void rtl88e_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rate_adaptive *p_ra = &(rtlpriv->ra);
struct ieee80211_sta *sta = NULL;
u32 low_rssi, hi_rssi;
if (is_hal_stop(rtlhal)) {
RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
"driver is going to unload\n");
return;
}
if (!rtlpriv->dm.useramask) {
RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
"driver does not control rate adaptive mask\n");
return;
}
if (mac->link_state == MAC80211_LINKED &&
mac->opmode == NL80211_IFTYPE_STATION) {
switch (p_ra->pre_ratr_state) {
case DM_RATR_STA_HIGH:
hi_rssi = 50;
low_rssi = 20;
break;
case DM_RATR_STA_MIDDLE:
hi_rssi = 55;
low_rssi = 20;
break;
case DM_RATR_STA_LOW:
hi_rssi = 50;
low_rssi = 25;
break;
default:
hi_rssi = 50;
low_rssi = 20;
break;
}
if (rtlpriv->dm.undec_sm_pwdb > (long)hi_rssi)
p_ra->ratr_state = DM_RATR_STA_HIGH;
else if (rtlpriv->dm.undec_sm_pwdb > (long)low_rssi)
p_ra->ratr_state = DM_RATR_STA_MIDDLE;
else
p_ra->ratr_state = DM_RATR_STA_LOW;
if (p_ra->pre_ratr_state != p_ra->ratr_state) {
RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
"RSSI = %ld\n",
rtlpriv->dm.undec_sm_pwdb);
RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
"RSSI_LEVEL = %d\n", p_ra->ratr_state);
RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
"PreState = %d, CurState = %d\n",
p_ra->pre_ratr_state, p_ra->ratr_state);
rcu_read_lock();
sta = rtl_find_sta(hw, mac->bssid);
if (sta)
rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
p_ra->ratr_state);
rcu_read_unlock();
p_ra->pre_ratr_state = p_ra->ratr_state;
}
}
}
static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
dm_pstable->pre_ccastate = CCA_MAX;
dm_pstable->cur_ccasate = CCA_MAX;
dm_pstable->pre_rfstate = RF_MAX;
dm_pstable->cur_rfstate = RF_MAX;
dm_pstable->rssi_val_min = 0;
}
static void rtl88e_dm_update_rx_idle_ant(struct ieee80211_hw *hw, u8 ant)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
u32 def_ant, opt_ant;
if (fat_tbl->rx_idle_ant != ant) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"need to update rx idle ant\n");
if (ant == MAIN_ANT) {
def_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ?
MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
opt_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ?
AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
} else {
def_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ?
AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
opt_ant = (fat_tbl->rx_idle_ant == CG_TRX_HW_ANTDIV) ?
MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
}
if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) {
rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(5) |
BIT(4) | BIT(3), def_ant);
rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) |
BIT(7) | BIT(6), opt_ant);
rtl_set_bbreg(hw, DM_REG_ANTSEL_CTRL_11N, BIT(14) |
BIT(13) | BIT(12), def_ant);
rtl_set_bbreg(hw, DM_REG_RESP_TX_11N, BIT(6) | BIT(7),
def_ant);
} else if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) {
rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(5) |
BIT(4) | BIT(3), def_ant);
rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) |
BIT(7) | BIT(6), opt_ant);
}
}
fat_tbl->rx_idle_ant = ant;
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RxIdleAnt %s\n",
((ant == MAIN_ANT) ? ("MAIN_ANT") : ("AUX_ANT")));
}
static void rtl88e_dm_update_tx_ant(struct ieee80211_hw *hw,
u8 ant, u32 mac_id)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
u8 target_ant;
if (ant == MAIN_ANT)
target_ant = MAIN_ANT_CG_TRX;
else
target_ant = AUX_ANT_CG_TRX;
fat_tbl->antsel_a[mac_id] = target_ant & BIT(0);
fat_tbl->antsel_b[mac_id] = (target_ant & BIT(1)) >> 1;
fat_tbl->antsel_c[mac_id] = (target_ant & BIT(2)) >> 2;
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "txfrominfo target ant %s\n",
((ant == MAIN_ANT) ? ("MAIN_ANT") : ("AUX_ANT")));
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "antsel_tr_mux = 3'b%d%d%d\n",
fat_tbl->antsel_c[mac_id],
fat_tbl->antsel_b[mac_id], fat_tbl->antsel_a[mac_id]);
}
static void rtl88e_dm_rx_hw_antena_div_init(struct ieee80211_hw *hw)
{
u32 value32;
/*MAC Setting*/
value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD);
rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD, value32 |
(BIT(23) | BIT(25)));
/*Pin Setting*/
rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 1);
rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1);
/*OFDM Setting*/
rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0);
/*CCK Setting*/
rtl_set_bbreg(hw, DM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
rtl88e_dm_update_rx_idle_ant(hw, MAIN_ANT);
rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKLWORD, 0x0201);
}
static void rtl88e_dm_trx_hw_antenna_div_init(struct ieee80211_hw *hw)
{
u32 value32;
/*MAC Setting*/
value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD);
rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD, value32 |
(BIT(23) | BIT(25)));
/*Pin Setting*/
rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 0);
rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1);
/*OFDM Setting*/
rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0);
/*CCK Setting*/
rtl_set_bbreg(hw, DM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
/*TX Setting*/
rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 0);
rtl88e_dm_update_rx_idle_ant(hw, MAIN_ANT);
rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKLWORD, 0x0201);
}
static void rtl88e_dm_fast_training_init(struct ieee80211_hw *hw)
{
struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
u32 ant_combo = 2;
u32 value32, i;
for (i = 0; i < 6; i++) {
fat_tbl->bssid[i] = 0;
fat_tbl->ant_sum[i] = 0;
fat_tbl->ant_cnt[i] = 0;
fat_tbl->ant_ave[i] = 0;
}
fat_tbl->train_idx = 0;
fat_tbl->fat_state = FAT_NORMAL_STATE;
/*MAC Setting*/
value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD);
rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD, value32 | (BIT(23) |
BIT(25)));
value32 = rtl_get_bbreg(hw, DM_REG_ANT_TRAIN_2, MASKDWORD);
rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2, MASKDWORD, value32 | (BIT(16) |
BIT(17)));
rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2, MASKLWORD, 0);
rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_1, MASKDWORD, 0);
/*Pin Setting*/
rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 0);
rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1);
/*OFDM Setting*/
rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0);
/*antenna mapping table*/
if (ant_combo == 2) {
rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE0, 1);
rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE1, 2);
} else if (ant_combo == 7) {
rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE0, 1);
rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE1, 2);
rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE2, 2);
rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE3, 3);
rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE0, 4);
rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE1, 5);
rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE2, 6);
rtl_set_bbreg(hw, DM_REG_ANT_MAPPING2_11N, MASKBYTE3, 7);
}
/*TX Setting*/
rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 1);
rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(5) | BIT(4) | BIT(3), 0);
rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) | BIT(7) | BIT(6), 1);
rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(2) | BIT(1) | BIT(0),
(ant_combo - 1));
rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1);
}
static void rtl88e_dm_antenna_div_init(struct ieee80211_hw *hw)
{
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV)
rtl88e_dm_rx_hw_antena_div_init(hw);
else if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
rtl88e_dm_trx_hw_antenna_div_init(hw);
else if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV)
rtl88e_dm_fast_training_init(hw);
}
void rtl88e_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw,
u8 *pdesc, u32 mac_id)
{
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) ||
(rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)) {
SET_TX_DESC_ANTSEL_A(pdesc, fat_tbl->antsel_a[mac_id]);
SET_TX_DESC_ANTSEL_B(pdesc, fat_tbl->antsel_b[mac_id]);
SET_TX_DESC_ANTSEL_C(pdesc, fat_tbl->antsel_c[mac_id]);
}
}
void rtl88e_dm_ant_sel_statistics(struct ieee80211_hw *hw,
u8 antsel_tr_mux, u32 mac_id, u32 rx_pwdb_all)
{
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) {
if (antsel_tr_mux == MAIN_ANT_CG_TRX) {
fat_tbl->main_ant_sum[mac_id] += rx_pwdb_all;
fat_tbl->main_ant_cnt[mac_id]++;
} else {
fat_tbl->aux_ant_sum[mac_id] += rx_pwdb_all;
fat_tbl->aux_ant_cnt[mac_id]++;
}
} else if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) {
if (antsel_tr_mux == MAIN_ANT_CGCS_RX) {
fat_tbl->main_ant_sum[mac_id] += rx_pwdb_all;
fat_tbl->main_ant_cnt[mac_id]++;
} else {
fat_tbl->aux_ant_sum[mac_id] += rx_pwdb_all;
fat_tbl->aux_ant_cnt[mac_id]++;
}
}
}
static void rtl88e_dm_hw_ant_div(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct dig_t *dm_dig = &rtlpriv->dm_digtable;
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
struct rtl_sta_info *drv_priv;
struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
u32 i, min_rssi = 0xff, ant_div_max_rssi = 0, max_rssi = 0;
u32 local_min_rssi, local_max_rssi;
u32 main_rssi, aux_rssi;
u8 rx_idle_ant = 0, target_ant = 7;
i = 0;
main_rssi = (fat_tbl->main_ant_cnt[i] != 0) ?
(fat_tbl->main_ant_sum[i] /
fat_tbl->main_ant_cnt[i]) : 0;
aux_rssi = (fat_tbl->aux_ant_cnt[i] != 0) ?
(fat_tbl->aux_ant_sum[i] / fat_tbl->aux_ant_cnt[i]) : 0;
target_ant = (main_rssi == aux_rssi) ?
fat_tbl->rx_idle_ant : ((main_rssi >= aux_rssi) ?
MAIN_ANT : AUX_ANT);
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"main_ant_sum %d main_ant_cnt %d\n",
fat_tbl->main_ant_sum[i], fat_tbl->main_ant_cnt[i]);
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"aux_ant_sum %d aux_ant_cnt %d\n",
fat_tbl->aux_ant_sum[i],
fat_tbl->aux_ant_cnt[i]);
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"main_rssi %d aux_rssi%d\n", main_rssi, aux_rssi);
local_max_rssi = (main_rssi > aux_rssi) ? main_rssi : aux_rssi;
if ((local_max_rssi > ant_div_max_rssi) && (local_max_rssi < 40))
ant_div_max_rssi = local_max_rssi;
if (local_max_rssi > max_rssi)
max_rssi = local_max_rssi;
if ((fat_tbl->rx_idle_ant == MAIN_ANT) && (main_rssi == 0))
main_rssi = aux_rssi;
else if ((fat_tbl->rx_idle_ant == AUX_ANT) && (aux_rssi == 0))
aux_rssi = main_rssi;
local_min_rssi = (main_rssi > aux_rssi) ? aux_rssi : main_rssi;
if (local_min_rssi < min_rssi) {
min_rssi = local_min_rssi;
rx_idle_ant = target_ant;
}
if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
rtl88e_dm_update_tx_ant(hw, target_ant, i);
if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) {
spin_lock_bh(&rtlpriv->locks.entry_list_lock);
list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
i++;
main_rssi = (fat_tbl->main_ant_cnt[i] != 0) ?
(fat_tbl->main_ant_sum[i] /
fat_tbl->main_ant_cnt[i]) : 0;
aux_rssi = (fat_tbl->aux_ant_cnt[i] != 0) ?
(fat_tbl->aux_ant_sum[i] /
fat_tbl->aux_ant_cnt[i]) : 0;
target_ant = (main_rssi == aux_rssi) ?
fat_tbl->rx_idle_ant : ((main_rssi >=
aux_rssi) ? MAIN_ANT : AUX_ANT);
local_max_rssi = max_t(u32, main_rssi, aux_rssi);
if ((local_max_rssi > ant_div_max_rssi) &&
(local_max_rssi < 40))
ant_div_max_rssi = local_max_rssi;
if (local_max_rssi > max_rssi)
max_rssi = local_max_rssi;
if ((fat_tbl->rx_idle_ant == MAIN_ANT) && !main_rssi)
main_rssi = aux_rssi;
else if ((fat_tbl->rx_idle_ant == AUX_ANT) &&
(aux_rssi == 0))
aux_rssi = main_rssi;
local_min_rssi = (main_rssi > aux_rssi) ?
aux_rssi : main_rssi;
if (local_min_rssi < min_rssi) {
min_rssi = local_min_rssi;
rx_idle_ant = target_ant;
}
if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
rtl88e_dm_update_tx_ant(hw, target_ant, i);
}
spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
}
for (i = 0; i < ASSOCIATE_ENTRY_NUM; i++) {
fat_tbl->main_ant_sum[i] = 0;
fat_tbl->aux_ant_sum[i] = 0;
fat_tbl->main_ant_cnt[i] = 0;
fat_tbl->aux_ant_cnt[i] = 0;
}
rtl88e_dm_update_rx_idle_ant(hw, rx_idle_ant);
dm_dig->antdiv_rssi_max = ant_div_max_rssi;
dm_dig->rssi_max = max_rssi;
}
static void rtl88e_set_next_mac_address_target(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
struct rtl_sta_info *drv_priv;
struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
u32 value32, i, j = 0;
if (mac->link_state >= MAC80211_LINKED) {
for (i = 0; i < ASSOCIATE_ENTRY_NUM; i++) {
if ((fat_tbl->train_idx + 1) == ASSOCIATE_ENTRY_NUM)
fat_tbl->train_idx = 0;
else
fat_tbl->train_idx++;
if (fat_tbl->train_idx == 0) {
value32 = (mac->mac_addr[5] << 8) |
mac->mac_addr[4];
rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2,
MASKLWORD, value32);
value32 = (mac->mac_addr[3] << 24) |
(mac->mac_addr[2] << 16) |
(mac->mac_addr[1] << 8) |
mac->mac_addr[0];
rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_1,
MASKDWORD, value32);
break;
}
if (rtlpriv->mac80211.opmode !=
NL80211_IFTYPE_STATION) {
spin_lock_bh(&rtlpriv->locks.entry_list_lock);
list_for_each_entry(drv_priv,
&rtlpriv->entry_list,
list) {
j++;
if (j != fat_tbl->train_idx)
continue;
value32 = (drv_priv->mac_addr[5] << 8) |
drv_priv->mac_addr[4];
rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_2,
MASKLWORD, value32);
value32 = (drv_priv->mac_addr[3]<<24) |
(drv_priv->mac_addr[2]<<16) |
(drv_priv->mac_addr[1]<<8) |
drv_priv->mac_addr[0];
rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_1,
MASKDWORD, value32);
break;
}
spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
/*find entry, break*/
if (j == fat_tbl->train_idx)
break;
}
}
}
}
static void rtl88e_dm_fast_ant_training(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
u32 i, max_rssi = 0;
u8 target_ant = 2;
bool bpkt_filter_match = false;
if (fat_tbl->fat_state == FAT_TRAINING_STATE) {
for (i = 0; i < 7; i++) {
if (fat_tbl->ant_cnt[i] == 0) {
fat_tbl->ant_ave[i] = 0;
} else {
fat_tbl->ant_ave[i] = fat_tbl->ant_sum[i] /
fat_tbl->ant_cnt[i];
bpkt_filter_match = true;
}
if (fat_tbl->ant_ave[i] > max_rssi) {
max_rssi = fat_tbl->ant_ave[i];
target_ant = (u8) i;
}
}
if (bpkt_filter_match == false) {
rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N,
BIT(16), 0);
rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0);
} else {
rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N,
BIT(16), 0);
rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) |
BIT(7) | BIT(6), target_ant);
rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 1);
fat_tbl->antsel_a[fat_tbl->train_idx] =
target_ant & BIT(0);
fat_tbl->antsel_b[fat_tbl->train_idx] =
(target_ant & BIT(1)) >> 1;
fat_tbl->antsel_c[fat_tbl->train_idx] =
(target_ant & BIT(2)) >> 2;
if (target_ant == 0)
rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0);
}
for (i = 0; i < 7; i++) {
fat_tbl->ant_sum[i] = 0;
fat_tbl->ant_cnt[i] = 0;
}
fat_tbl->fat_state = FAT_NORMAL_STATE;
return;
}
if (fat_tbl->fat_state == FAT_NORMAL_STATE) {
rtl88e_set_next_mac_address_target(hw);
fat_tbl->fat_state = FAT_TRAINING_STATE;
rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N, BIT(16), 1);
rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1);
mod_timer(&rtlpriv->works.fast_antenna_training_timer,
jiffies + MSECS(RTL_WATCH_DOG_TIME));
}
}
void rtl88e_dm_fast_antenna_training_callback(unsigned long data)
{
struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
rtl88e_dm_fast_ant_training(hw);
}
static void rtl88e_dm_antenna_diversity(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
struct fast_ant_training *fat_tbl = &(rtldm->fat_table);
if (mac->link_state < MAC80211_LINKED) {
RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "No Link\n");
if (fat_tbl->becomelinked == true) {
RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
"need to turn off HW AntDiv\n");
rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0);
rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA1_11N,
BIT(15), 0);
if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N,
BIT(21), 0);
fat_tbl->becomelinked =
(mac->link_state == MAC80211_LINKED) ? true : false;
}
return;
} else {
if (fat_tbl->becomelinked == false) {
RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
"Need to turn on HW AntDiv\n");
rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1);
rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA1_11N,
BIT(15), 1);
if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N,
BIT(21), 1);
fat_tbl->becomelinked =
(mac->link_state >= MAC80211_LINKED) ? true : false;
}
}
if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) ||
(rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV))
rtl88e_dm_hw_ant_div(hw);
else if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV)
rtl88e_dm_fast_ant_training(hw);
}
void rtl88e_dm_init(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
rtl88e_dm_diginit(hw);
rtl88e_dm_init_dynamic_txpower(hw);
rtl88e_dm_init_edca_turbo(hw);
rtl88e_dm_init_rate_adaptive_mask(hw);
rtl88e_dm_init_txpower_tracking(hw);
rtl92c_dm_init_dynamic_bb_powersaving(hw);
rtl88e_dm_antenna_div_init(hw);
}
void rtl88e_dm_watchdog(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
bool fw_current_inpsmode = false;
bool fw_ps_awake = true;
rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
(u8 *)(&fw_current_inpsmode));
rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
(u8 *)(&fw_ps_awake));
if (ppsc->p2p_ps_info.p2p_ps_mode)
fw_ps_awake = false;
if ((ppsc->rfpwr_state == ERFON) &&
((!fw_current_inpsmode) && fw_ps_awake) &&
(!ppsc->rfchange_inprogress)) {
rtl88e_dm_pwdb_monitor(hw);
rtl88e_dm_dig(hw);
rtl88e_dm_false_alarm_counter_statistics(hw);
rtl92c_dm_dynamic_txpower(hw);
rtl88e_dm_check_txpower_tracking(hw);
rtl88e_dm_refresh_rate_adaptive_mask(hw);
rtl88e_dm_check_edca_turbo(hw);
rtl88e_dm_antenna_diversity(hw);
}
}
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __RTL88E_DM_H__
#define __RTL88E_DM_H__
#define MAIN_ANT 0
#define AUX_ANT 1
#define MAIN_ANT_CG_TRX 1
#define AUX_ANT_CG_TRX 0
#define MAIN_ANT_CGCS_RX 0
#define AUX_ANT_CGCS_RX 1
/*RF REG LIST*/
#define DM_REG_RF_MODE_11N 0x00
#define DM_REG_RF_0B_11N 0x0B
#define DM_REG_CHNBW_11N 0x18
#define DM_REG_T_METER_11N 0x24
#define DM_REG_RF_25_11N 0x25
#define DM_REG_RF_26_11N 0x26
#define DM_REG_RF_27_11N 0x27
#define DM_REG_RF_2B_11N 0x2B
#define DM_REG_RF_2C_11N 0x2C
#define DM_REG_RXRF_A3_11N 0x3C
#define DM_REG_T_METER_92D_11N 0x42
#define DM_REG_T_METER_88E_11N 0x42
/*BB REG LIST*/
/*PAGE 8 */
#define DM_REG_BB_CTRL_11N 0x800
#define DM_REG_RF_PIN_11N 0x804
#define DM_REG_PSD_CTRL_11N 0x808
#define DM_REG_TX_ANT_CTRL_11N 0x80C
#define DM_REG_BB_PWR_SAV5_11N 0x818
#define DM_REG_CCK_RPT_FORMAT_11N 0x824
#define DM_REG_RX_DEFAULT_A_11N 0x858
#define DM_REG_RX_DEFAULT_B_11N 0x85A
#define DM_REG_BB_PWR_SAV3_11N 0x85C
#define DM_REG_ANTSEL_CTRL_11N 0x860
#define DM_REG_RX_ANT_CTRL_11N 0x864
#define DM_REG_PIN_CTRL_11N 0x870
#define DM_REG_BB_PWR_SAV1_11N 0x874
#define DM_REG_ANTSEL_PATH_11N 0x878
#define DM_REG_BB_3WIRE_11N 0x88C
#define DM_REG_SC_CNT_11N 0x8C4
#define DM_REG_PSD_DATA_11N 0x8B4
/*PAGE 9*/
#define DM_REG_ANT_MAPPING1_11N 0x914
#define DM_REG_ANT_MAPPING2_11N 0x918
/*PAGE A*/
#define DM_REG_CCK_ANTDIV_PARA1_11N 0xA00
#define DM_REG_CCK_CCA_11N 0xA0A
#define DM_REG_CCK_ANTDIV_PARA2_11N 0xA0C
#define DM_REG_CCK_ANTDIV_PARA3_11N 0xA10
#define DM_REG_CCK_ANTDIV_PARA4_11N 0xA14
#define DM_REG_CCK_FILTER_PARA1_11N 0xA22
#define DM_REG_CCK_FILTER_PARA2_11N 0xA23
#define DM_REG_CCK_FILTER_PARA3_11N 0xA24
#define DM_REG_CCK_FILTER_PARA4_11N 0xA25
#define DM_REG_CCK_FILTER_PARA5_11N 0xA26
#define DM_REG_CCK_FILTER_PARA6_11N 0xA27
#define DM_REG_CCK_FILTER_PARA7_11N 0xA28
#define DM_REG_CCK_FILTER_PARA8_11N 0xA29
#define DM_REG_CCK_FA_RST_11N 0xA2C
#define DM_REG_CCK_FA_MSB_11N 0xA58
#define DM_REG_CCK_FA_LSB_11N 0xA5C
#define DM_REG_CCK_CCA_CNT_11N 0xA60
#define DM_REG_BB_PWR_SAV4_11N 0xA74
/*PAGE B */
#define DM_REG_LNA_SWITCH_11N 0xB2C
#define DM_REG_PATH_SWITCH_11N 0xB30
#define DM_REG_RSSI_CTRL_11N 0xB38
#define DM_REG_CONFIG_ANTA_11N 0xB68
#define DM_REG_RSSI_BT_11N 0xB9C
/*PAGE C */
#define DM_REG_OFDM_FA_HOLDC_11N 0xC00
#define DM_REG_RX_PATH_11N 0xC04
#define DM_REG_TRMUX_11N 0xC08
#define DM_REG_OFDM_FA_RSTC_11N 0xC0C
#define DM_REG_RXIQI_MATRIX_11N 0xC14
#define DM_REG_TXIQK_MATRIX_LSB1_11N 0xC4C
#define DM_REG_IGI_A_11N 0xC50
#define DM_REG_ANTDIV_PARA2_11N 0xC54
#define DM_REG_IGI_B_11N 0xC58
#define DM_REG_ANTDIV_PARA3_11N 0xC5C
#define DM_REG_BB_PWR_SAV2_11N 0xC70
#define DM_REG_RX_OFF_11N 0xC7C
#define DM_REG_TXIQK_MATRIXA_11N 0xC80
#define DM_REG_TXIQK_MATRIXB_11N 0xC88
#define DM_REG_TXIQK_MATRIXA_LSB2_11N 0xC94
#define DM_REG_TXIQK_MATRIXB_LSB2_11N 0xC9C
#define DM_REG_RXIQK_MATRIX_LSB_11N 0xCA0
#define DM_REG_ANTDIV_PARA1_11N 0xCA4
#define DM_REG_OFDM_FA_TYPE1_11N 0xCF0
/*PAGE D */
#define DM_REG_OFDM_FA_RSTD_11N 0xD00
#define DM_REG_OFDM_FA_TYPE2_11N 0xDA0
#define DM_REG_OFDM_FA_TYPE3_11N 0xDA4
#define DM_REG_OFDM_FA_TYPE4_11N 0xDA8
/*PAGE E */
#define DM_REG_TXAGC_A_6_18_11N 0xE00
#define DM_REG_TXAGC_A_24_54_11N 0xE04
#define DM_REG_TXAGC_A_1_MCS32_11N 0xE08
#define DM_REG_TXAGC_A_MCS0_3_11N 0xE10
#define DM_REG_TXAGC_A_MCS4_7_11N 0xE14
#define DM_REG_TXAGC_A_MCS8_11_11N 0xE18
#define DM_REG_TXAGC_A_MCS12_15_11N 0xE1C
#define DM_REG_FPGA0_IQK_11N 0xE28
#define DM_REG_TXIQK_TONE_A_11N 0xE30
#define DM_REG_RXIQK_TONE_A_11N 0xE34
#define DM_REG_TXIQK_PI_A_11N 0xE38
#define DM_REG_RXIQK_PI_A_11N 0xE3C
#define DM_REG_TXIQK_11N 0xE40
#define DM_REG_RXIQK_11N 0xE44
#define DM_REG_IQK_AGC_PTS_11N 0xE48
#define DM_REG_IQK_AGC_RSP_11N 0xE4C
#define DM_REG_BLUETOOTH_11N 0xE6C
#define DM_REG_RX_WAIT_CCA_11N 0xE70
#define DM_REG_TX_CCK_RFON_11N 0xE74
#define DM_REG_TX_CCK_BBON_11N 0xE78
#define DM_REG_OFDM_RFON_11N 0xE7C
#define DM_REG_OFDM_BBON_11N 0xE80
#define DM_REG_TX2RX_11N 0xE84
#define DM_REG_TX2TX_11N 0xE88
#define DM_REG_RX_CCK_11N 0xE8C
#define DM_REG_RX_OFDM_11N 0xED0
#define DM_REG_RX_WAIT_RIFS_11N 0xED4
#define DM_REG_RX2RX_11N 0xED8
#define DM_REG_STANDBY_11N 0xEDC
#define DM_REG_SLEEP_11N 0xEE0
#define DM_REG_PMPD_ANAEN_11N 0xEEC
/*MAC REG LIST*/
#define DM_REG_BB_RST_11N 0x02
#define DM_REG_ANTSEL_PIN_11N 0x4C
#define DM_REG_EARLY_MODE_11N 0x4D0
#define DM_REG_RSSI_MONITOR_11N 0x4FE
#define DM_REG_EDCA_VO_11N 0x500
#define DM_REG_EDCA_VI_11N 0x504
#define DM_REG_EDCA_BE_11N 0x508
#define DM_REG_EDCA_BK_11N 0x50C
#define DM_REG_TXPAUSE_11N 0x522
#define DM_REG_RESP_TX_11N 0x6D8
#define DM_REG_ANT_TRAIN_1 0x7b0
#define DM_REG_ANT_TRAIN_2 0x7b4
/*DIG Related*/
#define DM_BIT_IGI_11N 0x0000007F
#define HAL_DM_DIG_DISABLE BIT(0)
#define HAL_DM_HIPWR_DISABLE BIT(1)
#define OFDM_TABLE_LENGTH 43
#define CCK_TABLE_LENGTH 33
#define OFDM_TABLE_SIZE 43
#define CCK_TABLE_SIZE 33
#define BW_AUTO_SWITCH_HIGH_LOW 25
#define BW_AUTO_SWITCH_LOW_HIGH 30
#define DM_DIG_THRESH_HIGH 40
#define DM_DIG_THRESH_LOW 35
#define DM_FALSEALARM_THRESH_LOW 400
#define DM_FALSEALARM_THRESH_HIGH 1000
#define DM_DIG_MAX 0x3e
#define DM_DIG_MIN 0x1e
#define DM_DIG_MAX_AP 0x32
#define DM_DIG_MIN_AP 0x20
#define DM_DIG_FA_UPPER 0x3e
#define DM_DIG_FA_LOWER 0x1e
#define DM_DIG_FA_TH0 0x200
#define DM_DIG_FA_TH1 0x300
#define DM_DIG_FA_TH2 0x400
#define DM_DIG_BACKOFF_MAX 12
#define DM_DIG_BACKOFF_MIN -4
#define DM_DIG_BACKOFF_DEFAULT 10
#define RXPATHSELECTION_SS_TH_LOW 30
#define RXPATHSELECTION_DIFF_TH 18
#define DM_RATR_STA_INIT 0
#define DM_RATR_STA_HIGH 1
#define DM_RATR_STA_MIDDLE 2
#define DM_RATR_STA_LOW 3
#define CTS2SELF_THVAL 30
#define REGC38_TH 20
#define WAIOTTHVAL 25
#define TXHIGHPWRLEVEL_NORMAL 0
#define TXHIGHPWRLEVEL_LEVEL1 1
#define TXHIGHPWRLEVEL_LEVEL2 2
#define TXHIGHPWRLEVEL_BT1 3
#define TXHIGHPWRLEVEL_BT2 4
#define DM_TYPE_BYFW 0
#define DM_TYPE_BYDRIVER 1
#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74
#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67
#define TXPWRTRACK_MAX_IDX 6
struct swat_t {
u8 failure_cnt;
u8 try_flag;
u8 stop_trying;
long pre_rssi;
long trying_threshold;
u8 cur_antenna;
u8 pre_antenna;
};
enum FAT_STATE {
FAT_NORMAL_STATE = 0,
FAT_TRAINING_STATE = 1,
};
enum tag_dynamic_init_gain_operation_type_definition {
DIG_TYPE_THRESH_HIGH = 0,
DIG_TYPE_THRESH_LOW = 1,
DIG_TYPE_BACKOFF = 2,
DIG_TYPE_RX_GAIN_MIN = 3,
DIG_TYPE_RX_GAIN_MAX = 4,
DIG_TYPE_ENABLE = 5,
DIG_TYPE_DISABLE = 6,
DIG_OP_TYPE_MAX
};
enum tag_cck_packet_detection_threshold_type_definition {
CCK_PD_STAGE_LOWRSSI = 0,
CCK_PD_STAGE_HIGHRSSI = 1,
CCK_FA_STAGE_LOW = 2,
CCK_FA_STAGE_HIGH = 3,
CCK_PD_STAGE_MAX = 4,
};
enum dm_1r_cca_e {
CCA_1R = 0,
CCA_2R = 1,
CCA_MAX = 2,
};
enum dm_rf_e {
RF_SAVE = 0,
RF_NORMAL = 1,
RF_MAX = 2,
};
enum dm_sw_ant_switch_e {
ANS_ANTENNA_B = 1,
ANS_ANTENNA_A = 2,
ANS_ANTENNA_MAX = 3,
};
enum dm_dig_ext_port_alg_e {
DIG_EXT_PORT_STAGE_0 = 0,
DIG_EXT_PORT_STAGE_1 = 1,
DIG_EXT_PORT_STAGE_2 = 2,
DIG_EXT_PORT_STAGE_3 = 3,
DIG_EXT_PORT_STAGE_MAX = 4,
};
enum dm_dig_connect_e {
DIG_STA_DISCONNECT = 0,
DIG_STA_CONNECT = 1,
DIG_STA_BEFORE_CONNECT = 2,
DIG_MULTISTA_DISCONNECT = 3,
DIG_MULTISTA_CONNECT = 4,
DIG_CONNECT_MAX
};
enum pwr_track_control_method {
BBSWING,
TXAGC
};
void rtl88e_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw,
u8 *pdesc, u32 mac_id);
void rtl88e_dm_ant_sel_statistics(struct ieee80211_hw *hw, u8 antsel_tr_mux,
u32 mac_id, u32 rx_pwdb_all);
void rtl88e_dm_fast_antenna_training_callback(unsigned long data);
void rtl88e_dm_init(struct ieee80211_hw *hw);
void rtl88e_dm_watchdog(struct ieee80211_hw *hw);
void rtl88e_dm_write_dig(struct ieee80211_hw *hw);
void rtl88e_dm_init_edca_turbo(struct ieee80211_hw *hw);
void rtl88e_dm_check_txpower_tracking(struct ieee80211_hw *hw);
void rtl88e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw);
void rtl88e_dm_txpower_track_adjust(struct ieee80211_hw *hw,
u8 type, u8 *pdirection,
u32 *poutwrite_val);
#endif
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "wifi.h"
#include "pci.h"
#include "base.h"
#include "reg.h"
#include "def.h"
#include "fw.h"
#include <linux/kmemleak.h>
static void _rtl88e_enable_fw_download(struct ieee80211_hw *hw, bool enable)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 tmp;
if (enable) {
tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
} else {
tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
}
}
static void _rtl88e_fw_block_write(struct ieee80211_hw *hw,
const u8 *buffer, u32 size)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 blk_sz = sizeof(u32);
u8 *buf_ptr = (u8 *)buffer;
u32 *pu4BytePtr = (u32 *)buffer;
u32 i, offset, blk_cnt, remain;
blk_cnt = size / blk_sz;
remain = size % blk_sz;
for (i = 0; i < blk_cnt; i++) {
offset = i * blk_sz;
rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
*(pu4BytePtr + i));
}
if (remain) {
offset = blk_cnt * blk_sz;
buf_ptr += offset;
for (i = 0; i < remain; i++) {
rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
offset + i), *(buf_ptr + i));
}
}
}
static void _rtl88e_fw_page_write(struct ieee80211_hw *hw,
u32 page, const u8 *buffer, u32 size)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 value8;
u8 u8page = (u8) (page & 0x07);
value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
_rtl88e_fw_block_write(hw, buffer, size);
}
static void _rtl88e_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
{
u32 fwlen = *pfwlen;
u8 remain = (u8) (fwlen % 4);
remain = (remain == 0) ? 0 : (4 - remain);
while (remain > 0) {
pfwbuf[fwlen] = 0;
fwlen++;
remain--;
}
*pfwlen = fwlen;
}
static void _rtl88e_write_fw(struct ieee80211_hw *hw,
enum version_8188e version, u8 *buffer, u32 size)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 *buf_ptr = (u8 *)buffer;
u32 page_no, remain;
u32 page, offset;
RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size);
_rtl88e_fill_dummy(buf_ptr, &size);
page_no = size / FW_8192C_PAGE_SIZE;
remain = size % FW_8192C_PAGE_SIZE;
if (page_no > 8) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Page numbers should not greater then 8\n");
}
for (page = 0; page < page_no; page++) {
offset = page * FW_8192C_PAGE_SIZE;
_rtl88e_fw_page_write(hw, page, (buf_ptr + offset),
FW_8192C_PAGE_SIZE);
}
if (remain) {
offset = page_no * FW_8192C_PAGE_SIZE;
page = page_no;
_rtl88e_fw_page_write(hw, page, (buf_ptr + offset), remain);
}
}
static int _rtl88e_fw_free_to_go(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
int err = -EIO;
u32 counter = 0;
u32 value32;
do {
value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
} while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
(!(value32 & FWDL_CHKSUM_RPT)));
if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"chksum report faill ! REG_MCUFWDL:0x%08x .\n",
value32);
goto exit;
}
RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
"Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32);
value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
value32 |= MCUFWDL_RDY;
value32 &= ~WINTINI_RDY;
rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
rtl88e_firmware_selfreset(hw);
counter = 0;
do {
value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
if (value32 & WINTINI_RDY) {
RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
"Polling FW ready success!! REG_MCUFWDL:0x%08x.\n",
value32);
err = 0;
goto exit;
}
udelay(FW_8192C_POLLING_DELAY);
} while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32);
exit:
return err;
}
int rtl88e_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl92c_firmware_header *pfwheader;
u8 *pfwdata;
u32 fwsize;
int err;
enum version_8188e version = rtlhal->version;
if (!rtlhal->pfirmware)
return 1;
pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
pfwdata = (u8 *)rtlhal->pfirmware;
fwsize = rtlhal->fwsize;
RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
"normal Firmware SIZE %d\n", fwsize);
if (IS_FW_HEADER_EXIST(pfwheader)) {
RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
"Firmware Version(%d), Signature(%#x), Size(%d)\n",
pfwheader->version, pfwheader->signature,
(int)sizeof(struct rtl92c_firmware_header));
pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
}
if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
rtl88e_firmware_selfreset(hw);
}
_rtl88e_enable_fw_download(hw, true);
_rtl88e_write_fw(hw, version, pfwdata, fwsize);
_rtl88e_enable_fw_download(hw, false);
err = _rtl88e_fw_free_to_go(hw);
RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
"Firmware is%s ready to run!\n", err ? " not" : "");
return 0;
}
static bool _rtl88e_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 val_hmetfr;
val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
return true;
return false;
}
static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw,
u8 element_id, u32 cmd_len,
u8 *cmd_b)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
u8 boxnum;
u16 box_reg = 0, box_extreg = 0;
u8 u1b_tmp;
bool isfw_read = false;
u8 buf_index = 0;
bool write_sucess = false;
u8 wait_h2c_limit = 100;
u8 wait_writeh2c_limit = 100;
u8 boxc[4], boxext[2];
u32 h2c_waitcounter = 0;
unsigned long flag;
u8 idx;
RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
while (true) {
spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
if (rtlhal->h2c_setinprogress) {
RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
"H2C set in progress! Wait to set..element_id(%d).\n",
element_id);
while (rtlhal->h2c_setinprogress) {
spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
flag);
h2c_waitcounter++;
RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
"Wait 100 us (%d times)...\n",
h2c_waitcounter);
udelay(100);
if (h2c_waitcounter > 1000)
return;
spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
flag);
}
spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
} else {
rtlhal->h2c_setinprogress = true;
spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
break;
}
}
while (!write_sucess) {
wait_writeh2c_limit--;
if (wait_writeh2c_limit == 0) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Write H2C fail because no trigger for FW INT!\n");
break;
}
boxnum = rtlhal->last_hmeboxnum;
switch (boxnum) {
case 0:
box_reg = REG_HMEBOX_0;
box_extreg = REG_HMEBOX_EXT_0;
break;
case 1:
box_reg = REG_HMEBOX_1;
box_extreg = REG_HMEBOX_EXT_1;
break;
case 2:
box_reg = REG_HMEBOX_2;
box_extreg = REG_HMEBOX_EXT_2;
break;
case 3:
box_reg = REG_HMEBOX_3;
box_extreg = REG_HMEBOX_EXT_3;
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not processed\n");
break;
}
isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
while (!isfw_read) {
wait_h2c_limit--;
if (wait_h2c_limit == 0) {
RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
"Wating too long for FW read "
"clear HMEBox(%d)!\n", boxnum);
break;
}
udelay(10);
isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum);
u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
"Wating for FW read clear HMEBox(%d)!!! "
"0x130 = %2x\n", boxnum, u1b_tmp);
}
if (!isfw_read) {
RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
"Write H2C register BOX[%d] fail!!!!! "
"Fw do not read.\n", boxnum);
break;
}
memset(boxc, 0, sizeof(boxc));
memset(boxext, 0, sizeof(boxext));
boxc[0] = element_id;
RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
"Write element_id box_reg(%4x) = %2x\n",
box_reg, element_id);
switch (cmd_len) {
case 1:
case 2:
case 3:
/*boxc[0] &= ~(BIT(7));*/
memcpy((u8 *)(boxc) + 1, cmd_b + buf_index, cmd_len);
for (idx = 0; idx < 4; idx++)
rtl_write_byte(rtlpriv, box_reg+idx, boxc[idx]);
break;
case 4:
case 5:
case 6:
case 7:
/*boxc[0] |= (BIT(7));*/
memcpy((u8 *)(boxext), cmd_b + buf_index+3, cmd_len-3);
memcpy((u8 *)(boxc) + 1, cmd_b + buf_index, 3);
for (idx = 0; idx < 2; idx++) {
rtl_write_byte(rtlpriv, box_extreg + idx,
boxext[idx]);
}
for (idx = 0; idx < 4; idx++) {
rtl_write_byte(rtlpriv, box_reg + idx,
boxc[idx]);
}
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not processed\n");
break;
}
write_sucess = true;
rtlhal->last_hmeboxnum = boxnum + 1;
if (rtlhal->last_hmeboxnum == 4)
rtlhal->last_hmeboxnum = 0;
RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
"pHalData->last_hmeboxnum = %d\n",
rtlhal->last_hmeboxnum);
}
spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
rtlhal->h2c_setinprogress = false;
spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
}
void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw,
u8 element_id, u32 cmd_len, u8 *cmd_b)
{
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
u32 tmp_cmdbuf[2];
if (rtlhal->fw_ready == false) {
RT_ASSERT(false, "fail H2C cmd - Fw download fail!!!\n");
return;
}
memset(tmp_cmdbuf, 0, 8);
memcpy(tmp_cmdbuf, cmd_b, cmd_len);
_rtl88e_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
return;
}
void rtl88e_firmware_selfreset(struct ieee80211_hw *hw)
{
u8 u1b_tmp;
struct rtl_priv *rtlpriv = rtl_priv(hw);
u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1);
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2))));
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2)));
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"8051Reset88E(): 8051 reset success.\n");
}
void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 u1_h2c_set_pwrmode[H2C_88E_PWEMODE_LENGTH] = { 0 };
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
u8 power_state = 0;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, 0);
SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
(rtlpriv->mac80211.p2p) ?
ppsc->smart_ps : 1);
SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
ppsc->reg_max_lps_awakeintvl);
SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
if (mode == FW_PS_ACTIVE_MODE)
power_state |= FW_PWR_STATE_ACTIVE;
else
power_state |= FW_PWR_STATE_RF_OFF;
SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
"rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
u1_h2c_set_pwrmode, H2C_88E_PWEMODE_LENGTH);
rtl88e_fill_h2c_cmd(hw, H2C_88E_SETPWRMODE, H2C_88E_PWEMODE_LENGTH,
u1_h2c_set_pwrmode);
}
void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
{
u8 u1_joinbssrpt_parm[1] = { 0 };
SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
rtl88e_fill_h2c_cmd(hw, H2C_88E_JOINBSSRPT, 1, u1_joinbssrpt_parm);
}
void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw,
u8 ap_offload_enable)
{
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
u8 u1_apoffload_parm[H2C_88E_AP_OFFLOAD_LENGTH] = { 0 };
SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm, ap_offload_enable);
SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid);
SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0);
rtl88e_fill_h2c_cmd(hw, H2C_88E_AP_OFFLOAD, H2C_88E_AP_OFFLOAD_LENGTH,
u1_apoffload_parm);
}
static bool _rtl88e_cmd_send_packet(struct ieee80211_hw *hw,
struct sk_buff *skb)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl8192_tx_ring *ring;
struct rtl_tx_desc *pdesc;
struct sk_buff *pskb = NULL;
unsigned long flags;
ring = &rtlpci->tx_ring[BEACON_QUEUE];
pskb = __skb_dequeue(&ring->queue);
if (pskb)
kfree_skb(pskb);
spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
pdesc = &ring->desc[0];
rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb);
__skb_queue_tail(&ring->queue, skb);
spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
return true;
}
#define BEACON_PG 0 /* ->1 */
#define PSPOLL_PG 2
#define NULL_PG 3
#define PROBERSP_PG 4 /* ->5 */
#define TOTAL_RESERVED_PKT_LEN 768
static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
/* page 0 beacon */
0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* page 1 beacon */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* page 2 ps-poll */
0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* page 3 null */
0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* page 4 probe_resp */
0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* page 5 probe_resp */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct sk_buff *skb = NULL;
u32 totalpacketlen;
u8 u1RsvdPageLoc[5] = { 0 };
u8 *beacon;
u8 *pspoll;
u8 *nullfunc;
u8 *probersp;
/*---------------------------------------------------------
* (1) beacon
*---------------------------------------------------------
*/
beacon = &reserved_page_packet[BEACON_PG * 128];
SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
/*-------------------------------------------------------
* (2) ps-poll
*--------------------------------------------------------
*/
pspoll = &reserved_page_packet[PSPOLL_PG * 128];
SET_80211_PS_POLL_AID(pspoll, (mac->assoc_id | 0xc000));
SET_80211_PS_POLL_BSSID(pspoll, mac->bssid);
SET_80211_PS_POLL_TA(pspoll, mac->mac_addr);
SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
/*--------------------------------------------------------
* (3) null data
*---------------------------------------------------------
*/
nullfunc = &reserved_page_packet[NULL_PG * 128];
SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
/*---------------------------------------------------------
* (4) probe response
*----------------------------------------------------------
*/
probersp = &reserved_page_packet[PROBERSP_PG * 128];
SET_80211_HDR_ADDRESS1(probersp, mac->bssid);
SET_80211_HDR_ADDRESS2(probersp, mac->mac_addr);
SET_80211_HDR_ADDRESS3(probersp, mac->bssid);
SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
totalpacketlen = TOTAL_RESERVED_PKT_LEN;
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
"rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
&reserved_page_packet[0], totalpacketlen);
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
"rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
u1RsvdPageLoc, 3);
skb = dev_alloc_skb(totalpacketlen);
if (!skb)
return;
kmemleak_not_leak(skb);
memcpy(skb_put(skb, totalpacketlen),
&reserved_page_packet, totalpacketlen);
if (_rtl88e_cmd_send_packet(hw, skb)) {
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"Set RSVD page location to Fw.\n");
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
"H2C_RSVDPAGE:\n", u1RsvdPageLoc, 3);
rtl88e_fill_h2c_cmd(hw, H2C_88E_RSVDPAGE,
sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
} else
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
"Set RSVD page location to Fw FAIL!!!!!!.\n");
}
/*Shoud check FW support p2p or not.*/
static void rtl88e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
{
u8 u1_ctwindow_period[1] = {ctwindow};
rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
}
void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
u8 i;
u16 ctwindow;
u32 start_time, tsf_low;
switch (p2p_ps_state) {
case P2P_PS_DISABLE:
RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n");
memset(p2p_ps_offload, 0, sizeof(struct p2p_ps_offload_t));
break;
case P2P_PS_ENABLE:
RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n");
/* update CTWindow value. */
if (p2pinfo->ctwindow > 0) {
p2p_ps_offload->ctwindow_en = 1;
ctwindow = p2pinfo->ctwindow;
rtl88e_set_p2p_ctw_period_cmd(hw, ctwindow);
}
/* hw only support 2 set of NoA */
for (i = 0; i < p2pinfo->noa_num; i++) {
/* To control the register setting for which NOA*/
rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
if (i == 0)
p2p_ps_offload->noa0_en = 1;
else
p2p_ps_offload->noa1_en = 1;
/* config P2P NoA Descriptor Register */
rtl_write_dword(rtlpriv, 0x5E0,
p2pinfo->noa_duration[i]);
rtl_write_dword(rtlpriv, 0x5E4,
p2pinfo->noa_interval[i]);
/*Get Current TSF value */
tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
start_time = p2pinfo->noa_start_time[i];
if (p2pinfo->noa_count_type[i] != 1) {
while (start_time <= (tsf_low + (50 * 1024))) {
start_time += p2pinfo->noa_interval[i];
if (p2pinfo->noa_count_type[i] != 255)
p2pinfo->noa_count_type[i]--;
}
}
rtl_write_dword(rtlpriv, 0x5E8, start_time);
rtl_write_dword(rtlpriv, 0x5EC,
p2pinfo->noa_count_type[i]);
}
if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
/* rst p2p circuit */
rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
p2p_ps_offload->offload_en = 1;
if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
p2p_ps_offload->role = 1;
p2p_ps_offload->allstasleep = 0;
} else {
p2p_ps_offload->role = 0;
}
p2p_ps_offload->discovery = 0;
}
break;
case P2P_PS_SCAN:
RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
p2p_ps_offload->discovery = 1;
break;
case P2P_PS_SCAN_DONE:
RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n");
p2p_ps_offload->discovery = 0;
p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
break;
default:
break;
}
rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_OFFLOAD, 1,
(u8 *)p2p_ps_offload);
}
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __RTL92C__FW__H__
#define __RTL92C__FW__H__
#define FW_8192C_SIZE 0x8000
#define FW_8192C_START_ADDRESS 0x1000
#define FW_8192C_END_ADDRESS 0x5FFF
#define FW_8192C_PAGE_SIZE 4096
#define FW_8192C_POLLING_DELAY 5
#define FW_8192C_POLLING_TIMEOUT_COUNT 3000
#define IS_FW_HEADER_EXIST(_pfwhdr) \
((_pfwhdr->signature&0xFFFF) == 0x88E1)
#define USE_OLD_WOWLAN_DEBUG_FW 0
#define H2C_88E_RSVDPAGE_LOC_LEN 5
#define H2C_88E_PWEMODE_LENGTH 5
#define H2C_88E_JOINBSSRPT_LENGTH 1
#define H2C_88E_AP_OFFLOAD_LENGTH 3
#define H2C_88E_WOWLAN_LENGTH 3
#define H2C_88E_KEEP_ALIVE_CTRL_LENGTH 3
#if (USE_OLD_WOWLAN_DEBUG_FW == 0)
#define H2C_88E_REMOTE_WAKE_CTRL_LEN 1
#else
#define H2C_88E_REMOTE_WAKE_CTRL_LEN 3
#endif
#define H2C_88E_AOAC_GLOBAL_INFO_LEN 2
#define H2C_88E_AOAC_RSVDPAGE_LOC_LEN 7
/* Fw PS state for RPWM.
* BIT[2:0] = HW state
* BIT[3] = Protocol PS state, 1: register active state, 0: register sleep state
* BIT[4] = sub-state
*/
#define FW_PS_GO_ON BIT(0)
#define FW_PS_TX_NULL BIT(1)
#define FW_PS_RF_ON BIT(2)
#define FW_PS_REGISTER_ACTIVE BIT(3)
#define FW_PS_DPS BIT(0)
#define FW_PS_LCLK (FW_PS_DPS)
#define FW_PS_RF_OFF BIT(1)
#define FW_PS_ALL_ON BIT(2)
#define FW_PS_ST_ACTIVE BIT(3)
#define FW_PS_ISR_ENABLE BIT(4)
#define FW_PS_IMR_ENABLE BIT(5)
#define FW_PS_ACK BIT(6)
#define FW_PS_TOGGLE BIT(7)
/* 88E RPWM value*/
/* BIT[0] = 1: 32k, 0: 40M*/
#define FW_PS_CLOCK_OFF BIT(0) /* 32k*/
#define FW_PS_CLOCK_ON 0 /*40M*/
#define FW_PS_STATE_MASK (0x0F)
#define FW_PS_STATE_HW_MASK (0x07)
/*ISR_ENABLE, IMR_ENABLE, and PS mode should be inherited.*/
#define FW_PS_STATE_INT_MASK (0x3F)
#define FW_PS_STATE(x) (FW_PS_STATE_MASK & (x))
#define FW_PS_STATE_HW(x) (FW_PS_STATE_HW_MASK & (x))
#define FW_PS_STATE_INT(x) (FW_PS_STATE_INT_MASK & (x))
#define FW_PS_ISR_VAL(x) ((x) & 0x70)
#define FW_PS_IMR_MASK(x) ((x) & 0xDF)
#define FW_PS_KEEP_IMR(x) ((x) & 0x20)
#define FW_PS_STATE_S0 (FW_PS_DPS)
#define FW_PS_STATE_S1 (FW_PS_LCLK)
#define FW_PS_STATE_S2 (FW_PS_RF_OFF)
#define FW_PS_STATE_S3 (FW_PS_ALL_ON)
#define FW_PS_STATE_S4 ((FW_PS_ST_ACTIVE) | (FW_PS_ALL_ON))
#define FW_PS_STATE_ALL_ON_88E (FW_PS_CLOCK_ON)
#define FW_PS_STATE_RF_ON_88E (FW_PS_CLOCK_ON)
#define FW_PS_STATE_RF_OFF_88E (FW_PS_CLOCK_ON)
#define FW_PS_STATE_RF_OFF_LOW_PWR_88E (FW_PS_CLOCK_OFF)
#define FW_PS_STATE_ALL_ON_92C (FW_PS_STATE_S4)
#define FW_PS_STATE_RF_ON_92C (FW_PS_STATE_S3)
#define FW_PS_STATE_RF_OFF_92C (FW_PS_STATE_S2)
#define FW_PS_STATE_RF_OFF_LOW_PWR_92C (FW_PS_STATE_S1)
/* For 88E H2C PwrMode Cmd ID 5.*/
#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE))
#define FW_PWR_STATE_RF_OFF 0
#define FW_PS_IS_ACK(x) ((x) & FW_PS_ACK)
#define FW_PS_IS_CLK_ON(x) ((x) & (FW_PS_RF_OFF | FW_PS_ALL_ON))
#define FW_PS_IS_RF_ON(x) ((x) & (FW_PS_ALL_ON))
#define FW_PS_IS_ACTIVE(x) ((x) & (FW_PS_ST_ACTIVE))
#define FW_PS_IS_CPWM_INT(x) ((x) & 0x40)
#define FW_CLR_PS_STATE(x) ((x) = ((x) & (0xF0)))
#define IS_IN_LOW_POWER_STATE_88E(fwpsstate) \
(FW_PS_STATE(fwpsstate) == FW_PS_CLOCK_OFF)
#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE))
#define FW_PWR_STATE_RF_OFF 0
struct rtl92c_firmware_header {
u16 signature;
u8 category;
u8 function;
u16 version;
u8 subversion;
u8 rsvd1;
u8 month;
u8 date;
u8 hour;
u8 minute;
u16 ramcodesize;
u16 rsvd2;
u32 svnindex;
u32 rsvd3;
u32 rsvd4;
u32 rsvd5;
};
enum rtl8192c_h2c_cmd {
H2C_88E_RSVDPAGE = 0,
H2C_88E_JOINBSSRPT = 1,
H2C_88E_SCAN = 2,
H2C_88E_KEEP_ALIVE_CTRL = 3,
H2C_88E_DISCONNECT_DECISION = 4,
#if (USE_OLD_WOWLAN_DEBUG_FW == 1)
H2C_88E_WO_WLAN = 5,
#endif
H2C_88E_INIT_OFFLOAD = 6,
#if (USE_OLD_WOWLAN_DEBUG_FW == 1)
H2C_88E_REMOTE_WAKE_CTRL = 7,
#endif
H2C_88E_AP_OFFLOAD = 8,
H2C_88E_BCN_RSVDPAGE = 9,
H2C_88E_PROBERSP_RSVDPAGE = 10,
H2C_88E_SETPWRMODE = 0x20,
H2C_88E_PS_TUNING_PARA = 0x21,
H2C_88E_PS_TUNING_PARA2 = 0x22,
H2C_88E_PS_LPS_PARA = 0x23,
H2C_88E_P2P_PS_OFFLOAD = 024,
#if (USE_OLD_WOWLAN_DEBUG_FW == 0)
H2C_88E_WO_WLAN = 0x80,
H2C_88E_REMOTE_WAKE_CTRL = 0x81,
H2C_88E_AOAC_GLOBAL_INFO = 0x82,
H2C_88E_AOAC_RSVDPAGE = 0x83,
#endif
/* Not defined in new 88E H2C CMD Format */
H2C_88E_RA_MASK,
H2C_88E_SELECTIVE_SUSPEND_ROF_CMD,
H2C_88E_P2P_PS_MODE,
H2C_88E_PSD_RESULT,
/*Not defined CTW CMD for P2P yet*/
H2C_88E_P2P_PS_CTW_CMD,
MAX_88E_H2CCMD
};
#define pagenum_128(_len) (u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0))
#define SET_88E_H2CCMD_WOWLAN_FUNC_ENABLE(__cmd, __value) \
SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value)
#define SET_88E_H2CCMD_WOWLAN_PATTERN_MATCH_ENABLE(__cmd, __value) \
SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value)
#define SET_88E_H2CCMD_WOWLAN_MAGIC_PKT_ENABLE(__cmd, __value) \
SET_BITS_TO_LE_1BYTE(__cmd, 2, 1, __value)
#define SET_88E_H2CCMD_WOWLAN_UNICAST_PKT_ENABLE(__cmd, __value) \
SET_BITS_TO_LE_1BYTE(__cmd, 3, 1, __value)
#define SET_88E_H2CCMD_WOWLAN_ALL_PKT_DROP(__cmd, __value) \
SET_BITS_TO_LE_1BYTE(__cmd, 4, 1, __value)
#define SET_88E_H2CCMD_WOWLAN_GPIO_ACTIVE(__cmd, __value) \
SET_BITS_TO_LE_1BYTE(__cmd, 5, 1, __value)
#define SET_88E_H2CCMD_WOWLAN_REKEY_WAKE_UP(__cmd, __value) \
SET_BITS_TO_LE_1BYTE(__cmd, 6, 1, __value)
#define SET_88E_H2CCMD_WOWLAN_DISCONNECT_WAKE_UP(__cmd, __value) \
SET_BITS_TO_LE_1BYTE(__cmd, 7, 1, __value)
#define SET_88E_H2CCMD_WOWLAN_GPIONUM(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value)
#define SET_88E_H2CCMD_WOWLAN_GPIO_DURATION(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value)
#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \
SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
#define SET_H2CCMD_PWRMODE_PARM_RLBM(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 4, __value)
#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+1, 4, 4, __value)
#define SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value)
#define SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value)
#define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value)
#define GET_88E_H2CCMD_PWRMODE_PARM_MODE(__cmd) \
LE_BITS_TO_1BYTE(__cmd, 0, 8)
#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \
SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \
SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \
SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val)
#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \
SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val)
/* AP_OFFLOAD */
#define SET_H2CCMD_AP_OFFLOAD_ON(__cmd, __value) \
SET_BITS_TO_LE_1BYTE(__cmd, 0, 8, __value)
#define SET_H2CCMD_AP_OFFLOAD_HIDDEN(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value)
#define SET_H2CCMD_AP_OFFLOAD_DENYANY(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value)
#define SET_H2CCMD_AP_OFFLOAD_WAKEUP_EVT_RPT(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value)
/* Keep Alive Control*/
#define SET_88E_H2CCMD_KEEP_ALIVE_ENABLE(__cmd, __value) \
SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value)
#define SET_88E_H2CCMD_KEEP_ALIVE_ACCPEPT_USER_DEFINED(__cmd, __value) \
SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value)
#define SET_88E_H2CCMD_KEEP_ALIVE_PERIOD(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value)
/*REMOTE_WAKE_CTRL */
#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_EN(__cmd, __value) \
SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value)
#if (USE_OLD_WOWLAN_DEBUG_FW == 0)
#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_ARP_OFFLOAD_EN(__cmd, __value) \
SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value)
#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_NDP_OFFLOAD_EN(__cmd, __value) \
SET_BITS_TO_LE_1BYTE(__cmd, 2, 1, __value)
#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN(__cmd, __value) \
SET_BITS_TO_LE_1BYTE(__cmd, 3, 1, __value)
#else
#define SET_88E_H2_REM_WAKE_ENC_ALG(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value)
#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_GROUP_ENC_ALG(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value)
#endif
/* GTK_OFFLOAD */
#define SET_88E_H2CCMD_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(__cmd, __value) \
SET_BITS_TO_LE_1BYTE(__cmd, 0, 8, __value)
#define SET_88E_H2CCMD_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value)
/* AOAC_RSVDPAGE_LOC */
#define SET_88E_H2CCMD_AOAC_RSVD_LOC_REM_WAKE_CTRL_INFO(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd), 0, 8, __value)
#define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value)
#define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_NEIGHBOR_ADV(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value)
#define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_RSP(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value)
#define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_INFO(__cmd, __value) \
SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value)
int rtl88e_download_fw(struct ieee80211_hw *hw,
bool buse_wake_on_wlan_fw);
void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
u32 cmd_len, u8 *p_cmdbuffer);
void rtl88e_firmware_selfreset(struct ieee80211_hw *hw);
void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw,
u8 mstatus);
void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw, u8 enable);
void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state);
#endif
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "wifi.h"
#include "efuse.h"
#include "base.h"
#include "regd.h"
#include "cam.h"
#include "ps.h"
#include "pci.h"
#include "reg.h"
#include "def.h"
#include "phy.h"
#include "dm.h"
#include "fw.h"
#include "led.h"
#include "hw.h"
#include "pwrseqcmd.h"
#include "pwrseq.h"
#define LLT_CONFIG 5
static void _rtl88ee_set_bcn_ctrl_reg(struct ieee80211_hw *hw,
u8 set_bits, u8 clear_bits)
{
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtlpci->reg_bcn_ctrl_val |= set_bits;
rtlpci->reg_bcn_ctrl_val &= ~clear_bits;
rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val);
}
static void _rtl88ee_stop_tx_beacon(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 tmp1byte;
tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6)));
rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64);
tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2);
tmp1byte &= ~(BIT(0));
rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte);
}
static void _rtl88ee_resume_tx_beacon(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 tmp1byte;
tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6));
rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff);
tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2);
tmp1byte |= BIT(0);
rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte);
}
static void _rtl88ee_enable_bcn_sub_func(struct ieee80211_hw *hw)
{
_rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(1));
}
static void _rtl88ee_return_beacon_queue_skb(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE];
while (skb_queue_len(&ring->queue)) {
struct rtl_tx_desc *entry = &ring->desc[ring->idx];
struct sk_buff *skb = __skb_dequeue(&ring->queue);
pci_unmap_single(rtlpci->pdev,
rtlpriv->cfg->ops->get_desc(
(u8 *)entry, true, HW_DESC_TXBUFF_ADDR),
skb->len, PCI_DMA_TODEVICE);
kfree_skb(skb);
ring->idx = (ring->idx + 1) % ring->entries;
}
}
static void _rtl88ee_disable_bcn_sub_func(struct ieee80211_hw *hw)
{
_rtl88ee_set_bcn_ctrl_reg(hw, BIT(1), 0);
}
static void _rtl88ee_set_fw_clock_on(struct ieee80211_hw *hw,
u8 rpwm_val, bool need_turn_off_ckk)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
bool support_remote_wake_up;
u32 count = 0, isr_regaddr, content;
bool schedule_timer = need_turn_off_ckk;
rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN,
(u8 *)(&support_remote_wake_up));
if (!rtlhal->fw_ready)
return;
if (!rtlpriv->psc.fw_current_inpsmode)
return;
while (1) {
spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
if (rtlhal->fw_clk_change_in_progress) {
while (rtlhal->fw_clk_change_in_progress) {
spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
udelay(100);
if (++count > 1000)
return;
spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
}
spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
} else {
rtlhal->fw_clk_change_in_progress = false;
spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
}
}
if (IS_IN_LOW_POWER_STATE_88E(rtlhal->fw_ps_state)) {
rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM,
(u8 *)(&rpwm_val));
if (FW_PS_IS_ACK(rpwm_val)) {
isr_regaddr = REG_HISR;
content = rtl_read_dword(rtlpriv, isr_regaddr);
while (!(content & IMR_CPWM) && (count < 500)) {
udelay(50);
count++;
content = rtl_read_dword(rtlpriv, isr_regaddr);
}
if (content & IMR_CPWM) {
rtl_write_word(rtlpriv, isr_regaddr, 0x0100);
rtlhal->fw_ps_state = FW_PS_STATE_RF_ON_88E;
RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
"Receive CPWM INT!!! Set pHalData->FwPSState = %X\n",
rtlhal->fw_ps_state);
}
}
spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
rtlhal->fw_clk_change_in_progress = false;
spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
if (schedule_timer) {
mod_timer(&rtlpriv->works.fw_clockoff_timer,
jiffies + MSECS(10));
}
} else {
spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
rtlhal->fw_clk_change_in_progress = false;
spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
}
}
static void _rtl88ee_set_fw_clock_off(struct ieee80211_hw *hw,
u8 rpwm_val)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl8192_tx_ring *ring;
enum rf_pwrstate rtstate;
bool schedule_timer = false;
u8 queue;
if (!rtlhal->fw_ready)
return;
if (!rtlpriv->psc.fw_current_inpsmode)
return;
if (!rtlhal->allow_sw_to_change_hwclc)
return;
rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, (u8 *)(&rtstate));
if (rtstate == ERFOFF || rtlpriv->psc.inactive_pwrstate == ERFOFF)
return;
for (queue = 0; queue < RTL_PCI_MAX_TX_QUEUE_COUNT; queue++) {
ring = &rtlpci->tx_ring[queue];
if (skb_queue_len(&ring->queue)) {
schedule_timer = true;
break;
}
}
if (schedule_timer) {
mod_timer(&rtlpriv->works.fw_clockoff_timer,
jiffies + MSECS(10));
return;
}
if (FW_PS_STATE(rtlhal->fw_ps_state) !=
FW_PS_STATE_RF_OFF_LOW_PWR_88E) {
spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
if (!rtlhal->fw_clk_change_in_progress) {
rtlhal->fw_clk_change_in_progress = true;
spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val);
rtl_write_word(rtlpriv, REG_HISR, 0x0100);
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM,
(u8 *)(&rpwm_val));
spin_lock_bh(&rtlpriv->locks.fw_ps_lock);
rtlhal->fw_clk_change_in_progress = false;
spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
} else {
spin_unlock_bh(&rtlpriv->locks.fw_ps_lock);
mod_timer(&rtlpriv->works.fw_clockoff_timer,
jiffies + MSECS(10));
}
}
}
static void _rtl88ee_set_fw_ps_rf_on(struct ieee80211_hw *hw)
{
u8 rpwm_val = 0;
rpwm_val |= (FW_PS_STATE_RF_OFF_88E | FW_PS_ACK);
_rtl88ee_set_fw_clock_on(hw, rpwm_val, true);
}
static void _rtl88ee_set_fw_ps_rf_off_low_power(struct ieee80211_hw *hw)
{
u8 rpwm_val = 0;
rpwm_val |= FW_PS_STATE_RF_OFF_LOW_PWR_88E;
_rtl88ee_set_fw_clock_off(hw, rpwm_val);
}
void rtl88ee_fw_clk_off_timer_callback(unsigned long data)
{
struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
_rtl88ee_set_fw_ps_rf_off_low_power(hw);
}
static void _rtl88ee_fwlps_leave(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
bool fw_current_inps = false;
u8 rpwm_val = 0, fw_pwrmode = FW_PS_ACTIVE_MODE;
if (ppsc->low_power_enable) {
rpwm_val = (FW_PS_STATE_ALL_ON_88E|FW_PS_ACK);/* RF on */
_rtl88ee_set_fw_clock_on(hw, rpwm_val, false);
rtlhal->allow_sw_to_change_hwclc = false;
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE,
(u8 *)(&fw_pwrmode));
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
(u8 *)(&fw_current_inps));
} else {
rpwm_val = FW_PS_STATE_ALL_ON_88E; /* RF on */
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM,
(u8 *)(&rpwm_val));
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE,
(u8 *)(&fw_pwrmode));
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
(u8 *)(&fw_current_inps));
}
}
static void _rtl88ee_fwlps_enter(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
bool fw_current_inps = true;
u8 rpwm_val;
if (ppsc->low_power_enable) {
rpwm_val = FW_PS_STATE_RF_OFF_LOW_PWR_88E; /* RF off */
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
(u8 *)(&fw_current_inps));
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE,
(u8 *)(&ppsc->fwctrl_psmode));
rtlhal->allow_sw_to_change_hwclc = true;
_rtl88ee_set_fw_clock_off(hw, rpwm_val);
} else {
rpwm_val = FW_PS_STATE_RF_OFF_88E; /* RF off */
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
(u8 *)(&fw_current_inps));
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE,
(u8 *)(&ppsc->fwctrl_psmode));
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM,
(u8 *)(&rpwm_val));
}
}
void rtl88ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
switch (variable) {
case HW_VAR_RCR:
*((u32 *)(val)) = rtlpci->receive_config;
break;
case HW_VAR_RF_STATE:
*((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state;
break;
case HW_VAR_FWLPS_RF_ON:{
enum rf_pwrstate rfstate;
u32 val_rcr;
rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE,
(u8 *)(&rfstate));
if (rfstate == ERFOFF) {
*((bool *)(val)) = true;
} else {
val_rcr = rtl_read_dword(rtlpriv, REG_RCR);
val_rcr &= 0x00070000;
if (val_rcr)
*((bool *)(val)) = false;
else
*((bool *)(val)) = true;
}
break;
}
case HW_VAR_FW_PSMODE_STATUS:
*((bool *)(val)) = ppsc->fw_current_inpsmode;
break;
case HW_VAR_CORRECT_TSF:{
u64 tsf;
u32 *ptsf_low = (u32 *)&tsf;
u32 *ptsf_high = ((u32 *)&tsf) + 1;
*ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4));
*ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
*((u64 *)(val)) = tsf;
break; }
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not process %x\n", variable);
break;
}
}
void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
u8 idx;
switch (variable) {
case HW_VAR_ETHER_ADDR:
for (idx = 0; idx < ETH_ALEN; idx++)
rtl_write_byte(rtlpriv, (REG_MACID + idx), val[idx]);
break;
case HW_VAR_BASIC_RATE:{
u16 rate_cfg = ((u16 *)val)[0];
u8 rate_index = 0;
rate_cfg = rate_cfg & 0x15f;
rate_cfg |= 0x01;
rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff);
rtl_write_byte(rtlpriv, REG_RRSR + 1, (rate_cfg >> 8) & 0xff);
while (rate_cfg > 0x1) {
rate_cfg = (rate_cfg >> 1);
rate_index++;
}
rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, rate_index);
break; }
case HW_VAR_BSSID:
for (idx = 0; idx < ETH_ALEN; idx++)
rtl_write_byte(rtlpriv, (REG_BSSID + idx), val[idx]);
break;
case HW_VAR_SIFS:
rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]);
rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]);
rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]);
rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]);
if (!mac->ht_enable)
rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, 0x0e0e);
else
rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM,
*((u16 *)val));
break;
case HW_VAR_SLOT_TIME:{
u8 e_aci;
RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
"HW_VAR_SLOT_TIME %x\n", val[0]);
rtl_write_byte(rtlpriv, REG_SLOT, val[0]);
for (e_aci = 0; e_aci < AC_MAX; e_aci++) {
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
(u8 *)(&e_aci));
}
break; }
case HW_VAR_ACK_PREAMBLE:{
u8 reg_tmp;
u8 short_preamble = (bool) (*(u8 *)val);
reg_tmp = rtl_read_byte(rtlpriv, REG_TRXPTCL_CTL+2);
if (short_preamble) {
reg_tmp |= 0x02;
rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, reg_tmp);
} else {
reg_tmp |= 0xFD;
rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, reg_tmp);
}
break; }
case HW_VAR_WPA_CONFIG:
rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *)val));
break;
case HW_VAR_AMPDU_MIN_SPACE:{
u8 min_spacing_to_set;
u8 sec_min_space;
min_spacing_to_set = *((u8 *)val);
if (min_spacing_to_set <= 7) {
sec_min_space = 0;
if (min_spacing_to_set < sec_min_space)
min_spacing_to_set = sec_min_space;
mac->min_space_cfg = ((mac->min_space_cfg &
0xf8) | min_spacing_to_set);
*val = min_spacing_to_set;
RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
"Set HW_VAR_AMPDU_MIN_SPACE: %#x\n",
mac->min_space_cfg);
rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE,
mac->min_space_cfg);
}
break; }
case HW_VAR_SHORTGI_DENSITY:{
u8 density_to_set;
density_to_set = *((u8 *)val);
mac->min_space_cfg |= (density_to_set << 3);
RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
"Set HW_VAR_SHORTGI_DENSITY: %#x\n",
mac->min_space_cfg);
rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE,
mac->min_space_cfg);
break; }
case HW_VAR_AMPDU_FACTOR:{
u8 regtoset_normal[4] = { 0x41, 0xa8, 0x72, 0xb9 };
u8 factor;
u8 *reg = NULL;
u8 id = 0;
reg = regtoset_normal;
factor = *((u8 *)val);
if (factor <= 3) {
factor = (1 << (factor + 2));
if (factor > 0xf)
factor = 0xf;
for (id = 0; id < 4; id++) {
if ((reg[id] & 0xf0) > (factor << 4))
reg[id] = (reg[id] & 0x0f) |
(factor << 4);
if ((reg[id] & 0x0f) > factor)
reg[id] = (reg[id] & 0xf0) | (factor);
rtl_write_byte(rtlpriv, (REG_AGGLEN_LMT + id),
reg[id]);
}
RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
"Set HW_VAR_AMPDU_FACTOR: %#x\n", factor);
}
break; }
case HW_VAR_AC_PARAM:{
u8 e_aci = *((u8 *)val);
rtl88e_dm_init_edca_turbo(hw);
if (rtlpci->acm_method != eAcmWay2_SW)
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL,
(u8 *)(&e_aci));
break; }
case HW_VAR_ACM_CTRL:{
u8 e_aci = *((u8 *)val);
union aci_aifsn *p_aci_aifsn =
(union aci_aifsn *)(&(mac->ac[0].aifs));
u8 acm = p_aci_aifsn->f.acm;
u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL);
acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1);
if (acm) {
switch (e_aci) {
case AC0_BE:
acm_ctrl |= ACMHW_BEQEN;
break;
case AC2_VI:
acm_ctrl |= ACMHW_VIQEN;
break;
case AC3_VO:
acm_ctrl |= ACMHW_VOQEN;
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
"HW_VAR_ACM_CTRL acm set failed: eACI is %d\n",
acm);
break;
}
} else {
switch (e_aci) {
case AC0_BE:
acm_ctrl &= (~ACMHW_BEQEN);
break;
case AC2_VI:
acm_ctrl &= (~ACMHW_VIQEN);
break;
case AC3_VO:
acm_ctrl &= (~ACMHW_BEQEN);
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not process\n");
break;
}
}
RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE,
"SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n",
acm_ctrl);
rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl);
break; }
case HW_VAR_RCR:
rtl_write_dword(rtlpriv, REG_RCR, ((u32 *)(val))[0]);
rtlpci->receive_config = ((u32 *)(val))[0];
break;
case HW_VAR_RETRY_LIMIT:{
u8 retry_limit = ((u8 *)(val))[0];
rtl_write_word(rtlpriv, REG_RL,
retry_limit << RETRY_LIMIT_SHORT_SHIFT |
retry_limit << RETRY_LIMIT_LONG_SHIFT);
break; }
case HW_VAR_DUAL_TSF_RST:
rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
break;
case HW_VAR_EFUSE_BYTES:
rtlefuse->efuse_usedbytes = *((u16 *)val);
break;
case HW_VAR_EFUSE_USAGE:
rtlefuse->efuse_usedpercentage = *((u8 *)val);
break;
case HW_VAR_IO_CMD:
rtl88e_phy_set_io_cmd(hw, (*(enum io_type *)val));
break;
case HW_VAR_SET_RPWM:{
u8 rpwm_val;
rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM);
udelay(1);
if (rpwm_val & BIT(7)) {
rtl_write_byte(rtlpriv, REG_PCIE_HRPWM,
(*(u8 *)val));
} else {
rtl_write_byte(rtlpriv, REG_PCIE_HRPWM,
((*(u8 *)val) | BIT(7)));
}
break; }
case HW_VAR_H2C_FW_PWRMODE:
rtl88e_set_fw_pwrmode_cmd(hw, (*(u8 *)val));
break;
case HW_VAR_FW_PSMODE_STATUS:
ppsc->fw_current_inpsmode = *((bool *)val);
break;
case HW_VAR_RESUME_CLK_ON:
_rtl88ee_set_fw_ps_rf_on(hw);
break;
case HW_VAR_FW_LPS_ACTION:{
bool enter_fwlps = *((bool *)val);
if (enter_fwlps)
_rtl88ee_fwlps_enter(hw);
else
_rtl88ee_fwlps_leave(hw);
break; }
case HW_VAR_H2C_FW_JOINBSSRPT:{
u8 mstatus = (*(u8 *)val);
u8 tmp, tmp_reg422, uval;
u8 count = 0, dlbcn_count = 0;
bool recover = false;
if (mstatus == RT_MEDIA_CONNECT) {
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, NULL);
tmp = rtl_read_byte(rtlpriv, REG_CR + 1);
rtl_write_byte(rtlpriv, REG_CR + 1, (tmp | BIT(0)));
_rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(3));
_rtl88ee_set_bcn_ctrl_reg(hw, BIT(4), 0);
tmp_reg422 = rtl_read_byte(rtlpriv,
REG_FWHW_TXQ_CTRL + 2);
rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
tmp_reg422 & (~BIT(6)));
if (tmp_reg422 & BIT(6))
recover = true;
do {
uval = rtl_read_byte(rtlpriv, REG_TDECTRL+2);
rtl_write_byte(rtlpriv, REG_TDECTRL+2,
(uval | BIT(0)));
_rtl88ee_return_beacon_queue_skb(hw);
rtl88e_set_fw_rsvdpagepkt(hw, 0);
uval = rtl_read_byte(rtlpriv, REG_TDECTRL+2);
count = 0;
while (!(uval & BIT(0)) && count < 20) {
count++;
udelay(10);
uval = rtl_read_byte(rtlpriv,
REG_TDECTRL+2);
}
dlbcn_count++;
} while (!(uval & BIT(0)) && dlbcn_count < 5);
if (uval & BIT(0))
rtl_write_byte(rtlpriv, REG_TDECTRL+2, BIT(0));
_rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0);
_rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(4));
if (recover) {
rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
tmp_reg422);
}
rtl_write_byte(rtlpriv, REG_CR + 1, (tmp & ~(BIT(0))));
}
rtl88e_set_fw_joinbss_report_cmd(hw, (*(u8 *)val));
break; }
case HW_VAR_H2C_FW_P2P_PS_OFFLOAD:
rtl88e_set_p2p_ps_offload_cmd(hw, (*(u8 *)val));
break;
case HW_VAR_AID:{
u16 u2btmp;
u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT);
u2btmp &= 0xC000;
rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp |
mac->assoc_id));
break; }
case HW_VAR_CORRECT_TSF:{
u8 btype_ibss = ((u8 *)(val))[0];
if (btype_ibss == true)
_rtl88ee_stop_tx_beacon(hw);
_rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(3));
rtl_write_dword(rtlpriv, REG_TSFTR,
(u32) (mac->tsf & 0xffffffff));
rtl_write_dword(rtlpriv, REG_TSFTR + 4,
(u32) ((mac->tsf >> 32) & 0xffffffff));
_rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0);
if (btype_ibss == true)
_rtl88ee_resume_tx_beacon(hw);
break; }
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not process %x\n", variable);
break;
}
}
static bool _rtl88ee_llt_write(struct ieee80211_hw *hw, u32 address, u32 data)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
bool status = true;
long count = 0;
u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) |
_LLT_OP(_LLT_WRITE_ACCESS);
rtl_write_dword(rtlpriv, REG_LLT_INIT, value);
do {
value = rtl_read_dword(rtlpriv, REG_LLT_INIT);
if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value))
break;
if (count > POLLING_LLT_THRESHOLD) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Failed to polling write LLT done at address %d!\n",
address);
status = false;
break;
}
} while (++count);
return status;
}
static bool _rtl88ee_llt_table_init(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
unsigned short i;
u8 txpktbuf_bndy;
u8 maxpage;
bool status;
maxpage = 0xAF;
txpktbuf_bndy = 0xAB;
rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x01);
rtl_write_dword(rtlpriv, REG_RQPN, 0x80730d29);
rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, (0x25FF0000 | txpktbuf_bndy));
rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy);
rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy);
rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy);
rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy);
rtl_write_byte(rtlpriv, REG_PBP, 0x11);
rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4);
for (i = 0; i < (txpktbuf_bndy - 1); i++) {
status = _rtl88ee_llt_write(hw, i, i + 1);
if (true != status)
return status;
}
status = _rtl88ee_llt_write(hw, (txpktbuf_bndy - 1), 0xFF);
if (true != status)
return status;
for (i = txpktbuf_bndy; i < maxpage; i++) {
status = _rtl88ee_llt_write(hw, i, (i + 1));
if (true != status)
return status;
}
status = _rtl88ee_llt_write(hw, maxpage, txpktbuf_bndy);
if (true != status)
return status;
return true;
}
static void _rtl88ee_gen_refresh_led_state(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
if (rtlpriv->rtlhal.up_first_time)
return;
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS)
rtl88ee_sw_led_on(hw, pLed0);
else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT)
rtl88ee_sw_led_on(hw, pLed0);
else
rtl88ee_sw_led_off(hw, pLed0);
}
static bool _rtl88ee_init_mac(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
u8 bytetmp;
u16 wordtmp;
/*Disable XTAL OUTPUT for power saving. YJ, add, 111206. */
bytetmp = rtl_read_byte(rtlpriv, REG_XCK_OUT_CTRL) & (~BIT(0));
rtl_write_byte(rtlpriv, REG_XCK_OUT_CTRL, bytetmp);
/*Auto Power Down to CHIP-off State*/
bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) & (~BIT(7));
rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp);
rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00);
/* HW Power on sequence */
if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
PWR_INTF_PCI_MSK,
Rtl8188E_NIC_ENABLE_FLOW)) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"init MAC Fail as rtl_hal_pwrseqcmdparsing\n");
return false;
}
bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO) | BIT(4);
rtl_write_byte(rtlpriv, REG_APS_FSMCO, bytetmp);
bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG+2);
rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+2, bytetmp|BIT(2));
bytetmp = rtl_read_byte(rtlpriv, REG_WATCH_DOG+1);
rtl_write_byte(rtlpriv, REG_WATCH_DOG+1, bytetmp|BIT(7));
bytetmp = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL_EXT+1);
rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL_EXT+1, bytetmp|BIT(1));
bytetmp = rtl_read_byte(rtlpriv, REG_TX_RPT_CTRL);
rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL, bytetmp|BIT(1)|BIT(0));
rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL+1, 2);
rtl_write_word(rtlpriv, REG_TX_RPT_TIME, 0xcdf0);
/*Add for wake up online*/
bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CLKR);
rtl_write_byte(rtlpriv, REG_SYS_CLKR, bytetmp|BIT(3));
bytetmp = rtl_read_byte(rtlpriv, REG_GPIO_MUXCFG+1);
rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG+1, (bytetmp & (~BIT(4))));
rtl_write_byte(rtlpriv, 0x367, 0x80);
rtl_write_word(rtlpriv, REG_CR, 0x2ff);
rtl_write_byte(rtlpriv, REG_CR+1, 0x06);
rtl_write_byte(rtlpriv, REG_CR+2, 0x00);
if (!rtlhal->mac_func_enable) {
if (_rtl88ee_llt_table_init(hw) == false) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"LLT table init fail\n");
return false;
}
}
rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff);
rtl_write_dword(rtlpriv, REG_HISRE, 0xffffffff);
wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL);
wordtmp &= 0xf;
wordtmp |= 0xE771;
rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp);
rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xffff);
rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config);
rtl_write_dword(rtlpriv, REG_BCNQ_DESA,
((u64) rtlpci->tx_ring[BEACON_QUEUE].dma) &
DMA_BIT_MASK(32));
rtl_write_dword(rtlpriv, REG_MGQ_DESA,
(u64) rtlpci->tx_ring[MGNT_QUEUE].dma &
DMA_BIT_MASK(32));
rtl_write_dword(rtlpriv, REG_VOQ_DESA,
(u64) rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32));
rtl_write_dword(rtlpriv, REG_VIQ_DESA,
(u64) rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32));
rtl_write_dword(rtlpriv, REG_BEQ_DESA,
(u64) rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32));
rtl_write_dword(rtlpriv, REG_BKQ_DESA,
(u64) rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32));
rtl_write_dword(rtlpriv, REG_HQ_DESA,
(u64) rtlpci->tx_ring[HIGH_QUEUE].dma &
DMA_BIT_MASK(32));
rtl_write_dword(rtlpriv, REG_RX_DESA,
(u64) rtlpci->rx_ring[RX_MPDU_QUEUE].dma &
DMA_BIT_MASK(32));
/* if we want to support 64 bit DMA, we should set it here,
* but at the moment we do not support 64 bit DMA
*/
rtl_write_dword(rtlpriv, REG_INT_MIG, 0);
rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0);
rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+1, 0);/*Enable RX DMA */
if (rtlhal->earlymode_enable) {/*Early mode enable*/
bytetmp = rtl_read_byte(rtlpriv, REG_EARLY_MODE_CONTROL);
bytetmp |= 0x1f;
rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, bytetmp);
rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL+3, 0x81);
}
_rtl88ee_gen_refresh_led_state(hw);
return true;
}
static void _rtl88ee_hw_configure(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 reg_prsr;
reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
rtl_write_dword(rtlpriv, REG_RRSR, reg_prsr);
rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF);
}
static void _rtl88ee_enable_aspm_back_door(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
u8 tmp1byte = 0;
u32 tmp4Byte = 0, count;
rtl_write_word(rtlpriv, 0x354, 0x8104);
rtl_write_word(rtlpriv, 0x358, 0x24);
rtl_write_word(rtlpriv, 0x350, 0x70c);
rtl_write_byte(rtlpriv, 0x352, 0x2);
tmp1byte = rtl_read_byte(rtlpriv, 0x352);
count = 0;
while (tmp1byte && count < 20) {
udelay(10);
tmp1byte = rtl_read_byte(rtlpriv, 0x352);
count++;
}
if (0 == tmp1byte) {
tmp4Byte = rtl_read_dword(rtlpriv, 0x34c);
rtl_write_dword(rtlpriv, 0x348, tmp4Byte|BIT(31));
rtl_write_word(rtlpriv, 0x350, 0xf70c);
rtl_write_byte(rtlpriv, 0x352, 0x1);
}
tmp1byte = rtl_read_byte(rtlpriv, 0x352);
count = 0;
while (tmp1byte && count < 20) {
udelay(10);
tmp1byte = rtl_read_byte(rtlpriv, 0x352);
count++;
}
rtl_write_word(rtlpriv, 0x350, 0x718);
rtl_write_byte(rtlpriv, 0x352, 0x2);
tmp1byte = rtl_read_byte(rtlpriv, 0x352);
count = 0;
while (tmp1byte && count < 20) {
udelay(10);
tmp1byte = rtl_read_byte(rtlpriv, 0x352);
count++;
}
if (ppsc->support_backdoor || (0 == tmp1byte)) {
tmp4Byte = rtl_read_dword(rtlpriv, 0x34c);
rtl_write_dword(rtlpriv, 0x348, tmp4Byte|BIT(11)|BIT(12));
rtl_write_word(rtlpriv, 0x350, 0xf718);
rtl_write_byte(rtlpriv, 0x352, 0x1);
}
tmp1byte = rtl_read_byte(rtlpriv, 0x352);
count = 0;
while (tmp1byte && count < 20) {
udelay(10);
tmp1byte = rtl_read_byte(rtlpriv, 0x352);
count++;
}
}
void rtl88ee_enable_hw_security_config(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 sec_reg_value;
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
"PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n",
rtlpriv->sec.pairwise_enc_algorithm,
rtlpriv->sec.group_enc_algorithm);
if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) {
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
"not open hw encryption\n");
return;
}
sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE;
if (rtlpriv->sec.use_defaultkey) {
sec_reg_value |= SCR_TXUSEDK;
sec_reg_value |= SCR_RXUSEDK;
}
sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK);
rtl_write_byte(rtlpriv, REG_CR + 1, 0x02);
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
"The SECR-value %x\n", sec_reg_value);
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value);
}
int rtl88ee_hw_init(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
bool rtstatus = true;
int err = 0;
u8 tmp_u1b, u1byte;
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Rtl8188EE hw init\n");
rtlpriv->rtlhal.being_init_adapter = true;
rtlpriv->intf_ops->disable_aspm(hw);
tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_CLKR+1);
u1byte = rtl_read_byte(rtlpriv, REG_CR);
if ((tmp_u1b & BIT(3)) && (u1byte != 0 && u1byte != 0xEA)) {
rtlhal->mac_func_enable = true;
} else {
rtlhal->mac_func_enable = false;
rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_88E;
}
rtstatus = _rtl88ee_init_mac(hw);
if (rtstatus != true) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n");
err = 1;
return err;
}
err = rtl88e_download_fw(hw, false);
if (err) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
"Failed to download FW. Init HW without FW now..\n");
err = 1;
rtlhal->fw_ready = false;
return err;
} else {
rtlhal->fw_ready = true;
}
/*fw related variable initialize */
rtlhal->last_hmeboxnum = 0;
rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_88E;
rtlhal->fw_clk_change_in_progress = false;
rtlhal->allow_sw_to_change_hwclc = false;
ppsc->fw_current_inpsmode = false;
rtl88e_phy_mac_config(hw);
/* because last function modifies RCR, we update
* rcr var here, or TP will be unstable for receive_config
* is wrong, RX RCR_ACRC32 will cause TP unstable & Rx
* RCR_APP_ICV will cause mac80211 disassoc for cisco 1252
*/
rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
rtl88e_phy_bb_config(hw);
rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1);
rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1);
rtlphy->rf_mode = RF_OP_BY_SW_3WIRE;
rtl88e_phy_rf_config(hw);
rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0,
RF_CHNLBW, RFREG_OFFSET_MASK);
rtlphy->rfreg_chnlval[0] = rtlphy->rfreg_chnlval[0] & 0xfff00fff;
_rtl88ee_hw_configure(hw);
rtl_cam_reset_all_entry(hw);
rtl88ee_enable_hw_security_config(hw);
rtlhal->mac_func_enable = true;
ppsc->rfpwr_state = ERFON;
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
_rtl88ee_enable_aspm_back_door(hw);
rtlpriv->intf_ops->enable_aspm(hw);
if (ppsc->rfpwr_state == ERFON) {
if ((rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) ||
((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) &&
(rtlhal->oem_id == RT_CID_819x_HP))) {
rtl88e_phy_set_rfpath_switch(hw, true);
rtlpriv->dm.fat_table.rx_idle_ant = MAIN_ANT;
} else {
rtl88e_phy_set_rfpath_switch(hw, false);
rtlpriv->dm.fat_table.rx_idle_ant = AUX_ANT;
}
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"rx idle ant %s\n",
(rtlpriv->dm.fat_table.rx_idle_ant == MAIN_ANT) ?
("MAIN_ANT") : ("AUX_ANT"));
if (rtlphy->iqk_initialized) {
rtl88e_phy_iq_calibrate(hw, true);
} else {
rtl88e_phy_iq_calibrate(hw, false);
rtlphy->iqk_initialized = true;
}
rtl88e_dm_check_txpower_tracking(hw);
rtl88e_phy_lc_calibrate(hw);
}
tmp_u1b = efuse_read_1byte(hw, 0x1FA);
if (!(tmp_u1b & BIT(0))) {
rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0F, 0x05);
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "PA BIAS path A\n");
}
if (!(tmp_u1b & BIT(4))) {
tmp_u1b = rtl_read_byte(rtlpriv, 0x16);
tmp_u1b &= 0x0F;
rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x80);
udelay(10);
rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x90);
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "under 1.5V\n");
}
rtl_write_byte(rtlpriv, REG_NAV_CTRL+2, ((30000+127)/128));
rtl88e_dm_init(hw);
rtlpriv->rtlhal.being_init_adapter = false;
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "end of Rtl8188EE hw init %x\n",
err);
return 0;
}
static enum version_8188e _rtl88ee_read_chip_version(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
enum version_8188e version = VERSION_UNKNOWN;
u32 value32;
value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG);
if (value32 & TRP_VAUX_EN) {
version = (enum version_8188e) VERSION_TEST_CHIP_88E;
} else {
version = NORMAL_CHIP;
version = version | ((value32 & TYPE_ID) ? RF_TYPE_2T2R : 0);
version = version | ((value32 & VENDOR_ID) ?
CHIP_VENDOR_UMC : 0);
}
rtlphy->rf_type = RF_1T1R;
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"Chip RF Type: %s\n", (rtlphy->rf_type == RF_2T2R) ?
"RF_2T2R" : "RF_1T1R");
return version;
}
static int _rtl88ee_set_media_status(struct ieee80211_hw *hw,
enum nl80211_iftype type)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 bt_msr = rtl_read_byte(rtlpriv, MSR);
enum led_ctl_mode ledaction = LED_CTL_NO_LINK;
bt_msr &= 0xfc;
if (type == NL80211_IFTYPE_UNSPECIFIED ||
type == NL80211_IFTYPE_STATION) {
_rtl88ee_stop_tx_beacon(hw);
_rtl88ee_enable_bcn_sub_func(hw);
} else if (type == NL80211_IFTYPE_ADHOC ||
type == NL80211_IFTYPE_AP ||
type == NL80211_IFTYPE_MESH_POINT) {
_rtl88ee_resume_tx_beacon(hw);
_rtl88ee_disable_bcn_sub_func(hw);
} else {
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
"Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n",
type);
}
switch (type) {
case NL80211_IFTYPE_UNSPECIFIED:
bt_msr |= MSR_NOLINK;
ledaction = LED_CTL_LINK;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"Set Network type to NO LINK!\n");
break;
case NL80211_IFTYPE_ADHOC:
bt_msr |= MSR_ADHOC;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"Set Network type to Ad Hoc!\n");
break;
case NL80211_IFTYPE_STATION:
bt_msr |= MSR_INFRA;
ledaction = LED_CTL_LINK;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"Set Network type to STA!\n");
break;
case NL80211_IFTYPE_AP:
bt_msr |= MSR_AP;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"Set Network type to AP!\n");
break;
case NL80211_IFTYPE_MESH_POINT:
bt_msr |= MSR_ADHOC;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"Set Network type to Mesh Point!\n");
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Network type %d not support!\n", type);
return 1;
}
rtl_write_byte(rtlpriv, (MSR), bt_msr);
rtlpriv->cfg->ops->led_control(hw, ledaction);
if ((bt_msr & 0xfc) == MSR_AP)
rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
else
rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
return 0;
}
void rtl88ee_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
u32 reg_rcr = rtlpci->receive_config;
if (rtlpriv->psc.rfpwr_state != ERFON)
return;
if (check_bssid == true) {
reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
(u8 *)(&reg_rcr));
_rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(4));
} else if (check_bssid == false) {
reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
_rtl88ee_set_bcn_ctrl_reg(hw, BIT(4), 0);
rtlpriv->cfg->ops->set_hw_reg(hw,
HW_VAR_RCR, (u8 *)(&reg_rcr));
}
}
int rtl88ee_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
if (_rtl88ee_set_media_status(hw, type))
return -EOPNOTSUPP;
if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
if (type != NL80211_IFTYPE_AP &&
type != NL80211_IFTYPE_MESH_POINT)
rtl88ee_set_check_bssid(hw, true);
} else {
rtl88ee_set_check_bssid(hw, false);
}
return 0;
}
/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */
void rtl88ee_set_qos(struct ieee80211_hw *hw, int aci)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl88e_dm_init_edca_turbo(hw);
switch (aci) {
case AC1_BK:
rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f);
break;
case AC0_BE:
break;
case AC2_VI:
rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322);
break;
case AC3_VO:
rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222);
break;
default:
RT_ASSERT(false, "invalid aci: %d !\n", aci);
break;
}
}
void rtl88ee_enable_interrupt(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
rtlpci->irq_enabled = true;
/* there are some C2H CMDs have been sent before system interrupt
* is enabled, e.g., C2H, CPWM.
* So we need to clear all C2H events that FW has notified, otherwise
* FW won't schedule any commands anymore.
*/
rtl_write_byte(rtlpriv, REG_C2HEVT_CLEAR, 0);
/*enable system interrupt*/
rtl_write_dword(rtlpriv, REG_HSIMR, rtlpci->sys_irq_mask & 0xFFFFFFFF);
}
void rtl88ee_disable_interrupt(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
rtl_write_dword(rtlpriv, REG_HIMR, IMR_DISABLED);
rtl_write_dword(rtlpriv, REG_HIMRE, IMR_DISABLED);
rtlpci->irq_enabled = false;
synchronize_irq(rtlpci->pdev->irq);
}
static void _rtl88ee_poweroff_adapter(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
u8 u1b_tmp;
u32 count = 0;
rtlhal->mac_func_enable = false;
rtlpriv->intf_ops->enable_aspm(hw);
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "POWER OFF adapter\n");
u1b_tmp = rtl_read_byte(rtlpriv, REG_TX_RPT_CTRL);
rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL, u1b_tmp & (~BIT(1)));
u1b_tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL);
while (!(u1b_tmp & BIT(1)) && (count++ < 100)) {
udelay(10);
u1b_tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL);
count++;
}
rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+1, 0xFF);
rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
PWR_INTF_PCI_MSK, Rtl8188E_NIC_LPS_ENTER_FLOW);
rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00);
if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready)
rtl88e_firmware_selfreset(hw);
u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1);
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
u1b_tmp = rtl_read_byte(rtlpriv, REG_32K_CTRL);
rtl_write_byte(rtlpriv, REG_32K_CTRL, (u1b_tmp & (~BIT(0))));
rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
PWR_INTF_PCI_MSK, Rtl8188E_NIC_DISABLE_FLOW);
u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1);
rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp & (~BIT(3))));
u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1);
rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp | BIT(3)));
rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0E);
u1b_tmp = rtl_read_byte(rtlpriv, GPIO_IN);
rtl_write_byte(rtlpriv, GPIO_OUT, u1b_tmp);
rtl_write_byte(rtlpriv, GPIO_IO_SEL, 0x7F);
u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL);
rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL, (u1b_tmp << 4) | u1b_tmp);
u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL+1);
rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL+1, u1b_tmp | 0x0F);
rtl_write_dword(rtlpriv, REG_GPIO_IO_SEL_2+2, 0x00080808);
}
void rtl88ee_card_disable(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
enum nl80211_iftype opmode;
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RTL8188ee card disable\n");
mac->link_state = MAC80211_NOLINK;
opmode = NL80211_IFTYPE_UNSPECIFIED;
_rtl88ee_set_media_status(hw, opmode);
if (rtlpriv->rtlhal.driver_is_goingto_unload ||
ppsc->rfoff_reason > RF_CHANGE_BY_PS)
rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
_rtl88ee_poweroff_adapter(hw);
/* after power off we should do iqk again */
rtlpriv->phy.iqk_initialized = false;
}
void rtl88ee_interrupt_recognized(struct ieee80211_hw *hw,
u32 *p_inta, u32 *p_intb)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
*p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0];
rtl_write_dword(rtlpriv, ISR, *p_inta);
*p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1];
rtl_write_dword(rtlpriv, REG_HISRE, *p_intb);
}
void rtl88ee_set_beacon_related_registers(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
u16 bcn_interval, atim_window;
bcn_interval = mac->beacon_interval;
atim_window = 2; /*FIX MERGE */
rtl88ee_disable_interrupt(hw);
rtl_write_word(rtlpriv, REG_ATIMWND, atim_window);
rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f);
rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18);
rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18);
rtl_write_byte(rtlpriv, 0x606, 0x30);
rtlpci->reg_bcn_ctrl_val |= BIT(3);
rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val);
/*rtl88ee_enable_interrupt(hw);*/
}
void rtl88ee_set_beacon_interval(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
u16 bcn_interval = mac->beacon_interval;
RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
"beacon_interval:%d\n", bcn_interval);
/*rtl88ee_disable_interrupt(hw);*/
rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
/*rtl88ee_enable_interrupt(hw);*/
}
void rtl88ee_update_interrupt_mask(struct ieee80211_hw *hw,
u32 add_msr, u32 rm_msr)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD,
"add_msr:%x, rm_msr:%x\n", add_msr, rm_msr);
rtl88ee_disable_interrupt(hw);
if (add_msr)
rtlpci->irq_mask[0] |= add_msr;
if (rm_msr)
rtlpci->irq_mask[0] &= (~rm_msr);
rtl88ee_enable_interrupt(hw);
}
static inline u8 get_chnl_group(u8 chnl)
{
u8 group;
group = chnl / 3;
if (chnl == 14)
group = 5;
return group;
}
static void set_diff0_2g(struct txpower_info_2g *pwr2g, u8 *hwinfo, u32 path,
u32 i, u32 eadr)
{
pwr2g->bw40_diff[path][i] = 0;
if (hwinfo[eadr] == 0xFF) {
pwr2g->bw20_diff[path][i] = 0x02;
} else {
pwr2g->bw20_diff[path][i] = (hwinfo[eadr]&0xf0)>>4;
/*bit sign number to 8 bit sign number*/
if (pwr2g->bw20_diff[path][i] & BIT(3))
pwr2g->bw20_diff[path][i] |= 0xF0;
}
if (hwinfo[eadr] == 0xFF) {
pwr2g->ofdm_diff[path][i] = 0x04;
} else {
pwr2g->ofdm_diff[path][i] = (hwinfo[eadr] & 0x0f);
/*bit sign number to 8 bit sign number*/
if (pwr2g->ofdm_diff[path][i] & BIT(3))
pwr2g->ofdm_diff[path][i] |= 0xF0;
}
pwr2g->cck_diff[path][i] = 0;
}
static void set_diff0_5g(struct txpower_info_5g *pwr5g, u8 *hwinfo, u32 path,
u32 i, u32 eadr)
{
pwr5g->bw40_diff[path][i] = 0;
if (hwinfo[eadr] == 0xFF) {
pwr5g->bw20_diff[path][i] = 0;
} else {
pwr5g->bw20_diff[path][i] = (hwinfo[eadr]&0xf0)>>4;
/*bit sign number to 8 bit sign number*/
if (pwr5g->bw20_diff[path][i] & BIT(3))
pwr5g->bw20_diff[path][i] |= 0xF0;
}
if (hwinfo[eadr] == 0xFF) {
pwr5g->ofdm_diff[path][i] = 0x04;
} else {
pwr5g->ofdm_diff[path][i] = (hwinfo[eadr] & 0x0f);
/*bit sign number to 8 bit sign number*/
if (pwr5g->ofdm_diff[path][i] & BIT(3))
pwr5g->ofdm_diff[path][i] |= 0xF0;
}
}
static void set_diff1_2g(struct txpower_info_2g *pwr2g, u8 *hwinfo, u32 path,
u32 i, u32 eadr)
{
if (hwinfo[eadr] == 0xFF) {
pwr2g->bw40_diff[path][i] = 0xFE;
} else {
pwr2g->bw40_diff[path][i] = (hwinfo[eadr]&0xf0)>>4;
if (pwr2g->bw40_diff[path][i] & BIT(3))
pwr2g->bw40_diff[path][i] |= 0xF0;
}
if (hwinfo[eadr] == 0xFF) {
pwr2g->bw20_diff[path][i] = 0xFE;
} else {
pwr2g->bw20_diff[path][i] = (hwinfo[eadr]&0x0f);
if (pwr2g->bw20_diff[path][i] & BIT(3))
pwr2g->bw20_diff[path][i] |= 0xF0;
}
}
static void set_diff1_5g(struct txpower_info_5g *pwr5g, u8 *hwinfo, u32 path,
u32 i, u32 eadr)
{
if (hwinfo[eadr] == 0xFF) {
pwr5g->bw40_diff[path][i] = 0xFE;
} else {
pwr5g->bw40_diff[path][i] = (hwinfo[eadr]&0xf0)>>4;
if (pwr5g->bw40_diff[path][i] & BIT(3))
pwr5g->bw40_diff[path][i] |= 0xF0;
}
if (hwinfo[eadr] == 0xFF) {
pwr5g->bw20_diff[path][i] = 0xFE;
} else {
pwr5g->bw20_diff[path][i] = (hwinfo[eadr] & 0x0f);
if (pwr5g->bw20_diff[path][i] & BIT(3))
pwr5g->bw20_diff[path][i] |= 0xF0;
}
}
static void set_diff2_2g(struct txpower_info_2g *pwr2g, u8 *hwinfo, u32 path,
u32 i, u32 eadr)
{
if (hwinfo[eadr] == 0xFF) {
pwr2g->ofdm_diff[path][i] = 0xFE;
} else {
pwr2g->ofdm_diff[path][i] = (hwinfo[eadr]&0xf0)>>4;
if (pwr2g->ofdm_diff[path][i] & BIT(3))
pwr2g->ofdm_diff[path][i] |= 0xF0;
}
if (hwinfo[eadr] == 0xFF) {
pwr2g->cck_diff[path][i] = 0xFE;
} else {
pwr2g->cck_diff[path][i] = (hwinfo[eadr]&0x0f);
if (pwr2g->cck_diff[path][i] & BIT(3))
pwr2g->cck_diff[path][i] |= 0xF0;
}
}
static void _rtl8188e_read_power_value_fromprom(struct ieee80211_hw *hw,
struct txpower_info_2g *pwr2g,
struct txpower_info_5g *pwr5g,
bool autoload_fail,
u8 *hwinfo)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 path, eadr = EEPROM_TX_PWR_INX, i;
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"hal_ReadPowerValueFromPROM88E(): PROMContent[0x%x]= 0x%x\n",
(eadr+1), hwinfo[eadr+1]);
if (0xFF == hwinfo[eadr+1])
autoload_fail = true;
if (autoload_fail) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"auto load fail : Use Default value!\n");
for (path = 0; path < MAX_RF_PATH; path++) {
/* 2.4G default value */
for (i = 0; i < MAX_CHNL_GROUP_24G; i++) {
pwr2g->index_cck_base[path][i] = 0x2D;
pwr2g->index_bw40_base[path][i] = 0x2D;
}
for (i = 0; i < MAX_TX_COUNT; i++) {
if (i == 0) {
pwr2g->bw20_diff[path][0] = 0x02;
pwr2g->ofdm_diff[path][0] = 0x04;
} else {
pwr2g->bw20_diff[path][i] = 0xFE;
pwr2g->bw40_diff[path][i] = 0xFE;
pwr2g->cck_diff[path][i] = 0xFE;
pwr2g->ofdm_diff[path][i] = 0xFE;
}
}
}
return;
}
for (path = 0; path < MAX_RF_PATH; path++) {
/*2.4G default value*/
for (i = 0; i < MAX_CHNL_GROUP_24G; i++) {
pwr2g->index_cck_base[path][i] = hwinfo[eadr++];
if (pwr2g->index_cck_base[path][i] == 0xFF)
pwr2g->index_cck_base[path][i] = 0x2D;
}
for (i = 0; i < MAX_CHNL_GROUP_24G-1; i++) {
pwr2g->index_bw40_base[path][i] = hwinfo[eadr++];
if (pwr2g->index_bw40_base[path][i] == 0xFF)
pwr2g->index_bw40_base[path][i] = 0x2D;
}
for (i = 0; i < MAX_TX_COUNT; i++) {
if (i == 0) {
set_diff0_2g(pwr2g, hwinfo, path, i, eadr);
eadr++;
} else {
set_diff1_2g(pwr2g, hwinfo, path, i, eadr);
eadr++;
set_diff2_2g(pwr2g, hwinfo, path, i, eadr);
eadr++;
}
}
/*5G default value*/
for (i = 0; i < MAX_CHNL_GROUP_5G; i++) {
pwr5g->index_bw40_base[path][i] = hwinfo[eadr++];
if (pwr5g->index_bw40_base[path][i] == 0xFF)
pwr5g->index_bw40_base[path][i] = 0xFE;
}
for (i = 0; i < MAX_TX_COUNT; i++) {
if (i == 0) {
set_diff0_5g(pwr5g, hwinfo, path, i, eadr);
eadr++;
} else {
set_diff1_5g(pwr5g, hwinfo, path, i, eadr);
eadr++;
}
}
if (hwinfo[eadr] == 0xFF) {
pwr5g->ofdm_diff[path][1] = 0xFE;
pwr5g->ofdm_diff[path][2] = 0xFE;
} else {
pwr5g->ofdm_diff[path][1] = (hwinfo[eadr] & 0xf0) >> 4;
pwr5g->ofdm_diff[path][2] = (hwinfo[eadr] & 0x0f);
}
eadr++;
if (hwinfo[eadr] == 0xFF)
pwr5g->ofdm_diff[path][3] = 0xFE;
else
pwr5g->ofdm_diff[path][3] = (hwinfo[eadr]&0x0f);
eadr++;
for (i = 1; i < MAX_TX_COUNT; i++) {
if (pwr5g->ofdm_diff[path][i] == 0xFF)
pwr5g->ofdm_diff[path][i] = 0xFE;
else if (pwr5g->ofdm_diff[path][i] & BIT(3))
pwr5g->ofdm_diff[path][i] |= 0xF0;
}
}
}
static void _rtl88ee_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
bool autoload_fail,
u8 *hwinfo)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct txpower_info_2g pwrinfo24g;
struct txpower_info_5g pwrinfo5g;
u8 rf_path, index;
u8 i;
int jj = EEPROM_RF_BOARD_OPTION_88E;
int kk = EEPROM_THERMAL_METER_88E;
_rtl8188e_read_power_value_fromprom(hw, &pwrinfo24g, &pwrinfo5g,
autoload_fail, hwinfo);
for (rf_path = 0; rf_path < 2; rf_path++) {
for (i = 0; i < 14; i++) {
index = get_chnl_group(i+1);
rtlefuse->txpwrlevel_cck[rf_path][i] =
pwrinfo24g.index_cck_base[rf_path][index];
if (i == 13)
rtlefuse->txpwrlevel_ht40_1s[rf_path][i] =
pwrinfo24g.index_bw40_base[rf_path][4];
else
rtlefuse->txpwrlevel_ht40_1s[rf_path][i] =
pwrinfo24g.index_bw40_base[rf_path][index];
rtlefuse->txpwr_ht20diff[rf_path][i] =
pwrinfo24g.bw20_diff[rf_path][0];
rtlefuse->txpwr_legacyhtdiff[rf_path][i] =
pwrinfo24g.ofdm_diff[rf_path][0];
}
for (i = 0; i < 14; i++) {
RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
"RF(%d)-Ch(%d) [CCK / HT40_1S ] = "
"[0x%x / 0x%x ]\n", rf_path, i,
rtlefuse->txpwrlevel_cck[rf_path][i],
rtlefuse->txpwrlevel_ht40_1s[rf_path][i]);
}
}
if (!autoload_fail)
rtlefuse->eeprom_thermalmeter = hwinfo[kk];
else
rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER;
if (rtlefuse->eeprom_thermalmeter == 0xff || autoload_fail) {
rtlefuse->apk_thermalmeterignore = true;
rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER;
}
rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter;
RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
"thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter);
if (!autoload_fail) {
rtlefuse->eeprom_regulatory = hwinfo[jj] & 0x07;/*bit0~2*/
if (hwinfo[jj] == 0xFF)
rtlefuse->eeprom_regulatory = 0;
} else {
rtlefuse->eeprom_regulatory = 0;
}
RTPRINT(rtlpriv, FINIT, INIT_TXPOWER,
"eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory);
}
static void _rtl88ee_read_adapter_info(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_pci_priv *rppriv = rtl_pcipriv(hw);
u16 i, usvalue;
u8 hwinfo[HWSET_MAX_SIZE];
u16 eeprom_id;
int jj = EEPROM_RF_BOARD_OPTION_88E;
int kk = EEPROM_RF_FEATURE_OPTION_88E;
if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) {
rtl_efuse_shadow_map_update(hw);
memcpy(hwinfo, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
HWSET_MAX_SIZE);
} else if (rtlefuse->epromtype == EEPROM_93C46) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"RTL819X Not boot from eeprom, check it !!");
}
RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"),
hwinfo, HWSET_MAX_SIZE);
eeprom_id = *((u16 *)&hwinfo[0]);
if (eeprom_id != RTL8188E_EEPROM_ID) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
"EEPROM ID(%#x) is invalid!!\n", eeprom_id);
rtlefuse->autoload_failflag = true;
} else {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n");
rtlefuse->autoload_failflag = false;
}
if (rtlefuse->autoload_failflag == true)
return;
/*VID DID SVID SDID*/
rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID];
rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID];
rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID];
rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID];
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"EEPROMId = 0x%4x\n", eeprom_id);
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid);
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did);
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid);
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid);
/*customer ID*/
rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID];
if (rtlefuse->eeprom_oemid == 0xFF)
rtlefuse->eeprom_oemid = 0;
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid);
/*EEPROM version*/
rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION];
/*mac address*/
for (i = 0; i < 6; i += 2) {
usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i];
*((u16 *)(&rtlefuse->dev_addr[i])) = usvalue;
}
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
"dev_addr: %pM\n", rtlefuse->dev_addr);
/*channel plan */
rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN];
/* set channel paln to world wide 13 */
rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13;
/*tx power*/
_rtl88ee_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag,
hwinfo);
rtlefuse->txpwr_fromeprom = true;
rtl8188ee_read_bt_coexist_info_from_hwpg(hw,
rtlefuse->autoload_failflag,
hwinfo);
/*board type*/
rtlefuse->board_type = (((*(u8 *)&hwinfo[jj]) & 0xE0) >> 5);
/*Wake on wlan*/
rtlefuse->wowlan_enable = ((hwinfo[kk] & 0x40) >> 6);
/*parse xtal*/
rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_88E];
if (hwinfo[EEPROM_XTAL_88E])
rtlefuse->crystalcap = 0x20;
/*antenna diversity*/
rtlefuse->antenna_div_cfg = (hwinfo[jj] & 0x18) >> 3;
if (hwinfo[jj] == 0xFF)
rtlefuse->antenna_div_cfg = 0;
if (rppriv->bt_coexist.eeprom_bt_coexist != 0 &&
rppriv->bt_coexist.eeprom_bt_ant_num == ANT_X1)
rtlefuse->antenna_div_cfg = 0;
rtlefuse->antenna_div_type = hwinfo[EEPROM_RF_ANTENNA_OPT_88E];
if (rtlefuse->antenna_div_type == 0xFF)
rtlefuse->antenna_div_type = 0x01;
if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV ||
rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV)
rtlefuse->antenna_div_cfg = 1;
if (rtlhal->oem_id == RT_CID_DEFAULT) {
switch (rtlefuse->eeprom_oemid) {
case EEPROM_CID_DEFAULT:
if (rtlefuse->eeprom_did == 0x8179) {
if (rtlefuse->eeprom_svid == 0x1025) {
rtlhal->oem_id = RT_CID_819x_Acer;
} else if ((rtlefuse->eeprom_svid == 0x10EC &&
rtlefuse->eeprom_smid == 0x0179) ||
(rtlefuse->eeprom_svid == 0x17AA &&
rtlefuse->eeprom_smid == 0x0179)) {
rtlhal->oem_id = RT_CID_819x_Lenovo;
} else if (rtlefuse->eeprom_svid == 0x103c &&
rtlefuse->eeprom_smid == 0x197d) {
rtlhal->oem_id = RT_CID_819x_HP;
} else {
rtlhal->oem_id = RT_CID_DEFAULT;
}
} else {
rtlhal->oem_id = RT_CID_DEFAULT;
}
break;
case EEPROM_CID_TOSHIBA:
rtlhal->oem_id = RT_CID_TOSHIBA;
break;
case EEPROM_CID_QMI:
rtlhal->oem_id = RT_CID_819x_QMI;
break;
case EEPROM_CID_WHQL:
default:
rtlhal->oem_id = RT_CID_DEFAULT;
break;
}
}
}
static void _rtl88ee_hal_customized_behavior(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
pcipriv->ledctl.led_opendrain = true;
switch (rtlhal->oem_id) {
case RT_CID_819x_HP:
pcipriv->ledctl.led_opendrain = true;
break;
case RT_CID_819x_Lenovo:
case RT_CID_DEFAULT:
case RT_CID_TOSHIBA:
case RT_CID_CCX:
case RT_CID_819x_Acer:
case RT_CID_WHQL:
default:
break;
}
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
"RT Customized ID: 0x%02X\n", rtlhal->oem_id);
}
void rtl88ee_read_eeprom_info(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
u8 tmp_u1b;
rtlhal->version = _rtl88ee_read_chip_version(hw);
if (get_rf_type(rtlphy) == RF_1T1R) {
rtlpriv->dm.rfpath_rxenable[0] = true;
} else {
rtlpriv->dm.rfpath_rxenable[0] = true;
rtlpriv->dm.rfpath_rxenable[1] = true;
}
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n",
rtlhal->version);
tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR);
if (tmp_u1b & BIT(4)) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n");
rtlefuse->epromtype = EEPROM_93C46;
} else {
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n");
rtlefuse->epromtype = EEPROM_BOOT_EFUSE;
}
if (tmp_u1b & BIT(5)) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n");
rtlefuse->autoload_failflag = false;
_rtl88ee_read_adapter_info(hw);
} else {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n");
}
_rtl88ee_hal_customized_behavior(hw);
}
static void rtl88ee_update_hal_rate_table(struct ieee80211_hw *hw,
struct ieee80211_sta *sta)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci_priv *rppriv = rtl_pcipriv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
u32 ratr_value;
u8 ratr_index = 0;
u8 nmode = mac->ht_enable;
u8 mimo_ps = IEEE80211_SMPS_OFF;
u16 shortgi_rate;
u32 tmp_ratr_value;
u8 ctx40 = mac->bw_40;
u16 cap = sta->ht_cap.cap;
u8 short40 = (cap & IEEE80211_HT_CAP_SGI_40) ? 1 : 0;
u8 short20 = (cap & IEEE80211_HT_CAP_SGI_20) ? 1 : 0;
enum wireless_mode wirelessmode = mac->mode;
if (rtlhal->current_bandtype == BAND_ON_5G)
ratr_value = sta->supp_rates[1] << 4;
else
ratr_value = sta->supp_rates[0];
if (mac->opmode == NL80211_IFTYPE_ADHOC)
ratr_value = 0xfff;
ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
sta->ht_cap.mcs.rx_mask[0] << 12);
switch (wirelessmode) {
case WIRELESS_MODE_B:
if (ratr_value & 0x0000000c)
ratr_value &= 0x0000000d;
else
ratr_value &= 0x0000000f;
break;
case WIRELESS_MODE_G:
ratr_value &= 0x00000FF5;
break;
case WIRELESS_MODE_N_24G:
case WIRELESS_MODE_N_5G:
nmode = 1;
if (mimo_ps == IEEE80211_SMPS_STATIC) {
ratr_value &= 0x0007F005;
} else {
u32 ratr_mask;
if (get_rf_type(rtlphy) == RF_1T2R ||
get_rf_type(rtlphy) == RF_1T1R)
ratr_mask = 0x000ff005;
else
ratr_mask = 0x0f0ff005;
ratr_value &= ratr_mask;
}
break;
default:
if (rtlphy->rf_type == RF_1T2R)
ratr_value &= 0x000ff0ff;
else
ratr_value &= 0x0f0ff0ff;
break;
}
if ((rppriv->bt_coexist.bt_coexistence) &&
(rppriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) &&
(rppriv->bt_coexist.bt_cur_state) &&
(rppriv->bt_coexist.bt_ant_isolation) &&
((rppriv->bt_coexist.bt_service == BT_SCO) ||
(rppriv->bt_coexist.bt_service == BT_BUSY)))
ratr_value &= 0x0fffcfc0;
else
ratr_value &= 0x0FFFFFFF;
if (nmode && ((ctx40 && short40) ||
(!ctx40 && short20))) {
ratr_value |= 0x10000000;
tmp_ratr_value = (ratr_value >> 12);
for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) {
if ((1 << shortgi_rate) & tmp_ratr_value)
break;
}
shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) |
(shortgi_rate << 4) | (shortgi_rate);
}
rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value);
RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
"%x\n", rtl_read_dword(rtlpriv, REG_ARFR0));
}
static void rtl88ee_update_hal_rate_mask(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u8 rssi)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_sta_info *sta_entry = NULL;
u32 ratr_bitmap;
u8 ratr_index;
u16 cap = sta->ht_cap.cap;
u8 ctx40 = (cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0;
u8 short40 = (cap & IEEE80211_HT_CAP_SGI_40) ? 1 : 0;
u8 short20 = (cap & IEEE80211_HT_CAP_SGI_20) ? 1 : 0;
enum wireless_mode wirelessmode = 0;
bool shortgi = false;
u8 rate_mask[5];
u8 macid = 0;
u8 mimo_ps = IEEE80211_SMPS_OFF;
sta_entry = (struct rtl_sta_info *)sta->drv_priv;
wirelessmode = sta_entry->wireless_mode;
if (mac->opmode == NL80211_IFTYPE_STATION ||
mac->opmode == NL80211_IFTYPE_MESH_POINT)
ctx40 = mac->bw_40;
else if (mac->opmode == NL80211_IFTYPE_AP ||
mac->opmode == NL80211_IFTYPE_ADHOC)
macid = sta->aid + 1;
if (rtlhal->current_bandtype == BAND_ON_5G)
ratr_bitmap = sta->supp_rates[1] << 4;
else
ratr_bitmap = sta->supp_rates[0];
if (mac->opmode == NL80211_IFTYPE_ADHOC)
ratr_bitmap = 0xfff;
ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 |
sta->ht_cap.mcs.rx_mask[0] << 12);
switch (wirelessmode) {
case WIRELESS_MODE_B:
ratr_index = RATR_INX_WIRELESS_B;
if (ratr_bitmap & 0x0000000c)
ratr_bitmap &= 0x0000000d;
else
ratr_bitmap &= 0x0000000f;
break;
case WIRELESS_MODE_G:
ratr_index = RATR_INX_WIRELESS_GB;
if (rssi == 1)
ratr_bitmap &= 0x00000f00;
else if (rssi == 2)
ratr_bitmap &= 0x00000ff0;
else
ratr_bitmap &= 0x00000ff5;
break;
case WIRELESS_MODE_A:
ratr_index = RATR_INX_WIRELESS_A;
ratr_bitmap &= 0x00000ff0;
break;
case WIRELESS_MODE_N_24G:
case WIRELESS_MODE_N_5G:
ratr_index = RATR_INX_WIRELESS_NGB;
if (mimo_ps == IEEE80211_SMPS_STATIC) {
if (rssi == 1)
ratr_bitmap &= 0x00070000;
else if (rssi == 2)
ratr_bitmap &= 0x0007f000;
else
ratr_bitmap &= 0x0007f005;
} else {
if (rtlphy->rf_type == RF_1T2R ||
rtlphy->rf_type == RF_1T1R) {
if (ctx40) {
if (rssi == 1)
ratr_bitmap &= 0x000f0000;
else if (rssi == 2)
ratr_bitmap &= 0x000ff000;
else
ratr_bitmap &= 0x000ff015;
} else {
if (rssi == 1)
ratr_bitmap &= 0x000f0000;
else if (rssi == 2)
ratr_bitmap &= 0x000ff000;
else
ratr_bitmap &= 0x000ff005;
}
} else {
if (ctx40) {
if (rssi == 1)
ratr_bitmap &= 0x0f8f0000;
else if (rssi == 2)
ratr_bitmap &= 0x0f8ff000;
else
ratr_bitmap &= 0x0f8ff015;
} else {
if (rssi == 1)
ratr_bitmap &= 0x0f8f0000;
else if (rssi == 2)
ratr_bitmap &= 0x0f8ff000;
else
ratr_bitmap &= 0x0f8ff005;
}
}
}
if ((ctx40 && short40) || (!ctx40 && short20)) {
if (macid == 0)
shortgi = true;
else if (macid == 1)
shortgi = false;
}
break;
default:
ratr_index = RATR_INX_WIRELESS_NGB;
if (rtlphy->rf_type == RF_1T2R)
ratr_bitmap &= 0x000ff0ff;
else
ratr_bitmap &= 0x0f0ff0ff;
break;
}
sta_entry->ratr_index = ratr_index;
RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
"ratr_bitmap :%x\n", ratr_bitmap);
*(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) |
(ratr_index << 28);
rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
"Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n",
ratr_index, ratr_bitmap, rate_mask[0], rate_mask[1],
rate_mask[2], rate_mask[3], rate_mask[4]);
rtl88e_fill_h2c_cmd(hw, H2C_88E_RA_MASK, 5, rate_mask);
_rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0);
}
void rtl88ee_update_hal_rate_tbl(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u8 rssi)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
if (rtlpriv->dm.useramask)
rtl88ee_update_hal_rate_mask(hw, sta, rssi);
else
rtl88ee_update_hal_rate_table(hw, sta);
}
void rtl88ee_update_channel_access_setting(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
u16 sifs_timer;
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME,
(u8 *)&mac->slot_time);
if (!mac->ht_enable)
sifs_timer = 0x0a0a;
else
sifs_timer = 0x0e0e;
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer);
}
bool rtl88ee_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
enum rf_pwrstate state_toset;
u32 u4tmp;
bool actuallyset = false;
if (rtlpriv->rtlhal.being_init_adapter)
return false;
if (ppsc->swrf_processing)
return false;
spin_lock(&rtlpriv->locks.rf_ps_lock);
if (ppsc->rfchange_inprogress) {
spin_unlock(&rtlpriv->locks.rf_ps_lock);
return false;
} else {
ppsc->rfchange_inprogress = true;
spin_unlock(&rtlpriv->locks.rf_ps_lock);
}
u4tmp = rtl_read_dword(rtlpriv, REG_GPIO_OUTPUT);
state_toset = (u4tmp & BIT(31)) ? ERFON : ERFOFF;
if ((ppsc->hwradiooff == true) && (state_toset == ERFON)) {
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
"GPIOChangeRF - HW Radio ON, RF ON\n");
state_toset = ERFON;
ppsc->hwradiooff = false;
actuallyset = true;
} else if ((ppsc->hwradiooff == false) && (state_toset == ERFOFF)) {
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
"GPIOChangeRF - HW Radio OFF, RF OFF\n");
state_toset = ERFOFF;
ppsc->hwradiooff = true;
actuallyset = true;
}
if (actuallyset) {
spin_lock(&rtlpriv->locks.rf_ps_lock);
ppsc->rfchange_inprogress = false;
spin_unlock(&rtlpriv->locks.rf_ps_lock);
} else {
if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC)
RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
spin_lock(&rtlpriv->locks.rf_ps_lock);
ppsc->rfchange_inprogress = false;
spin_unlock(&rtlpriv->locks.rf_ps_lock);
}
*valid = 1;
return !ppsc->hwradiooff;
}
static void add_one_key(struct ieee80211_hw *hw, u8 *macaddr,
struct rtl_mac *mac, u32 key, u32 id,
u8 enc_algo, bool is_pairwise)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "add one entry\n");
if (is_pairwise) {
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "set Pairwise key\n");
rtl_cam_add_one_entry(hw, macaddr, key, id, enc_algo,
CAM_CONFIG_NO_USEDK,
rtlpriv->sec.key_buf[key]);
} else {
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "set group key\n");
if (mac->opmode == NL80211_IFTYPE_ADHOC) {
rtl_cam_add_one_entry(hw, rtlefuse->dev_addr,
PAIRWISE_KEYIDX,
CAM_PAIRWISE_KEY_POSITION,
enc_algo,
CAM_CONFIG_NO_USEDK,
rtlpriv->sec.key_buf[id]);
}
rtl_cam_add_one_entry(hw, macaddr, key, id, enc_algo,
CAM_CONFIG_NO_USEDK,
rtlpriv->sec.key_buf[id]);
}
}
void rtl88ee_set_key(struct ieee80211_hw *hw, u32 key,
u8 *mac_ad, bool is_group, u8 enc_algo,
bool is_wepkey, bool clear_all)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
u8 *macaddr = mac_ad;
u32 id = 0;
bool is_pairwise = false;
static u8 cam_const_addr[4][6] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
};
static u8 cam_const_broad[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
if (clear_all) {
u8 idx = 0;
u8 cam_offset = 0;
u8 clear_number = 5;
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n");
for (idx = 0; idx < clear_number; idx++) {
rtl_cam_mark_invalid(hw, cam_offset + idx);
rtl_cam_empty_entry(hw, cam_offset + idx);
if (idx < 5) {
memset(rtlpriv->sec.key_buf[idx], 0,
MAX_KEY_LEN);
rtlpriv->sec.key_len[idx] = 0;
}
}
} else {
switch (enc_algo) {
case WEP40_ENCRYPTION:
enc_algo = CAM_WEP40;
break;
case WEP104_ENCRYPTION:
enc_algo = CAM_WEP104;
break;
case TKIP_ENCRYPTION:
enc_algo = CAM_TKIP;
break;
case AESCCMP_ENCRYPTION:
enc_algo = CAM_AES;
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not processed\n");
enc_algo = CAM_TKIP;
break;
}
if (is_wepkey || rtlpriv->sec.use_defaultkey) {
macaddr = cam_const_addr[key];
id = key;
} else {
if (is_group) {
macaddr = cam_const_broad;
id = key;
} else {
if (mac->opmode == NL80211_IFTYPE_AP ||
mac->opmode == NL80211_IFTYPE_MESH_POINT) {
id = rtl_cam_get_free_entry(hw, mac_ad);
if (id >= TOTAL_CAM_ENTRY) {
RT_TRACE(rtlpriv, COMP_SEC,
DBG_EMERG,
"Can not find free hw security cam entry\n");
return;
}
} else {
id = CAM_PAIRWISE_KEY_POSITION;
}
key = PAIRWISE_KEYIDX;
is_pairwise = true;
}
}
if (rtlpriv->sec.key_len[key] == 0) {
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
"delete one entry, id is %d\n", id);
if (mac->opmode == NL80211_IFTYPE_AP ||
mac->opmode == NL80211_IFTYPE_MESH_POINT)
rtl_cam_del_entry(hw, mac_ad);
rtl_cam_delete_one_entry(hw, mac_ad, id);
} else {
add_one_key(hw, macaddr, mac, key, id, enc_algo,
is_pairwise);
}
}
}
static void rtl8188ee_bt_var_init(struct ieee80211_hw *hw)
{
struct rtl_pci_priv *rppriv = rtl_pcipriv(hw);
struct bt_coexist_info coexist = rppriv->bt_coexist;
coexist.bt_coexistence = rppriv->bt_coexist.eeprom_bt_coexist;
coexist.bt_ant_num = coexist.eeprom_bt_ant_num;
coexist.bt_coexist_type = coexist.eeprom_bt_type;
if (coexist.reg_bt_iso == 2)
coexist.bt_ant_isolation = coexist.eeprom_bt_ant_isol;
else
coexist.bt_ant_isolation = coexist.reg_bt_iso;
coexist.bt_radio_shared_type = coexist.eeprom_bt_radio_shared;
if (coexist.bt_coexistence) {
if (coexist.reg_bt_sco == 1)
coexist.bt_service = BT_OTHER_ACTION;
else if (coexist.reg_bt_sco == 2)
coexist.bt_service = BT_SCO;
else if (coexist.reg_bt_sco == 4)
coexist.bt_service = BT_BUSY;
else if (coexist.reg_bt_sco == 5)
coexist.bt_service = BT_OTHERBUSY;
else
coexist.bt_service = BT_IDLE;
coexist.bt_edca_ul = 0;
coexist.bt_edca_dl = 0;
coexist.bt_rssi_state = 0xff;
}
}
void rtl8188ee_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
bool auto_load_fail, u8 *hwinfo)
{
rtl8188ee_bt_var_init(hw);
}
void rtl8188ee_bt_reg_init(struct ieee80211_hw *hw)
{
struct rtl_pci_priv *rppriv = rtl_pcipriv(hw);
/* 0:Low, 1:High, 2:From Efuse. */
rppriv->bt_coexist.reg_bt_iso = 2;
/* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */
rppriv->bt_coexist.reg_bt_sco = 3;
/* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */
rppriv->bt_coexist.reg_bt_sco = 0;
}
void rtl8188ee_bt_hw_init(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_pci_priv *rppriv = rtl_pcipriv(hw);
struct bt_coexist_info coexist = rppriv->bt_coexist;
u8 u1_tmp;
if (coexist.bt_coexistence &&
((coexist.bt_coexist_type == BT_CSR_BC4) ||
coexist.bt_coexist_type == BT_CSR_BC8)) {
if (coexist.bt_ant_isolation)
rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
u1_tmp = rtl_read_byte(rtlpriv, 0x4fd) &
BIT_OFFSET_LEN_MASK_32(0, 1);
u1_tmp = u1_tmp | ((coexist.bt_ant_isolation == 1) ?
0 : BIT_OFFSET_LEN_MASK_32(1, 1)) |
((coexist.bt_service == BT_SCO) ?
0 : BIT_OFFSET_LEN_MASK_32(2, 1));
rtl_write_byte(rtlpriv, 0x4fd, u1_tmp);
rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+4, 0xaaaa9aaa);
rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+8, 0xffbd0040);
rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+0xc, 0x40000010);
/* Config to 1T1R. */
if (rtlphy->rf_type == RF_1T1R) {
u1_tmp = rtl_read_byte(rtlpriv, ROFDM0_TRXPATHENABLE);
u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1));
rtl_write_byte(rtlpriv, ROFDM0_TRXPATHENABLE, u1_tmp);
u1_tmp = rtl_read_byte(rtlpriv, ROFDM1_TRXPATHENABLE);
u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1));
rtl_write_byte(rtlpriv, ROFDM1_TRXPATHENABLE, u1_tmp);
}
}
}
void rtl88ee_suspend(struct ieee80211_hw *hw)
{
}
void rtl88ee_resume(struct ieee80211_hw *hw)
{
}
/* Turn on AAP (RCR:bit 0) for promicuous mode. */
void rtl88ee_allow_all_destaddr(struct ieee80211_hw *hw,
bool allow_all_da, bool write_into_reg)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
if (allow_all_da) /* Set BIT0 */
rtlpci->receive_config |= RCR_AAP;
else /* Clear BIT0 */
rtlpci->receive_config &= ~RCR_AAP;
if (write_into_reg)
rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD,
"receive_config = 0x%08X, write_into_reg =%d\n",
rtlpci->receive_config, write_into_reg);
}
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __RTL92CE_HW_H__
#define __RTL92CE_HW_H__
void rtl88ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
void rtl88ee_read_eeprom_info(struct ieee80211_hw *hw);
void rtl88ee_interrupt_recognized(struct ieee80211_hw *hw,
u32 *p_inta, u32 *p_intb);
int rtl88ee_hw_init(struct ieee80211_hw *hw);
void rtl88ee_card_disable(struct ieee80211_hw *hw);
void rtl88ee_enable_interrupt(struct ieee80211_hw *hw);
void rtl88ee_disable_interrupt(struct ieee80211_hw *hw);
int rtl88ee_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type);
void rtl88ee_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
void rtl88ee_set_qos(struct ieee80211_hw *hw, int aci);
void rtl88ee_set_beacon_related_registers(struct ieee80211_hw *hw);
void rtl88ee_set_beacon_interval(struct ieee80211_hw *hw);
void rtl88ee_update_interrupt_mask(struct ieee80211_hw *hw,
u32 add_msr, u32 rm_msr);
void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
void rtl88ee_update_hal_rate_tbl(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u8 rssi_level);
void rtl88ee_update_channel_access_setting(struct ieee80211_hw *hw);
bool rtl88ee_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid);
void rtl88ee_enable_hw_security_config(struct ieee80211_hw *hw);
void rtl88ee_set_key(struct ieee80211_hw *hw, u32 key_index,
u8 *p_macaddr, bool is_group, u8 enc_algo,
bool is_wepkey, bool clear_all);
void rtl8188ee_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
bool autoload_fail, u8 *hwinfo);
void rtl8188ee_bt_reg_init(struct ieee80211_hw *hw);
void rtl8188ee_bt_hw_init(struct ieee80211_hw *hw);
void rtl88ee_suspend(struct ieee80211_hw *hw);
void rtl88ee_resume(struct ieee80211_hw *hw);
void rtl88ee_allow_all_destaddr(struct ieee80211_hw *hw,
bool allow_all_da, bool write_into_reg);
void rtl88ee_fw_clk_off_timer_callback(unsigned long data);
#endif
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "wifi.h"
#include "pci.h"
#include "reg.h"
#include "led.h"
static void rtl88ee_init_led(struct ieee80211_hw *hw,
struct rtl_led *pled, enum rtl_led_pin ledpin)
{
pled->hw = hw;
pled->ledpin = ledpin;
pled->ledon = false;
}
void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
{
u8 ledcfg;
struct rtl_priv *rtlpriv = rtl_priv(hw);
RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
"LedAddr:%X ledpin =%d\n", REG_LEDCFG2, pled->ledpin);
switch (pled->ledpin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
rtl_write_byte(rtlpriv, REG_LEDCFG2,
(ledcfg & 0xf0) | BIT(5) | BIT(6));
break;
case LED_PIN_LED1:
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1);
rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10);
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not processed\n");
break;
}
pled->ledon = true;
}
void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
u8 ledcfg;
u8 val;
RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
"LedAddr:%X ledpin =%d\n", REG_LEDCFG2, pled->ledpin);
switch (pled->ledpin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
ledcfg &= 0xf0;
val = ledcfg | BIT(3) | BIT(5) | BIT(6);
if (pcipriv->ledctl.led_opendrain == true) {
rtl_write_byte(rtlpriv, REG_LEDCFG2, val);
ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG);
val = ledcfg & 0xFE;
rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, val);
} else {
rtl_write_byte(rtlpriv, REG_LEDCFG2, val);
}
break;
case LED_PIN_LED1:
ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1);
ledcfg &= 0x10;
rtl_write_byte(rtlpriv, REG_LEDCFG1, (ledcfg | BIT(3)));
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not processed\n");
break;
}
pled->ledon = false;
}
void rtl88ee_init_sw_leds(struct ieee80211_hw *hw)
{
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
rtl88ee_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0);
rtl88ee_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1);
}
static void rtl88ee_sw_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0);
switch (ledaction) {
case LED_CTL_POWER_ON:
case LED_CTL_LINK:
case LED_CTL_NO_LINK:
rtl88ee_sw_led_on(hw, pLed0);
break;
case LED_CTL_POWER_OFF:
rtl88ee_sw_led_off(hw, pLed0);
break;
default:
break;
}
}
void rtl88ee_led_control(struct ieee80211_hw *hw,
enum led_ctl_mode ledaction)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) &&
(ledaction == LED_CTL_TX ||
ledaction == LED_CTL_RX ||
ledaction == LED_CTL_SITE_SURVEY ||
ledaction == LED_CTL_LINK ||
ledaction == LED_CTL_NO_LINK ||
ledaction == LED_CTL_START_TO_LINK ||
ledaction == LED_CTL_POWER_ON)) {
return;
}
RT_TRACE(rtlpriv, COMP_LED, DBG_TRACE, "ledaction %d,\n",
ledaction);
rtl88ee_sw_led_control(hw, ledaction);
}
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __RTL92CE_LED_H__
#define __RTL92CE_LED_H__
void rtl88ee_init_sw_leds(struct ieee80211_hw *hw);
void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
void rtl88ee_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
#endif
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "wifi.h"
#include "pci.h"
#include "ps.h"
#include "reg.h"
#include "def.h"
#include "phy.h"
#include "rf.h"
#include "dm.h"
#include "table.h"
static void set_baseband_phy_config(struct ieee80211_hw *hw);
static void set_baseband_agc_config(struct ieee80211_hw *hw);
static void store_pwrindex_offset(struct ieee80211_hw *hw,
u32 regaddr, u32 bitmask,
u32 data);
static bool check_cond(struct ieee80211_hw *hw, const u32 condition);
static u32 rf_serial_read(struct ieee80211_hw *hw,
enum radio_path rfpath, u32 offset)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct bb_reg_def *phreg = &rtlphy->phyreg_def[rfpath];
u32 newoffset;
u32 tmplong, tmplong2;
u8 rfpi_enable = 0;
u32 ret;
int jj = RF90_PATH_A;
int kk = RF90_PATH_B;
offset &= 0xff;
newoffset = offset;
if (RT_CANNOT_IO(hw)) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "return all one\n");
return 0xFFFFFFFF;
}
tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD);
if (rfpath == jj)
tmplong2 = tmplong;
else
tmplong2 = rtl_get_bbreg(hw, phreg->rfhssi_para2, MASKDWORD);
tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) |
(newoffset << 23) | BLSSIREADEDGE;
rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD,
tmplong & (~BLSSIREADEDGE));
mdelay(1);
rtl_set_bbreg(hw, phreg->rfhssi_para2, MASKDWORD, tmplong2);
mdelay(2);
if (rfpath == jj)
rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1,
BIT(8));
else if (rfpath == kk)
rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1,
BIT(8));
if (rfpi_enable)
ret = rtl_get_bbreg(hw, phreg->rf_rbpi, BLSSIREADBACKDATA);
else
ret = rtl_get_bbreg(hw, phreg->rf_rb, BLSSIREADBACKDATA);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]= 0x%x\n",
rfpath, phreg->rf_rb, ret);
return ret;
}
static void rf_serial_write(struct ieee80211_hw *hw,
enum radio_path rfpath, u32 offset,
u32 data)
{
u32 data_and_addr;
u32 newoffset;
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct bb_reg_def *phreg = &rtlphy->phyreg_def[rfpath];
if (RT_CANNOT_IO(hw)) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "stop\n");
return;
}
offset &= 0xff;
newoffset = offset;
data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff;
rtl_set_bbreg(hw, phreg->rf3wire_offset, MASKDWORD, data_and_addr);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFW-%d Addr[0x%x]= 0x%x\n",
rfpath, phreg->rf3wire_offset, data_and_addr);
}
static u32 cal_bit_shift(u32 bitmask)
{
u32 i;
for (i = 0; i <= 31; i++) {
if (((bitmask >> i) & 0x1) == 1)
break;
}
return i;
}
static bool config_bb_with_header(struct ieee80211_hw *hw,
u8 configtype)
{
if (configtype == BASEBAND_CONFIG_PHY_REG)
set_baseband_phy_config(hw);
else if (configtype == BASEBAND_CONFIG_AGC_TAB)
set_baseband_agc_config(hw);
return true;
}
static bool config_bb_with_pgheader(struct ieee80211_hw *hw,
u8 configtype)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
int i;
u32 *table_pg;
u16 tbl_page_len;
u32 v1 = 0, v2 = 0;
tbl_page_len = RTL8188EEPHY_REG_ARRAY_PGLEN;
table_pg = RTL8188EEPHY_REG_ARRAY_PG;
if (configtype == BASEBAND_CONFIG_PHY_REG) {
for (i = 0; i < tbl_page_len; i = i + 3) {
v1 = table_pg[i];
v2 = table_pg[i + 1];
if (v1 < 0xcdcdcdcd) {
if (table_pg[i] == 0xfe)
mdelay(50);
else if (table_pg[i] == 0xfd)
mdelay(5);
else if (table_pg[i] == 0xfc)
mdelay(1);
else if (table_pg[i] == 0xfb)
udelay(50);
else if (table_pg[i] == 0xfa)
udelay(5);
else if (table_pg[i] == 0xf9)
udelay(1);
store_pwrindex_offset(hw, table_pg[i],
table_pg[i + 1],
table_pg[i + 2]);
continue;
} else {
if (!check_cond(hw, table_pg[i])) {
/*don't need the hw_body*/
i += 2; /* skip the pair of expression*/
v1 = table_pg[i];
v2 = table_pg[i + 1];
while (v2 != 0xDEAD) {
i += 3;
v1 = table_pg[i];
v2 = table_pg[i + 1];
}
}
}
}
} else {
RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
"configtype != BaseBand_Config_PHY_REG\n");
}
return true;
}
static bool config_parafile(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw));
bool rtstatus;
rtstatus = config_bb_with_header(hw, BASEBAND_CONFIG_PHY_REG);
if (rtstatus != true) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!");
return false;
}
if (fuse->autoload_failflag == false) {
rtlphy->pwrgroup_cnt = 0;
rtstatus = config_bb_with_pgheader(hw, BASEBAND_CONFIG_PHY_REG);
}
if (rtstatus != true) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!");
return false;
}
rtstatus = config_bb_with_header(hw, BASEBAND_CONFIG_AGC_TAB);
if (rtstatus != true) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n");
return false;
}
rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw,
RFPGA0_XA_HSSIPARAMETER2, 0x200));
return true;
}
static void rtl88e_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
int jj = RF90_PATH_A;
int kk = RF90_PATH_B;
rtlphy->phyreg_def[jj].rfintfs = RFPGA0_XAB_RFINTERFACESW;
rtlphy->phyreg_def[kk].rfintfs = RFPGA0_XAB_RFINTERFACESW;
rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW;
rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW;
rtlphy->phyreg_def[jj].rfintfi = RFPGA0_XAB_RFINTERFACERB;
rtlphy->phyreg_def[kk].rfintfi = RFPGA0_XAB_RFINTERFACERB;
rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB;
rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB;
rtlphy->phyreg_def[jj].rfintfo = RFPGA0_XA_RFINTERFACEOE;
rtlphy->phyreg_def[kk].rfintfo = RFPGA0_XB_RFINTERFACEOE;
rtlphy->phyreg_def[jj].rfintfe = RFPGA0_XA_RFINTERFACEOE;
rtlphy->phyreg_def[kk].rfintfe = RFPGA0_XB_RFINTERFACEOE;
rtlphy->phyreg_def[jj].rf3wire_offset = RFPGA0_XA_LSSIPARAMETER;
rtlphy->phyreg_def[kk].rf3wire_offset = RFPGA0_XB_LSSIPARAMETER;
rtlphy->phyreg_def[jj].rflssi_select = rFPGA0_XAB_RFPARAMETER;
rtlphy->phyreg_def[kk].rflssi_select = rFPGA0_XAB_RFPARAMETER;
rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = rFPGA0_XCD_RFPARAMETER;
rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = rFPGA0_XCD_RFPARAMETER;
rtlphy->phyreg_def[jj].rftxgain_stage = RFPGA0_TXGAINSTAGE;
rtlphy->phyreg_def[kk].rftxgain_stage = RFPGA0_TXGAINSTAGE;
rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE;
rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE;
rtlphy->phyreg_def[jj].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1;
rtlphy->phyreg_def[kk].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1;
rtlphy->phyreg_def[jj].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2;
rtlphy->phyreg_def[kk].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2;
rtlphy->phyreg_def[jj].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
rtlphy->phyreg_def[kk].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL;
rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL;
rtlphy->phyreg_def[jj].rfagc_control1 = ROFDM0_XAAGCCORE1;
rtlphy->phyreg_def[kk].rfagc_control1 = ROFDM0_XBAGCCORE1;
rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1;
rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1;
rtlphy->phyreg_def[jj].rfagc_control2 = ROFDM0_XAAGCCORE2;
rtlphy->phyreg_def[kk].rfagc_control2 = ROFDM0_XBAGCCORE2;
rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2;
rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2;
rtlphy->phyreg_def[jj].rfrxiq_imbal = ROFDM0_XARXIQIMBAL;
rtlphy->phyreg_def[kk].rfrxiq_imbal = ROFDM0_XBRXIQIMBAL;
rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBAL;
rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBAL;
rtlphy->phyreg_def[jj].rfrx_afe = ROFDM0_XARXAFE;
rtlphy->phyreg_def[kk].rfrx_afe = ROFDM0_XBRXAFE;
rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE;
rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
rtlphy->phyreg_def[jj].rftxiq_imbal = ROFDM0_XATXIQIMBAL;
rtlphy->phyreg_def[kk].rftxiq_imbal = ROFDM0_XBTXIQIMBAL;
rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBAL;
rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBAL;
rtlphy->phyreg_def[jj].rftx_afe = ROFDM0_XATXAFE;
rtlphy->phyreg_def[kk].rftx_afe = ROFDM0_XBTXAFE;
rtlphy->phyreg_def[jj].rf_rb = RFPGA0_XA_LSSIREADBACK;
rtlphy->phyreg_def[kk].rf_rb = RFPGA0_XB_LSSIREADBACK;
rtlphy->phyreg_def[jj].rf_rbpi = TRANSCEIVEA_HSPI_READBACK;
rtlphy->phyreg_def[kk].rf_rbpi = TRANSCEIVEB_HSPI_READBACK;
}
static bool rtl88e_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
u32 cmdtableidx, u32 cmdtablesz,
enum swchnlcmd_id cmdid,
u32 para1, u32 para2, u32 msdelay)
{
struct swchnlcmd *pcmd;
if (cmdtable == NULL) {
RT_ASSERT(false, "cmdtable cannot be NULL.\n");
return false;
}
if (cmdtableidx >= cmdtablesz)
return false;
pcmd = cmdtable + cmdtableidx;
pcmd->cmdid = cmdid;
pcmd->para1 = para1;
pcmd->para2 = para2;
pcmd->msdelay = msdelay;
return true;
}
static bool chnl_step_by_step(struct ieee80211_hw *hw,
u8 channel, u8 *stage, u8 *step,
u32 *delay)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct swchnlcmd precommoncmd[MAX_PRECMD_CNT];
u32 precommoncmdcnt;
struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT];
u32 postcommoncmdcnt;
struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT];
u32 rfdependcmdcnt;
struct swchnlcmd *currentcmd = NULL;
u8 rfpath;
u8 num_total_rfpath = rtlphy->num_total_rfpath;
precommoncmdcnt = 0;
rtl88e_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
MAX_PRECMD_CNT,
CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0);
rtl88e_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
MAX_PRECMD_CNT, CMDID_END, 0, 0, 0);
postcommoncmdcnt = 0;
rtl88e_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++,
MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0);
rfdependcmdcnt = 0;
RT_ASSERT((channel >= 1 && channel <= 14),
"illegal channel for Zebra: %d\n", channel);
rtl88e_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG,
RF_CHNLBW, channel, 10);
rtl88e_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0,
0);
do {
switch (*stage) {
case 0:
currentcmd = &precommoncmd[*step];
break;
case 1:
currentcmd = &rfdependcmd[*step];
break;
case 2:
currentcmd = &postcommoncmd[*step];
break;
}
if (currentcmd->cmdid == CMDID_END) {
if ((*stage) == 2) {
return true;
} else {
(*stage)++;
(*step) = 0;
continue;
}
}
switch (currentcmd->cmdid) {
case CMDID_SET_TXPOWEROWER_LEVEL:
rtl88e_phy_set_txpower_level(hw, channel);
break;
case CMDID_WRITEPORT_ULONG:
rtl_write_dword(rtlpriv, currentcmd->para1,
currentcmd->para2);
break;
case CMDID_WRITEPORT_USHORT:
rtl_write_word(rtlpriv, currentcmd->para1,
(u16) currentcmd->para2);
break;
case CMDID_WRITEPORT_UCHAR:
rtl_write_byte(rtlpriv, currentcmd->para1,
(u8) currentcmd->para2);
break;
case CMDID_RF_WRITEREG:
for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) {
rtlphy->rfreg_chnlval[rfpath] =
((rtlphy->rfreg_chnlval[rfpath] &
0xfffffc00) | currentcmd->para2);
rtl_set_rfreg(hw, (enum radio_path)rfpath,
currentcmd->para1,
RFREG_OFFSET_MASK,
rtlphy->rfreg_chnlval[rfpath]);
}
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not processed\n");
break;
}
break;
} while (true);
(*delay) = currentcmd->msdelay;
(*step)++;
return false;
}
static long rtl88e_pwr_idx_dbm(struct ieee80211_hw *hw,
enum wireless_mode wirelessmode,
u8 txpwridx)
{
long offset;
long pwrout_dbm;
switch (wirelessmode) {
case WIRELESS_MODE_B:
offset = -7;
break;
case WIRELESS_MODE_G:
case WIRELESS_MODE_N_24G:
offset = -8;
break;
default:
offset = -8;
break;
}
pwrout_dbm = txpwridx / 2 + offset;
return pwrout_dbm;
}
static void rtl88e_phy_set_io(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
"--->Cmd(%#x), set_io_inprogress(%d)\n",
rtlphy->current_io_type, rtlphy->set_io_inprogress);
switch (rtlphy->current_io_type) {
case IO_CMD_RESUME_DM_BY_SCAN:
dm_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1;
/*rtl92c_dm_write_dig(hw);*/
rtl88e_phy_set_txpower_level(hw, rtlphy->current_channel);
rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x83);
break;
case IO_CMD_PAUSE_DM_BY_SCAN:
rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue;
dm_digtable->cur_igvalue = 0x17;
rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x40);
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not processed\n");
break;
}
rtlphy->set_io_inprogress = false;
RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
"(%#x)\n", rtlphy->current_io_type);
}
u32 rtl88e_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 returnvalue, originalvalue, bitshift;
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
"regaddr(%#x), bitmask(%#x)\n", regaddr, bitmask);
originalvalue = rtl_read_dword(rtlpriv, regaddr);
bitshift = cal_bit_shift(bitmask);
returnvalue = (originalvalue & bitmask) >> bitshift;
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
"BBR MASK = 0x%x Addr[0x%x]= 0x%x\n", bitmask,
regaddr, originalvalue);
return returnvalue;
}
void rtl88e_phy_set_bb_reg(struct ieee80211_hw *hw,
u32 regaddr, u32 bitmask, u32 data)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 originalvalue, bitshift;
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
"regaddr(%#x), bitmask(%#x),data(%#x)\n",
regaddr, bitmask, data);
if (bitmask != MASKDWORD) {
originalvalue = rtl_read_dword(rtlpriv, regaddr);
bitshift = cal_bit_shift(bitmask);
data = ((originalvalue & (~bitmask)) | (data << bitshift));
}
rtl_write_dword(rtlpriv, regaddr, data);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
"regaddr(%#x), bitmask(%#x), data(%#x)\n",
regaddr, bitmask, data);
}
u32 rtl88e_phy_query_rf_reg(struct ieee80211_hw *hw,
enum radio_path rfpath, u32 regaddr, u32 bitmask)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 original_value, readback_value, bitshift;
unsigned long flags;
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
"regaddr(%#x), rfpath(%#x), bitmask(%#x)\n",
regaddr, rfpath, bitmask);
spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
original_value = rf_serial_read(hw, rfpath, regaddr);
bitshift = cal_bit_shift(bitmask);
readback_value = (original_value & bitmask) >> bitshift;
spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
"regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n",
regaddr, rfpath, bitmask, original_value);
return readback_value;
}
void rtl88e_phy_set_rf_reg(struct ieee80211_hw *hw,
enum radio_path rfpath,
u32 regaddr, u32 bitmask, u32 data)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 original_value, bitshift;
unsigned long flags;
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
"regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
regaddr, bitmask, data, rfpath);
spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
if (bitmask != RFREG_OFFSET_MASK) {
original_value = rf_serial_read(hw, rfpath, regaddr);
bitshift = cal_bit_shift(bitmask);
data = ((original_value & (~bitmask)) |
(data << bitshift));
}
rf_serial_write(hw, rfpath, regaddr, data);
spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
"regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
regaddr, bitmask, data, rfpath);
}
static bool config_mac_with_header(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 i;
u32 arraylength;
u32 *ptrarray;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl8188EMACPHY_Array\n");
arraylength = RTL8188EEMAC_1T_ARRAYLEN;
ptrarray = RTL8188EEMAC_1T_ARRAY;
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"Img:RTL8188EEMAC_1T_ARRAY LEN %d\n", arraylength);
for (i = 0; i < arraylength; i = i + 2)
rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]);
return true;
}
bool rtl88e_phy_mac_config(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
bool rtstatus = config_mac_with_header(hw);
rtl_write_byte(rtlpriv, 0x04CA, 0x0B);
return rtstatus;
}
bool rtl88e_phy_bb_config(struct ieee80211_hw *hw)
{
bool rtstatus = true;
struct rtl_priv *rtlpriv = rtl_priv(hw);
u16 regval;
u8 reg_hwparafile = 1;
u32 tmp;
rtl88e_phy_init_bb_rf_register_definition(hw);
regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
rtl_write_word(rtlpriv, REG_SYS_FUNC_EN,
regval | BIT(13) | BIT(0) | BIT(1));
rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB);
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN,
FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE |
FEN_BB_GLB_RSTN | FEN_BBRSTB);
tmp = rtl_read_dword(rtlpriv, 0x4c);
rtl_write_dword(rtlpriv, 0x4c, tmp | BIT(23));
if (reg_hwparafile == 1)
rtstatus = config_parafile(hw);
return rtstatus;
}
bool rtl88e_phy_rf_config(struct ieee80211_hw *hw)
{
return rtl88e_phy_rf6052_config(hw);
}
static bool check_cond(struct ieee80211_hw *hw,
const u32 condition)
{
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw));
u32 _board = fuse->board_type; /*need efuse define*/
u32 _interface = rtlhal->interface;
u32 _platform = 0x08;/*SupportPlatform */
u32 cond = condition;
if (condition == 0xCDCDCDCD)
return true;
cond = condition & 0xFF;
if ((_board & cond) == 0 && cond != 0x1F)
return false;
cond = condition & 0xFF00;
cond = cond >> 8;
if ((_interface & cond) == 0 && cond != 0x07)
return false;
cond = condition & 0xFF0000;
cond = cond >> 16;
if ((_platform & cond) == 0 && cond != 0x0F)
return false;
return true;
}
static void _rtl8188e_config_rf_reg(struct ieee80211_hw *hw,
u32 addr, u32 data, enum radio_path rfpath,
u32 regaddr)
{
if (addr == 0xffe) {
mdelay(50);
} else if (addr == 0xfd) {
mdelay(5);
} else if (addr == 0xfc) {
mdelay(1);
} else if (addr == 0xfb) {
udelay(50);
} else if (addr == 0xfa) {
udelay(5);
} else if (addr == 0xf9) {
udelay(1);
} else {
rtl_set_rfreg(hw, rfpath, regaddr,
RFREG_OFFSET_MASK,
data);
udelay(1);
}
}
static void rtl88_config_s(struct ieee80211_hw *hw,
u32 addr, u32 data)
{
u32 content = 0x1000; /*RF Content: radio_a_txt*/
u32 maskforphyset = (u32)(content & 0xE000);
_rtl8188e_config_rf_reg(hw, addr, data, RF90_PATH_A,
addr | maskforphyset);
}
static void _rtl8188e_config_bb_reg(struct ieee80211_hw *hw,
u32 addr, u32 data)
{
if (addr == 0xfe) {
mdelay(50);
} else if (addr == 0xfd) {
mdelay(5);
} else if (addr == 0xfc) {
mdelay(1);
} else if (addr == 0xfb) {
udelay(50);
} else if (addr == 0xfa) {
udelay(5);
} else if (addr == 0xf9) {
udelay(1);
} else {
rtl_set_bbreg(hw, addr, MASKDWORD, data);
udelay(1);
}
}
#define NEXT_PAIR(v1, v2, i) \
do { \
i += 2; v1 = array_table[i]; \
v2 = array_table[i + 1]; \
} while (0)
static void set_baseband_agc_config(struct ieee80211_hw *hw)
{
int i;
u32 *array_table;
u16 arraylen;
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 v1 = 0, v2 = 0;
arraylen = RTL8188EEAGCTAB_1TARRAYLEN;
array_table = RTL8188EEAGCTAB_1TARRAY;
for (i = 0; i < arraylen; i += 2) {
v1 = array_table[i];
v2 = array_table[i + 1];
if (v1 < 0xCDCDCDCD) {
rtl_set_bbreg(hw, array_table[i], MASKDWORD,
array_table[i + 1]);
udelay(1);
continue;
} else {/*This line is the start line of branch.*/
if (!check_cond(hw, array_table[i])) {
/*Discard the following (offset, data) pairs*/
NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD && v2 != 0xCDEF &&
v2 != 0xCDCD && i < arraylen - 2) {
NEXT_PAIR(v1, v2, i);
}
i -= 2; /* compensate for loop's += 2*/
} else {
/* Configure matched pairs and skip to end */
NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD && v2 != 0xCDEF &&
v2 != 0xCDCD && i < arraylen - 2) {
rtl_set_bbreg(hw, array_table[i],
MASKDWORD,
array_table[i + 1]);
udelay(1);
NEXT_PAIR(v1, v2, i);
}
while (v2 != 0xDEAD && i < arraylen - 2)
NEXT_PAIR(v1, v2, i);
}
}
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"The agctab_array_table[0] is %x Rtl818EEPHY_REGArray[1] is %x\n",
array_table[i],
array_table[i + 1]);
}
}
static void set_baseband_phy_config(struct ieee80211_hw *hw)
{
int i;
u32 *array_table;
u16 arraylen;
u32 v1 = 0, v2 = 0;
arraylen = RTL8188EEPHY_REG_1TARRAYLEN;
array_table = RTL8188EEPHY_REG_1TARRAY;
for (i = 0; i < arraylen; i += 2) {
v1 = array_table[i];
v2 = array_table[i + 1];
if (v1 < 0xcdcdcdcd) {
_rtl8188e_config_bb_reg(hw, v1, v2);
} else {/*This line is the start line of branch.*/
if (!check_cond(hw, array_table[i])) {
/*Discard the following (offset, data) pairs*/
NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < arraylen - 2)
NEXT_PAIR(v1, v2, i);
i -= 2; /* prevent from for-loop += 2*/
} else {
/* Configure matched pairs and skip to end */
NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < arraylen - 2) {
_rtl8188e_config_bb_reg(hw, v1, v2);
NEXT_PAIR(v1, v2, i);
}
while (v2 != 0xDEAD && i < arraylen - 2)
NEXT_PAIR(v1, v2, i);
}
}
}
}
static void store_pwrindex_offset(struct ieee80211_hw *hw,
u32 regaddr, u32 bitmask,
u32 data)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
if (regaddr == RTXAGC_A_RATE18_06) {
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][0] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n",
rtlphy->pwrgroup_cnt,
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][0]);
}
if (regaddr == RTXAGC_A_RATE54_24) {
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][1] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n",
rtlphy->pwrgroup_cnt,
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][1]);
}
if (regaddr == RTXAGC_A_CCK1_MCS32) {
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][6] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n",
rtlphy->pwrgroup_cnt,
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][6]);
}
if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) {
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][7] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n",
rtlphy->pwrgroup_cnt,
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][7]);
}
if (regaddr == RTXAGC_A_MCS03_MCS00) {
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][2] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n",
rtlphy->pwrgroup_cnt,
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][2]);
}
if (regaddr == RTXAGC_A_MCS07_MCS04) {
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][3] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n",
rtlphy->pwrgroup_cnt,
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][3]);
}
if (regaddr == RTXAGC_A_MCS11_MCS08) {
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][4] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n",
rtlphy->pwrgroup_cnt,
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][4]);
}
if (regaddr == RTXAGC_A_MCS15_MCS12) {
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][5] = data;
if (get_rf_type(rtlphy) == RF_1T1R)
rtlphy->pwrgroup_cnt++;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n",
rtlphy->pwrgroup_cnt,
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][5]);
}
if (regaddr == RTXAGC_B_RATE18_06) {
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][8] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n",
rtlphy->pwrgroup_cnt,
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][8]);
}
if (regaddr == RTXAGC_B_RATE54_24) {
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][9] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n",
rtlphy->pwrgroup_cnt,
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][9]);
}
if (regaddr == RTXAGC_B_CCK1_55_MCS32) {
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][14] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n",
rtlphy->pwrgroup_cnt,
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][14]);
}
if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) {
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][15] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n",
rtlphy->pwrgroup_cnt,
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][15]);
}
if (regaddr == RTXAGC_B_MCS03_MCS00) {
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][10] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n",
rtlphy->pwrgroup_cnt,
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][10]);
}
if (regaddr == RTXAGC_B_MCS07_MCS04) {
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][11] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n",
rtlphy->pwrgroup_cnt,
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][11]);
}
if (regaddr == RTXAGC_B_MCS11_MCS08) {
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][12] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n",
rtlphy->pwrgroup_cnt,
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][12]);
}
if (regaddr == RTXAGC_B_MCS15_MCS12) {
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][13] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n",
rtlphy->pwrgroup_cnt,
rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][13]);
if (get_rf_type(rtlphy) != RF_1T1R)
rtlphy->pwrgroup_cnt++;
}
}
#define READ_NEXT_RF_PAIR(v1, v2, i) \
do { \
i += 2; v1 = a_table[i]; \
v2 = a_table[i + 1]; \
} while (0)
bool rtl88e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
enum radio_path rfpath)
{
int i;
u32 *a_table;
u16 a_len;
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
u32 v1 = 0, v2 = 0;
a_len = RTL8188EE_RADIOA_1TARRAYLEN;
a_table = RTL8188EE_RADIOA_1TARRAY;
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"Radio_A:RTL8188EE_RADIOA_1TARRAY %d\n", a_len);
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath);
switch (rfpath) {
case RF90_PATH_A:
for (i = 0; i < a_len; i = i + 2) {
v1 = a_table[i];
v2 = a_table[i + 1];
if (v1 < 0xcdcdcdcd) {
rtl88_config_s(hw, v1, v2);
} else {/*This line is the start line of branch.*/
if (!check_cond(hw, a_table[i])) {
/* Discard the following (offset, data)
* pairs
*/
READ_NEXT_RF_PAIR(v1, v2, i);
while (v2 != 0xDEAD && v2 != 0xCDEF &&
v2 != 0xCDCD && i < a_len - 2)
READ_NEXT_RF_PAIR(v1, v2, i);
i -= 2; /* prevent from for-loop += 2*/
} else {
/* Configure matched pairs and skip to
* end of if-else.
*/
READ_NEXT_RF_PAIR(v1, v2, i);
while (v2 != 0xDEAD && v2 != 0xCDEF &&
v2 != 0xCDCD && i < a_len - 2) {
rtl88_config_s(hw, v1, v2);
READ_NEXT_RF_PAIR(v1, v2, i);
}
while (v2 != 0xDEAD && i < a_len - 2)
READ_NEXT_RF_PAIR(v1, v2, i);
}
}
}
if (rtlhal->oem_id == RT_CID_819x_HP)
rtl88_config_s(hw, 0x52, 0x7E4BD);
break;
case RF90_PATH_B:
case RF90_PATH_C:
case RF90_PATH_D:
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not processed\n");
break;
}
return true;
}
void rtl88e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
rtlphy->default_initialgain[0] = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1,
MASKBYTE0);
rtlphy->default_initialgain[1] = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1,
MASKBYTE0);
rtlphy->default_initialgain[2] = rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1,
MASKBYTE0);
rtlphy->default_initialgain[3] = rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1,
MASKBYTE0);
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"Default initial gain (c50 = 0x%x, c58 = 0x%x, c60 = 0x%x, c68 = 0x%x\n",
rtlphy->default_initialgain[0],
rtlphy->default_initialgain[1],
rtlphy->default_initialgain[2],
rtlphy->default_initialgain[3]);
rtlphy->framesync = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3,
MASKBYTE0);
rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2,
MASKDWORD);
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"Default framesync (0x%x) = 0x%x\n",
ROFDM0_RXDETECTOR3, rtlphy->framesync);
}
void rtl88e_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
u8 level;
long dbm;
level = rtlphy->cur_cck_txpwridx;
dbm = rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_B, level);
level = rtlphy->cur_ofdm24g_txpwridx;
if (rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_G, level) > dbm)
dbm = rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_G, level);
level = rtlphy->cur_ofdm24g_txpwridx;
if (rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_N_24G, level) > dbm)
dbm = rtl88e_pwr_idx_dbm(hw, WIRELESS_MODE_N_24G, level);
*powerlevel = dbm;
}
static void _rtl88e_get_txpower_index(struct ieee80211_hw *hw, u8 channel,
u8 *cckpower, u8 *ofdm, u8 *bw20_pwr,
u8 *bw40_pwr)
{
struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw));
u8 i = (channel - 1);
u8 rf_path = 0;
int jj = RF90_PATH_A;
int kk = RF90_PATH_B;
for (rf_path = 0; rf_path < 2; rf_path++) {
if (rf_path == jj) {
cckpower[jj] = fuse->txpwrlevel_cck[jj][i];
if (fuse->txpwr_ht20diff[jj][i] > 0x0f) /*-8~7 */
bw20_pwr[jj] = fuse->txpwrlevel_ht40_1s[jj][i] -
(~(fuse->txpwr_ht20diff[jj][i]) + 1);
else
bw20_pwr[jj] = fuse->txpwrlevel_ht40_1s[jj][i] +
fuse->txpwr_ht20diff[jj][i];
if (fuse->txpwr_legacyhtdiff[jj][i] > 0xf)
ofdm[jj] = fuse->txpwrlevel_ht40_1s[jj][i] -
(~(fuse->txpwr_legacyhtdiff[jj][i])+1);
else
ofdm[jj] = fuse->txpwrlevel_ht40_1s[jj][i] +
fuse->txpwr_legacyhtdiff[jj][i];
bw40_pwr[jj] = fuse->txpwrlevel_ht40_1s[jj][i];
} else if (rf_path == kk) {
cckpower[kk] = fuse->txpwrlevel_cck[kk][i];
bw20_pwr[kk] = fuse->txpwrlevel_ht40_1s[kk][i] +
fuse->txpwr_ht20diff[kk][i];
ofdm[kk] = fuse->txpwrlevel_ht40_1s[kk][i] +
fuse->txpwr_legacyhtdiff[kk][i];
bw40_pwr[kk] = fuse->txpwrlevel_ht40_1s[kk][i];
}
}
}
static void _rtl88e_ccxpower_index_check(struct ieee80211_hw *hw,
u8 channel, u8 *cckpower,
u8 *ofdm, u8 *bw20_pwr,
u8 *bw40_pwr)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
rtlphy->cur_cck_txpwridx = cckpower[0];
rtlphy->cur_ofdm24g_txpwridx = ofdm[0];
rtlphy->cur_bw20_txpwridx = bw20_pwr[0];
rtlphy->cur_bw40_txpwridx = bw40_pwr[0];
}
void rtl88e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel)
{
struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw));
u8 cckpower[MAX_TX_COUNT] = {0}, ofdm[MAX_TX_COUNT] = {0};
u8 bw20_pwr[MAX_TX_COUNT] = {0}, bw40_pwr[MAX_TX_COUNT] = {0};
if (fuse->txpwr_fromeprom == false)
return;
_rtl88e_get_txpower_index(hw, channel, &cckpower[0], &ofdm[0],
&bw20_pwr[0], &bw40_pwr[0]);
_rtl88e_ccxpower_index_check(hw, channel, &cckpower[0], &ofdm[0],
&bw20_pwr[0], &bw40_pwr[0]);
rtl88e_phy_rf6052_set_cck_txpower(hw, &cckpower[0]);
rtl88e_phy_rf6052_set_ofdm_txpower(hw, &ofdm[0], &bw20_pwr[0],
&bw40_pwr[0], channel);
}
void rtl88e_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
enum io_type iotype;
if (!is_hal_stop(rtlhal)) {
switch (operation) {
case SCAN_OPT_BACKUP:
iotype = IO_CMD_PAUSE_DM_BY_SCAN;
rtlpriv->cfg->ops->set_hw_reg(hw,
HW_VAR_IO_CMD,
(u8 *)&iotype);
break;
case SCAN_OPT_RESTORE:
iotype = IO_CMD_RESUME_DM_BY_SCAN;
rtlpriv->cfg->ops->set_hw_reg(hw,
HW_VAR_IO_CMD,
(u8 *)&iotype);
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Unknown Scan Backup operation.\n");
break;
}
}
}
void rtl88e_phy_set_bw_mode_callback(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
u8 reg_bw_opmode;
u8 reg_prsr_rsc;
RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
"Switch to %s bandwidth\n",
rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
"20MHz" : "40MHz");
if (is_hal_stop(rtlhal)) {
rtlphy->set_bwmode_inprogress = false;
return;
}
reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE);
reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2);
switch (rtlphy->current_chan_bw) {
case HT_CHANNEL_WIDTH_20:
reg_bw_opmode |= BW_OPMODE_20MHZ;
rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
break;
case HT_CHANNEL_WIDTH_20_40:
reg_bw_opmode &= ~BW_OPMODE_20MHZ;
rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
reg_prsr_rsc =
(reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5);
rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc);
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"unknown bandwidth: %#X\n", rtlphy->current_chan_bw);
break;
}
switch (rtlphy->current_chan_bw) {
case HT_CHANNEL_WIDTH_20:
rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0);
rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0);
/* rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);*/
break;
case HT_CHANNEL_WIDTH_20_40:
rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1);
rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1);
rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND,
(mac->cur_40_prime_sc >> 1));
rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc);
/*rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);*/
rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)),
(mac->cur_40_prime_sc ==
HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"unknown bandwidth: %#X\n", rtlphy->current_chan_bw);
break;
}
rtl88e_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
rtlphy->set_bwmode_inprogress = false;
RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, "\n");
}
void rtl88e_phy_set_bw_mode(struct ieee80211_hw *hw,
enum nl80211_channel_type ch_type)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
u8 tmp_bw = rtlphy->current_chan_bw;
if (rtlphy->set_bwmode_inprogress)
return;
rtlphy->set_bwmode_inprogress = true;
if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
rtl88e_phy_set_bw_mode_callback(hw);
} else {
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
"FALSE driver sleep or unload\n");
rtlphy->set_bwmode_inprogress = false;
rtlphy->current_chan_bw = tmp_bw;
}
}
void rtl88e_phy_sw_chnl_callback(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_phy *rtlphy = &(rtlpriv->phy);
u32 delay;
RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
"switch to channel%d\n", rtlphy->current_channel);
if (is_hal_stop(rtlhal))
return;
do {
if (!rtlphy->sw_chnl_inprogress)
break;
if (!chnl_step_by_step(hw, rtlphy->current_channel,
&rtlphy->sw_chnl_stage,
&rtlphy->sw_chnl_step, &delay)) {
if (delay > 0)
mdelay(delay);
else
continue;
} else {
rtlphy->sw_chnl_inprogress = false;
}
break;
} while (true);
RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n");
}
u8 rtl88e_phy_sw_chnl(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
if (rtlphy->sw_chnl_inprogress)
return 0;
if (rtlphy->set_bwmode_inprogress)
return 0;
RT_ASSERT((rtlphy->current_channel <= 14),
"WIRELESS_MODE_G but channel>14");
rtlphy->sw_chnl_inprogress = true;
rtlphy->sw_chnl_stage = 0;
rtlphy->sw_chnl_step = 0;
if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
rtl88e_phy_sw_chnl_callback(hw);
RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
"sw_chnl_inprogress false schdule workitem current channel %d\n",
rtlphy->current_channel);
rtlphy->sw_chnl_inprogress = false;
} else {
RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
"sw_chnl_inprogress false driver sleep or unload\n");
rtlphy->sw_chnl_inprogress = false;
}
return 1;
}
static u8 _rtl88e_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb)
{
u32 reg_eac, reg_e94, reg_e9c;
u8 result = 0x00;
rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1c);
rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x30008c1c);
rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x8214032a);
rtl_set_bbreg(hw, 0xe3c, MASKDWORD, 0x28160000);
rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x00462911);
rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000);
rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000);
mdelay(IQK_DELAY_TIME);
reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD);
reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD);
reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD);
if (!(reg_eac & BIT(28)) &&
(((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
(((reg_e9c & 0x03FF0000) >> 16) != 0x42))
result |= 0x01;
return result;
}
static u8 _rtl88e_phy_path_b_iqk(struct ieee80211_hw *hw)
{
u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc;
u8 result = 0x00;
rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002);
rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000);
mdelay(IQK_DELAY_TIME);
reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD);
reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD);
reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD);
reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD);
reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD);
if (!(reg_eac & BIT(31)) &&
(((reg_eb4 & 0x03FF0000) >> 16) != 0x142) &&
(((reg_ebc & 0x03FF0000) >> 16) != 0x42))
result |= 0x01;
else
return result;
if (!(reg_eac & BIT(30)) &&
(((reg_ec4 & 0x03FF0000) >> 16) != 0x132) &&
(((reg_ecc & 0x03FF0000) >> 16) != 0x36))
result |= 0x02;
return result;
}
static u8 _rtl88e_phy_path_a_rx_iqk(struct ieee80211_hw *hw, bool config_pathb)
{
u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u32temp;
u8 result = 0x00;
int jj = RF90_PATH_A;
/*Get TXIMR Setting*/
/*Modify RX IQK mode table*/
rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000);
rtl_set_rfreg(hw, jj, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0);
rtl_set_rfreg(hw, jj, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000);
rtl_set_rfreg(hw, jj, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f);
rtl_set_rfreg(hw, jj, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf117b);
rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000);
/*IQK Setting*/
rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00);
rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x81004800);
/*path a IQK setting*/
rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x10008c1c);
rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x30008c1c);
rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160804);
rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28160000);
/*LO calibration Setting*/
rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911);
/*one shot, path A LOK & iqk*/
rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000);
rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000);
mdelay(IQK_DELAY_TIME);
reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD);
reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD);
reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD);
if (!(reg_eac & BIT(28)) &&
(((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
(((reg_e9c & 0x03FF0000) >> 16) != 0x42))
result |= 0x01;
else
return result;
u32temp = 0x80007C00 | (reg_e94&0x3FF0000) |
((reg_e9c&0x3FF0000) >> 16);
rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, u32temp);
/*RX IQK*/
/*Modify RX IQK mode table*/
rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000);
rtl_set_rfreg(hw, jj, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0);
rtl_set_rfreg(hw, jj, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000);
rtl_set_rfreg(hw, jj, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f);
rtl_set_rfreg(hw, jj, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7ffa);
rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000);
/*IQK Setting*/
rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800);
/*path a IQK setting*/
rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x30008c1c);
rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x10008c1c);
rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160c05);
rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28160c05);
/*LO calibration Setting*/
rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911);
/*one shot, path A LOK & iqk*/
rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000);
rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000);
mdelay(IQK_DELAY_TIME);
reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD);
reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD);
reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD);
reg_ea4 = rtl_get_bbreg(hw, RRX_POWER_BEFORE_IQK_A_2, MASKDWORD);
if (!(reg_eac & BIT(27)) &&
(((reg_ea4 & 0x03FF0000) >> 16) != 0x132) &&
(((reg_eac & 0x03FF0000) >> 16) != 0x36))
result |= 0x02;
return result;
}
static void fill_iqk(struct ieee80211_hw *hw, bool iqk_ok, long result[][8],
u8 final, bool btxonly)
{
u32 oldval_0, x, tx0_a, reg;
long y, tx0_c;
if (final == 0xFF) {
return;
} else if (iqk_ok) {
oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBAL,
MASKDWORD) >> 22) & 0x3FF;
x = result[final][0];
if ((x & 0x00000200) != 0)
x = x | 0xFFFFFC00;
tx0_a = (x * oldval_0) >> 8;
rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, 0x3FF, tx0_a);
rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(31),
((x * oldval_0 >> 7) & 0x1));
y = result[final][1];
if ((y & 0x00000200) != 0)
y |= 0xFFFFFC00;
tx0_c = (y * oldval_0) >> 8;
rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000,
((tx0_c & 0x3C0) >> 6));
rtl_set_bbreg(hw, ROFDM0_XATXIQIMBAL, 0x003F0000,
(tx0_c & 0x3F));
rtl_set_bbreg(hw, ROFDM0_ECCATHRES, BIT(29),
((y * oldval_0 >> 7) & 0x1));
if (btxonly)
return;
reg = result[final][2];
rtl_set_bbreg(hw, ROFDM0_XARXIQIMBAL, 0x3FF, reg);
reg = result[final][3] & 0x3F;
rtl_set_bbreg(hw, ROFDM0_XARXIQIMBAL, 0xFC00, reg);
reg = (result[final][3] >> 6) & 0xF;
rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg);
}
}
static void save_adda_reg(struct ieee80211_hw *hw,
const u32 *addareg, u32 *backup,
u32 registernum)
{
u32 i;
for (i = 0; i < registernum; i++)
backup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD);
}
static void save_mac_reg(struct ieee80211_hw *hw, const u32 *macreg,
u32 *macbackup)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 i;
for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]);
macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]);
}
static void reload_adda(struct ieee80211_hw *hw, const u32 *addareg,
u32 *backup, u32 reg_num)
{
u32 i;
for (i = 0; i < reg_num; i++)
rtl_set_bbreg(hw, addareg[i], MASKDWORD, backup[i]);
}
static void reload_mac(struct ieee80211_hw *hw, const u32 *macreg,
u32 *macbackup)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 i;
for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]);
rtl_write_dword(rtlpriv, macreg[i], macbackup[i]);
}
static void _rtl88e_phy_path_adda_on(struct ieee80211_hw *hw,
const u32 *addareg, bool is_patha_on,
bool is2t)
{
u32 pathon;
u32 i;
pathon = is_patha_on ? 0x04db25a4 : 0x0b1b25a4;
if (false == is2t) {
pathon = 0x0bdb25a0;
rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0b1b25a0);
} else {
rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathon);
}
for (i = 1; i < IQK_ADDA_REG_NUM; i++)
rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathon);
}
static void _rtl88e_phy_mac_setting_calibration(struct ieee80211_hw *hw,
const u32 *macreg,
u32 *macbackup)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 i = 0;
rtl_write_byte(rtlpriv, macreg[i], 0x3F);
for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++)
rtl_write_byte(rtlpriv, macreg[i],
(u8) (macbackup[i] & (~BIT(3))));
rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5))));
}
static void _rtl88e_phy_path_a_standby(struct ieee80211_hw *hw)
{
rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0);
rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000);
rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000);
}
static void _rtl88e_phy_pi_mode_switch(struct ieee80211_hw *hw, bool pi_mode)
{
u32 mode;
mode = pi_mode ? 0x01000100 : 0x01000000;
rtl_set_bbreg(hw, 0x820, MASKDWORD, mode);
rtl_set_bbreg(hw, 0x828, MASKDWORD, mode);
}
static bool sim_comp(struct ieee80211_hw *hw, long result[][8], u8 c1, u8 c2)
{
u32 i, j, diff, bitmap, bound;
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
u8 final[2] = {0xFF, 0xFF};
bool bresult = true, is2t = IS_92C_SERIAL(rtlhal->version);
if (is2t)
bound = 8;
else
bound = 4;
bitmap = 0;
for (i = 0; i < bound; i++) {
diff = (result[c1][i] > result[c2][i]) ?
(result[c1][i] - result[c2][i]) :
(result[c2][i] - result[c1][i]);
if (diff > MAX_TOLERANCE) {
if ((i == 2 || i == 6) && !bitmap) {
if (result[c1][i] + result[c1][i + 1] == 0)
final[(i / 4)] = c2;
else if (result[c2][i] + result[c2][i + 1] == 0)
final[(i / 4)] = c1;
else
bitmap = bitmap | (1 << i);
} else {
bitmap = bitmap | (1 << i);
}
}
}
if (bitmap == 0) {
for (i = 0; i < (bound / 4); i++) {
if (final[i] != 0xFF) {
for (j = i * 4; j < (i + 1) * 4 - 2; j++)
result[3][j] = result[final[i]][j];
bresult = false;
}
}
return bresult;
} else if (!(bitmap & 0x0F)) {
for (i = 0; i < 4; i++)
result[3][i] = result[c1][i];
return false;
} else if (!(bitmap & 0xF0) && is2t) {
for (i = 4; i < 8; i++)
result[3][i] = result[c1][i];
return false;
} else {
return false;
}
}
static void _rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw,
long result[][8], u8 t, bool is2t)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
u32 i;
u8 patha_ok, pathb_ok;
const u32 adda_reg[IQK_ADDA_REG_NUM] = {
0x85c, 0xe6c, 0xe70, 0xe74,
0xe78, 0xe7c, 0xe80, 0xe84,
0xe88, 0xe8c, 0xed0, 0xed4,
0xed8, 0xedc, 0xee0, 0xeec
};
const u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
0x522, 0x550, 0x551, 0x040
};
const u32 iqk_bb_reg[IQK_BB_REG_NUM] = {
ROFDM0_TRXPATHENABLE, ROFDM0_TRMUXPAR, RFPGA0_XCD_RFINTERFACESW,
0xb68, 0xb6c, 0x870, 0x860, 0x864, 0x800
};
const u32 retrycount = 2;
if (t == 0) {
save_adda_reg(hw, adda_reg, rtlphy->adda_backup, 16);
save_mac_reg(hw, iqk_mac_reg, rtlphy->iqk_mac_backup);
save_adda_reg(hw, iqk_bb_reg, rtlphy->iqk_bb_backup,
IQK_BB_REG_NUM);
}
_rtl88e_phy_path_adda_on(hw, adda_reg, true, is2t);
if (t == 0) {
rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw,
RFPGA0_XA_HSSIPARAMETER1, BIT(8));
}
if (!rtlphy->rfpi_enable)
_rtl88e_phy_pi_mode_switch(hw, true);
/*BB Setting*/
rtl_set_bbreg(hw, 0x800, BIT(24), 0x00);
rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600);
rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4);
rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000);
rtl_set_bbreg(hw, 0x870, BIT(10), 0x01);
rtl_set_bbreg(hw, 0x870, BIT(26), 0x01);
rtl_set_bbreg(hw, 0x860, BIT(10), 0x00);
rtl_set_bbreg(hw, 0x864, BIT(10), 0x00);
if (is2t) {
rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000);
rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000);
}
_rtl88e_phy_mac_setting_calibration(hw, iqk_mac_reg,
rtlphy->iqk_mac_backup);
rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x0f600000);
if (is2t)
rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x0f600000);
rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000);
rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00);
rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x81004800);
for (i = 0; i < retrycount; i++) {
patha_ok = _rtl88e_phy_path_a_iqk(hw, is2t);
if (patha_ok == 0x01) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"Path A Tx IQK Success!!\n");
result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) &
0x3FF0000) >> 16;
result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) &
0x3FF0000) >> 16;
break;
}
}
for (i = 0; i < retrycount; i++) {
patha_ok = _rtl88e_phy_path_a_rx_iqk(hw, is2t);
if (patha_ok == 0x03) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"Path A Rx IQK Success!!\n");
result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) &
0x3FF0000) >> 16;
result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) &
0x3FF0000) >> 16;
break;
} else {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"Path a RX iqk fail!!!\n");
}
}
if (0 == patha_ok) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"Path A IQK Success!!\n");
}
if (is2t) {
_rtl88e_phy_path_a_standby(hw);
_rtl88e_phy_path_adda_on(hw, adda_reg, false, is2t);
for (i = 0; i < retrycount; i++) {
pathb_ok = _rtl88e_phy_path_b_iqk(hw);
if (pathb_ok == 0x03) {
result[t][4] = (rtl_get_bbreg(hw,
0xeb4, MASKDWORD) &
0x3FF0000) >> 16;
result[t][5] =
(rtl_get_bbreg(hw, 0xebc, MASKDWORD) &
0x3FF0000) >> 16;
result[t][6] =
(rtl_get_bbreg(hw, 0xec4, MASKDWORD) &
0x3FF0000) >> 16;
result[t][7] =
(rtl_get_bbreg(hw, 0xecc, MASKDWORD) &
0x3FF0000) >> 16;
break;
} else if (i == (retrycount - 1) && pathb_ok == 0x01) {
result[t][4] = (rtl_get_bbreg(hw,
0xeb4, MASKDWORD) &
0x3FF0000) >> 16;
}
result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) &
0x3FF0000) >> 16;
}
}
rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0);
if (t != 0) {
if (!rtlphy->rfpi_enable)
_rtl88e_phy_pi_mode_switch(hw, false);
reload_adda(hw, adda_reg, rtlphy->adda_backup, 16);
reload_mac(hw, iqk_mac_reg, rtlphy->iqk_mac_backup);
reload_adda(hw, iqk_bb_reg, rtlphy->iqk_bb_backup,
IQK_BB_REG_NUM);
rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3);
if (is2t)
rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3);
rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x01008c00);
rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x01008c00);
}
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "88ee IQK Finish!!\n");
}
static void _rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
{
u8 tmpreg;
u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
struct rtl_priv *rtlpriv = rtl_priv(hw);
int jj = RF90_PATH_A;
int kk = RF90_PATH_B;
tmpreg = rtl_read_byte(rtlpriv, 0xd03);
if ((tmpreg & 0x70) != 0)
rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F);
else
rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
if ((tmpreg & 0x70) != 0) {
rf_a_mode = rtl_get_rfreg(hw, jj, 0x00, MASK12BITS);
if (is2t)
rf_b_mode = rtl_get_rfreg(hw, kk, 0x00,
MASK12BITS);
rtl_set_rfreg(hw, jj, 0x00, MASK12BITS,
(rf_a_mode & 0x8FFFF) | 0x10000);
if (is2t)
rtl_set_rfreg(hw, kk, 0x00, MASK12BITS,
(rf_b_mode & 0x8FFFF) | 0x10000);
}
lc_cal = rtl_get_rfreg(hw, jj, 0x18, MASK12BITS);
rtl_set_rfreg(hw, jj, 0x18, MASK12BITS, lc_cal | 0x08000);
mdelay(100);
if ((tmpreg & 0x70) != 0) {
rtl_write_byte(rtlpriv, 0xd03, tmpreg);
rtl_set_rfreg(hw, jj, 0x00, MASK12BITS, rf_a_mode);
if (is2t)
rtl_set_rfreg(hw, kk, 0x00, MASK12BITS,
rf_b_mode);
} else {
rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
}
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n");
}
static void rfpath_switch(struct ieee80211_hw *hw,
bool bmain, bool is2t)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_efuse *fuse = rtl_efuse(rtl_priv(hw));
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n");
if (is_hal_stop(rtlhal)) {
u8 u1btmp;
u1btmp = rtl_read_byte(rtlpriv, REG_LEDCFG0);
rtl_write_byte(rtlpriv, REG_LEDCFG0, u1btmp | BIT(7));
rtl_set_bbreg(hw, rFPGA0_XAB_RFPARAMETER, BIT(13), 0x01);
}
if (is2t) {
if (bmain)
rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE,
BIT(5) | BIT(6), 0x1);
else
rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE,
BIT(5) | BIT(6), 0x2);
} else {
rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BIT(8) | BIT(9), 0);
rtl_set_bbreg(hw, 0x914, MASKLWORD, 0x0201);
/* We use the RF definition of MAIN and AUX, left antenna and
* right antenna repectively.
* Default output at AUX.
*/
if (bmain) {
rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(14) |
BIT(13) | BIT(12), 0);
rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BIT(5) |
BIT(4) | BIT(3), 0);
if (fuse->antenna_div_type == CGCS_RX_HW_ANTDIV)
rtl_set_bbreg(hw, RCONFIG_RAM64X16, BIT(31), 0);
} else {
rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(14) |
BIT(13) | BIT(12), 1);
rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BIT(5) |
BIT(4) | BIT(3), 1);
if (fuse->antenna_div_type == CGCS_RX_HW_ANTDIV)
rtl_set_bbreg(hw, RCONFIG_RAM64X16, BIT(31), 1);
}
}
}
#undef IQK_ADDA_REG_NUM
#undef IQK_DELAY_TIME
void rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
long result[4][8];
u8 i, final;
bool patha_ok;
long reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_tmp = 0;
bool is12simular, is13simular, is23simular;
u32 iqk_bb_reg[9] = {
ROFDM0_XARXIQIMBAL,
ROFDM0_XBRXIQIMBAL,
ROFDM0_ECCATHRES,
ROFDM0_AGCRSSITABLE,
ROFDM0_XATXIQIMBAL,
ROFDM0_XBTXIQIMBAL,
ROFDM0_XCTXAFE,
ROFDM0_XDTXAFE,
ROFDM0_RXIQEXTANTA
};
if (recovery) {
reload_adda(hw, iqk_bb_reg, rtlphy->iqk_bb_backup, 9);
return;
}
memset(result, 0, 32 * sizeof(long));
final = 0xff;
patha_ok = false;
is12simular = false;
is23simular = false;
is13simular = false;
for (i = 0; i < 3; i++) {
if (get_rf_type(rtlphy) == RF_2T2R)
_rtl88e_phy_iq_calibrate(hw, result, i, true);
else
_rtl88e_phy_iq_calibrate(hw, result, i, false);
if (i == 1) {
is12simular = sim_comp(hw, result, 0, 1);
if (is12simular) {
final = 0;
break;
}
}
if (i == 2) {
is13simular = sim_comp(hw, result, 0, 2);
if (is13simular) {
final = 0;
break;
}
is23simular = sim_comp(hw, result, 1, 2);
if (is23simular) {
final = 1;
} else {
for (i = 0; i < 8; i++)
reg_tmp += result[3][i];
if (reg_tmp != 0)
final = 3;
else
final = 0xFF;
}
}
}
for (i = 0; i < 4; i++) {
reg_e94 = result[i][0];
reg_e9c = result[i][1];
reg_ea4 = result[i][2];
reg_eb4 = result[i][4];
reg_ebc = result[i][5];
}
if (final != 0xff) {
reg_e94 = result[final][0];
rtlphy->reg_e94 = reg_e94;
reg_e9c = result[final][1];
rtlphy->reg_e9c = reg_e9c;
reg_ea4 = result[final][2];
reg_eb4 = result[final][4];
rtlphy->reg_eb4 = reg_eb4;
reg_ebc = result[final][5];
rtlphy->reg_ebc = reg_ebc;
patha_ok = true;
} else {
rtlphy->reg_e94 = 0x100;
rtlphy->reg_eb4 = 0x100;
rtlphy->reg_ebc = 0x0;
rtlphy->reg_e9c = 0x0;
}
if (reg_e94 != 0) /*&&(reg_ea4 != 0) */
fill_iqk(hw, patha_ok, result, final, (reg_ea4 == 0));
if (final != 0xFF) {
for (i = 0; i < IQK_MATRIX_REG_NUM; i++)
rtlphy->iqk_matrix[0].value[0][i] = result[final][i];
rtlphy->iqk_matrix[0].iqk_done = true;
}
save_adda_reg(hw, iqk_bb_reg, rtlphy->iqk_bb_backup, 9);
}
void rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_hal *rtlhal = &(rtlpriv->rtlhal);
bool start_conttx = false, singletone = false;
u32 timeout = 2000, timecount = 0;
if (start_conttx || singletone)
return;
while (rtlpriv->mac80211.act_scanning && timecount < timeout) {
udelay(50);
timecount += 50;
}
rtlphy->lck_inprogress = true;
RTPRINT(rtlpriv, FINIT, INIT_IQK,
"LCK:Start!!! currentband %x delay %d ms\n",
rtlhal->current_bandtype, timecount);
_rtl88e_phy_lc_calibrate(hw, false);
rtlphy->lck_inprogress = false;
}
void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
if (rtlphy->apk_done)
return;
return;
}
void rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain)
{
rfpath_switch(hw, bmain, false);
}
bool rtl88e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
bool postprocessing = false;
RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
"-->IO Cmd(%#x), set_io_inprogress(%d)\n",
iotype, rtlphy->set_io_inprogress);
do {
switch (iotype) {
case IO_CMD_RESUME_DM_BY_SCAN:
RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
"[IO CMD] Resume DM after scan.\n");
postprocessing = true;
break;
case IO_CMD_PAUSE_DM_BY_SCAN:
RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
"[IO CMD] Pause DM before scan.\n");
postprocessing = true;
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not processed\n");
break;
}
} while (false);
if (postprocessing && !rtlphy->set_io_inprogress) {
rtlphy->set_io_inprogress = true;
rtlphy->current_io_type = iotype;
} else {
return false;
}
rtl88e_phy_set_io(hw);
RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype);
return true;
}
static void rtl88ee_phy_set_rf_on(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b);
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
/*rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);*/
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
}
static void _rtl88ee_phy_set_rf_sleep(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
int jj = RF90_PATH_A;
rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
rtl_set_rfreg(hw, jj, 0x00, RFREG_OFFSET_MASK, 0x00);
rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22);
}
static bool _rtl88ee_phy_set_rf_power_state(struct ieee80211_hw *hw,
enum rf_pwrstate rfpwr_state)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
struct rtl8192_tx_ring *ring = NULL;
bool bresult = true;
u8 i, queue_id;
switch (rfpwr_state) {
case ERFON:{
if ((ppsc->rfpwr_state == ERFOFF) &&
RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
bool rtstatus;
u32 init = 0;
do {
init++;
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
"IPS Set eRf nic enable\n");
rtstatus = rtl_ps_enable_nic(hw);
} while ((rtstatus != true) && (init < 10));
RT_CLEAR_PS_LEVEL(ppsc,
RT_RF_OFF_LEVL_HALT_NIC);
} else {
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
"Set ERFON sleeped:%d ms\n",
jiffies_to_msecs(jiffies - ppsc->
last_sleep_jiffies));
ppsc->last_awake_jiffies = jiffies;
rtl88ee_phy_set_rf_on(hw);
}
if (mac->link_state == MAC80211_LINKED)
rtlpriv->cfg->ops->led_control(hw, LED_CTL_LINK);
else
rtlpriv->cfg->ops->led_control(hw, LED_CTL_NO_LINK);
break; }
case ERFOFF:{
for (queue_id = 0, i = 0;
queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
ring = &pcipriv->dev.tx_ring[queue_id];
if (skb_queue_len(&ring->queue) == 0) {
queue_id++;
continue;
} else {
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
"eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n",
(i + 1), queue_id,
skb_queue_len(&ring->queue));
udelay(10);
i++;
}
if (i >= MAX_DOZE_WAITING_TIMES_9x) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
"\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n",
MAX_DOZE_WAITING_TIMES_9x,
queue_id,
skb_queue_len(&ring->queue));
break;
}
}
if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) {
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
"IPS Set eRf nic disable\n");
rtl_ps_disable_nic(hw);
RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
} else {
if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) {
rtlpriv->cfg->ops->led_control(hw,
LED_CTL_NO_LINK);
} else {
rtlpriv->cfg->ops->led_control(hw,
LED_CTL_POWER_OFF);
}
}
break; }
case ERFSLEEP:{
if (ppsc->rfpwr_state == ERFOFF)
break;
for (queue_id = 0, i = 0;
queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
ring = &pcipriv->dev.tx_ring[queue_id];
if (skb_queue_len(&ring->queue) == 0) {
queue_id++;
continue;
} else {
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
"eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n",
(i + 1), queue_id,
skb_queue_len(&ring->queue));
udelay(10);
i++;
}
if (i >= MAX_DOZE_WAITING_TIMES_9x) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
"\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n",
MAX_DOZE_WAITING_TIMES_9x,
queue_id,
skb_queue_len(&ring->queue));
break;
}
}
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
"Set ERFSLEEP awaked:%d ms\n",
jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies));
ppsc->last_sleep_jiffies = jiffies;
_rtl88ee_phy_set_rf_sleep(hw);
break; }
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not processed\n");
bresult = false;
break;
}
if (bresult)
ppsc->rfpwr_state = rfpwr_state;
return bresult;
}
bool rtl88e_phy_set_rf_power_state(struct ieee80211_hw *hw,
enum rf_pwrstate rfpwr_state)
{
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
bool bresult;
if (rfpwr_state == ppsc->rfpwr_state)
return false;
bresult = _rtl88ee_phy_set_rf_power_state(hw, rfpwr_state);
return bresult;
}
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __RTL92C_PHY_H__
#define __RTL92C_PHY_H__
/*It must always set to 4, otherwise read efuse table secquence will be wrong.*/
#define MAX_TX_COUNT 4
#define MAX_PRECMD_CNT 16
#define MAX_RFDEPENDCMD_CNT 16
#define MAX_POSTCMD_CNT 16
#define MAX_DOZE_WAITING_TIMES_9x 64
#define RT_CANNOT_IO(hw) false
#define HIGHPOWER_RADIOA_ARRAYLEN 22
#define IQK_ADDA_REG_NUM 16
#define IQK_BB_REG_NUM 9
#define MAX_TOLERANCE 5
#define IQK_DELAY_TIME 10
#define IDX_MAP 15
#define APK_BB_REG_NUM 5
#define APK_AFE_REG_NUM 16
#define APK_CURVE_REG_NUM 4
#define PATH_NUM 2
#define LOOP_LIMIT 5
#define MAX_STALL_TIME 50
#define ANTENNADIVERSITYVALUE 0x80
#define MAX_TXPWR_IDX_NMODE_92S 63
#define RESET_CNT_LIMIT 3
#define IQK_ADDA_REG_NUM 16
#define IQK_MAC_REG_NUM 4
#define RF6052_MAX_PATH 2
#define CT_OFFSET_MAC_ADDR 0X16
#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A
#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60
#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66
#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69
#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C
#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F
#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72
#define CT_OFFSET_CHANNEL_PLAH 0x75
#define CT_OFFSET_THERMAL_METER 0x78
#define CT_OFFSET_RF_OPTION 0x79
#define CT_OFFSET_VERSION 0x7E
#define CT_OFFSET_CUSTOMER_ID 0x7F
#define RTL92C_MAX_PATH_NUM 2
enum swchnlcmd_id {
CMDID_END,
CMDID_SET_TXPOWEROWER_LEVEL,
CMDID_BBREGWRITE10,
CMDID_WRITEPORT_ULONG,
CMDID_WRITEPORT_USHORT,
CMDID_WRITEPORT_UCHAR,
CMDID_RF_WRITEREG,
};
struct swchnlcmd {
enum swchnlcmd_id cmdid;
u32 para1;
u32 para2;
u32 msdelay;
};
enum hw90_block_e {
HW90_BLOCK_MAC = 0,
HW90_BLOCK_PHY0 = 1,
HW90_BLOCK_PHY1 = 2,
HW90_BLOCK_RF = 3,
HW90_BLOCK_MAXIMUM = 4,
};
enum baseband_config_type {
BASEBAND_CONFIG_PHY_REG = 0,
BASEBAND_CONFIG_AGC_TAB = 1,
};
enum ra_offset_area {
RA_OFFSET_LEGACY_OFDM1,
RA_OFFSET_LEGACY_OFDM2,
RA_OFFSET_HT_OFDM1,
RA_OFFSET_HT_OFDM2,
RA_OFFSET_HT_OFDM3,
RA_OFFSET_HT_OFDM4,
RA_OFFSET_HT_CCK,
};
enum antenna_path {
ANTENNA_NONE,
ANTENNA_D,
ANTENNA_C,
ANTENNA_CD,
ANTENNA_B,
ANTENNA_BD,
ANTENNA_BC,
ANTENNA_BCD,
ANTENNA_A,
ANTENNA_AD,
ANTENNA_AC,
ANTENNA_ACD,
ANTENNA_AB,
ANTENNA_ABD,
ANTENNA_ABC,
ANTENNA_ABCD
};
struct r_antenna_select_ofdm {
u32 r_tx_antenna:4;
u32 r_ant_l:4;
u32 r_ant_non_ht:4;
u32 r_ant_ht1:4;
u32 r_ant_ht2:4;
u32 r_ant_ht_s1:4;
u32 r_ant_non_ht_s1:4;
u32 ofdm_txsc:2;
u32 reserved:2;
};
struct r_antenna_select_cck {
u8 r_cckrx_enable_2:2;
u8 r_cckrx_enable:2;
u8 r_ccktx_enable:4;
};
struct efuse_contents {
u8 mac_addr[ETH_ALEN];
u8 cck_tx_power_idx[6];
u8 ht40_1s_tx_power_idx[6];
u8 ht40_2s_tx_power_idx_diff[3];
u8 ht20_tx_power_idx_diff[3];
u8 ofdm_tx_power_idx_diff[3];
u8 ht40_max_power_offset[3];
u8 ht20_max_power_offset[3];
u8 channel_plan;
u8 thermal_meter;
u8 rf_option[5];
u8 version;
u8 oem_id;
u8 regulatory;
};
struct tx_power_struct {
u8 cck[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
u8 ht40_1s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
u8 ht40_2s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
u8 ht20_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
u8 legacy_ht_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
u8 legacy_ht_txpowerdiff;
u8 groupht20[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
u8 groupht40[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
u8 pwrgroup_cnt;
u32 mcs_original_offset[4][16];
};
enum _ANT_DIV_TYPE {
NO_ANTDIV = 0xFF,
CG_TRX_HW_ANTDIV = 0x01,
CGCS_RX_HW_ANTDIV = 0x02,
FIXED_HW_ANTDIV = 0x03,
CG_TRX_SMART_ANTDIV = 0x04,
CGCS_RX_SW_ANTDIV = 0x05,
};
extern u32 rtl88e_phy_query_bb_reg(struct ieee80211_hw *hw,
u32 regaddr, u32 bitmask);
extern void rtl88e_phy_set_bb_reg(struct ieee80211_hw *hw,
u32 regaddr, u32 bitmask, u32 data);
extern u32 rtl88e_phy_query_rf_reg(struct ieee80211_hw *hw,
enum radio_path rfpath, u32 regaddr,
u32 bitmask);
extern void rtl88e_phy_set_rf_reg(struct ieee80211_hw *hw,
enum radio_path rfpath, u32 regaddr,
u32 bitmask, u32 data);
extern bool rtl88e_phy_mac_config(struct ieee80211_hw *hw);
extern bool rtl88e_phy_bb_config(struct ieee80211_hw *hw);
extern bool rtl88e_phy_rf_config(struct ieee80211_hw *hw);
extern void rtl88e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw);
extern void rtl88e_phy_get_txpower_level(struct ieee80211_hw *hw,
long *powerlevel);
extern void rtl88e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel);
extern void rtl88e_phy_scan_operation_backup(struct ieee80211_hw *hw,
u8 operation);
extern void rtl88e_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
extern void rtl88e_phy_set_bw_mode(struct ieee80211_hw *hw,
enum nl80211_channel_type ch_type);
extern void rtl88e_phy_sw_chnl_callback(struct ieee80211_hw *hw);
extern u8 rtl88e_phy_sw_chnl(struct ieee80211_hw *hw);
extern void rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery);
void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta);
void rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw);
void rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain);
bool rtl88e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
enum radio_path rfpath);
bool rtl88e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
extern bool rtl88e_phy_set_rf_power_state(struct ieee80211_hw *hw,
enum rf_pwrstate rfpwr_state);
#endif
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "pwrseqcmd.h"
#include "pwrseq.h"
/* drivers should parse below arrays and do the corresponding actions */
/*3 Power on Array*/
struct wlan_pwr_cfg rtl8188e_power_on_flow[RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS +
RTL8188E_TRANS_END_STEPS] = {
RTL8188E_TRANS_CARDEMU_TO_ACT
RTL8188E_TRANS_END
};
/*3Radio off GPIO Array */
struct wlan_pwr_cfg rtl8188e_radio_off_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS
+ RTL8188E_TRANS_END_STEPS] = {
RTL8188E_TRANS_ACT_TO_CARDEMU
RTL8188E_TRANS_END
};
/*3Card Disable Array*/
struct wlan_pwr_cfg rtl8188e_card_disable_flow
[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
RTL8188E_TRANS_END_STEPS] = {
RTL8188E_TRANS_ACT_TO_CARDEMU
RTL8188E_TRANS_CARDEMU_TO_CARDDIS
RTL8188E_TRANS_END
};
/*3 Card Enable Array*/
struct wlan_pwr_cfg rtl8188e_card_enable_flow
[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
RTL8188E_TRANS_END_STEPS] = {
RTL8188E_TRANS_CARDDIS_TO_CARDEMU
RTL8188E_TRANS_CARDEMU_TO_ACT
RTL8188E_TRANS_END
};
/*3Suspend Array*/
struct wlan_pwr_cfg rtl8188e_suspend_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS
+ RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS
+ RTL8188E_TRANS_END_STEPS] = {
RTL8188E_TRANS_ACT_TO_CARDEMU
RTL8188E_TRANS_CARDEMU_TO_SUS
RTL8188E_TRANS_END
};
/*3 Resume Array*/
struct wlan_pwr_cfg rtl8188e_resume_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS
+ RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS
+ RTL8188E_TRANS_END_STEPS] = {
RTL8188E_TRANS_SUS_TO_CARDEMU
RTL8188E_TRANS_CARDEMU_TO_ACT
RTL8188E_TRANS_END
};
/*3HWPDN Array*/
struct wlan_pwr_cfg rtl8188e_hwpdn_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS
+ RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS
+ RTL8188E_TRANS_END_STEPS] = {
RTL8188E_TRANS_ACT_TO_CARDEMU
RTL8188E_TRANS_CARDEMU_TO_PDN
RTL8188E_TRANS_END
};
/*3 Enter LPS */
struct wlan_pwr_cfg rtl8188e_enter_lps_flow[RTL8188E_TRANS_ACT_TO_LPS_STEPS
+ RTL8188E_TRANS_END_STEPS] = {
/*FW behavior*/
RTL8188E_TRANS_ACT_TO_LPS
RTL8188E_TRANS_END
};
/*3 Leave LPS */
struct wlan_pwr_cfg rtl8188e_leave_lps_flow[RTL8188E_TRANS_LPS_TO_ACT_STEPS
+ RTL8188E_TRANS_END_STEPS] = {
/*FW behavior*/
RTL8188E_TRANS_LPS_TO_ACT
RTL8188E_TRANS_END
};
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __RTL8723E_PWRSEQ_H__
#define __RTL8723E_PWRSEQ_H__
#include "pwrseqcmd.h"
/*
Check document WM-20110607-Paul-RTL8188E_Power_Architecture-R02.vsd
There are 6 HW Power States:
0: POFF--Power Off
1: PDN--Power Down
2: CARDEMU--Card Emulation
3: ACT--Active Mode
4: LPS--Low Power State
5: SUS--Suspend
The transision from different states are defined below
TRANS_CARDEMU_TO_ACT
TRANS_ACT_TO_CARDEMU
TRANS_CARDEMU_TO_SUS
TRANS_SUS_TO_CARDEMU
TRANS_CARDEMU_TO_PDN
TRANS_ACT_TO_LPS
TRANS_LPS_TO_ACT
TRANS_END
PWR SEQ Version: rtl8188e_PwrSeq_V09.h
*/
#define RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS 10
#define RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS 10
#define RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS 10
#define RTL8188E_TRANS_SUS_TO_CARDEMU_STEPS 10
#define RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS 10
#define RTL8188E_TRANS_PDN_TO_CARDEMU_STEPS 10
#define RTL8188E_TRANS_ACT_TO_LPS_STEPS 15
#define RTL8188E_TRANS_LPS_TO_ACT_STEPS 15
#define RTL8188E_TRANS_END_STEPS 1
#define RTL8188E_TRANS_CARDEMU_TO_ACT \
/* format */ \
/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\
{0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/* wait till 0x04[17] = 1 power ready*/ \
PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1)}, \
{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/* 0x02[1:0] = 0 reset BB*/ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0)|BIT(1), 0}, \
{0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*0x24[23] = 2b'01 schmit trigger */ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)}, \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/* 0x04[15] = 0 disable HWPDN (control by DRV)*/ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0}, \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*0x04[12:11] = 2b'00 disable WL suspend*/ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4)|BIT(3), 0}, \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*0x04[8] = 1 polling until return 0*/ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*wait till 0x04[8] = 0*/ \
PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(0), 0}, \
{0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*LDO normal mode*/\
{0x0074, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*SDIO Driving*/\
#define RTL8188E_TRANS_ACT_TO_CARDEMU \
/* format */ \
/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\
{0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0},/*0x1F[7:0] = 0 turn off RF*/\
{0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*LDO Sleep mode*/\
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*0x04[9] = 1 turn off MAC by HW state machine*/ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*wait till 0x04[9] = 0 polling until return 0 to disable*/ \
PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0}, \
#define RTL8188E_TRANS_CARDEMU_TO_SUS \
/* format */ \
/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \
PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \
/*0x04[12:11] = 2b'01enable WL suspend*/ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \
/*0x04[12:11] = 2b'11enable WL suspend for PCIe*/ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)|BIT(4)},\
{0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \
PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \
/* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */\
PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, BIT(7)}, \
{0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \
PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \
/*Clear SIC_EN register 0x40[12] = 1'b0 */ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \
{0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \
PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \
/*Set USB suspend enable local register 0xfe10[4]= 1 */ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, \
{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
/*Set SDIO suspend local register*/ \
PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, \
{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
/*wait power state to suspend*/ \
PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0},
#define RTL8188E_TRANS_SUS_TO_CARDEMU \
/* format */ \
/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
/*Set SDIO suspend local register*/ \
PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0}, \
{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
/*wait power state to suspend*/ \
PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*0x04[12:11] = 2b'01enable WL suspend*/ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0},
#define RTL8188E_TRANS_CARDEMU_TO_CARDDIS \
/* format */ \
/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
{0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*0x24[23] = 2b'01 schmit trigger */ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)}, \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \
PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \
/*0x04[12:11] = 2b'01 enable WL suspend*/ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, \
{0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \
PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \
/* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */\
PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, \
{0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \
PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \
/*Clear SIC_EN register 0x40[12] = 1'b0 */ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \
{0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \
/*Set USB suspend enable local register 0xfe10[4]= 1 */ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, \
{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
/*Set SDIO suspend local register*/ \
PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, \
{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
PWR_CMD_POLLING, BIT(1), 0}, /*wait power state to suspend*/
#define RTL8188E_TRANS_CARDDIS_TO_CARDEMU \
/* format */ \
/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
PWR_BASEADDR_SDIO,\
PWR_CMD_WRITE, BIT(0), 0}, /*Set SDIO suspend local register*/ \
{0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
PWR_BASEADDR_SDIO,\
PWR_CMD_POLLING, BIT(1), BIT(1)}, /*wait power state to suspend*/\
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
PWR_BASEADDR_MAC, \
PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, \
/*0x04[12:11] = 2b'01enable WL suspend*/
#define RTL8188E_TRANS_CARDEMU_TO_PDN \
/* format */ \
/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
{0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0},/* 0x04[16] = 0*/ \
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)},/* 0x04[15] = 1*/
#define RTL8188E_TRANS_PDN_TO_CARDEMU \
/* format */ \
/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
{0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},/* 0x04[15] = 0*/
#define RTL8188E_TRANS_ACT_TO_LPS \
/* format */ \
/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\
{0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x7F},/*Tx Pause*/ \
{0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*zero if no pkt is tx*/\
PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \
{0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*Should be zero if no packet is transmitting*/ \
PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \
{0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*Should be zero if no packet is transmitting*/ \
PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \
{0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*Should be zero if no packet is transmitting*/ \
PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \
{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*CCK and OFDM are disabled, and clock are gated*/ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, \
{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US},/*Delay 1us*/\
{0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x3F},/*Reset MAC TRX*/ \
{0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*check if removed later*/ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0}, \
{0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*Respond TxOK to scheduler*/ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)}, \
#define RTL8188E_TRANS_LPS_TO_ACT \
/* format */ \
/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\
{0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \
PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84}, /*SDIO RPWM*/ \
{0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*USB RPWM*/ \
{0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*PCIe RPWM*/ \
{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, /*Delay*/ \
{0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*. 0x08[4] = 0 switch TSF to 40M*/ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \
{0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*Polling 0x109[7]= 0 TSF in 40M*/ \
PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(7), 0}, \
{0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*. 0x29[7:6] = 2b'00 enable BB clock*/ \
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6)|BIT(7), 0}, \
{0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*. 0x101[1] = 1*/\
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \
{0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*. 0x100[7:0] = 0xFF enable WMAC TRX*/\
PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF}, \
{0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \
/*. 0x02[1:0] = 2b'11 enable BB macro*/\
PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1)|BIT(0), BIT(1)|BIT(0)}, \
{0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\
PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, /*. 0x522 = 0*/
#define RTL8188E_TRANS_END \
/* format */ \
/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\
{0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\
0, PWR_CMD_END, 0, 0}
extern struct wlan_pwr_cfg rtl8188e_power_on_flow
[RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS +
RTL8188E_TRANS_END_STEPS];
extern struct wlan_pwr_cfg rtl8188e_radio_off_flow
[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
RTL8188E_TRANS_END_STEPS];
extern struct wlan_pwr_cfg rtl8188e_card_disable_flow
[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
RTL8188E_TRANS_END_STEPS];
extern struct wlan_pwr_cfg rtl8188e_card_enable_flow
[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
RTL8188E_TRANS_END_STEPS];
extern struct wlan_pwr_cfg rtl8188e_suspend_flow
[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS +
RTL8188E_TRANS_END_STEPS];
extern struct wlan_pwr_cfg rtl8188e_resume_flow
[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS +
RTL8188E_TRANS_END_STEPS];
extern struct wlan_pwr_cfg rtl8188e_hwpdn_flow
[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
RTL8188E_TRANS_END_STEPS];
extern struct wlan_pwr_cfg rtl8188e_enter_lps_flow
[RTL8188E_TRANS_ACT_TO_LPS_STEPS +
RTL8188E_TRANS_END_STEPS];
extern struct wlan_pwr_cfg rtl8188e_leave_lps_flow
[RTL8188E_TRANS_LPS_TO_ACT_STEPS +
RTL8188E_TRANS_END_STEPS];
/* RTL8723 Power Configuration CMDs for PCIe interface */
#define Rtl8188E_NIC_PWR_ON_FLOW rtl8188e_power_on_flow
#define Rtl8188E_NIC_RF_OFF_FLOW rtl8188e_radio_off_flow
#define Rtl8188E_NIC_DISABLE_FLOW rtl8188e_card_disable_flow
#define Rtl8188E_NIC_ENABLE_FLOW rtl8188e_card_enable_flow
#define Rtl8188E_NIC_SUSPEND_FLOW rtl8188e_suspend_flow
#define Rtl8188E_NIC_RESUME_FLOW rtl8188e_resume_flow
#define Rtl8188E_NIC_PDN_FLOW rtl8188e_hwpdn_flow
#define Rtl8188E_NIC_LPS_ENTER_FLOW rtl8188e_enter_lps_flow
#define Rtl8188E_NIC_LPS_LEAVE_FLOW rtl8188e_leave_lps_flow
#endif
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "pwrseq.h"
/* Description:
* This routine deal with the Power Configuration CMDs
* parsing for RTL8723/RTL8188E Series IC.
* Assumption:
* We should follow specific format which was released from HW SD.
*
* 2011.07.07, added by Roger.
*/
bool rtl_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version,
u8 fab_version, u8 interface_type,
struct wlan_pwr_cfg pwrcfgcmd[])
{
struct wlan_pwr_cfg cmd = {0};
bool polling_bit = false;
u32 ary_idx = 0;
u8 val = 0;
u32 offset = 0;
u32 polling_count = 0;
u32 max_polling_cnt = 5000;
do {
cmd = pwrcfgcmd[ary_idx];
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"rtl_hal_pwrseqcmdparsing(): offset(%#x), cut_msk(%#x), fab_msk(%#x),"
"interface_msk(%#x), base(%#x), cmd(%#x), msk(%#x), val(%#x)\n",
GET_PWR_CFG_OFFSET(cmd),
GET_PWR_CFG_CUT_MASK(cmd),
GET_PWR_CFG_FAB_MASK(cmd),
GET_PWR_CFG_INTF_MASK(cmd),
GET_PWR_CFG_BASE(cmd),
GET_PWR_CFG_CMD(cmd),
GET_PWR_CFG_MASK(cmd),
GET_PWR_CFG_VALUE(cmd));
if ((GET_PWR_CFG_FAB_MASK(cmd) & fab_version) &&
(GET_PWR_CFG_CUT_MASK(cmd) & cut_version) &&
(GET_PWR_CFG_INTF_MASK(cmd) & interface_type)) {
switch (GET_PWR_CFG_CMD(cmd)) {
case PWR_CMD_READ:
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"rtl_hal_pwrseqcmdparsing(): PWR_CMD_READ\n");
break;
case PWR_CMD_WRITE: {
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"rtl_hal_pwrseqcmdparsing(): PWR_CMD_WRITE\n");
offset = GET_PWR_CFG_OFFSET(cmd);
/*Read the val from system register*/
val = rtl_read_byte(rtlpriv, offset);
val &= (~(GET_PWR_CFG_MASK(cmd)));
val |= (GET_PWR_CFG_VALUE(cmd) &
GET_PWR_CFG_MASK(cmd));
/*Write the val back to sytem register*/
rtl_write_byte(rtlpriv, offset, val);
}
break;
case PWR_CMD_POLLING:
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"rtl_hal_pwrseqcmdparsing(): PWR_CMD_POLLING\n");
polling_bit = false;
offset = GET_PWR_CFG_OFFSET(cmd);
do {
val = rtl_read_byte(rtlpriv, offset);
val = val & GET_PWR_CFG_MASK(cmd);
if (val == (GET_PWR_CFG_VALUE(cmd) &
GET_PWR_CFG_MASK(cmd)))
polling_bit = true;
else
udelay(10);
if (polling_count++ > max_polling_cnt) {
RT_TRACE(rtlpriv, COMP_INIT,
DBG_LOUD,
"polling fail in pwrseqcmd\n");
return false;
}
} while (!polling_bit);
break;
case PWR_CMD_DELAY:
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"rtl_hal_pwrseqcmdparsing(): PWR_CMD_DELAY\n");
if (GET_PWR_CFG_VALUE(cmd) == PWRSEQ_DELAY_US)
udelay(GET_PWR_CFG_OFFSET(cmd));
else
mdelay(GET_PWR_CFG_OFFSET(cmd));
break;
case PWR_CMD_END:
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"rtl_hal_pwrseqcmdparsing(): PWR_CMD_END\n");
return true;
break;
default:
RT_ASSERT(false,
"rtl_hal_pwrseqcmdparsing(): Unknown CMD!!\n");
break;
}
}
ary_idx++;
} while (1);
return true;
}
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __RTL8723E_PWRSEQCMD_H__
#define __RTL8723E_PWRSEQCMD_H__
#include "wifi.h"
/*---------------------------------------------*/
/* The value of cmd: 4 bits */
/*---------------------------------------------*/
#define PWR_CMD_READ 0x00
#define PWR_CMD_WRITE 0x01
#define PWR_CMD_POLLING 0x02
#define PWR_CMD_DELAY 0x03
#define PWR_CMD_END 0x04
/* define the base address of each block */
#define PWR_BASEADDR_MAC 0x00
#define PWR_BASEADDR_USB 0x01
#define PWR_BASEADDR_PCIE 0x02
#define PWR_BASEADDR_SDIO 0x03
#define PWR_INTF_SDIO_MSK BIT(0)
#define PWR_INTF_USB_MSK BIT(1)
#define PWR_INTF_PCI_MSK BIT(2)
#define PWR_INTF_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3))
#define PWR_FAB_TSMC_MSK BIT(0)
#define PWR_FAB_UMC_MSK BIT(1)
#define PWR_FAB_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3))
#define PWR_CUT_TESTCHIP_MSK BIT(0)
#define PWR_CUT_A_MSK BIT(1)
#define PWR_CUT_B_MSK BIT(2)
#define PWR_CUT_C_MSK BIT(3)
#define PWR_CUT_D_MSK BIT(4)
#define PWR_CUT_E_MSK BIT(5)
#define PWR_CUT_F_MSK BIT(6)
#define PWR_CUT_G_MSK BIT(7)
#define PWR_CUT_ALL_MSK 0xFF
enum pwrseq_delay_unit {
PWRSEQ_DELAY_US,
PWRSEQ_DELAY_MS,
};
struct wlan_pwr_cfg {
u16 offset;
u8 cut_msk;
u8 fab_msk:4;
u8 interface_msk:4;
u8 base:4;
u8 cmd:4;
u8 msk;
u8 value;
};
#define GET_PWR_CFG_OFFSET(__PWR) (__PWR.offset)
#define GET_PWR_CFG_CUT_MASK(__PWR) (__PWR.cut_msk)
#define GET_PWR_CFG_FAB_MASK(__PWR) (__PWR.fab_msk)
#define GET_PWR_CFG_INTF_MASK(__PWR) (__PWR.interface_msk)
#define GET_PWR_CFG_BASE(__PWR) (__PWR.base)
#define GET_PWR_CFG_CMD(__PWR) (__PWR.cmd)
#define GET_PWR_CFG_MASK(__PWR) (__PWR.msk)
#define GET_PWR_CFG_VALUE(__PWR) (__PWR.value)
bool rtl_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version,
u8 fab_version, u8 interface_type,
struct wlan_pwr_cfg pwrcfgcmd[]);
#endif
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __RTL92C_REG_H__
#define __RTL92C_REG_H__
#define TXPKT_BUF_SELECT 0x69
#define RXPKT_BUF_SELECT 0xA5
#define DISABLE_TRXPKT_BUF_ACCESS 0x0
#define REG_SYS_ISO_CTRL 0x0000
#define REG_SYS_FUNC_EN 0x0002
#define REG_APS_FSMCO 0x0004
#define REG_SYS_CLKR 0x0008
#define REG_9346CR 0x000A
#define REG_EE_VPD 0x000C
#define REG_AFE_MISC 0x0010
#define REG_SPS0_CTRL 0x0011
#define REG_SPS_OCP_CFG 0x0018
#define REG_RSV_CTRL 0x001C
#define REG_RF_CTRL 0x001F
#define REG_LDOA15_CTRL 0x0020
#define REG_LDOV12D_CTRL 0x0021
#define REG_LDOHCI12_CTRL 0x0022
#define REG_LPLDO_CTRL 0x0023
#define REG_AFE_XTAL_CTRL 0x0024
#define REG_AFE_LDO_CTRL 0x0027 /* 1.5v for 8188EE test
* chip, 1.4v for MP chip
*/
#define REG_AFE_PLL_CTRL 0x0028
#define REG_EFUSE_CTRL 0x0030
#define REG_EFUSE_TEST 0x0034
#define REG_PWR_DATA 0x0038
#define REG_CAL_TIMER 0x003C
#define REG_ACLK_MON 0x003E
#define REG_GPIO_MUXCFG 0x0040
#define REG_GPIO_IO_SEL 0x0042
#define REG_MAC_PINMUX_CFG 0x0043
#define REG_GPIO_PIN_CTRL 0x0044
#define REG_GPIO_INTM 0x0048
#define REG_LEDCFG0 0x004C
#define REG_LEDCFG1 0x004D
#define REG_LEDCFG2 0x004E
#define REG_LEDCFG3 0x004F
#define REG_FSIMR 0x0050
#define REG_FSISR 0x0054
#define REG_HSIMR 0x0058
#define REG_HSISR 0x005c
#define REG_GPIO_PIN_CTRL_2 0x0060
#define REG_GPIO_IO_SEL_2 0x0062
#define REG_GPIO_OUTPUT 0x006c
#define REG_AFE_XTAL_CTRL_EXT 0x0078
#define REG_XCK_OUT_CTRL 0x007c
#define REG_MCUFWDL 0x0080
#define REG_WOL_EVENT 0x0081
#define REG_MCUTSTCFG 0x0084
#define REG_HIMR 0x00B0
#define REG_HISR 0x00B4
#define REG_HIMRE 0x00B8
#define REG_HISRE 0x00BC
#define REG_EFUSE_ACCESS 0x00CF
#define REG_BIST_SCAN 0x00D0
#define REG_BIST_RPT 0x00D4
#define REG_BIST_ROM_RPT 0x00D8
#define REG_USB_SIE_INTF 0x00E0
#define REG_PCIE_MIO_INTF 0x00E4
#define REG_PCIE_MIO_INTD 0x00E8
#define REG_HPON_FSM 0x00EC
#define REG_SYS_CFG 0x00F0
#define REG_CR 0x0100
#define REG_PBP 0x0104
#define REG_PKT_BUFF_ACCESS_CTRL 0x0106
#define REG_TRXDMA_CTRL 0x010C
#define REG_TRXFF_BNDY 0x0114
#define REG_TRXFF_STATUS 0x0118
#define REG_RXFF_PTR 0x011C
#define REG_CPWM 0x012F
#define REG_FWIMR 0x0130
#define REG_FWISR 0x0134
#define REG_PKTBUF_DBG_CTRL 0x0140
#define REG_PKTBUF_DBG_DATA_L 0x0144
#define REG_PKTBUF_DBG_DATA_H 0x0148
#define REG_RXPKTBUF_CTRL (REG_PKTBUF_DBG_CTRL+2)
#define REG_TC0_CTRL 0x0150
#define REG_TC1_CTRL 0x0154
#define REG_TC2_CTRL 0x0158
#define REG_TC3_CTRL 0x015C
#define REG_TC4_CTRL 0x0160
#define REG_TCUNIT_BASE 0x0164
#define REG_MBIST_START 0x0174
#define REG_MBIST_DONE 0x0178
#define REG_MBIST_FAIL 0x017C
#define REG_32K_CTRL 0x0194
#define REG_C2HEVT_MSG_NORMAL 0x01A0
#define REG_C2HEVT_CLEAR 0x01AF
#define REG_C2HEVT_MSG_TEST 0x01B8
#define REG_MCUTST_1 0x01c0
#define REG_FMETHR 0x01C8
#define REG_HMETFR 0x01CC
#define REG_HMEBOX_0 0x01D0
#define REG_HMEBOX_1 0x01D4
#define REG_HMEBOX_2 0x01D8
#define REG_HMEBOX_3 0x01DC
#define REG_LLT_INIT 0x01E0
#define REG_BB_ACCEESS_CTRL 0x01E8
#define REG_BB_ACCESS_DATA 0x01EC
#define REG_HMEBOX_EXT_0 0x01F0
#define REG_HMEBOX_EXT_1 0x01F4
#define REG_HMEBOX_EXT_2 0x01F8
#define REG_HMEBOX_EXT_3 0x01FC
#define REG_RQPN 0x0200
#define REG_FIFOPAGE 0x0204
#define REG_TDECTRL 0x0208
#define REG_TXDMA_OFFSET_CHK 0x020C
#define REG_TXDMA_STATUS 0x0210
#define REG_RQPN_NPQ 0x0214
#define REG_RXDMA_AGG_PG_TH 0x0280
#define REG_FW_UPD_RDPTR 0x0284 /* FW shall update this
* register before FW * write
* RXPKT_RELEASE_POLL to 1
*/
#define REG_RXDMA_CONTROL 0x0286 /* Control the RX DMA.*/
#define REG_RXPKT_NUM 0x0287 /* The number of packets
* in RXPKTBUF.
*/
#define REG_PCIE_CTRL_REG 0x0300
#define REG_INT_MIG 0x0304
#define REG_BCNQ_DESA 0x0308
#define REG_HQ_DESA 0x0310
#define REG_MGQ_DESA 0x0318
#define REG_VOQ_DESA 0x0320
#define REG_VIQ_DESA 0x0328
#define REG_BEQ_DESA 0x0330
#define REG_BKQ_DESA 0x0338
#define REG_RX_DESA 0x0340
#define REG_DBI 0x0348
#define REG_MDIO 0x0354
#define REG_DBG_SEL 0x0360
#define REG_PCIE_HRPWM 0x0361
#define REG_PCIE_HCPWM 0x0363
#define REG_UART_CTRL 0x0364
#define REG_WATCH_DOG 0x0368
#define REG_UART_TX_DESA 0x0370
#define REG_UART_RX_DESA 0x0378
#define REG_HDAQ_DESA_NODEF 0x0000
#define REG_CMDQ_DESA_NODEF 0x0000
#define REG_VOQ_INFORMATION 0x0400
#define REG_VIQ_INFORMATION 0x0404
#define REG_BEQ_INFORMATION 0x0408
#define REG_BKQ_INFORMATION 0x040C
#define REG_MGQ_INFORMATION 0x0410
#define REG_HGQ_INFORMATION 0x0414
#define REG_BCNQ_INFORMATION 0x0418
#define REG_TXPKT_EMPTY 0x041A
#define REG_CPU_MGQ_INFORMATION 0x041C
#define REG_FWHW_TXQ_CTRL 0x0420
#define REG_HWSEQ_CTRL 0x0423
#define REG_TXPKTBUF_BCNQ_BDNY 0x0424
#define REG_TXPKTBUF_MGQ_BDNY 0x0425
#define REG_MULTI_BCNQ_EN 0x0426
#define REG_MULTI_BCNQ_OFFSET 0x0427
#define REG_SPEC_SIFS 0x0428
#define REG_RL 0x042A
#define REG_DARFRC 0x0430
#define REG_RARFRC 0x0438
#define REG_RRSR 0x0440
#define REG_ARFR0 0x0444
#define REG_ARFR1 0x0448
#define REG_ARFR2 0x044C
#define REG_ARFR3 0x0450
#define REG_AGGLEN_LMT 0x0458
#define REG_AMPDU_MIN_SPACE 0x045C
#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D
#define REG_FAST_EDCA_CTRL 0x0460
#define REG_RD_RESP_PKT_TH 0x0463
#define REG_INIRTS_RATE_SEL 0x0480
#define REG_INIDATA_RATE_SEL 0x0484
#define REG_POWER_STATUS 0x04A4
#define REG_POWER_STAGE1 0x04B4
#define REG_POWER_STAGE2 0x04B8
#define REG_PKT_LIFE_TIME 0x04C0
#define REG_STBC_SETTING 0x04C4
#define REG_PROT_MODE_CTRL 0x04C8
#define REG_BAR_MODE_CTRL 0x04CC
#define REG_RA_TRY_RATE_AGG_LMT 0x04CF
#define REG_EARLY_MODE_CONTROL 0x04D0
#define REG_NQOS_SEQ 0x04DC
#define REG_QOS_SEQ 0x04DE
#define REG_NEED_CPU_HANDLE 0x04E0
#define REG_PKT_LOSE_RPT 0x04E1
#define REG_PTCL_ERR_STATUS 0x04E2
#define REG_TX_RPT_CTRL 0x04EC
#define REG_TX_RPT_TIME 0x04F0
#define REG_DUMMY 0x04FC
#define REG_EDCA_VO_PARAM 0x0500
#define REG_EDCA_VI_PARAM 0x0504
#define REG_EDCA_BE_PARAM 0x0508
#define REG_EDCA_BK_PARAM 0x050C
#define REG_BCNTCFG 0x0510
#define REG_PIFS 0x0512
#define REG_RDG_PIFS 0x0513
#define REG_SIFS_CTX 0x0514
#define REG_SIFS_TRX 0x0516
#define REG_AGGR_BREAK_TIME 0x051A
#define REG_SLOT 0x051B
#define REG_TX_PTCL_CTRL 0x0520
#define REG_TXPAUSE 0x0522
#define REG_DIS_TXREQ_CLR 0x0523
#define REG_RD_CTRL 0x0524
#define REG_TBTT_PROHIBIT 0x0540
#define REG_RD_NAV_NXT 0x0544
#define REG_NAV_PROT_LEN 0x0546
#define REG_BCN_CTRL 0x0550
#define REG_USTIME_TSF 0x0551
#define REG_MBID_NUM 0x0552
#define REG_DUAL_TSF_RST 0x0553
#define REG_BCN_INTERVAL 0x0554
#define REG_MBSSID_BCN_SPACE 0x0554
#define REG_DRVERLYINT 0x0558
#define REG_BCNDMATIM 0x0559
#define REG_ATIMWND 0x055A
#define REG_BCN_MAX_ERR 0x055D
#define REG_RXTSF_OFFSET_CCK 0x055E
#define REG_RXTSF_OFFSET_OFDM 0x055F
#define REG_TSFTR 0x0560
#define REG_INIT_TSFTR 0x0564
#define REG_PSTIMER 0x0580
#define REG_TIMER0 0x0584
#define REG_TIMER1 0x0588
#define REG_ACMHWCTRL 0x05C0
#define REG_ACMRSTCTRL 0x05C1
#define REG_ACMAVG 0x05C2
#define REG_VO_ADMTIME 0x05C4
#define REG_VI_ADMTIME 0x05C6
#define REG_BE_ADMTIME 0x05C8
#define REG_EDCA_RANDOM_GEN 0x05CC
#define REG_SCH_TXCMD 0x05D0
#define REG_APSD_CTRL 0x0600
#define REG_BWOPMODE 0x0603
#define REG_TCR 0x0604
#define REG_RCR 0x0608
#define REG_RX_PKT_LIMIT 0x060C
#define REG_RX_DLK_TIME 0x060D
#define REG_RX_DRVINFO_SZ 0x060F
#define REG_MACID 0x0610
#define REG_BSSID 0x0618
#define REG_MAR 0x0620
#define REG_MBIDCAMCFG 0x0628
#define REG_USTIME_EDCA 0x0638
#define REG_MAC_SPEC_SIFS 0x063A
#define REG_RESP_SIFS_CCK 0x063C
#define REG_RESP_SIFS_OFDM 0x063E
#define REG_ACKTO 0x0640
#define REG_CTS2TO 0x0641
#define REG_EIFS 0x0642
#define REG_NAV_CTRL 0x0650
#define REG_BACAMCMD 0x0654
#define REG_BACAMCONTENT 0x0658
#define REG_LBDLY 0x0660
#define REG_FWDLY 0x0661
#define REG_RXERR_RPT 0x0664
#define REG_TRXPTCL_CTL 0x0668
#define REG_CAMCMD 0x0670
#define REG_CAMWRITE 0x0674
#define REG_CAMREAD 0x0678
#define REG_CAMDBG 0x067C
#define REG_SECCFG 0x0680
#define REG_WOW_CTRL 0x0690
#define REG_PSSTATUS 0x0691
#define REG_PS_RX_INFO 0x0692
#define REG_UAPSD_TID 0x0693
#define REG_LPNAV_CTRL 0x0694
#define REG_WKFMCAM_NUM 0x0698
#define REG_WKFMCAM_RWD 0x069C
#define REG_RXFLTMAP0 0x06A0
#define REG_RXFLTMAP1 0x06A2
#define REG_RXFLTMAP2 0x06A4
#define REG_BCN_PSR_RPT 0x06A8
#define REG_CALB32K_CTRL 0x06AC
#define REG_PKT_MON_CTRL 0x06B4
#define REG_BT_COEX_TABLE 0x06C0
#define REG_WMAC_RESP_TXINFO 0x06D8
#define REG_USB_INFO 0xFE17
#define REG_USB_SPECIAL_OPTION 0xFE55
#define REG_USB_DMA_AGG_TO 0xFE5B
#define REG_USB_AGG_TO 0xFE5C
#define REG_USB_AGG_TH 0xFE5D
#define REG_TEST_USB_TXQS 0xFE48
#define REG_TEST_SIE_VID 0xFE60
#define REG_TEST_SIE_PID 0xFE62
#define REG_TEST_SIE_OPTIONAL 0xFE64
#define REG_TEST_SIE_CHIRP_K 0xFE65
#define REG_TEST_SIE_PHY 0xFE66
#define REG_TEST_SIE_MAC_ADDR 0xFE70
#define REG_TEST_SIE_STRING 0xFE80
#define REG_NORMAL_SIE_VID 0xFE60
#define REG_NORMAL_SIE_PID 0xFE62
#define REG_NORMAL_SIE_OPTIONAL 0xFE64
#define REG_NORMAL_SIE_EP 0xFE65
#define REG_NORMAL_SIE_PHY 0xFE68
#define REG_NORMAL_SIE_MAC_ADDR 0xFE70
#define REG_NORMAL_SIE_STRING 0xFE80
#define CR9346 REG_9346CR
#define MSR (REG_CR + 2)
#define ISR REG_HISR
#define TSFR REG_TSFTR
#define MACIDR0 REG_MACID
#define MACIDR4 (REG_MACID + 4)
#define PBP REG_PBP
#define IDR0 MACIDR0
#define IDR4 MACIDR4
#define UNUSED_REGISTER 0x1BF
#define DCAM UNUSED_REGISTER
#define PSR UNUSED_REGISTER
#define BBADDR UNUSED_REGISTER
#define PHYDATAR UNUSED_REGISTER
#define INVALID_BBRF_VALUE 0x12345678
#define MAX_MSS_DENSITY_2T 0x13
#define MAX_MSS_DENSITY_1T 0x0A
#define CMDEEPROM_EN BIT(5)
#define CMDEEPROM_SEL BIT(4)
#define CMD9346CR_9356SEL BIT(4)
#define AUTOLOAD_EEPROM (CMDEEPROM_EN|CMDEEPROM_SEL)
#define AUTOLOAD_EFUSE CMDEEPROM_EN
#define GPIOSEL_GPIO 0
#define GPIOSEL_ENBT BIT(5)
#define GPIO_IN REG_GPIO_PIN_CTRL
#define GPIO_OUT (REG_GPIO_PIN_CTRL+1)
#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2)
#define GPIO_MOD (REG_GPIO_PIN_CTRL+3)
/* 8723/8188E Host System Interrupt Mask Register (offset 0x58, 32 byte) */
#define HSIMR_GPIO12_0_INT_EN BIT(0)
#define HSIMR_SPS_OCP_INT_EN BIT(5)
#define HSIMR_RON_INT_EN BIT(6)
#define HSIMR_PDN_INT_EN BIT(7)
#define HSIMR_GPIO9_INT_EN BIT(25)
/* 8723/8188E Host System Interrupt Status Register (offset 0x5C, 32 byte) */
#define HSISR_GPIO12_0_INT BIT(0)
#define HSISR_SPS_OCP_INT BIT(5)
#define HSISR_RON_INT_EN BIT(6)
#define HSISR_PDNINT BIT(7)
#define HSISR_GPIO9_INT BIT(25)
#define MSR_NOLINK 0x00
#define MSR_ADHOC 0x01
#define MSR_INFRA 0x02
#define MSR_AP 0x03
#define RRSR_RSC_OFFSET 21
#define RRSR_SHORT_OFFSET 23
#define RRSR_RSC_BW_40M 0x600000
#define RRSR_RSC_UPSUBCHNL 0x400000
#define RRSR_RSC_LOWSUBCHNL 0x200000
#define RRSR_SHORT 0x800000
#define RRSR_1M BIT(0)
#define RRSR_2M BIT(1)
#define RRSR_5_5M BIT(2)
#define RRSR_11M BIT(3)
#define RRSR_6M BIT(4)
#define RRSR_9M BIT(5)
#define RRSR_12M BIT(6)
#define RRSR_18M BIT(7)
#define RRSR_24M BIT(8)
#define RRSR_36M BIT(9)
#define RRSR_48M BIT(10)
#define RRSR_54M BIT(11)
#define RRSR_MCS0 BIT(12)
#define RRSR_MCS1 BIT(13)
#define RRSR_MCS2 BIT(14)
#define RRSR_MCS3 BIT(15)
#define RRSR_MCS4 BIT(16)
#define RRSR_MCS5 BIT(17)
#define RRSR_MCS6 BIT(18)
#define RRSR_MCS7 BIT(19)
#define BRSR_ACKSHORTPMB BIT(23)
#define RATR_1M 0x00000001
#define RATR_2M 0x00000002
#define RATR_55M 0x00000004
#define RATR_11M 0x00000008
#define RATR_6M 0x00000010
#define RATR_9M 0x00000020
#define RATR_12M 0x00000040
#define RATR_18M 0x00000080
#define RATR_24M 0x00000100
#define RATR_36M 0x00000200
#define RATR_48M 0x00000400
#define RATR_54M 0x00000800
#define RATR_MCS0 0x00001000
#define RATR_MCS1 0x00002000
#define RATR_MCS2 0x00004000
#define RATR_MCS3 0x00008000
#define RATR_MCS4 0x00010000
#define RATR_MCS5 0x00020000
#define RATR_MCS6 0x00040000
#define RATR_MCS7 0x00080000
#define RATR_MCS8 0x00100000
#define RATR_MCS9 0x00200000
#define RATR_MCS10 0x00400000
#define RATR_MCS11 0x00800000
#define RATR_MCS12 0x01000000
#define RATR_MCS13 0x02000000
#define RATR_MCS14 0x04000000
#define RATR_MCS15 0x08000000
#define RATE_1M BIT(0)
#define RATE_2M BIT(1)
#define RATE_5_5M BIT(2)
#define RATE_11M BIT(3)
#define RATE_6M BIT(4)
#define RATE_9M BIT(5)
#define RATE_12M BIT(6)
#define RATE_18M BIT(7)
#define RATE_24M BIT(8)
#define RATE_36M BIT(9)
#define RATE_48M BIT(10)
#define RATE_54M BIT(11)
#define RATE_MCS0 BIT(12)
#define RATE_MCS1 BIT(13)
#define RATE_MCS2 BIT(14)
#define RATE_MCS3 BIT(15)
#define RATE_MCS4 BIT(16)
#define RATE_MCS5 BIT(17)
#define RATE_MCS6 BIT(18)
#define RATE_MCS7 BIT(19)
#define RATE_MCS8 BIT(20)
#define RATE_MCS9 BIT(21)
#define RATE_MCS10 BIT(22)
#define RATE_MCS11 BIT(23)
#define RATE_MCS12 BIT(24)
#define RATE_MCS13 BIT(25)
#define RATE_MCS14 BIT(26)
#define RATE_MCS15 BIT(27)
#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M)
#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M | \
RATR_24M | RATR_36M | RATR_48M | RATR_54M)
#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \
RATR_MCS3 | RATR_MCS4 | RATR_MCS5 | \
RATR_MCS6 | RATR_MCS7)
#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \
RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \
RATR_MCS14 | RATR_MCS15)
#define BW_OPMODE_20MHZ BIT(2)
#define BW_OPMODE_5G BIT(1)
#define BW_OPMODE_11J BIT(0)
#define CAM_VALID BIT(15)
#define CAM_NOTVALID 0x0000
#define CAM_USEDK BIT(5)
#define CAM_NONE 0x0
#define CAM_WEP40 0x01
#define CAM_TKIP 0x02
#define CAM_AES 0x04
#define CAM_WEP104 0x05
#define TOTAL_CAM_ENTRY 32
#define HALF_CAM_ENTRY 16
#define CAM_WRITE BIT(16)
#define CAM_READ 0x00000000
#define CAM_POLLINIG BIT(31)
#define SCR_USEDK 0x01
#define SCR_TXSEC_ENABLE 0x02
#define SCR_RXSEC_ENABLE 0x04
#define WOW_PMEN BIT(0)
#define WOW_WOMEN BIT(1)
#define WOW_MAGIC BIT(2)
#define WOW_UWF BIT(3)
/*********************************************
* 8188 IMR/ISR bits
**********************************************/
#define IMR_DISABLED 0x0
/* IMR DW0(0x0060-0063) Bit 0-31 */
#define IMR_TXCCK BIT(30) /* TXRPT interrupt when CCX bit of
* the packet is set
*/
#define IMR_PSTIMEOUT BIT(29) /* Power Save Time Out Interrupt */
#define IMR_GTINT4 BIT(28) /* When GTIMER4 expires,
* this bit is set to 1
*/
#define IMR_GTINT3 BIT(27) /* When GTIMER3 expires,
* this bit is set to 1
*/
#define IMR_TBDER BIT(26) /* Transmit Beacon0 Error */
#define IMR_TBDOK BIT(25) /* Transmit Beacon0 OK */
#define IMR_TSF_BIT32_TOGGLE BIT(24) /* TSF Timer BIT32 toggle ind int */
#define IMR_BCNDMAINT0 BIT(20) /* Beacon DMA Interrupt 0 */
#define IMR_BCNDOK0 BIT(16) /* Beacon Queue DMA OK0 */
#define IMR_HSISR_IND_ON_INT BIT(15) /* HSISR Indicator (HSIMR & HSISR is
* true, this bit is set to 1)
*/
#define IMR_BCNDMAINT_E BIT(14) /* Beacon DMA Int Extension for Win7 */
#define IMR_ATIMEND BIT(12) /* CTWidnow End or ATIM Window End */
#define IMR_HISR1_IND_INT BIT(11) /* HISR1 Indicator (HISR1 & HIMR1 is
* true, this bit is set to 1)
*/
#define IMR_C2HCMD BIT(10) /* CPU to Host Command INT Status,
* Write 1 clear
*/
#define IMR_CPWM2 BIT(9) /* CPU power Mode exchange INT Status,
* Write 1 clear
*/
#define IMR_CPWM BIT(8) /* CPU power Mode exchange INT Status,
* Write 1 clear
*/
#define IMR_HIGHDOK BIT(7) /* High Queue DMA OK */
#define IMR_MGNTDOK BIT(6) /* Management Queue DMA OK */
#define IMR_BKDOK BIT(5) /* AC_BK DMA OK */
#define IMR_BEDOK BIT(4) /* AC_BE DMA OK */
#define IMR_VIDOK BIT(3) /* AC_VI DMA OK */
#define IMR_VODOK BIT(2) /* AC_VO DMA OK */
#define IMR_RDU BIT(1) /* Rx Descriptor Unavailable */
#define IMR_ROK BIT(0) /* Receive DMA OK */
/* IMR DW1(0x00B4-00B7) Bit 0-31 */
#define IMR_BCNDMAINT7 BIT(27) /* Beacon DMA Interrupt 7 */
#define IMR_BCNDMAINT6 BIT(26) /* Beacon DMA Interrupt 6 */
#define IMR_BCNDMAINT5 BIT(25) /* Beacon DMA Interrupt 5 */
#define IMR_BCNDMAINT4 BIT(24) /* Beacon DMA Interrupt 4 */
#define IMR_BCNDMAINT3 BIT(23) /* Beacon DMA Interrupt 3 */
#define IMR_BCNDMAINT2 BIT(22) /* Beacon DMA Interrupt 2 */
#define IMR_BCNDMAINT1 BIT(21) /* Beacon DMA Interrupt 1 */
#define IMR_BCNDOK7 BIT(20) /* Beacon Queue DMA OK Interrup 7 */
#define IMR_BCNDOK6 BIT(19) /* Beacon Queue DMA OK Interrup 6 */
#define IMR_BCNDOK5 BIT(18) /* Beacon Queue DMA OK Interrup 5 */
#define IMR_BCNDOK4 BIT(17) /* Beacon Queue DMA OK Interrup 4 */
#define IMR_BCNDOK3 BIT(16) /* Beacon Queue DMA OK Interrup 3 */
#define IMR_BCNDOK2 BIT(15) /* Beacon Queue DMA OK Interrup 2 */
#define IMR_BCNDOK1 BIT(14) /* Beacon Queue DMA OK Interrup 1 */
#define IMR_ATIMEND_E BIT(13) /* ATIM Window End Extension for Win7 */
#define IMR_TXERR BIT(11) /* Tx Err Flag Int Status,
* write 1 clear.
*/
#define IMR_RXERR BIT(10) /* Rx Err Flag INT Status,
* Write 1 clear
*/
#define IMR_TXFOVW BIT(9) /* Transmit FIFO Overflow */
#define IMR_RXFOVW BIT(8) /* Receive FIFO Overflow */
#define HWSET_MAX_SIZE 512
#define EFUSE_MAX_SECTION 64
#define EFUSE_REAL_CONTENT_LEN 256
#define EFUSE_OOB_PROTECT_BYTES 18 /* PG data exclude header,
* dummy 7 bytes frome CP
* test and reserved 1byte.
*/
#define EEPROM_DEFAULT_TSSI 0x0
#define EEPROM_DEFAULT_TXPOWERDIFF 0x0
#define EEPROM_DEFAULT_CRYSTALCAP 0x5
#define EEPROM_DEFAULT_BOARDTYPE 0x02
#define EEPROM_DEFAULT_TXPOWER 0x1010
#define EEPROM_DEFAULT_HT2T_TXPWR 0x10
#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3
#define EEPROM_DEFAULT_THERMALMETER 0x18
#define EEPROM_DEFAULT_ANTTXPOWERDIFF 0x0
#define EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP 0x5
#define EEPROM_DEFAULT_TXPOWERLEVEL 0x22
#define EEPROM_DEFAULT_HT40_2SDIFF 0x0
#define EEPROM_DEFAULT_HT20_DIFF 2
#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3
#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0
#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0
#define RF_OPTION1 0x79
#define RF_OPTION2 0x7A
#define RF_OPTION3 0x7B
#define RF_OPTION4 0x7C
#define EEPROM_DEFAULT_PID 0x1234
#define EEPROM_DEFAULT_VID 0x5678
#define EEPROM_DEFAULT_CUSTOMERID 0xAB
#define EEPROM_DEFAULT_SUBCUSTOMERID 0xCD
#define EEPROM_DEFAULT_VERSION 0
#define EEPROM_CHANNEL_PLAN_FCC 0x0
#define EEPROM_CHANNEL_PLAN_IC 0x1
#define EEPROM_CHANNEL_PLAN_ETSI 0x2
#define EEPROM_CHANNEL_PLAN_SPAIN 0x3
#define EEPROM_CHANNEL_PLAN_FRANCE 0x4
#define EEPROM_CHANNEL_PLAN_MKK 0x5
#define EEPROM_CHANNEL_PLAN_MKK1 0x6
#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7
#define EEPROM_CHANNEL_PLAN_TELEC 0x8
#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9
#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA
#define EEPROM_CHANNEL_PLAN_NCC 0xB
#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80
#define EEPROM_CID_DEFAULT 0x0
#define EEPROM_CID_TOSHIBA 0x4
#define EEPROM_CID_CCX 0x10
#define EEPROM_CID_QMI 0x0D
#define EEPROM_CID_WHQL 0xFE
#define RTL8188E_EEPROM_ID 0x8129
#define EEPROM_HPON 0x02
#define EEPROM_CLK 0x06
#define EEPROM_TESTR 0x08
#define EEPROM_TXPOWERCCK 0x10
#define EEPROM_TXPOWERHT40_1S 0x16
#define EEPROM_TXPOWERHT20DIFF 0x1B
#define EEPROM_TXPOWER_OFDMDIFF 0x1B
#define EEPROM_TX_PWR_INX 0x10
#define EEPROM_CHANNELPLAN 0xB8
#define EEPROM_XTAL_88E 0xB9
#define EEPROM_THERMAL_METER_88E 0xBA
#define EEPROM_IQK_LCK_88E 0xBB
#define EEPROM_RF_BOARD_OPTION_88E 0xC1
#define EEPROM_RF_FEATURE_OPTION_88E 0xC2
#define EEPROM_RF_BT_SETTING_88E 0xC3
#define EEPROM_VERSION 0xC4
#define EEPROM_CUSTOMER_ID 0xC5
#define EEPROM_RF_ANTENNA_OPT_88E 0xC9
#define EEPROM_MAC_ADDR 0xD0
#define EEPROM_VID 0xD6
#define EEPROM_DID 0xD8
#define EEPROM_SVID 0xDA
#define EEPROM_SMID 0xDC
#define STOPBECON BIT(6)
#define STOPHIGHT BIT(5)
#define STOPMGT BIT(4)
#define STOPVO BIT(3)
#define STOPVI BIT(2)
#define STOPBE BIT(1)
#define STOPBK BIT(0)
#define RCR_APPFCS BIT(31)
#define RCR_APP_MIC BIT(30)
#define RCR_APP_ICV BIT(29)
#define RCR_APP_PHYST_RXFF BIT(28)
#define RCR_APP_BA_SSN BIT(27)
#define RCR_ENMBID BIT(24)
#define RCR_LSIGEN BIT(23)
#define RCR_MFBEN BIT(22)
#define RCR_HTC_LOC_CTRL BIT(14)
#define RCR_AMF BIT(13)
#define RCR_ACF BIT(12)
#define RCR_ADF BIT(11)
#define RCR_AICV BIT(9)
#define RCR_ACRC32 BIT(8)
#define RCR_CBSSID_BCN BIT(7)
#define RCR_CBSSID_DATA BIT(6)
#define RCR_CBSSID RCR_CBSSID_DATA
#define RCR_APWRMGT BIT(5)
#define RCR_ADD3 BIT(4)
#define RCR_AB BIT(3)
#define RCR_AM BIT(2)
#define RCR_APM BIT(1)
#define RCR_AAP BIT(0)
#define RCR_MXDMA_OFFSET 8
#define RCR_FIFO_OFFSET 13
#define RSV_CTRL 0x001C
#define RD_CTRL 0x0524
#define REG_USB_INFO 0xFE17
#define REG_USB_SPECIAL_OPTION 0xFE55
#define REG_USB_DMA_AGG_TO 0xFE5B
#define REG_USB_AGG_TO 0xFE5C
#define REG_USB_AGG_TH 0xFE5D
#define REG_USB_VID 0xFE60
#define REG_USB_PID 0xFE62
#define REG_USB_OPTIONAL 0xFE64
#define REG_USB_CHIRP_K 0xFE65
#define REG_USB_PHY 0xFE66
#define REG_USB_MAC_ADDR 0xFE70
#define REG_USB_HRPWM 0xFE58
#define REG_USB_HCPWM 0xFE57
#define SW18_FPWM BIT(3)
#define ISO_MD2PP BIT(0)
#define ISO_UA2USB BIT(1)
#define ISO_UD2CORE BIT(2)
#define ISO_PA2PCIE BIT(3)
#define ISO_PD2CORE BIT(4)
#define ISO_IP2MAC BIT(5)
#define ISO_DIOP BIT(6)
#define ISO_DIOE BIT(7)
#define ISO_EB2CORE BIT(8)
#define ISO_DIOR BIT(9)
#define PWC_EV25V BIT(14)
#define PWC_EV12V BIT(15)
#define FEN_BBRSTB BIT(0)
#define FEN_BB_GLB_RSTN BIT(1)
#define FEN_USBA BIT(2)
#define FEN_UPLL BIT(3)
#define FEN_USBD BIT(4)
#define FEN_DIO_PCIE BIT(5)
#define FEN_PCIEA BIT(6)
#define FEN_PPLL BIT(7)
#define FEN_PCIED BIT(8)
#define FEN_DIOE BIT(9)
#define FEN_CPUEN BIT(10)
#define FEN_DCORE BIT(11)
#define FEN_ELDR BIT(12)
#define FEN_DIO_RF BIT(13)
#define FEN_HWPDN BIT(14)
#define FEN_MREGEN BIT(15)
#define PFM_LDALL BIT(0)
#define PFM_ALDN BIT(1)
#define PFM_LDKP BIT(2)
#define PFM_WOWL BIT(3)
#define ENPDN BIT(4)
#define PDN_PL BIT(5)
#define APFM_ONMAC BIT(8)
#define APFM_OFF BIT(9)
#define APFM_RSM BIT(10)
#define AFSM_HSUS BIT(11)
#define AFSM_PCIE BIT(12)
#define APDM_MAC BIT(13)
#define APDM_HOST BIT(14)
#define APDM_HPDN BIT(15)
#define RDY_MACON BIT(16)
#define SUS_HOST BIT(17)
#define ROP_ALD BIT(20)
#define ROP_PWR BIT(21)
#define ROP_SPS BIT(22)
#define SOP_MRST BIT(25)
#define SOP_FUSE BIT(26)
#define SOP_ABG BIT(27)
#define SOP_AMB BIT(28)
#define SOP_RCK BIT(29)
#define SOP_A8M BIT(30)
#define XOP_BTCK BIT(31)
#define ANAD16V_EN BIT(0)
#define ANA8M BIT(1)
#define MACSLP BIT(4)
#define LOADER_CLK_EN BIT(5)
#define _80M_SSC_DIS BIT(7)
#define _80M_SSC_EN_HO BIT(8)
#define PHY_SSC_RSTB BIT(9)
#define SEC_CLK_EN BIT(10)
#define MAC_CLK_EN BIT(11)
#define SYS_CLK_EN BIT(12)
#define RING_CLK_EN BIT(13)
#define BOOT_FROM_EEPROM BIT(4)
#define EEPROM_EN BIT(5)
#define AFE_BGEN BIT(0)
#define AFE_MBEN BIT(1)
#define MAC_ID_EN BIT(7)
#define WLOCK_ALL BIT(0)
#define WLOCK_00 BIT(1)
#define WLOCK_04 BIT(2)
#define WLOCK_08 BIT(3)
#define WLOCK_40 BIT(4)
#define R_DIS_PRST_0 BIT(5)
#define R_DIS_PRST_1 BIT(6)
#define LOCK_ALL_EN BIT(7)
#define RF_EN BIT(0)
#define RF_RSTB BIT(1)
#define RF_SDMRSTB BIT(2)
#define LDA15_EN BIT(0)
#define LDA15_STBY BIT(1)
#define LDA15_OBUF BIT(2)
#define LDA15_REG_VOS BIT(3)
#define _LDA15_VOADJ(x) (((x) & 0x7) << 4)
#define LDV12_EN BIT(0)
#define LDV12_SDBY BIT(1)
#define LPLDO_HSM BIT(2)
#define LPLDO_LSM_DIS BIT(3)
#define _LDV12_VADJ(x) (((x) & 0xF) << 4)
#define XTAL_EN BIT(0)
#define XTAL_BSEL BIT(1)
#define _XTAL_BOSC(x) (((x) & 0x3) << 2)
#define _XTAL_CADJ(x) (((x) & 0xF) << 4)
#define XTAL_GATE_USB BIT(8)
#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9)
#define XTAL_GATE_AFE BIT(11)
#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12)
#define XTAL_RF_GATE BIT(14)
#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15)
#define XTAL_GATE_DIG BIT(17)
#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18)
#define XTAL_BT_GATE BIT(20)
#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21)
#define _XTAL_GPIO(x) (((x) & 0x7) << 23)
#define CKDLY_AFE BIT(26)
#define CKDLY_USB BIT(27)
#define CKDLY_DIG BIT(28)
#define CKDLY_BT BIT(29)
#define APLL_EN BIT(0)
#define APLL_320_EN BIT(1)
#define APLL_FREF_SEL BIT(2)
#define APLL_EDGE_SEL BIT(3)
#define APLL_WDOGB BIT(4)
#define APLL_LPFEN BIT(5)
#define APLL_REF_CLK_13MHZ 0x1
#define APLL_REF_CLK_19_2MHZ 0x2
#define APLL_REF_CLK_20MHZ 0x3
#define APLL_REF_CLK_25MHZ 0x4
#define APLL_REF_CLK_26MHZ 0x5
#define APLL_REF_CLK_38_4MHZ 0x6
#define APLL_REF_CLK_40MHZ 0x7
#define APLL_320EN BIT(14)
#define APLL_80EN BIT(15)
#define APLL_1MEN BIT(24)
#define ALD_EN BIT(18)
#define EF_PD BIT(19)
#define EF_FLAG BIT(31)
#define EF_TRPT BIT(7)
#define LDOE25_EN BIT(31)
#define RSM_EN BIT(0)
#define TIMER_EN BIT(4)
#define TRSW0EN BIT(2)
#define TRSW1EN BIT(3)
#define EROM_EN BIT(4)
#define ENBT BIT(5)
#define ENUART BIT(8)
#define UART_910 BIT(9)
#define ENPMAC BIT(10)
#define SIC_SWRST BIT(11)
#define ENSIC BIT(12)
#define SIC_23 BIT(13)
#define ENHDP BIT(14)
#define SIC_LBK BIT(15)
#define LED0PL BIT(4)
#define LED1PL BIT(12)
#define LED0DIS BIT(7)
#define MCUFWDL_EN BIT(0)
#define MCUFWDL_RDY BIT(1)
#define FWDL_CHKSUM_RPT BIT(2)
#define MACINI_RDY BIT(3)
#define BBINI_RDY BIT(4)
#define RFINI_RDY BIT(5)
#define WINTINI_RDY BIT(6)
#define CPRST BIT(23)
#define XCLK_VLD BIT(0)
#define ACLK_VLD BIT(1)
#define UCLK_VLD BIT(2)
#define PCLK_VLD BIT(3)
#define PCIRSTB BIT(4)
#define V15_VLD BIT(5)
#define TRP_B15V_EN BIT(7)
#define SIC_IDLE BIT(8)
#define BD_MAC2 BIT(9)
#define BD_MAC1 BIT(10)
#define IC_MACPHY_MODE BIT(11)
#define VENDOR_ID BIT(19)
#define PAD_HWPD_IDN BIT(22)
#define TRP_VAUX_EN BIT(23)
#define TRP_BT_EN BIT(24)
#define BD_PKG_SEL BIT(25)
#define BD_HCI_SEL BIT(26)
#define TYPE_ID BIT(27)
#define CHIP_VER_RTL_MASK 0xF000
#define CHIP_VER_RTL_SHIFT 12
#define REG_LBMODE (REG_CR + 3)
#define HCI_TXDMA_EN BIT(0)
#define HCI_RXDMA_EN BIT(1)
#define TXDMA_EN BIT(2)
#define RXDMA_EN BIT(3)
#define PROTOCOL_EN BIT(4)
#define SCHEDULE_EN BIT(5)
#define MACTXEN BIT(6)
#define MACRXEN BIT(7)
#define ENSWBCN BIT(8)
#define ENSEC BIT(9)
#define _NETTYPE(x) (((x) & 0x3) << 16)
#define MASK_NETTYPE 0x30000
#define NT_NO_LINK 0x0
#define NT_LINK_AD_HOC 0x1
#define NT_LINK_AP 0x2
#define NT_AS_AP 0x3
#define _LBMODE(x) (((x) & 0xF) << 24)
#define MASK_LBMODE 0xF000000
#define LOOPBACK_NORMAL 0x0
#define LOOPBACK_IMMEDIATELY 0xB
#define LOOPBACK_MAC_DELAY 0x3
#define LOOPBACK_PHY 0x1
#define LOOPBACK_DMA 0x7
#define GET_RX_PAGE_SIZE(value) ((value) & 0xF)
#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4)
#define _PSRX_MASK 0xF
#define _PSTX_MASK 0xF0
#define _PSRX(x) (x)
#define _PSTX(x) ((x) << 4)
#define PBP_64 0x0
#define PBP_128 0x1
#define PBP_256 0x2
#define PBP_512 0x3
#define PBP_1024 0x4
#define RXDMA_ARBBW_EN BIT(0)
#define RXSHFT_EN BIT(1)
#define RXDMA_AGG_EN BIT(2)
#define QS_VO_QUEUE BIT(8)
#define QS_VI_QUEUE BIT(9)
#define QS_BE_QUEUE BIT(10)
#define QS_BK_QUEUE BIT(11)
#define QS_MANAGER_QUEUE BIT(12)
#define QS_HIGH_QUEUE BIT(13)
#define HQSEL_VOQ BIT(0)
#define HQSEL_VIQ BIT(1)
#define HQSEL_BEQ BIT(2)
#define HQSEL_BKQ BIT(3)
#define HQSEL_MGTQ BIT(4)
#define HQSEL_HIQ BIT(5)
#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14)
#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12)
#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10)
#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8)
#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6)
#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4)
#define QUEUE_LOW 1
#define QUEUE_NORMAL 2
#define QUEUE_HIGH 3
#define _LLT_NO_ACTIVE 0x0
#define _LLT_WRITE_ACCESS 0x1
#define _LLT_READ_ACCESS 0x2
#define _LLT_INIT_DATA(x) ((x) & 0xFF)
#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8)
#define _LLT_OP(x) (((x) & 0x3) << 30)
#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3)
#define BB_WRITE_READ_MASK (BIT(31) | BIT(30))
#define BB_WRITE_EN BIT(30)
#define BB_READ_EN BIT(31)
#define _HPQ(x) ((x) & 0xFF)
#define _LPQ(x) (((x) & 0xFF) << 8)
#define _PUBQ(x) (((x) & 0xFF) << 16)
#define _NPQ(x) ((x) & 0xFF)
#define HPQ_PUBLIC_DIS BIT(24)
#define LPQ_PUBLIC_DIS BIT(25)
#define LD_RQPN BIT(31)
#define BCN_VALID BIT(16)
#define BCN_HEAD(x) (((x) & 0xFF) << 8)
#define BCN_HEAD_MASK 0xFF00
#define BLK_DESC_NUM_SHIFT 4
#define BLK_DESC_NUM_MASK 0xF
#define DROP_DATA_EN BIT(9)
#define EN_AMPDU_RTY_NEW BIT(7)
#define _INIRTSMCS_SEL(x) ((x) & 0x3F)
#define _SPEC_SIFS_CCK(x) ((x) & 0xFF)
#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8)
#define RATE_REG_BITMAP_ALL 0xFFFFF
#define _RRSC_BITMAP(x) ((x) & 0xFFFFF)
#define _RRSR_RSC(x) (((x) & 0x3) << 21)
#define RRSR_RSC_RESERVED 0x0
#define RRSR_RSC_UPPER_SUBCHANNEL 0x1
#define RRSR_RSC_LOWER_SUBCHANNEL 0x2
#define RRSR_RSC_DUPLICATE_MODE 0x3
#define USE_SHORT_G1 BIT(20)
#define _AGGLMT_MCS0(x) ((x) & 0xF)
#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4)
#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8)
#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12)
#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16)
#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20)
#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24)
#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28)
#define RETRY_LIMIT_SHORT_SHIFT 8
#define RETRY_LIMIT_LONG_SHIFT 0
#define _DARF_RC1(x) ((x) & 0x1F)
#define _DARF_RC2(x) (((x) & 0x1F) << 8)
#define _DARF_RC3(x) (((x) & 0x1F) << 16)
#define _DARF_RC4(x) (((x) & 0x1F) << 24)
#define _DARF_RC5(x) ((x) & 0x1F)
#define _DARF_RC6(x) (((x) & 0x1F) << 8)
#define _DARF_RC7(x) (((x) & 0x1F) << 16)
#define _DARF_RC8(x) (((x) & 0x1F) << 24)
#define _RARF_RC1(x) ((x) & 0x1F)
#define _RARF_RC2(x) (((x) & 0x1F) << 8)
#define _RARF_RC3(x) (((x) & 0x1F) << 16)
#define _RARF_RC4(x) (((x) & 0x1F) << 24)
#define _RARF_RC5(x) ((x) & 0x1F)
#define _RARF_RC6(x) (((x) & 0x1F) << 8)
#define _RARF_RC7(x) (((x) & 0x1F) << 16)
#define _RARF_RC8(x) (((x) & 0x1F) << 24)
#define AC_PARAM_TXOP_LIMIT_OFFSET 16
#define AC_PARAM_ECW_MAX_OFFSET 12
#define AC_PARAM_ECW_MIN_OFFSET 8
#define AC_PARAM_AIFS_OFFSET 0
#define _AIFS(x) (x)
#define _ECW_MAX_MIN(x) ((x) << 8)
#define _TXOP_LIMIT(x) ((x) << 16)
#define _BCNIFS(x) ((x) & 0xFF)
#define _BCNECW(x) ((((x) & 0xF)) << 8)
#define _LRL(x) ((x) & 0x3F)
#define _SRL(x) (((x) & 0x3F) << 8)
#define _SIFS_CCK_CTX(x) ((x) & 0xFF)
#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8);
#define _SIFS_OFDM_CTX(x) ((x) & 0xFF)
#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8);
#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8)
#define DIS_EDCA_CNT_DWN BIT(11)
#define EN_MBSSID BIT(1)
#define EN_TXBCN_RPT BIT(2)
#define EN_BCN_FUNCTION BIT(3)
#define TSFTR_RST BIT(0)
#define TSFTR1_RST BIT(1)
#define STOP_BCNQ BIT(6)
#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4)
#define DIS_TSF_UDT0_TEST_CHIP BIT(5)
#define ACMHW_HWEN BIT(0)
#define ACMHW_BEQEN BIT(1)
#define ACMHW_VIQEN BIT(2)
#define ACMHW_VOQEN BIT(3)
#define ACMHW_BEQSTATUS BIT(4)
#define ACMHW_VIQSTATUS BIT(5)
#define ACMHW_VOQSTATUS BIT(6)
#define APSDOFF BIT(6)
#define APSDOFF_STATUS BIT(7)
#define BW_20MHZ BIT(2)
#define RATE_BITMAP_ALL 0xFFFFF
#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1
#define TSFRST BIT(0)
#define DIS_GCLK BIT(1)
#define PAD_SEL BIT(2)
#define PWR_ST BIT(6)
#define PWRBIT_OW_EN BIT(7)
#define ACRC BIT(8)
#define CFENDFORM BIT(9)
#define ICV BIT(10)
#define AAP BIT(0)
#define APM BIT(1)
#define AM BIT(2)
#define AB BIT(3)
#define ADD3 BIT(4)
#define APWRMGT BIT(5)
#define CBSSID BIT(6)
#define CBSSID_DATA BIT(6)
#define CBSSID_BCN BIT(7)
#define ACRC32 BIT(8)
#define AICV BIT(9)
#define ADF BIT(11)
#define ACF BIT(12)
#define AMF BIT(13)
#define HTC_LOC_CTRL BIT(14)
#define UC_DATA_EN BIT(16)
#define BM_DATA_EN BIT(17)
#define MFBEN BIT(22)
#define LSIGEN BIT(23)
#define ENMBID BIT(24)
#define APP_BASSN BIT(27)
#define APP_PHYSTS BIT(28)
#define APP_ICV BIT(29)
#define APP_MIC BIT(30)
#define APP_FCS BIT(31)
#define _MIN_SPACE(x) ((x) & 0x7)
#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3)
#define RXERR_TYPE_OFDM_PPDU 0
#define RXERR_TYPE_OFDM_FALSE_ALARM 1
#define RXERR_TYPE_OFDM_MPDU_OK 2
#define RXERR_TYPE_OFDM_MPDU_FAIL 3
#define RXERR_TYPE_CCK_PPDU 4
#define RXERR_TYPE_CCK_FALSE_ALARM 5
#define RXERR_TYPE_CCK_MPDU_OK 6
#define RXERR_TYPE_CCK_MPDU_FAIL 7
#define RXERR_TYPE_HT_PPDU 8
#define RXERR_TYPE_HT_FALSE_ALARM 9
#define RXERR_TYPE_HT_MPDU_TOTAL 10
#define RXERR_TYPE_HT_MPDU_OK 11
#define RXERR_TYPE_HT_MPDU_FAIL 12
#define RXERR_TYPE_RX_FULL_DROP 15
#define RXERR_COUNTER_MASK 0xFFFFF
#define RXERR_RPT_RST BIT(27)
#define _RXERR_RPT_SEL(type) ((type) << 28)
#define SCR_TXUSEDK BIT(0)
#define SCR_RXUSEDK BIT(1)
#define SCR_TXENCENABLE BIT(2)
#define SCR_RXDECENABLE BIT(3)
#define SCR_SKBYA2 BIT(4)
#define SCR_NOSKMC BIT(5)
#define SCR_TXBCUSEDK BIT(6)
#define SCR_RXBCUSEDK BIT(7)
#define USB_IS_HIGH_SPEED 0
#define USB_IS_FULL_SPEED 1
#define USB_SPEED_MASK BIT(5)
#define USB_NORMAL_SIE_EP_MASK 0xF
#define USB_NORMAL_SIE_EP_SHIFT 4
#define USB_TEST_EP_MASK 0x30
#define USB_TEST_EP_SHIFT 4
#define USB_AGG_EN BIT(3)
#define MAC_ADDR_LEN 6
#define LAST_ENTRY_OF_TX_PKT_BUFFER 175/*255 88e*/
#define POLLING_LLT_THRESHOLD 20
#define POLLING_READY_TIMEOUT_COUNT 3000
#define MAX_MSS_DENSITY_2T 0x13
#define MAX_MSS_DENSITY_1T 0x0A
#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6))
#define EPROM_CMD_CONFIG 0x3
#define EPROM_CMD_LOAD 1
#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE
#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2)
#define RPMAC_RESET 0x100
#define RPMAC_TXSTART 0x104
#define RPMAC_TXLEGACYSIG 0x108
#define RPMAC_TXHTSIG1 0x10c
#define RPMAC_TXHTSIG2 0x110
#define RPMAC_PHYDEBUG 0x114
#define RPMAC_TXPACKETNUM 0x118
#define RPMAC_TXIDLE 0x11c
#define RPMAC_TXMACHEADER0 0x120
#define RPMAC_TXMACHEADER1 0x124
#define RPMAC_TXMACHEADER2 0x128
#define RPMAC_TXMACHEADER3 0x12c
#define RPMAC_TXMACHEADER4 0x130
#define RPMAC_TXMACHEADER5 0x134
#define RPMAC_TXDADATYPE 0x138
#define RPMAC_TXRANDOMSEED 0x13c
#define RPMAC_CCKPLCPPREAMBLE 0x140
#define RPMAC_CCKPLCPHEADER 0x144
#define RPMAC_CCKCRC16 0x148
#define RPMAC_OFDMRXCRC32OK 0x170
#define RPMAC_OFDMRXCRC32Er 0x174
#define RPMAC_OFDMRXPARITYER 0x178
#define RPMAC_OFDMRXCRC8ER 0x17c
#define RPMAC_CCKCRXRC16ER 0x180
#define RPMAC_CCKCRXRC32ER 0x184
#define RPMAC_CCKCRXRC32OK 0x188
#define RPMAC_TXSTATUS 0x18c
#define RFPGA0_RFMOD 0x800
#define RFPGA0_TXINFO 0x804
#define RFPGA0_PSDFUNCTION 0x808
#define RFPGA0_TXGAINSTAGE 0x80c
#define RFPGA0_RFTIMING1 0x810
#define RFPGA0_RFTIMING2 0x814
#define RFPGA0_XA_HSSIPARAMETER1 0x820
#define RFPGA0_XA_HSSIPARAMETER2 0x824
#define RFPGA0_XB_HSSIPARAMETER1 0x828
#define RFPGA0_XB_HSSIPARAMETER2 0x82c
#define RFPGA0_XA_LSSIPARAMETER 0x840
#define RFPGA0_XB_LSSIPARAMETER 0x844
#define RFPGA0_RFWAKEUPPARAMETER 0x850
#define RFPGA0_RFSLEEPUPPARAMETER 0x854
#define RFPGA0_XAB_SWITCHCONTROL 0x858
#define RFPGA0_XCD_SWITCHCONTROL 0x85c
#define RFPGA0_XA_RFINTERFACEOE 0x860
#define RFPGA0_XB_RFINTERFACEOE 0x864
#define RFPGA0_XAB_RFINTERFACESW 0x870
#define RFPGA0_XCD_RFINTERFACESW 0x874
#define rFPGA0_XAB_RFPARAMETER 0x878
#define rFPGA0_XCD_RFPARAMETER 0x87c
#define RFPGA0_ANALOGPARAMETER1 0x880
#define RFPGA0_ANALOGPARAMETER2 0x884
#define RFPGA0_ANALOGPARAMETER3 0x888
#define RFPGA0_ANALOGPARAMETER4 0x88c
#define RFPGA0_XA_LSSIREADBACK 0x8a0
#define RFPGA0_XB_LSSIREADBACK 0x8a4
#define RFPGA0_XC_LSSIREADBACK 0x8a8
#define RFPGA0_XD_LSSIREADBACK 0x8ac
#define RFPGA0_PSDREPORT 0x8b4
#define TRANSCEIVEA_HSPI_READBACK 0x8b8
#define TRANSCEIVEB_HSPI_READBACK 0x8bc
#define REG_SC_CNT 0x8c4
#define RFPGA0_XAB_RFINTERFACERB 0x8e0
#define RFPGA0_XCD_RFINTERFACERB 0x8e4
#define RFPGA1_RFMOD 0x900
#define RFPGA1_TXBLOCK 0x904
#define RFPGA1_DEBUGSELECT 0x908
#define RFPGA1_TXINFO 0x90c
#define RCCK0_SYSTEM 0xa00
#define RCCK0_AFESETTING 0xa04
#define RCCK0_CCA 0xa08
#define RCCK0_RXAGC1 0xa0c
#define RCCK0_RXAGC2 0xa10
#define RCCK0_RXHP 0xa14
#define RCCK0_DSPPARAMETER1 0xa18
#define RCCK0_DSPPARAMETER2 0xa1c
#define RCCK0_TXFILTER1 0xa20
#define RCCK0_TXFILTER2 0xa24
#define RCCK0_DEBUGPORT 0xa28
#define RCCK0_FALSEALARMREPORT 0xa2c
#define RCCK0_TRSSIREPORT 0xa50
#define RCCK0_RXREPORT 0xa54
#define RCCK0_FACOUNTERLOWER 0xa5c
#define RCCK0_FACOUNTERUPPER 0xa58
#define RCCK0_CCA_CNT 0xa60
/* PageB(0xB00) */
#define RPDP_ANTA 0xb00
#define RPDP_ANTA_4 0xb04
#define RPDP_ANTA_8 0xb08
#define RPDP_ANTA_C 0xb0c
#define RPDP_ANTA_10 0xb10
#define RPDP_ANTA_14 0xb14
#define RPDP_ANTA_18 0xb18
#define RPDP_ANTA_1C 0xb1c
#define RPDP_ANTA_20 0xb20
#define RPDP_ANTA_24 0xb24
#define RCONFIG_PMPD_ANTA 0xb28
#define RCONFIG_RAM64X16 0xb2c
#define RBNDA 0xb30
#define RHSSIPAR 0xb34
#define RCONFIG_ANTA 0xb68
#define RCONFIG_ANTB 0xb6c
#define RPDP_ANTB 0xb70
#define RPDP_ANTB_4 0xb74
#define RPDP_ANTB_8 0xb78
#define RPDP_ANTB_C 0xb7c
#define RPDP_ANTB_10 0xb80
#define RPDP_ANTB_14 0xb84
#define RPDP_ANTB_18 0xb88
#define RPDP_ANTB_1C 0xb8c
#define RPDP_ANTB_20 0xb90
#define RPDP_ANTB_24 0xb94
#define RCONFIG_PMPD_ANTB 0xb98
#define RBNDB 0xba0
#define RAPK 0xbd8
#define rPm_Rx0_AntA 0xbdc
#define rPm_Rx1_AntA 0xbe0
#define rPm_Rx2_AntA 0xbe4
#define rPm_Rx3_AntA 0xbe8
#define rPm_Rx0_AntB 0xbec
#define rPm_Rx1_AntB 0xbf0
#define rPm_Rx2_AntB 0xbf4
#define rPm_Rx3_AntB 0xbf8
/*Page C*/
#define ROFDM0_LSTF 0xc00
#define ROFDM0_TRXPATHENABLE 0xc04
#define ROFDM0_TRMUXPAR 0xc08
#define ROFDM0_TRSWISOLATION 0xc0c
#define ROFDM0_XARXAFE 0xc10
#define ROFDM0_XARXIQIMBAL 0xc14
#define ROFDM0_XBRXAFE 0xc18
#define ROFDM0_XBRXIQIMBAL 0xc1c
#define ROFDM0_XCRXAFE 0xc20
#define ROFDM0_XCRXIQIMBAL 0xc24
#define ROFDM0_XDRXAFE 0xc28
#define ROFDM0_XDRXIQIMBAL 0xc2c
#define ROFDM0_RXDETECTOR1 0xc30
#define ROFDM0_RXDETECTOR2 0xc34
#define ROFDM0_RXDETECTOR3 0xc38
#define ROFDM0_RXDETECTOR4 0xc3c
#define ROFDM0_RXDSP 0xc40
#define ROFDM0_CFOANDDAGC 0xc44
#define ROFDM0_CCADROPTHRES 0xc48
#define ROFDM0_ECCATHRES 0xc4c
#define ROFDM0_XAAGCCORE1 0xc50
#define ROFDM0_XAAGCCORE2 0xc54
#define ROFDM0_XBAGCCORE1 0xc58
#define ROFDM0_XBAGCCORE2 0xc5c
#define ROFDM0_XCAGCCORE1 0xc60
#define ROFDM0_XCAGCCORE2 0xc64
#define ROFDM0_XDAGCCORE1 0xc68
#define ROFDM0_XDAGCCORE2 0xc6c
#define ROFDM0_AGCPARAMETER1 0xc70
#define ROFDM0_AGCPARAMETER2 0xc74
#define ROFDM0_AGCRSSITABLE 0xc78
#define ROFDM0_HTSTFAGC 0xc7c
#define ROFDM0_XATXIQIMBAL 0xc80
#define ROFDM0_XATXAFE 0xc84
#define ROFDM0_XBTXIQIMBAL 0xc88
#define ROFDM0_XBTXAFE 0xc8c
#define ROFDM0_XCTXIQIMBAL 0xc90
#define ROFDM0_XCTXAFE 0xc94
#define ROFDM0_XDTXIQIMBAL 0xc98
#define ROFDM0_XDTXAFE 0xc9c
#define ROFDM0_RXIQEXTANTA 0xca0
#define ROFDM0_TXCOEFF1 0xca4
#define ROFDM0_TXCOEFF2 0xca8
#define ROFDM0_TXCOEFF3 0xcac
#define ROFDM0_TXCOEFF4 0xcb0
#define ROFDM0_TXCOEFF5 0xcb4
#define ROFDM0_TXCOEFF6 0xcb8
#define ROFDM0_RXHPPARAMETER 0xce0
#define ROFDM0_TXPSEUDONOISEWGT 0xce4
#define ROFDM0_FRAMESYNC 0xcf0
#define ROFDM0_DFSREPORT 0xcf4
#define ROFDM1_LSTF 0xd00
#define ROFDM1_TRXPATHENABLE 0xd04
#define ROFDM1_CF0 0xd08
#define ROFDM1_CSI1 0xd10
#define ROFDM1_SBD 0xd14
#define ROFDM1_CSI2 0xd18
#define ROFDM1_CFOTRACKING 0xd2c
#define ROFDM1_TRXMESAURE1 0xd34
#define ROFDM1_INTFDET 0xd3c
#define ROFDM1_PSEUDONOISESTATEAB 0xd50
#define ROFDM1_PSEUDONOISESTATECD 0xd54
#define ROFDM1_RXPSEUDONOISEWGT 0xd58
#define ROFDM_PHYCOUNTER1 0xda0
#define ROFDM_PHYCOUNTER2 0xda4
#define ROFDM_PHYCOUNTER3 0xda8
#define ROFDM_SHORTCFOAB 0xdac
#define ROFDM_SHORTCFOCD 0xdb0
#define ROFDM_LONGCFOAB 0xdb4
#define ROFDM_LONGCFOCD 0xdb8
#define ROFDM_TAILCF0AB 0xdbc
#define ROFDM_TAILCF0CD 0xdc0
#define ROFDM_PWMEASURE1 0xdc4
#define ROFDM_PWMEASURE2 0xdc8
#define ROFDM_BWREPORT 0xdcc
#define ROFDM_AGCREPORT 0xdd0
#define ROFDM_RXSNR 0xdd4
#define ROFDM_RXEVMCSI 0xdd8
#define ROFDM_SIGREPORT 0xddc
#define RTXAGC_A_RATE18_06 0xe00
#define RTXAGC_A_RATE54_24 0xe04
#define RTXAGC_A_CCK1_MCS32 0xe08
#define RTXAGC_A_MCS03_MCS00 0xe10
#define RTXAGC_A_MCS07_MCS04 0xe14
#define RTXAGC_A_MCS11_MCS08 0xe18
#define RTXAGC_A_MCS15_MCS12 0xe1c
#define RTXAGC_B_RATE18_06 0x830
#define RTXAGC_B_RATE54_24 0x834
#define RTXAGC_B_CCK1_55_MCS32 0x838
#define RTXAGC_B_MCS03_MCS00 0x83c
#define RTXAGC_B_MCS07_MCS04 0x848
#define RTXAGC_B_MCS11_MCS08 0x84c
#define RTXAGC_B_MCS15_MCS12 0x868
#define RTXAGC_B_CCK11_A_CCK2_11 0x86c
#define RFPGA0_IQK 0xe28
#define RTX_IQK_TONE_A 0xe30
#define RRX_IQK_TONE_A 0xe34
#define RTX_IQK_PI_A 0xe38
#define RRX_IQK_PI_A 0xe3c
#define RTX_IQK 0xe40
#define RRX_IQK 0xe44
#define RIQK_AGC_PTS 0xe48
#define RIQK_AGC_RSP 0xe4c
#define RTX_IQK_TONE_B 0xe50
#define RRX_IQK_TONE_B 0xe54
#define RTX_IQK_PI_B 0xe58
#define RRX_IQK_PI_B 0xe5c
#define RIQK_AGC_CONT 0xe60
#define RBLUE_TOOTH 0xe6c
#define RRX_WAIT_CCA 0xe70
#define RTX_CCK_RFON 0xe74
#define RTX_CCK_BBON 0xe78
#define RTX_OFDM_RFON 0xe7c
#define RTX_OFDM_BBON 0xe80
#define RTX_TO_RX 0xe84
#define RTX_TO_TX 0xe88
#define RRX_CCK 0xe8c
#define RTX_POWER_BEFORE_IQK_A 0xe94
#define RTX_POWER_AFTER_IQK_A 0xe9c
#define RRX_POWER_BEFORE_IQK_A 0xea0
#define RRX_POWER_BEFORE_IQK_A_2 0xea4
#define RRX_POWER_AFTER_IQK_A 0xea8
#define RRX_POWER_AFTER_IQK_A_2 0xeac
#define RTX_POWER_BEFORE_IQK_B 0xeb4
#define RTX_POWER_AFTER_IQK_B 0xebc
#define RRX_POWER_BEFORE_IQK_B 0xec0
#define RRX_POWER_BEFORE_IQK_B_2 0xec4
#define RRX_POWER_AFTER_IQK_B 0xec8
#define RRX_POWER_AFTER_IQK_B_2 0xecc
#define RRX_OFDM 0xed0
#define RRX_WAIT_RIFS 0xed4
#define RRX_TO_RX 0xed8
#define RSTANDBY 0xedc
#define RSLEEP 0xee0
#define RPMPD_ANAEN 0xeec
#define RZEBRA1_HSSIENABLE 0x0
#define RZEBRA1_TRXENABLE1 0x1
#define RZEBRA1_TRXENABLE2 0x2
#define RZEBRA1_AGC 0x4
#define RZEBRA1_CHARGEPUMP 0x5
#define RZEBRA1_CHANNEL 0x7
#define RZEBRA1_TXGAIN 0x8
#define RZEBRA1_TXLPF 0x9
#define RZEBRA1_RXLPF 0xb
#define RZEBRA1_RXHPFCORNER 0xc
#define RGLOBALCTRL 0
#define RRTL8256_TXLPF 19
#define RRTL8256_RXLPF 11
#define RRTL8258_TXLPF 0x11
#define RRTL8258_RXLPF 0x13
#define RRTL8258_RSSILPF 0xa
#define RF_AC 0x00
#define RF_IQADJ_G1 0x01
#define RF_IQADJ_G2 0x02
#define RF_POW_TRSW 0x05
#define RF_GAIN_RX 0x06
#define RF_GAIN_TX 0x07
#define RF_TXM_IDAC 0x08
#define RF_BS_IQGEN 0x0F
#define RF_MODE1 0x10
#define RF_MODE2 0x11
#define RF_RX_AGC_HP 0x12
#define RF_TX_AGC 0x13
#define RF_BIAS 0x14
#define RF_IPA 0x15
#define RF_POW_ABILITY 0x17
#define RF_MODE_AG 0x18
#define RRFCHANNEL 0x18
#define RF_CHNLBW 0x18
#define RF_TOP 0x19
#define RF_RX_G1 0x1A
#define RF_RX_G2 0x1B
#define RF_RX_BB2 0x1C
#define RF_RX_BB1 0x1D
#define RF_RCK1 0x1E
#define RF_RCK2 0x1F
#define RF_TX_G1 0x20
#define RF_TX_G2 0x21
#define RF_TX_G3 0x22
#define RF_TX_BB1 0x23
#define RF_T_METER 0x42
#define RF_SYN_G1 0x25
#define RF_SYN_G2 0x26
#define RF_SYN_G3 0x27
#define RF_SYN_G4 0x28
#define RF_SYN_G5 0x29
#define RF_SYN_G6 0x2A
#define RF_SYN_G7 0x2B
#define RF_SYN_G8 0x2C
#define RF_RCK_OS 0x30
#define RF_TXPA_G1 0x31
#define RF_TXPA_G2 0x32
#define RF_TXPA_G3 0x33
#define RF_TX_BIAS_A 0x35
#define RF_TX_BIAS_D 0x36
#define RF_LOBF_9 0x38
#define RF_RXRF_A3 0x3C
#define RF_TRSW 0x3F
#define RF_TXRF_A2 0x41
#define RF_TXPA_G4 0x46
#define RF_TXPA_A4 0x4B
#define RF_WE_LUT 0xEF
#define BBBRESETB 0x100
#define BGLOBALRESETB 0x200
#define BOFDMTXSTART 0x4
#define BCCKTXSTART 0x8
#define BCRC32DEBUG 0x100
#define BPMACLOOPBACK 0x10
#define BTXLSIG 0xffffff
#define BOFDMTXRATE 0xf
#define BOFDMTXRESERVED 0x10
#define BOFDMTXLENGTH 0x1ffe0
#define BOFDMTXPARITY 0x20000
#define BTXHTSIG1 0xffffff
#define BTXHTMCSRATE 0x7f
#define BTXHTBW 0x80
#define BTXHTLENGTH 0xffff00
#define BTXHTSIG2 0xffffff
#define BTXHTSMOOTHING 0x1
#define BTXHTSOUNDING 0x2
#define BTXHTRESERVED 0x4
#define BTXHTAGGREATION 0x8
#define BTXHTSTBC 0x30
#define BTXHTADVANCECODING 0x40
#define BTXHTSHORTGI 0x80
#define BTXHTNUMBERHT_LTF 0x300
#define BTXHTCRC8 0x3fc00
#define BCOUNTERRESET 0x10000
#define BNUMOFOFDMTX 0xffff
#define BNUMOFCCKTX 0xffff0000
#define BTXIDLEINTERVAL 0xffff
#define BOFDMSERVICE 0xffff0000
#define BTXMACHEADER 0xffffffff
#define BTXDATAINIT 0xff
#define BTXHTMODE 0x100
#define BTXDATATYPE 0x30000
#define BTXRANDOMSEED 0xffffffff
#define BCCKTXPREAMBLE 0x1
#define BCCKTXSFD 0xffff0000
#define BCCKTXSIG 0xff
#define BCCKTXSERVICE 0xff00
#define BCCKLENGTHEXT 0x8000
#define BCCKTXLENGHT 0xffff0000
#define BCCKTXCRC16 0xffff
#define BCCKTXSTATUS 0x1
#define BOFDMTXSTATUS 0x2
#define IS_BB_REG_OFFSET_92S(_offset) \
((_offset >= 0x800) && (_offset <= 0xfff))
#define BRFMOD 0x1
#define BJAPANMODE 0x2
#define BCCKTXSC 0x30
#define BCCKEN 0x1000000
#define BOFDMEN 0x2000000
#define BOFDMRXADCPHASE 0x10000
#define BOFDMTXDACPHASE 0x40000
#define BXATXAGC 0x3f
#define BXBTXAGC 0xf00
#define BXCTXAGC 0xf000
#define BXDTXAGC 0xf0000
#define BPASTART 0xf0000000
#define BTRSTART 0x00f00000
#define BRFSTART 0x0000f000
#define BBBSTART 0x000000f0
#define BBBCCKSTART 0x0000000f
#define BPAEND 0xf
#define BTREND 0x0f000000
#define BRFEND 0x000f0000
#define BCCAMASK 0x000000f0
#define BR2RCCAMASK 0x00000f00
#define BHSSI_R2TDELAY 0xf8000000
#define BHSSI_T2RDELAY 0xf80000
#define BCONTXHSSI 0x400
#define BIGFROMCCK 0x200
#define BAGCADDRESS 0x3f
#define BRXHPTX 0x7000
#define BRXHP2RX 0x38000
#define BRXHPCCKINI 0xc0000
#define BAGCTXCODE 0xc00000
#define BAGCRXCODE 0x300000
#define B3WIREDATALENGTH 0x800
#define B3WIREADDREAALENGTH 0x400
#define B3WIRERFPOWERDOWN 0x1
#define B5GPAPEPOLARITY 0x40000000
#define B2GPAPEPOLARITY 0x80000000
#define BRFSW_TXDEFAULTANT 0x3
#define BRFSW_TXOPTIONANT 0x30
#define BRFSW_RXDEFAULTANT 0x300
#define BRFSW_RXOPTIONANT 0x3000
#define BRFSI_3WIREDATA 0x1
#define BRFSI_3WIRECLOCK 0x2
#define BRFSI_3WIRELOAD 0x4
#define BRFSI_3WIRERW 0x8
#define BRFSI_3WIRE 0xf
#define BRFSI_RFENV 0x10
#define BRFSI_TRSW 0x20
#define BRFSI_TRSWB 0x40
#define BRFSI_ANTSW 0x100
#define BRFSI_ANTSWB 0x200
#define BRFSI_PAPE 0x400
#define BRFSI_PAPE5G 0x800
#define BBANDSELECT 0x1
#define BHTSIG2_GI 0x80
#define BHTSIG2_SMOOTHING 0x01
#define BHTSIG2_SOUNDING 0x02
#define BHTSIG2_AGGREATON 0x08
#define BHTSIG2_STBC 0x30
#define BHTSIG2_ADVCODING 0x40
#define BHTSIG2_NUMOFHTLTF 0x300
#define BHTSIG2_CRC8 0x3fc
#define BHTSIG1_MCS 0x7f
#define BHTSIG1_BANDWIDTH 0x80
#define BHTSIG1_HTLENGTH 0xffff
#define BLSIG_RATE 0xf
#define BLSIG_RESERVED 0x10
#define BLSIG_LENGTH 0x1fffe
#define BLSIG_PARITY 0x20
#define BCCKRXPHASE 0x4
#define BLSSIREADADDRESS 0x7f800000
#define BLSSIREADEDGE 0x80000000
#define BLSSIREADBACKDATA 0xfffff
#define BLSSIREADOKFLAG 0x1000
#define BCCKSAMPLERATE 0x8
#define BREGULATOR0STANDBY 0x1
#define BREGULATORPLLSTANDBY 0x2
#define BREGULATOR1STANDBY 0x4
#define BPLLPOWERUP 0x8
#define BDPLLPOWERUP 0x10
#define BDA10POWERUP 0x20
#define BAD7POWERUP 0x200
#define BDA6POWERUP 0x2000
#define BXTALPOWERUP 0x4000
#define B40MDCLKPOWERUP 0x8000
#define BDA6DEBUGMODE 0x20000
#define BDA6SWING 0x380000
#define BADCLKPHASE 0x4000000
#define B80MCLKDELAY 0x18000000
#define BAFEWATCHDOGENABLE 0x20000000
#define BXTALCAP01 0xc0000000
#define BXTALCAP23 0x3
#define BXTALCAP92X 0x0f000000
#define BXTALCAP 0x0f000000
#define BINTDIFCLKENABLE 0x400
#define BEXTSIGCLKENABLE 0x800
#define BBANDGAP_MBIAS_POWERUP 0x10000
#define BAD11SH_GAIN 0xc0000
#define BAD11NPUT_RANGE 0x700000
#define BAD110P_CURRENT 0x3800000
#define BLPATH_LOOPBACK 0x4000000
#define BQPATH_LOOPBACK 0x8000000
#define BAFE_LOOPBACK 0x10000000
#define BDA10_SWING 0x7e0
#define BDA10_REVERSE 0x800
#define BDA_CLK_SOURCE 0x1000
#define BDA7INPUT_RANGE 0x6000
#define BDA7_GAIN 0x38000
#define BDA7OUTPUT_CM_MODE 0x40000
#define BDA7INPUT_CM_MODE 0x380000
#define BDA7CURRENT 0xc00000
#define BREGULATOR_ADJUST 0x7000000
#define BAD11POWERUP_ATTX 0x1
#define BDA10PS_ATTX 0x10
#define BAD11POWERUP_ATRX 0x100
#define BDA10PS_ATRX 0x1000
#define BCCKRX_AGC_FORMAT 0x200
#define BPSDFFT_SAMPLE_POINT 0xc000
#define BPSD_AVERAGE_NUM 0x3000
#define BIQPATH_CONTROL 0xc00
#define BPSD_FREQ 0x3ff
#define BPSD_ANTENNA_PATH 0x30
#define BPSD_IQ_SWITCH 0x40
#define BPSD_RX_TRIGGER 0x400000
#define BPSD_TX_TRIGGERCW 0x80000000
#define BPSD_SINE_TONE_SCALE 0x7f000000
#define BPSD_REPORT 0xffff
#define BOFDM_TXSC 0x30000000
#define BCCK_TXON 0x1
#define BOFDM_TXON 0x2
#define BDEBUG_PAGE 0xfff
#define BDEBUG_ITEM 0xff
#define BANTL 0x10
#define BANT_NONHT 0x100
#define BANT_HT1 0x1000
#define BANT_HT2 0x10000
#define BANT_HT1S1 0x100000
#define BANT_NONHTS1 0x1000000
#define BCCK_BBMODE 0x3
#define BCCK_TXPOWERSAVING 0x80
#define BCCK_RXPOWERSAVING 0x40
#define BCCK_SIDEBAND 0x10
#define BCCK_SCRAMBLE 0x8
#define BCCK_ANTDIVERSITY 0x8000
#define BCCK_CARRIER_RECOVERY 0x4000
#define BCCK_TXRATE 0x3000
#define BCCK_DCCANCEL 0x0800
#define BCCK_ISICANCEL 0x0400
#define BCCK_MATCH_FILTER 0x0200
#define BCCK_EQUALIZER 0x0100
#define BCCK_PREAMBLE_DETECT 0x800000
#define BCCK_FAST_FALSECCA 0x400000
#define BCCK_CH_ESTSTART 0x300000
#define BCCK_CCA_COUNT 0x080000
#define BCCK_CS_LIM 0x070000
#define BCCK_BIST_MODE 0x80000000
#define BCCK_CCAMASK 0x40000000
#define BCCK_TX_DAC_PHASE 0x4
#define BCCK_RX_ADC_PHASE 0x20000000
#define BCCKR_CP_MODE 0x0100
#define BCCK_TXDC_OFFSET 0xf0
#define BCCK_RXDC_OFFSET 0xf
#define BCCK_CCA_MODE 0xc000
#define BCCK_FALSECS_LIM 0x3f00
#define BCCK_CS_RATIO 0xc00000
#define BCCK_CORGBIT_SEL 0x300000
#define BCCK_PD_LIM 0x0f0000
#define BCCK_NEWCCA 0x80000000
#define BCCK_RXHP_OF_IG 0x8000
#define BCCK_RXIG 0x7f00
#define BCCK_LNA_POLARITY 0x800000
#define BCCK_RX1ST_BAIN 0x7f0000
#define BCCK_RF_EXTEND 0x20000000
#define BCCK_RXAGC_SATLEVEL 0x1f000000
#define BCCK_RXAGC_SATCOUNT 0xe0
#define BCCKRXRFSETTLE 0x1f
#define BCCK_FIXED_RXAGC 0x8000
#define BCCK_ANTENNA_POLARITY 0x2000
#define BCCK_TXFILTER_TYPE 0x0c00
#define BCCK_RXAGC_REPORTTYPE 0x0300
#define BCCK_RXDAGC_EN 0x80000000
#define BCCK_RXDAGC_PERIOD 0x20000000
#define BCCK_RXDAGC_SATLEVEL 0x1f000000
#define BCCK_TIMING_RECOVERY 0x800000
#define BCCK_TXC0 0x3f0000
#define BCCK_TXC1 0x3f000000
#define BCCK_TXC2 0x3f
#define BCCK_TXC3 0x3f00
#define BCCK_TXC4 0x3f0000
#define BCCK_TXC5 0x3f000000
#define BCCK_TXC6 0x3f
#define BCCK_TXC7 0x3f00
#define BCCK_DEBUGPORT 0xff0000
#define BCCK_DAC_DEBUG 0x0f000000
#define BCCK_FALSEALARM_ENABLE 0x8000
#define BCCK_FALSEALARM_READ 0x4000
#define BCCK_TRSSI 0x7f
#define BCCK_RXAGC_REPORT 0xfe
#define BCCK_RXREPORT_ANTSEL 0x80000000
#define BCCK_RXREPORT_MFOFF 0x40000000
#define BCCK_RXREPORT_SQLOSS 0x20000000
#define BCCK_RXREPORT_PKTLOSS 0x10000000
#define BCCK_RXREPORT_LOCKEDBIT 0x08000000
#define BCCK_RXREPORT_RATEERROR 0x04000000
#define BCCK_RXREPORT_RXRATE 0x03000000
#define BCCK_RXFA_COUNTER_LOWER 0xff
#define BCCK_RXFA_COUNTER_UPPER 0xff000000
#define BCCK_RXHPAGC_START 0xe000
#define BCCK_RXHPAGC_FINAL 0x1c00
#define BCCK_RXFALSEALARM_ENABLE 0x8000
#define BCCK_FACOUNTER_FREEZE 0x4000
#define BCCK_TXPATH_SEL 0x10000000
#define BCCK_DEFAULT_RXPATH 0xc000000
#define BCCK_OPTION_RXPATH 0x3000000
#define BNUM_OFSTF 0x3
#define BSHIFT_L 0xc0
#define BGI_TH 0xc
#define BRXPATH_A 0x1
#define BRXPATH_B 0x2
#define BRXPATH_C 0x4
#define BRXPATH_D 0x8
#define BTXPATH_A 0x1
#define BTXPATH_B 0x2
#define BTXPATH_C 0x4
#define BTXPATH_D 0x8
#define BTRSSI_FREQ 0x200
#define BADC_BACKOFF 0x3000
#define BDFIR_BACKOFF 0xc000
#define BTRSSI_LATCH_PHASE 0x10000
#define BRX_LDC_OFFSET 0xff
#define BRX_QDC_OFFSET 0xff00
#define BRX_DFIR_MODE 0x1800000
#define BRX_DCNF_TYPE 0xe000000
#define BRXIQIMB_A 0x3ff
#define BRXIQIMB_B 0xfc00
#define BRXIQIMB_C 0x3f0000
#define BRXIQIMB_D 0xffc00000
#define BDC_DC_NOTCH 0x60000
#define BRXNB_NOTCH 0x1f000000
#define BPD_TH 0xf
#define BPD_TH_OPT2 0xc000
#define BPWED_TH 0x700
#define BIFMF_WIN_L 0x800
#define BPD_OPTION 0x1000
#define BMF_WIN_L 0xe000
#define BBW_SEARCH_L 0x30000
#define BWIN_ENH_L 0xc0000
#define BBW_TH 0x700000
#define BED_TH2 0x3800000
#define BBW_OPTION 0x4000000
#define BRADIO_TH 0x18000000
#define BWINDOW_L 0xe0000000
#define BSBD_OPTION 0x1
#define BFRAME_TH 0x1c
#define BFS_OPTION 0x60
#define BDC_SLOPE_CHECK 0x80
#define BFGUARD_COUNTER_DC_L 0xe00
#define BFRAME_WEIGHT_SHORT 0x7000
#define BSUB_TUNE 0xe00000
#define BFRAME_DC_LENGTH 0xe000000
#define BSBD_START_OFFSET 0x30000000
#define BFRAME_TH_2 0x7
#define BFRAME_GI2_TH 0x38
#define BGI2_SYNC_EN 0x40
#define BSARCH_SHORT_EARLY 0x300
#define BSARCH_SHORT_LATE 0xc00
#define BSARCH_GI2_LATE 0x70000
#define BCFOANTSUM 0x1
#define BCFOACC 0x2
#define BCFOSTARTOFFSET 0xc
#define BCFOLOOPBACK 0x70
#define BCFOSUMWEIGHT 0x80
#define BDAGCENABLE 0x10000
#define BTXIQIMB_A 0x3ff
#define BTXIQIMB_B 0xfc00
#define BTXIQIMB_C 0x3f0000
#define BTXIQIMB_D 0xffc00000
#define BTXIDCOFFSET 0xff
#define BTXIQDCOFFSET 0xff00
#define BTXDFIRMODE 0x10000
#define BTXPESUDO_NOISEON 0x4000000
#define BTXPESUDO_NOISE_A 0xff
#define BTXPESUDO_NOISE_B 0xff00
#define BTXPESUDO_NOISE_C 0xff0000
#define BTXPESUDO_NOISE_D 0xff000000
#define BCCA_DROPOPTION 0x20000
#define BCCA_DROPTHRES 0xfff00000
#define BEDCCA_H 0xf
#define BEDCCA_L 0xf0
#define BLAMBDA_ED 0x300
#define BRX_INITIALGAIN 0x7f
#define BRX_ANTDIV_EN 0x80
#define BRX_AGC_ADDRESS_FOR_LNA 0x7f00
#define BRX_HIGHPOWER_FLOW 0x8000
#define BRX_AGC_FREEZE_THRES 0xc0000
#define BRX_FREEZESTEP_AGC1 0x300000
#define BRX_FREEZESTEP_AGC2 0xc00000
#define BRX_FREEZESTEP_AGC3 0x3000000
#define BRX_FREEZESTEP_AGC0 0xc000000
#define BRXRSSI_CMP_EN 0x10000000
#define BRXQUICK_AGCEN 0x20000000
#define BRXAGC_FREEZE_THRES_MODE 0x40000000
#define BRX_OVERFLOW_CHECKTYPE 0x80000000
#define BRX_AGCSHIFT 0x7f
#define BTRSW_TRI_ONLY 0x80
#define BPOWER_THRES 0x300
#define BRXAGC_EN 0x1
#define BRXAGC_TOGETHER_EN 0x2
#define BRXAGC_MIN 0x4
#define BRXHP_INI 0x7
#define BRXHP_TRLNA 0x70
#define BRXHP_RSSI 0x700
#define BRXHP_BBP1 0x7000
#define BRXHP_BBP2 0x70000
#define BRXHP_BBP3 0x700000
#define BRSSI_H 0x7f0000
#define BRSSI_GEN 0x7f000000
#define BRXSETTLE_TRSW 0x7
#define BRXSETTLE_LNA 0x38
#define BRXSETTLE_RSSI 0x1c0
#define BRXSETTLE_BBP 0xe00
#define BRXSETTLE_RXHP 0x7000
#define BRXSETTLE_ANTSW_RSSI 0x38000
#define BRXSETTLE_ANTSW 0xc0000
#define BRXPROCESS_TIME_DAGC 0x300000
#define BRXSETTLE_HSSI 0x400000
#define BRXPROCESS_TIME_BBPPW 0x800000
#define BRXANTENNA_POWER_SHIFT 0x3000000
#define BRSSI_TABLE_SELECT 0xc000000
#define BRXHP_FINAL 0x7000000
#define BRXHPSETTLE_BBP 0x7
#define BRXHTSETTLE_HSSI 0x8
#define BRXHTSETTLE_RXHP 0x70
#define BRXHTSETTLE_BBPPW 0x80
#define BRXHTSETTLE_IDLE 0x300
#define BRXHTSETTLE_RESERVED 0x1c00
#define BRXHT_RXHP_EN 0x8000
#define BRXAGC_FREEZE_THRES 0x30000
#define BRXAGC_TOGETHEREN 0x40000
#define BRXHTAGC_MIN 0x80000
#define BRXHTAGC_EN 0x100000
#define BRXHTDAGC_EN 0x200000
#define BRXHT_RXHP_BBP 0x1c00000
#define BRXHT_RXHP_FINAL 0xe0000000
#define BRXPW_RADIO_TH 0x3
#define BRXPW_RADIO_EN 0x4
#define BRXMF_HOLD 0x3800
#define BRXPD_DELAY_TH1 0x38
#define BRXPD_DELAY_TH2 0x1c0
#define BRXPD_DC_COUNT_MAX 0x600
#define BRXPD_DELAY_TH 0x8000
#define BRXPROCESS_DELAY 0xf0000
#define BRXSEARCHRANGE_GI2_EARLY 0x700000
#define BRXFRAME_FUARD_COUNTER_L 0x3800000
#define BRXSGI_GUARD_L 0xc000000
#define BRXSGI_SEARCH_L 0x30000000
#define BRXSGI_TH 0xc0000000
#define BDFSCNT0 0xff
#define BDFSCNT1 0xff00
#define BDFSFLAG 0xf0000
#define BMF_WEIGHT_SUM 0x300000
#define BMINIDX_TH 0x7f000000
#define BDAFORMAT 0x40000
#define BTXCH_EMU_ENABLE 0x01000000
#define BTRSW_ISOLATION_A 0x7f
#define BTRSW_ISOLATION_B 0x7f00
#define BTRSW_ISOLATION_C 0x7f0000
#define BTRSW_ISOLATION_D 0x7f000000
#define BEXT_LNA_GAIN 0x7c00
#define BSTBC_EN 0x4
#define BANTENNA_MAPPING 0x10
#define BNSS 0x20
#define BCFO_ANTSUM_ID 0x200
#define BPHY_COUNTER_RESET 0x8000000
#define BCFO_REPORT_GET 0x4000000
#define BOFDM_CONTINUE_TX 0x10000000
#define BOFDM_SINGLE_CARRIER 0x20000000
#define BOFDM_SINGLE_TONE 0x40000000
#define BHT_DETECT 0x100
#define BCFOEN 0x10000
#define BCFOVALUE 0xfff00000
#define BSIGTONE_RE 0x3f
#define BSIGTONE_IM 0x7f00
#define BCOUNTER_CCA 0xffff
#define BCOUNTER_PARITYFAIL 0xffff0000
#define BCOUNTER_RATEILLEGAL 0xffff
#define BCOUNTER_CRC8FAIL 0xffff0000
#define BCOUNTER_MCSNOSUPPORT 0xffff
#define BCOUNTER_FASTSYNC 0xffff
#define BSHORTCFO 0xfff
#define BSHORTCFOT_LENGTH 12
#define BSHORTCFOF_LENGTH 11
#define BLONGCFO 0x7ff
#define BLONGCFOT_LENGTH 11
#define BLONGCFOF_LENGTH 11
#define BTAILCFO 0x1fff
#define BTAILCFOT_LENGTH 13
#define BTAILCFOF_LENGTH 12
#define BNOISE_EN_PWDB 0xffff
#define BCC_POWER_DB 0xffff0000
#define BMOISE_PWDB 0xffff
#define BPOWERMEAST_LENGTH 10
#define BPOWERMEASF_LENGTH 3
#define BRX_HT_BW 0x1
#define BRXSC 0x6
#define BRX_HT 0x8
#define BNB_INTF_DET_ON 0x1
#define BINTF_WIN_LEN_CFG 0x30
#define BNB_INTF_TH_CFG 0x1c0
#define BRFGAIN 0x3f
#define BTABLESEL 0x40
#define BTRSW 0x80
#define BRXSNR_A 0xff
#define BRXSNR_B 0xff00
#define BRXSNR_C 0xff0000
#define BRXSNR_D 0xff000000
#define BSNR_EVMT_LENGTH 8
#define BSNR_EVMF_LENGTH 1
#define BCSI1ST 0xff
#define BCSI2ND 0xff00
#define BRXEVM1ST 0xff0000
#define BRXEVM2ND 0xff000000
#define BSIGEVM 0xff
#define BPWDB 0xff00
#define BSGIEN 0x10000
#define BSFACTOR_QMA1 0xf
#define BSFACTOR_QMA2 0xf0
#define BSFACTOR_QMA3 0xf00
#define BSFACTOR_QMA4 0xf000
#define BSFACTOR_QMA5 0xf0000
#define BSFACTOR_QMA6 0xf0000
#define BSFACTOR_QMA7 0xf00000
#define BSFACTOR_QMA8 0xf000000
#define BSFACTOR_QMA9 0xf0000000
#define BCSI_SCHEME 0x100000
#define BNOISE_LVL_TOP_SET 0x3
#define BCHSMOOTH 0x4
#define BCHSMOOTH_CFG1 0x38
#define BCHSMOOTH_CFG2 0x1c0
#define BCHSMOOTH_CFG3 0xe00
#define BCHSMOOTH_CFG4 0x7000
#define BMRCMODE 0x800000
#define BTHEVMCFG 0x7000000
#define BLOOP_FIT_TYPE 0x1
#define BUPD_CFO 0x40
#define BUPD_CFO_OFFDATA 0x80
#define BADV_UPD_CFO 0x100
#define BADV_TIME_CTRL 0x800
#define BUPD_CLKO 0x1000
#define BFC 0x6000
#define BTRACKING_MODE 0x8000
#define BPHCMP_ENABLE 0x10000
#define BUPD_CLKO_LTF 0x20000
#define BCOM_CH_CFO 0x40000
#define BCSI_ESTI_MODE 0x80000
#define BADV_UPD_EQZ 0x100000
#define BUCHCFG 0x7000000
#define BUPDEQZ 0x8000000
#define BRX_PESUDO_NOISE_ON 0x20000000
#define BRX_PESUDO_NOISE_A 0xff
#define BRX_PESUDO_NOISE_B 0xff00
#define BRX_PESUDO_NOISE_C 0xff0000
#define BRX_PESUDO_NOISE_D 0xff000000
#define BRX_PESUDO_NOISESTATE_A 0xffff
#define BRX_PESUDO_NOISESTATE_B 0xffff0000
#define BRX_PESUDO_NOISESTATE_C 0xffff
#define BRX_PESUDO_NOISESTATE_D 0xffff0000
#define BZEBRA1_HSSIENABLE 0x8
#define BZEBRA1_TRXCONTROL 0xc00
#define BZEBRA1_TRXGAINSETTING 0x07f
#define BZEBRA1_RXCOUNTER 0xc00
#define BZEBRA1_TXCHANGEPUMP 0x38
#define BZEBRA1_RXCHANGEPUMP 0x7
#define BZEBRA1_CHANNEL_NUM 0xf80
#define BZEBRA1_TXLPFBW 0x400
#define BZEBRA1_RXLPFBW 0x600
#define BRTL8256REG_MODE_CTRL1 0x100
#define BRTL8256REG_MODE_CTRL0 0x40
#define BRTL8256REG_TXLPFBW 0x18
#define BRTL8256REG_RXLPFBW 0x600
#define BRTL8258_TXLPFBW 0xc
#define BRTL8258_RXLPFBW 0xc00
#define BRTL8258_RSSILPFBW 0xc0
#define BBYTE0 0x1
#define BBYTE1 0x2
#define BBYTE2 0x4
#define BBYTE3 0x8
#define BWORD0 0x3
#define BWORD1 0xc
#define BWORD 0xf
#define MASKBYTE0 0xff
#define MASKBYTE1 0xff00
#define MASKBYTE2 0xff0000
#define MASKBYTE3 0xff000000
#define MASKHWORD 0xffff0000
#define MASKLWORD 0x0000ffff
#define MASKDWORD 0xffffffff
#define MASK12BITS 0xfff
#define MASKH4BITS 0xf0000000
#define MASKOFDM_D 0xffc00000
#define MASKCCK 0x3f3f3f3f
#define MASK4BITS 0x0f
#define MASK20BITS 0xfffff
#define RFREG_OFFSET_MASK 0xfffff
#define BENABLE 0x1
#define BDISABLE 0x0
#define LEFT_ANTENNA 0x0
#define RIGHT_ANTENNA 0x1
#define TCHECK_TXSTATUS 500
#define TUPDATE_RXCOUNTER 100
#define REG_UN_USED_REGISTER 0x01bf
/* WOL bit information */
#define HAL92C_WOL_PTK_UPDATE_EVENT BIT(0)
#define HAL92C_WOL_GTK_UPDATE_EVENT BIT(1)
#define HAL92C_WOL_DISASSOC_EVENT BIT(2)
#define HAL92C_WOL_DEAUTH_EVENT BIT(3)
#define HAL92C_WOL_FW_DISCONNECT_EVENT BIT(4)
#define WOL_REASON_PTK_UPDATE BIT(0)
#define WOL_REASON_GTK_UPDATE BIT(1)
#define WOL_REASON_DISASSOC BIT(2)
#define WOL_REASON_DEAUTH BIT(3)
#define WOL_REASON_FW_DISCONNECT BIT(4)
#endif
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "wifi.h"
#include "reg.h"
#include "def.h"
#include "phy.h"
#include "rf.h"
#include "dm.h"
void rtl88e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
switch (bandwidth) {
case HT_CHANNEL_WIDTH_20:
rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
0xfffff3ff) | BIT(10) | BIT(11));
rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
rtlphy->rfreg_chnlval[0]);
break;
case HT_CHANNEL_WIDTH_20_40:
rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
0xfffff3ff) | BIT(10));
rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
rtlphy->rfreg_chnlval[0]);
break;
default:
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"unknown bandwidth: %#X\n", bandwidth);
break;
}
}
void rtl88e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
u8 *plevel)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
u32 tx_agc[2] = {0, 0}, tmpval;
bool turbo_scanoff = false;
u8 idx1, idx2;
u8 *ptr;
u8 direction;
u32 pwrtrac_value;
if (rtlefuse->eeprom_regulatory != 0)
turbo_scanoff = true;
if (mac->act_scanning == true) {
tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
if (turbo_scanoff) {
for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
tx_agc[idx1] = plevel[idx1] |
(plevel[idx1] << 8) |
(plevel[idx1] << 16) |
(plevel[idx1] << 24);
}
}
} else {
for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
tx_agc[idx1] = plevel[idx1] | (plevel[idx1] << 8) |
(plevel[idx1] << 16) |
(plevel[idx1] << 24);
}
if (rtlefuse->eeprom_regulatory == 0) {
tmpval = (rtlphy->mcs_offset[0][6]) +
(rtlphy->mcs_offset[0][7] << 8);
tx_agc[RF90_PATH_A] += tmpval;
tmpval = (rtlphy->mcs_offset[0][14]) +
(rtlphy->mcs_offset[0][15] << 24);
tx_agc[RF90_PATH_B] += tmpval;
}
}
for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
ptr = (u8 *)(&(tx_agc[idx1]));
for (idx2 = 0; idx2 < 4; idx2++) {
if (*ptr > RF6052_MAX_TX_PWR)
*ptr = RF6052_MAX_TX_PWR;
ptr++;
}
}
rtl88e_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value);
if (direction == 1) {
tx_agc[0] += pwrtrac_value;
tx_agc[1] += pwrtrac_value;
} else if (direction == 2) {
tx_agc[0] -= pwrtrac_value;
tx_agc[1] -= pwrtrac_value;
}
tmpval = tx_agc[RF90_PATH_A] & 0xff;
rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
"CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
RTXAGC_A_CCK1_MCS32);
tmpval = tx_agc[RF90_PATH_A] >> 8;
rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
"CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
RTXAGC_B_CCK11_A_CCK2_11);
tmpval = tx_agc[RF90_PATH_B] >> 24;
rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
"CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
RTXAGC_B_CCK11_A_CCK2_11);
tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff;
rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
"CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
RTXAGC_B_CCK1_55_MCS32);
}
static void rtl88e_phy_get_power_base(struct ieee80211_hw *hw,
u8 *pwrlvlofdm, u8 *pwrlvlbw20,
u8 *pwrlvlbw40, u8 channel,
u32 *ofdmbase, u32 *mcsbase)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
u32 base0, base1;
u8 i, powerlevel[2];
for (i = 0; i < 2; i++) {
base0 = pwrlvlofdm[i];
base0 = (base0 << 24) | (base0 << 16) |
(base0 << 8) | base0;
*(ofdmbase + i) = base0;
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
"[OFDM power base index rf(%c) = 0x%x]\n",
((i == 0) ? 'A' : 'B'), *(ofdmbase + i));
}
for (i = 0; i < 2; i++) {
if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20)
powerlevel[i] = pwrlvlbw20[i];
else
powerlevel[i] = pwrlvlbw40[i];
base1 = powerlevel[i];
base1 = (base1 << 24) |
(base1 << 16) | (base1 << 8) | base1;
*(mcsbase + i) = base1;
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
"[MCS power base index rf(%c) = 0x%x]\n",
((i == 0) ? 'A' : 'B'), *(mcsbase + i));
}
}
static void get_txpwr_by_reg(struct ieee80211_hw *hw, u8 chan, u8 index,
u32 *base0, u32 *base1, u32 *outval)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
u8 i, chg = 0, pwr_lim[4], pwr_diff = 0, cust_pwr_dif;
u32 writeval, cust_lim, rf, tmp;
u8 ch = chan - 1;
u8 j;
for (rf = 0; rf < 2; rf++) {
j = index + (rf ? 8 : 0);
tmp = ((index < 2) ? base0[rf] : base1[rf]);
switch (rtlefuse->eeprom_regulatory) {
case 0:
chg = 0;
writeval = rtlphy->mcs_offset[chg][j] + tmp;
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
"RTK better performance, "
"writeval(%c) = 0x%x\n",
((rf == 0) ? 'A' : 'B'), writeval);
break;
case 1:
if (rtlphy->pwrgroup_cnt == 1) {
chg = 0;
} else {
chg = chan / 3;
if (chan == 14)
chg = 5;
}
writeval = rtlphy->mcs_offset[chg][j] + tmp;
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
"Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n",
((rf == 0) ? 'A' : 'B'), writeval);
break;
case 2:
writeval = ((index < 2) ? base0[rf] : base1[rf]);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
"Better regulatory, writeval(%c) = 0x%x\n",
((rf == 0) ? 'A' : 'B'), writeval);
break;
case 3:
chg = 0;
if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
"customer's limit, 40MHz rf(%c) = 0x%x\n",
((rf == 0) ? 'A' : 'B'),
rtlefuse->pwrgroup_ht40[rf][ch]);
} else {
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
"customer's limit, 20MHz rf(%c) = 0x%x\n",
((rf == 0) ? 'A' : 'B'),
rtlefuse->pwrgroup_ht20[rf][ch]);
}
if (index < 2)
pwr_diff = rtlefuse->txpwr_legacyhtdiff[rf][ch];
else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20)
pwr_diff = rtlefuse->txpwr_ht20diff[rf][ch];
if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40)
cust_pwr_dif = rtlefuse->pwrgroup_ht40[rf][ch];
else
cust_pwr_dif = rtlefuse->pwrgroup_ht20[rf][ch];
if (pwr_diff > cust_pwr_dif)
pwr_diff = 0;
else
pwr_diff = cust_pwr_dif - pwr_diff;
for (i = 0; i < 4; i++) {
pwr_lim[i] = (u8)((rtlphy->mcs_offset[chg][j] &
(0x7f << (i * 8))) >> (i * 8));
if (pwr_lim[i] > pwr_diff)
pwr_lim[i] = pwr_diff;
}
cust_lim = (pwr_lim[3] << 24) | (pwr_lim[2] << 16) |
(pwr_lim[1] << 8) | (pwr_lim[0]);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
"Customer's limit rf(%c) = 0x%x\n",
((rf == 0) ? 'A' : 'B'), cust_lim);
writeval = cust_lim + tmp;
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
"Customer, writeval rf(%c) = 0x%x\n",
((rf == 0) ? 'A' : 'B'), writeval);
break;
default:
chg = 0;
writeval = rtlphy->mcs_offset[chg][j] + tmp;
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
"RTK better performance, writeval "
"rf(%c) = 0x%x\n",
((rf == 0) ? 'A' : 'B'), writeval);
break;
}
if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
writeval = writeval - 0x06060606;
else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
TXHIGHPWRLEVEL_BT2)
writeval -= 0x0c0c0c0c;
*(outval + rf) = writeval;
}
}
static void write_ofdm_pwr(struct ieee80211_hw *hw, u8 index, u32 *pvalue)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u16 regoffset_a[6] = {
RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24,
RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,
RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12
};
u16 regoffset_b[6] = {
RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24,
RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,
RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
};
u8 i, rf, pwr_val[4];
u32 writeval;
u16 regoffset;
for (rf = 0; rf < 2; rf++) {
writeval = pvalue[rf];
for (i = 0; i < 4; i++) {
pwr_val[i] = (u8) ((writeval & (0x7f <<
(i * 8))) >> (i * 8));
if (pwr_val[i] > RF6052_MAX_TX_PWR)
pwr_val[i] = RF6052_MAX_TX_PWR;
}
writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
(pwr_val[1] << 8) | pwr_val[0];
if (rf == 0)
regoffset = regoffset_a[index];
else
regoffset = regoffset_b[index];
rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval);
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
"Set 0x%x = %08x\n", regoffset, writeval);
}
}
void rtl88e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
u8 *pwrlvlofdm,
u8 *pwrlvlbw20,
u8 *pwrlvlbw40, u8 chan)
{
u32 writeval[2], base0[2], base1[2];
u8 index;
u8 direction;
u32 pwrtrac_value;
rtl88e_phy_get_power_base(hw, pwrlvlofdm, pwrlvlbw20,
pwrlvlbw40, chan, &base0[0],
&base1[0]);
rtl88e_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value);
for (index = 0; index < 6; index++) {
get_txpwr_by_reg(hw, chan, index, &base0[0], &base1[0],
&writeval[0]);
if (direction == 1) {
writeval[0] += pwrtrac_value;
writeval[1] += pwrtrac_value;
} else if (direction == 2) {
writeval[0] -= pwrtrac_value;
writeval[1] -= pwrtrac_value;
}
write_ofdm_pwr(hw, index, &writeval[0]);
}
}
static bool rf6052_conf_para(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
u32 u4val = 0;
u8 rfpath;
bool rtstatus = true;
struct bb_reg_def *pphyreg;
for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
pphyreg = &rtlphy->phyreg_def[rfpath];
switch (rfpath) {
case RF90_PATH_A:
case RF90_PATH_C:
u4val = rtl_get_bbreg(hw, pphyreg->rfintfs,
BRFSI_RFENV);
break;
case RF90_PATH_B:
case RF90_PATH_D:
u4val = rtl_get_bbreg(hw, pphyreg->rfintfs,
BRFSI_RFENV << 16);
break;
}
rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
udelay(1);
rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
udelay(1);
rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
B3WIREADDREAALENGTH, 0x0);
udelay(1);
rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
udelay(1);
switch (rfpath) {
case RF90_PATH_A:
rtstatus = rtl88e_phy_config_rf_with_headerfile(hw,
(enum radio_path)rfpath);
break;
case RF90_PATH_B:
rtstatus = rtl88e_phy_config_rf_with_headerfile(hw,
(enum radio_path)rfpath);
break;
case RF90_PATH_C:
break;
case RF90_PATH_D:
break;
}
switch (rfpath) {
case RF90_PATH_A:
case RF90_PATH_C:
rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV, u4val);
break;
case RF90_PATH_B:
case RF90_PATH_D:
rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16,
u4val);
break;
}
if (rtstatus != true) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
"Radio[%d] Fail!!", rfpath);
return false;
}
}
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n");
return rtstatus;
}
bool rtl88e_phy_rf6052_config(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
if (rtlphy->rf_type == RF_1T1R)
rtlphy->num_total_rfpath = 1;
else
rtlphy->num_total_rfpath = 2;
return rf6052_conf_para(hw);
}
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __RTL92C_RF_H__
#define __RTL92C_RF_H__
#define RF6052_MAX_TX_PWR 0x3F
#define RF6052_MAX_REG 0x3F
void rtl88e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw,
u8 bandwidth);
void rtl88e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
u8 *ppowerlevel);
void rtl88e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
u8 *ppowerlevel_ofdm,
u8 *ppowerlevel_bw20,
u8 *ppowerlevel_bw40, u8 channel);
bool rtl88e_phy_rf6052_config(struct ieee80211_hw *hw);
#endif
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "wifi.h"
#include "core.h"
#include "pci.h"
#include "reg.h"
#include "def.h"
#include "phy.h"
#include "dm.h"
#include "hw.h"
#include "sw.h"
#include "trx.h"
#include "led.h"
#include "table.h"
#include <linux/vmalloc.h>
#include <linux/module.h>
static void rtl88e_init_aspm_vars(struct ieee80211_hw *hw)
{
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
/*close ASPM for AMD defaultly */
rtlpci->const_amdpci_aspm = 0;
/* ASPM PS mode.
* 0 - Disable ASPM,
* 1 - Enable ASPM without Clock Req,
* 2 - Enable ASPM with Clock Req,
* 3 - Alwyas Enable ASPM with Clock Req,
* 4 - Always Enable ASPM without Clock Req.
* set defult to RTL8192CE:3 RTL8192E:2
*/
rtlpci->const_pci_aspm = 3;
/*Setting for PCI-E device */
rtlpci->const_devicepci_aspm_setting = 0x03;
/*Setting for PCI-E bridge */
rtlpci->const_hostpci_aspm_setting = 0x02;
/* In Hw/Sw Radio Off situation.
* 0 - Default,
* 1 - From ASPM setting without low Mac Pwr,
* 2 - From ASPM setting with low Mac Pwr,
* 3 - Bus D3
* set default to RTL8192CE:0 RTL8192SE:2
*/
rtlpci->const_hwsw_rfoff_d3 = 0;
/* This setting works for those device with
* backdoor ASPM setting such as EPHY setting.
* 0 - Not support ASPM,
* 1 - Support ASPM,
* 2 - According to chipset.
*/
rtlpci->const_support_pciaspm = 1;
}
int rtl88e_init_sw_vars(struct ieee80211_hw *hw)
{
int err = 0;
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
u8 tid;
rtl8188ee_bt_reg_init(hw);
rtlpriv->dm.dm_initialgain_enable = 1;
rtlpriv->dm.dm_flag = 0;
rtlpriv->dm.disable_framebursting = 0;
rtlpriv->dm.thermalvalue = 0;
rtlpci->transmit_config = CFENDFORM | BIT(15);
/* compatible 5G band 88ce just 2.4G band & smsp */
rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G;
rtlpriv->rtlhal.bandset = BAND_ON_2_4G;
rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY;
rtlpci->receive_config = (RCR_APPFCS |
RCR_APP_MIC |
RCR_APP_ICV |
RCR_APP_PHYST_RXFF |
RCR_HTC_LOC_CTRL |
RCR_AMF |
RCR_ACF |
RCR_ADF |
RCR_AICV |
RCR_ACRC32 |
RCR_AB |
RCR_AM |
RCR_APM |
0);
rtlpci->irq_mask[0] =
(u32) (IMR_PSTIMEOUT |
IMR_HSISR_IND_ON_INT |
IMR_C2HCMD |
IMR_HIGHDOK |
IMR_MGNTDOK |
IMR_BKDOK |
IMR_BEDOK |
IMR_VIDOK |
IMR_VODOK |
IMR_RDU |
IMR_ROK |
0);
rtlpci->irq_mask[1] = (u32) (IMR_RXFOVW | 0);
rtlpci->sys_irq_mask = (u32) (HSIMR_PDN_INT_EN | HSIMR_RON_INT_EN);
/* for debug level */
rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug;
/* for LPS & IPS */
rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
if (!rtlpriv->psc.inactiveps)
pr_info("rtl8188ee: Power Save off (module option)\n");
if (!rtlpriv->psc.fwctrl_lps)
pr_info("rtl8188ee: FW Power Save off (module option)\n");
rtlpriv->psc.reg_fwctrl_lps = 3;
rtlpriv->psc.reg_max_lps_awakeintvl = 5;
/* for ASPM, you can close aspm through
* set const_support_pciaspm = 0
*/
rtl88e_init_aspm_vars(hw);
if (rtlpriv->psc.reg_fwctrl_lps == 1)
rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE;
else if (rtlpriv->psc.reg_fwctrl_lps == 2)
rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE;
else if (rtlpriv->psc.reg_fwctrl_lps == 3)
rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE;
/* for firmware buf */
rtlpriv->rtlhal.pfirmware = vmalloc(0x8000);
if (!rtlpriv->rtlhal.pfirmware) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Can't alloc buffer for fw.\n");
return 1;
}
rtlpriv->cfg->fw_name = "rtlwifi/rtl8188efw.bin";
rtlpriv->max_fw_size = 0x8000;
pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
rtlpriv->io.dev, GFP_KERNEL, hw,
rtl_fw_cb);
if (err) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"Failed to request firmware!\n");
return 1;
}
/* for early mode */
rtlpriv->rtlhal.earlymode_enable = false;
rtlpriv->rtlhal.max_earlymode_num = 10;
for (tid = 0; tid < 8; tid++)
skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]);
/*low power */
rtlpriv->psc.low_power_enable = false;
if (rtlpriv->psc.low_power_enable) {
init_timer(&rtlpriv->works.fw_clockoff_timer);
setup_timer(&rtlpriv->works.fw_clockoff_timer,
rtl88ee_fw_clk_off_timer_callback,
(unsigned long)hw);
}
init_timer(&rtlpriv->works.fast_antenna_training_timer);
setup_timer(&rtlpriv->works.fast_antenna_training_timer,
rtl88e_dm_fast_antenna_training_callback,
(unsigned long)hw);
return err;
}
void rtl88e_deinit_sw_vars(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
if (rtlpriv->rtlhal.pfirmware) {
vfree(rtlpriv->rtlhal.pfirmware);
rtlpriv->rtlhal.pfirmware = NULL;
}
if (rtlpriv->psc.low_power_enable)
del_timer_sync(&rtlpriv->works.fw_clockoff_timer);
del_timer_sync(&rtlpriv->works.fast_antenna_training_timer);
}
static struct rtl_hal_ops rtl8188ee_hal_ops = {
.init_sw_vars = rtl88e_init_sw_vars,
.deinit_sw_vars = rtl88e_deinit_sw_vars,
.read_eeprom_info = rtl88ee_read_eeprom_info,
.interrupt_recognized = rtl88ee_interrupt_recognized,/*need check*/
.hw_init = rtl88ee_hw_init,
.hw_disable = rtl88ee_card_disable,
.hw_suspend = rtl88ee_suspend,
.hw_resume = rtl88ee_resume,
.enable_interrupt = rtl88ee_enable_interrupt,
.disable_interrupt = rtl88ee_disable_interrupt,
.set_network_type = rtl88ee_set_network_type,
.set_chk_bssid = rtl88ee_set_check_bssid,
.set_qos = rtl88ee_set_qos,
.set_bcn_reg = rtl88ee_set_beacon_related_registers,
.set_bcn_intv = rtl88ee_set_beacon_interval,
.update_interrupt_mask = rtl88ee_update_interrupt_mask,
.get_hw_reg = rtl88ee_get_hw_reg,
.set_hw_reg = rtl88ee_set_hw_reg,
.update_rate_tbl = rtl88ee_update_hal_rate_tbl,
.fill_tx_desc = rtl88ee_tx_fill_desc,
.fill_tx_cmddesc = rtl88ee_tx_fill_cmddesc,
.query_rx_desc = rtl88ee_rx_query_desc,
.set_channel_access = rtl88ee_update_channel_access_setting,
.radio_onoff_checking = rtl88ee_gpio_radio_on_off_checking,
.set_bw_mode = rtl88e_phy_set_bw_mode,
.switch_channel = rtl88e_phy_sw_chnl,
.dm_watchdog = rtl88e_dm_watchdog,
.scan_operation_backup = rtl88e_phy_scan_operation_backup,
.set_rf_power_state = rtl88e_phy_set_rf_power_state,
.led_control = rtl88ee_led_control,
.set_desc = rtl88ee_set_desc,
.get_desc = rtl88ee_get_desc,
.tx_polling = rtl88ee_tx_polling,
.enable_hw_sec = rtl88ee_enable_hw_security_config,
.set_key = rtl88ee_set_key,
.init_sw_leds = rtl88ee_init_sw_leds,
.allow_all_destaddr = rtl88ee_allow_all_destaddr,
.get_bbreg = rtl88e_phy_query_bb_reg,
.set_bbreg = rtl88e_phy_set_bb_reg,
.get_rfreg = rtl88e_phy_query_rf_reg,
.set_rfreg = rtl88e_phy_set_rf_reg,
};
static struct rtl_mod_params rtl88ee_mod_params = {
.sw_crypto = false,
.inactiveps = true,
.swctrl_lps = false,
.fwctrl_lps = true,
.debug = DBG_EMERG,
};
static struct rtl_hal_cfg rtl88ee_hal_cfg = {
.bar_id = 2,
.write_readback = true,
.name = "rtl88e_pci",
.ops = &rtl8188ee_hal_ops,
.mod_params = &rtl88ee_mod_params,
.maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL,
.maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN,
.maps[SYS_CLK] = REG_SYS_CLKR,
.maps[MAC_RCR_AM] = AM,
.maps[MAC_RCR_AB] = AB,
.maps[MAC_RCR_ACRC32] = ACRC32,
.maps[MAC_RCR_ACF] = ACF,
.maps[MAC_RCR_AAP] = AAP,
.maps[EFUSE_ACCESS] = REG_EFUSE_ACCESS,
.maps[EFUSE_TEST] = REG_EFUSE_TEST,
.maps[EFUSE_CTRL] = REG_EFUSE_CTRL,
.maps[EFUSE_CLK] = 0,
.maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL,
.maps[EFUSE_PWC_EV12V] = PWC_EV12V,
.maps[EFUSE_FEN_ELDR] = FEN_ELDR,
.maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN,
.maps[EFUSE_ANA8M] = ANA8M,
.maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE,
.maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION,
.maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN,
.maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES,
.maps[RWCAM] = REG_CAMCMD,
.maps[WCAMI] = REG_CAMWRITE,
.maps[RCAMO] = REG_CAMREAD,
.maps[CAMDBG] = REG_CAMDBG,
.maps[SECR] = REG_SECCFG,
.maps[SEC_CAM_NONE] = CAM_NONE,
.maps[SEC_CAM_WEP40] = CAM_WEP40,
.maps[SEC_CAM_TKIP] = CAM_TKIP,
.maps[SEC_CAM_AES] = CAM_AES,
.maps[SEC_CAM_WEP104] = CAM_WEP104,
.maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6,
.maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5,
.maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4,
.maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3,
.maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2,
.maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1,
/* .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, */ /*need check*/
.maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7,
.maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6,
.maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5,
.maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4,
.maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3,
.maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2,
.maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1,
/* .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,*/
/* .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,*/
.maps[RTL_IMR_TXFOVW] = IMR_TXFOVW,
.maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT,
.maps[RTL_IMR_BCNINT] = IMR_BCNDMAINT0,
.maps[RTL_IMR_RXFOVW] = IMR_RXFOVW,
.maps[RTL_IMR_RDU] = IMR_RDU,
.maps[RTL_IMR_ATIMEND] = IMR_ATIMEND,
.maps[RTL_IMR_BDOK] = IMR_BCNDOK0,
.maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK,
.maps[RTL_IMR_TBDER] = IMR_TBDER,
.maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK,
.maps[RTL_IMR_TBDOK] = IMR_TBDOK,
.maps[RTL_IMR_BKDOK] = IMR_BKDOK,
.maps[RTL_IMR_BEDOK] = IMR_BEDOK,
.maps[RTL_IMR_VIDOK] = IMR_VIDOK,
.maps[RTL_IMR_VODOK] = IMR_VODOK,
.maps[RTL_IMR_ROK] = IMR_ROK,
.maps[RTL_IBSS_INT_MASKS] = (IMR_BCNDMAINT0 | IMR_TBDOK | IMR_TBDER),
.maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M,
.maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M,
.maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M,
.maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M,
.maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M,
.maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M,
.maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M,
.maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M,
.maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M,
.maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M,
.maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M,
.maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M,
.maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7,
.maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15,
};
static DEFINE_PCI_DEVICE_TABLE(rtl88ee_pci_ids) = {
{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8179, rtl88ee_hal_cfg)},
{},
};
MODULE_DEVICE_TABLE(pci, rtl88ee_pci_ids);
MODULE_AUTHOR("zhiyuan_yang <zhiyuan_yang@realsil.com.cn>");
MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek 8188E 802.11n PCI wireless");
MODULE_FIRMWARE("rtlwifi/rtl8188efw.bin");
module_param_named(swenc, rtl88ee_mod_params.sw_crypto, bool, 0444);
module_param_named(debug, rtl88ee_mod_params.debug, int, 0444);
module_param_named(ips, rtl88ee_mod_params.inactiveps, bool, 0444);
module_param_named(swlps, rtl88ee_mod_params.swctrl_lps, bool, 0444);
module_param_named(fwlps, rtl88ee_mod_params.fwctrl_lps, bool, 0444);
MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
static struct pci_driver rtl88ee_driver = {
.name = KBUILD_MODNAME,
.id_table = rtl88ee_pci_ids,
.probe = rtl_pci_probe,
.remove = rtl_pci_disconnect,
.driver.pm = &rtlwifi_pm_ops,
};
module_pci_driver(rtl88ee_driver);
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __RTL92CE_SW_H__
#define __RTL92CE_SW_H__
int rtl88e_init_sw_vars(struct ieee80211_hw *hw);
void rtl88e_deinit_sw_vars(struct ieee80211_hw *hw);
#endif
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Created on 2010/ 5/18, 1:41
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "table.h"
u32 RTL8188EEPHY_REG_1TARRAY[] = {
0x800, 0x80040000,
0x804, 0x00000003,
0x808, 0x0000FC00,
0x80C, 0x0000000A,
0x810, 0x10001331,
0x814, 0x020C3D10,
0x818, 0x02200385,
0x81C, 0x00000000,
0x820, 0x01000100,
0x824, 0x00390204,
0x828, 0x00000000,
0x82C, 0x00000000,
0x830, 0x00000000,
0x834, 0x00000000,
0x838, 0x00000000,
0x83C, 0x00000000,
0x840, 0x00010000,
0x844, 0x00000000,
0x848, 0x00000000,
0x84C, 0x00000000,
0x850, 0x00000000,
0x854, 0x00000000,
0x858, 0x569A11A9,
0x85C, 0x01000014,
0x860, 0x66F60110,
0x864, 0x061F0649,
0x868, 0x00000000,
0x86C, 0x27272700,
0x870, 0x07000760,
0x874, 0x25004000,
0x878, 0x00000808,
0x87C, 0x00000000,
0x880, 0xB0000C1C,
0x884, 0x00000001,
0x888, 0x00000000,
0x88C, 0xCCC000C0,
0x890, 0x00000800,
0x894, 0xFFFFFFFE,
0x898, 0x40302010,
0x89C, 0x00706050,
0x900, 0x00000000,
0x904, 0x00000023,
0x908, 0x00000000,
0x90C, 0x81121111,
0x910, 0x00000002,
0x914, 0x00000201,
0xA00, 0x00D047C8,
0xA04, 0x80FF000C,
0xA08, 0x8C838300,
0xA0C, 0x2E7F120F,
0xA10, 0x9500BB78,
0xA14, 0x1114D028,
0xA18, 0x00881117,
0xA1C, 0x89140F00,
0xA20, 0x1A1B0000,
0xA24, 0x090E1317,
0xA28, 0x00000204,
0xA2C, 0x00D30000,
0xA70, 0x101FBF00,
0xA74, 0x00000007,
0xA78, 0x00000900,
0xA7C, 0x225B0606,
0xA80, 0x218075B1,
0xB2C, 0x80000000,
0xC00, 0x48071D40,
0xC04, 0x03A05611,
0xC08, 0x000000E4,
0xC0C, 0x6C6C6C6C,
0xC10, 0x08800000,
0xC14, 0x40000100,
0xC18, 0x08800000,
0xC1C, 0x40000100,
0xC20, 0x00000000,
0xC24, 0x00000000,
0xC28, 0x00000000,
0xC2C, 0x00000000,
0xC30, 0x69E9AC47,
0xC34, 0x469652AF,
0xC38, 0x49795994,
0xC3C, 0x0A97971C,
0xC40, 0x1F7C403F,
0xC44, 0x000100B7,
0xC48, 0xEC020107,
0xC4C, 0x007F037F,
0xC50, 0x69553420,
0xC54, 0x43BC0094,
0xC58, 0x00013169,
0xC5C, 0x00250492,
0xC60, 0x00000000,
0xC64, 0x7112848B,
0xC68, 0x47C00BFF,
0xC6C, 0x00000036,
0xC70, 0x2C7F000D,
0xC74, 0x020610DB,
0xC78, 0x0000001F,
0xC7C, 0x00B91612,
0xC80, 0x390000E4,
0xC84, 0x20F60000,
0xC88, 0x40000100,
0xC8C, 0x20200000,
0xC90, 0x00091521,
0xC94, 0x00000000,
0xC98, 0x00121820,
0xC9C, 0x00007F7F,
0xCA0, 0x00000000,
0xCA4, 0x000300A0,
0xCA8, 0x00000000,
0xCAC, 0x00000000,
0xCB0, 0x00000000,
0xCB4, 0x00000000,
0xCB8, 0x00000000,
0xCBC, 0x28000000,
0xCC0, 0x00000000,
0xCC4, 0x00000000,
0xCC8, 0x00000000,
0xCCC, 0x00000000,
0xCD0, 0x00000000,
0xCD4, 0x00000000,
0xCD8, 0x64B22427,
0xCDC, 0x00766932,
0xCE0, 0x00222222,
0xCE4, 0x00000000,
0xCE8, 0x37644302,
0xCEC, 0x2F97D40C,
0xD00, 0x00000740,
0xD04, 0x00020401,
0xD08, 0x0000907F,
0xD0C, 0x20010201,
0xD10, 0xA0633333,
0xD14, 0x3333BC43,
0xD18, 0x7A8F5B6F,
0xD2C, 0xCC979975,
0xD30, 0x00000000,
0xD34, 0x80608000,
0xD38, 0x00000000,
0xD3C, 0x00127353,
0xD40, 0x00000000,
0xD44, 0x00000000,
0xD48, 0x00000000,
0xD4C, 0x00000000,
0xD50, 0x6437140A,
0xD54, 0x00000000,
0xD58, 0x00000282,
0xD5C, 0x30032064,
0xD60, 0x4653DE68,
0xD64, 0x04518A3C,
0xD68, 0x00002101,
0xD6C, 0x2A201C16,
0xD70, 0x1812362E,
0xD74, 0x322C2220,
0xD78, 0x000E3C24,
0xE00, 0x2D2D2D2D,
0xE04, 0x2D2D2D2D,
0xE08, 0x0390272D,
0xE10, 0x2D2D2D2D,
0xE14, 0x2D2D2D2D,
0xE18, 0x2D2D2D2D,
0xE1C, 0x2D2D2D2D,
0xE28, 0x00000000,
0xE30, 0x1000DC1F,
0xE34, 0x10008C1F,
0xE38, 0x02140102,
0xE3C, 0x681604C2,
0xE40, 0x01007C00,
0xE44, 0x01004800,
0xE48, 0xFB000000,
0xE4C, 0x000028D1,
0xE50, 0x1000DC1F,
0xE54, 0x10008C1F,
0xE58, 0x02140102,
0xE5C, 0x28160D05,
0xE60, 0x00000008,
0xE68, 0x001B25A4,
0xE6C, 0x00C00014,
0xE70, 0x00C00014,
0xE74, 0x01000014,
0xE78, 0x01000014,
0xE7C, 0x01000014,
0xE80, 0x01000014,
0xE84, 0x00C00014,
0xE88, 0x01000014,
0xE8C, 0x00C00014,
0xED0, 0x00C00014,
0xED4, 0x00C00014,
0xED8, 0x00C00014,
0xEDC, 0x00000014,
0xEE0, 0x00000014,
0xEEC, 0x01C00014,
0xF14, 0x00000003,
0xF4C, 0x00000000,
0xF00, 0x00000300,
};
u32 RTL8188EEPHY_REG_ARRAY_PG[] = {
0xE00, 0xFFFFFFFF, 0x06070809,
0xE04, 0xFFFFFFFF, 0x02020405,
0xE08, 0x0000FF00, 0x00000006,
0x86C, 0xFFFFFF00, 0x00020400,
0xE10, 0xFFFFFFFF, 0x08090A0B,
0xE14, 0xFFFFFFFF, 0x01030607,
0xE18, 0xFFFFFFFF, 0x08090A0B,
0xE1C, 0xFFFFFFFF, 0x01030607,
0xE00, 0xFFFFFFFF, 0x00000000,
0xE04, 0xFFFFFFFF, 0x00000000,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x02020202,
0xE04, 0xFFFFFFFF, 0x00020202,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x04040404,
0xE14, 0xFFFFFFFF, 0x00020404,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x02020202,
0xE04, 0xFFFFFFFF, 0x00020202,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x04040404,
0xE14, 0xFFFFFFFF, 0x00020404,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x00000000,
0xE04, 0xFFFFFFFF, 0x00000000,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x02020202,
0xE04, 0xFFFFFFFF, 0x00020202,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x04040404,
0xE14, 0xFFFFFFFF, 0x00020404,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x00000000,
0xE04, 0xFFFFFFFF, 0x00000000,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x00000000,
0xE04, 0xFFFFFFFF, 0x00000000,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x00000000,
0xE04, 0xFFFFFFFF, 0x00000000,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x00000000,
0xE04, 0xFFFFFFFF, 0x00000000,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x00000000,
0xE04, 0xFFFFFFFF, 0x00000000,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
};
u32 RTL8188EE_RADIOA_1TARRAY[] = {
0x000, 0x00030000,
0x008, 0x00084000,
0x018, 0x00000407,
0x019, 0x00000012,
0x01E, 0x00080009,
0x01F, 0x00000880,
0x02F, 0x0001A060,
0x03F, 0x00000000,
0x042, 0x000060C0,
0x057, 0x000D0000,
0x058, 0x000BE180,
0x067, 0x00001552,
0x083, 0x00000000,
0x0B0, 0x000FF8FC,
0x0B1, 0x00054400,
0x0B2, 0x000CCC19,
0x0B4, 0x00043003,
0x0B6, 0x0004953E,
0x0B7, 0x0001C718,
0x0B8, 0x000060FF,
0x0B9, 0x00080001,
0x0BA, 0x00040000,
0x0BB, 0x00000400,
0x0BF, 0x000C0000,
0x0C2, 0x00002400,
0x0C3, 0x00000009,
0x0C4, 0x00040C91,
0x0C5, 0x00099999,
0x0C6, 0x000000A3,
0x0C7, 0x00088820,
0x0C8, 0x00076C06,
0x0C9, 0x00000000,
0x0CA, 0x00080000,
0x0DF, 0x00000180,
0x0EF, 0x000001A0,
0x051, 0x0006B27D,
0x052, 0x0007E49D,
0x053, 0x00000073,
0x056, 0x00051FF3,
0x035, 0x00000086,
0x035, 0x00000186,
0x035, 0x00000286,
0x036, 0x00001C25,
0x036, 0x00009C25,
0x036, 0x00011C25,
0x036, 0x00019C25,
0x0B6, 0x00048538,
0x018, 0x00000C07,
0x05A, 0x0004BD00,
0x019, 0x000739D0,
0x034, 0x0000ADF3,
0x034, 0x00009DF0,
0x034, 0x00008DED,
0x034, 0x00007DEA,
0x034, 0x00006DE7,
0x034, 0x000054EE,
0x034, 0x000044EB,
0x034, 0x000034E8,
0x034, 0x0000246B,
0x034, 0x00001468,
0x034, 0x0000006D,
0x000, 0x00030159,
0x084, 0x00068200,
0x086, 0x000000CE,
0x087, 0x00048A00,
0x08E, 0x00065540,
0x08F, 0x00088000,
0x0EF, 0x000020A0,
0x03B, 0x000F02B0,
0x03B, 0x000EF7B0,
0x03B, 0x000D4FB0,
0x03B, 0x000CF060,
0x03B, 0x000B0090,
0x03B, 0x000A0080,
0x03B, 0x00090080,
0x03B, 0x0008F780,
0x03B, 0x000722B0,
0x03B, 0x0006F7B0,
0x03B, 0x00054FB0,
0x03B, 0x0004F060,
0x03B, 0x00030090,
0x03B, 0x00020080,
0x03B, 0x00010080,
0x03B, 0x0000F780,
0x0EF, 0x000000A0,
0x000, 0x00010159,
0x018, 0x0000F407,
0xFFE, 0x00000000,
0xFFE, 0x00000000,
0x01F, 0x00080003,
0xFFE, 0x00000000,
0xFFE, 0x00000000,
0x01E, 0x00000001,
0x01F, 0x00080000,
0x000, 0x00033E60,
};
u32 RTL8188EEMAC_1T_ARRAY[] = {
0x026, 0x00000041,
0x027, 0x00000035,
0x428, 0x0000000A,
0x429, 0x00000010,
0x430, 0x00000000,
0x431, 0x00000001,
0x432, 0x00000002,
0x433, 0x00000004,
0x434, 0x00000005,
0x435, 0x00000006,
0x436, 0x00000007,
0x437, 0x00000008,
0x438, 0x00000000,
0x439, 0x00000000,
0x43A, 0x00000001,
0x43B, 0x00000002,
0x43C, 0x00000004,
0x43D, 0x00000005,
0x43E, 0x00000006,
0x43F, 0x00000007,
0x440, 0x0000005D,
0x441, 0x00000001,
0x442, 0x00000000,
0x444, 0x00000015,
0x445, 0x000000F0,
0x446, 0x0000000F,
0x447, 0x00000000,
0x458, 0x00000041,
0x459, 0x000000A8,
0x45A, 0x00000072,
0x45B, 0x000000B9,
0x460, 0x00000066,
0x461, 0x00000066,
0x480, 0x00000008,
0x4C8, 0x000000FF,
0x4C9, 0x00000008,
0x4CC, 0x000000FF,
0x4CD, 0x000000FF,
0x4CE, 0x00000001,
0x4D3, 0x00000001,
0x500, 0x00000026,
0x501, 0x000000A2,
0x502, 0x0000002F,
0x503, 0x00000000,
0x504, 0x00000028,
0x505, 0x000000A3,
0x506, 0x0000005E,
0x507, 0x00000000,
0x508, 0x0000002B,
0x509, 0x000000A4,
0x50A, 0x0000005E,
0x50B, 0x00000000,
0x50C, 0x0000004F,
0x50D, 0x000000A4,
0x50E, 0x00000000,
0x50F, 0x00000000,
0x512, 0x0000001C,
0x514, 0x0000000A,
0x516, 0x0000000A,
0x525, 0x0000004F,
0x550, 0x00000010,
0x551, 0x00000010,
0x559, 0x00000002,
0x55D, 0x000000FF,
0x605, 0x00000030,
0x608, 0x0000000E,
0x609, 0x0000002A,
0x620, 0x000000FF,
0x621, 0x000000FF,
0x622, 0x000000FF,
0x623, 0x000000FF,
0x624, 0x000000FF,
0x625, 0x000000FF,
0x626, 0x000000FF,
0x627, 0x000000FF,
0x652, 0x00000020,
0x63C, 0x0000000A,
0x63D, 0x0000000A,
0x63E, 0x0000000E,
0x63F, 0x0000000E,
0x640, 0x00000040,
0x66E, 0x00000005,
0x700, 0x00000021,
0x701, 0x00000043,
0x702, 0x00000065,
0x703, 0x00000087,
0x708, 0x00000021,
0x709, 0x00000043,
0x70A, 0x00000065,
0x70B, 0x00000087,
};
u32 RTL8188EEAGCTAB_1TARRAY[] = {
0xC78, 0xFB000001,
0xC78, 0xFB010001,
0xC78, 0xFB020001,
0xC78, 0xFB030001,
0xC78, 0xFB040001,
0xC78, 0xFB050001,
0xC78, 0xFA060001,
0xC78, 0xF9070001,
0xC78, 0xF8080001,
0xC78, 0xF7090001,
0xC78, 0xF60A0001,
0xC78, 0xF50B0001,
0xC78, 0xF40C0001,
0xC78, 0xF30D0001,
0xC78, 0xF20E0001,
0xC78, 0xF10F0001,
0xC78, 0xF0100001,
0xC78, 0xEF110001,
0xC78, 0xEE120001,
0xC78, 0xED130001,
0xC78, 0xEC140001,
0xC78, 0xEB150001,
0xC78, 0xEA160001,
0xC78, 0xE9170001,
0xC78, 0xE8180001,
0xC78, 0xE7190001,
0xC78, 0xE61A0001,
0xC78, 0xE51B0001,
0xC78, 0xE41C0001,
0xC78, 0xE31D0001,
0xC78, 0xE21E0001,
0xC78, 0xE11F0001,
0xC78, 0x8A200001,
0xC78, 0x89210001,
0xC78, 0x88220001,
0xC78, 0x87230001,
0xC78, 0x86240001,
0xC78, 0x85250001,
0xC78, 0x84260001,
0xC78, 0x83270001,
0xC78, 0x82280001,
0xC78, 0x6B290001,
0xC78, 0x6A2A0001,
0xC78, 0x692B0001,
0xC78, 0x682C0001,
0xC78, 0x672D0001,
0xC78, 0x662E0001,
0xC78, 0x652F0001,
0xC78, 0x64300001,
0xC78, 0x63310001,
0xC78, 0x62320001,
0xC78, 0x61330001,
0xC78, 0x46340001,
0xC78, 0x45350001,
0xC78, 0x44360001,
0xC78, 0x43370001,
0xC78, 0x42380001,
0xC78, 0x41390001,
0xC78, 0x403A0001,
0xC78, 0x403B0001,
0xC78, 0x403C0001,
0xC78, 0x403D0001,
0xC78, 0x403E0001,
0xC78, 0x403F0001,
0xC78, 0xFB400001,
0xC78, 0xFB410001,
0xC78, 0xFB420001,
0xC78, 0xFB430001,
0xC78, 0xFB440001,
0xC78, 0xFB450001,
0xC78, 0xFB460001,
0xC78, 0xFB470001,
0xC78, 0xFB480001,
0xC78, 0xFA490001,
0xC78, 0xF94A0001,
0xC78, 0xF84B0001,
0xC78, 0xF74C0001,
0xC78, 0xF64D0001,
0xC78, 0xF54E0001,
0xC78, 0xF44F0001,
0xC78, 0xF3500001,
0xC78, 0xF2510001,
0xC78, 0xF1520001,
0xC78, 0xF0530001,
0xC78, 0xEF540001,
0xC78, 0xEE550001,
0xC78, 0xED560001,
0xC78, 0xEC570001,
0xC78, 0xEB580001,
0xC78, 0xEA590001,
0xC78, 0xE95A0001,
0xC78, 0xE85B0001,
0xC78, 0xE75C0001,
0xC78, 0xE65D0001,
0xC78, 0xE55E0001,
0xC78, 0xE45F0001,
0xC78, 0xE3600001,
0xC78, 0xE2610001,
0xC78, 0xC3620001,
0xC78, 0xC2630001,
0xC78, 0xC1640001,
0xC78, 0x8B650001,
0xC78, 0x8A660001,
0xC78, 0x89670001,
0xC78, 0x88680001,
0xC78, 0x87690001,
0xC78, 0x866A0001,
0xC78, 0x856B0001,
0xC78, 0x846C0001,
0xC78, 0x676D0001,
0xC78, 0x666E0001,
0xC78, 0x656F0001,
0xC78, 0x64700001,
0xC78, 0x63710001,
0xC78, 0x62720001,
0xC78, 0x61730001,
0xC78, 0x60740001,
0xC78, 0x46750001,
0xC78, 0x45760001,
0xC78, 0x44770001,
0xC78, 0x43780001,
0xC78, 0x42790001,
0xC78, 0x417A0001,
0xC78, 0x407B0001,
0xC78, 0x407C0001,
0xC78, 0x407D0001,
0xC78, 0x407E0001,
0xC78, 0x407F0001,
};
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Created on 2010/ 5/18, 1:41
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __RTL92CE_TABLE__H_
#define __RTL92CE_TABLE__H_
#include <linux/types.h>
#define RTL8188EEPHY_REG_1TARRAYLEN 382
extern u32 RTL8188EEPHY_REG_1TARRAY[];
#define RTL8188EEPHY_REG_ARRAY_PGLEN 264
extern u32 RTL8188EEPHY_REG_ARRAY_PG[];
#define RTL8188EE_RADIOA_1TARRAYLEN 190
extern u32 RTL8188EE_RADIOA_1TARRAY[];
#define RTL8188EEMAC_1T_ARRAYLEN 180
extern u32 RTL8188EEMAC_1T_ARRAY[];
#define RTL8188EEAGCTAB_1TARRAYLEN 256
extern u32 RTL8188EEAGCTAB_1TARRAY[];
#endif
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include "wifi.h"
#include "pci.h"
#include "base.h"
#include "stats.h"
#include "reg.h"
#include "def.h"
#include "phy.h"
#include "trx.h"
#include "led.h"
#include "dm.h"
static u8 _rtl88ee_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
{
__le16 fc = rtl_get_fc(skb);
if (unlikely(ieee80211_is_beacon(fc)))
return QSLT_BEACON;
if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc))
return QSLT_MGNT;
return skb->priority;
}
static void _rtl88ee_query_rxphystatus(struct ieee80211_hw *hw,
struct rtl_stats *pstatus, u8 *pdesc,
struct rx_fwinfo_88e *p_drvinfo,
bool bpacket_match_bssid,
bool bpacket_toself, bool packet_beacon)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
struct phy_sts_cck_8192s_t *cck_buf;
struct phy_status_rpt *phystrpt = (struct phy_status_rpt *)p_drvinfo;
struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
char rx_pwr_all = 0, rx_pwr[4];
u8 rf_rx_num = 0, evm, pwdb_all;
u8 i, max_spatial_stream;
u32 rssi, total_rssi = 0;
bool is_cck = pstatus->is_cck;
u8 lan_idx, vga_idx;
/* Record it for next packet processing */
pstatus->packet_matchbssid = bpacket_match_bssid;
pstatus->packet_toself = bpacket_toself;
pstatus->packet_beacon = packet_beacon;
pstatus->rx_mimo_sig_qual[0] = -1;
pstatus->rx_mimo_sig_qual[1] = -1;
if (is_cck) {
u8 cck_hipwr;
u8 cck_agc_rpt;
/* CCK Driver info Structure is not the same as OFDM packet. */
cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
cck_agc_rpt = cck_buf->cck_agc_rpt;
/* (1)Hardware does not provide RSSI for CCK
* (2)PWDB, Average PWDB cacluated by
* hardware (for rate adaptive)
*/
if (ppsc->rfpwr_state == ERFON)
cck_hipwr = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2,
BIT(9));
else
cck_hipwr = false;
lan_idx = ((cck_agc_rpt & 0xE0) >> 5);
vga_idx = (cck_agc_rpt & 0x1f);
switch (lan_idx) {
case 7:
if (vga_idx <= 27)
rx_pwr_all = -100 + 2 * (27 - vga_idx);
else
rx_pwr_all = -100;
break;
case 6:
rx_pwr_all = -48 + 2 * (2 - vga_idx); /*VGA_idx = 2~0*/
break;
case 5:
rx_pwr_all = -42 + 2 * (7 - vga_idx); /*VGA_idx = 7~5*/
break;
case 4:
rx_pwr_all = -36 + 2 * (7 - vga_idx); /*VGA_idx = 7~4*/
break;
case 3:
rx_pwr_all = -24 + 2 * (7 - vga_idx); /*VGA_idx = 7~0*/
break;
case 2:
if (cck_hipwr)
rx_pwr_all = -12 + 2 * (5 - vga_idx);
else
rx_pwr_all = -6 + 2 * (5 - vga_idx);
break;
case 1:
rx_pwr_all = 8 - 2 * vga_idx;
break;
case 0:
rx_pwr_all = 14 - 2 * vga_idx;
break;
default:
break;
}
rx_pwr_all += 6;
pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
/* CCK gain is smaller than OFDM/MCS gain,
* so we add gain diff by experiences,
* the val is 6
*/
pwdb_all += 6;
if (pwdb_all > 100)
pwdb_all = 100;
/* modify the offset to make the same
* gain index with OFDM.
*/
if (pwdb_all > 34 && pwdb_all <= 42)
pwdb_all -= 2;
else if (pwdb_all > 26 && pwdb_all <= 34)
pwdb_all -= 6;
else if (pwdb_all > 14 && pwdb_all <= 26)
pwdb_all -= 8;
else if (pwdb_all > 4 && pwdb_all <= 14)
pwdb_all -= 4;
if (cck_hipwr == false) {
if (pwdb_all >= 80)
pwdb_all = ((pwdb_all - 80)<<1) +
((pwdb_all - 80)>>1) + 80;
else if ((pwdb_all <= 78) && (pwdb_all >= 20))
pwdb_all += 3;
if (pwdb_all > 100)
pwdb_all = 100;
}
pstatus->rx_pwdb_all = pwdb_all;
pstatus->recvsignalpower = rx_pwr_all;
/* (3) Get Signal Quality (EVM) */
if (bpacket_match_bssid) {
u8 sq;
if (pstatus->rx_pwdb_all > 40) {
sq = 100;
} else {
sq = cck_buf->sq_rpt;
if (sq > 64)
sq = 0;
else if (sq < 20)
sq = 100;
else
sq = ((64 - sq) * 100) / 44;
}
pstatus->signalquality = sq;
pstatus->rx_mimo_sig_qual[0] = sq;
pstatus->rx_mimo_sig_qual[1] = -1;
}
} else {
rtlpriv->dm.rfpath_rxenable[0] =
rtlpriv->dm.rfpath_rxenable[1] = true;
/* (1)Get RSSI for HT rate */
for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) {
/* we will judge RF RX path now. */
if (rtlpriv->dm.rfpath_rxenable[i])
rf_rx_num++;
rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & 0x3f) * 2)-110;
/* Translate DBM to percentage. */
rssi = rtl_query_rxpwrpercentage(rx_pwr[i]);
total_rssi += rssi;
/* Get Rx snr value in DB */
rtlpriv->stats.rx_snr_db[i] = p_drvinfo->rxsnr[i] / 2;
/* Record Signal Strength for next packet */
if (bpacket_match_bssid)
pstatus->rx_mimo_signalstrength[i] = (u8) rssi;
}
/* (2)PWDB, Average PWDB cacluated by
* hardware (for rate adaptive)
*/
rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
pstatus->rx_pwdb_all = pwdb_all;
pstatus->rxpower = rx_pwr_all;
pstatus->recvsignalpower = rx_pwr_all;
/* (3)EVM of HT rate */
if (pstatus->is_ht && pstatus->rate >= DESC92C_RATEMCS8 &&
pstatus->rate <= DESC92C_RATEMCS15)
max_spatial_stream = 2;
else
max_spatial_stream = 1;
for (i = 0; i < max_spatial_stream; i++) {
evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]);
if (bpacket_match_bssid) {
/* Fill value in RFD, Get the first
* spatial stream only
*/
if (i == 0)
pstatus->signalquality = evm & 0xff;
pstatus->rx_mimo_sig_qual[i] = evm & 0xff;
}
}
}
/* UI BSS List signal strength(in percentage),
* make it good looking, from 0~100.
*/
if (is_cck)
pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw,
pwdb_all));
else if (rf_rx_num != 0)
pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw,
total_rssi /= rf_rx_num));
/*HW antenna diversity*/
rtldm->fat_table.antsel_rx_keep_0 = phystrpt->ant_sel;
rtldm->fat_table.antsel_rx_keep_1 = phystrpt->ant_sel_b;
rtldm->fat_table.antsel_rx_keep_2 = phystrpt->antsel_rx_keep_2;
}
static void _rtl88ee_smart_antenna(struct ieee80211_hw *hw,
struct rtl_stats *pstatus)
{
struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
u8 ant_mux;
struct fast_ant_training *pfat = &(rtldm->fat_table);
if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV) {
if (pfat->fat_state == FAT_TRAINING_STATE) {
if (pstatus->packet_toself) {
ant_mux = (pfat->antsel_rx_keep_2 << 2) |
(pfat->antsel_rx_keep_1 << 1) |
pfat->antsel_rx_keep_0;
pfat->ant_sum[ant_mux] += pstatus->rx_pwdb_all;
pfat->ant_cnt[ant_mux]++;
}
}
} else if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) ||
(rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV)) {
if (pstatus->packet_toself || pstatus->packet_matchbssid) {
ant_mux = (pfat->antsel_rx_keep_2 << 2) |
(pfat->antsel_rx_keep_1 << 1) |
pfat->antsel_rx_keep_0;
rtl88e_dm_ant_sel_statistics(hw, ant_mux, 0,
pstatus->rx_pwdb_all);
}
}
}
static void _rtl88ee_translate_rx_signal_stuff(struct ieee80211_hw *hw,
struct sk_buff *skb, struct rtl_stats *pstatus,
u8 *pdesc, struct rx_fwinfo_88e *p_drvinfo)
{
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct ieee80211_hdr *hdr;
u8 *tmp_buf;
u8 *praddr;
u8 *psaddr;
__le16 fc;
u16 type, ufc;
bool match_bssid, packet_toself, packet_beacon, addr;
tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift;
hdr = (struct ieee80211_hdr *)tmp_buf;
fc = hdr->frame_control;
ufc = le16_to_cpu(fc);
type = WLAN_FC_GET_TYPE(fc);
praddr = hdr->addr1;
psaddr = ieee80211_get_SA(hdr);
memcpy(pstatus->psaddr, psaddr, ETH_ALEN);
addr = (!compare_ether_addr(mac->bssid, (ufc & IEEE80211_FCTL_TODS) ?
hdr->addr1 : (ufc & IEEE80211_FCTL_FROMDS) ?
hdr->addr2 : hdr->addr3));
match_bssid = ((IEEE80211_FTYPE_CTL != type) && (!pstatus->hwerror) &&
(!pstatus->crc) && (!pstatus->icv)) && addr;
addr = (!compare_ether_addr(praddr, rtlefuse->dev_addr));
packet_toself = match_bssid && addr;
if (ieee80211_is_beacon(fc))
packet_beacon = true;
_rtl88ee_query_rxphystatus(hw, pstatus, pdesc, p_drvinfo,
match_bssid, packet_toself, packet_beacon);
_rtl88ee_smart_antenna(hw, pstatus);
rtl_process_phyinfo(hw, tmp_buf, pstatus);
}
static void insert_em(struct rtl_tcb_desc *ptcb_desc, u8 *virtualaddress)
{
u32 dwtmp = 0;
memset(virtualaddress, 0, 8);
SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num);
if (ptcb_desc->empkt_num == 1) {
dwtmp = ptcb_desc->empkt_len[0];
} else {
dwtmp = ptcb_desc->empkt_len[0];
dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
dwtmp += ptcb_desc->empkt_len[1];
}
SET_EARLYMODE_LEN0(virtualaddress, dwtmp);
if (ptcb_desc->empkt_num <= 3) {
dwtmp = ptcb_desc->empkt_len[2];
} else {
dwtmp = ptcb_desc->empkt_len[2];
dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
dwtmp += ptcb_desc->empkt_len[3];
}
SET_EARLYMODE_LEN1(virtualaddress, dwtmp);
if (ptcb_desc->empkt_num <= 5) {
dwtmp = ptcb_desc->empkt_len[4];
} else {
dwtmp = ptcb_desc->empkt_len[4];
dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
dwtmp += ptcb_desc->empkt_len[5];
}
SET_EARLYMODE_LEN2_1(virtualaddress, dwtmp & 0xF);
SET_EARLYMODE_LEN2_2(virtualaddress, dwtmp >> 4);
if (ptcb_desc->empkt_num <= 7) {
dwtmp = ptcb_desc->empkt_len[6];
} else {
dwtmp = ptcb_desc->empkt_len[6];
dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
dwtmp += ptcb_desc->empkt_len[7];
}
SET_EARLYMODE_LEN3(virtualaddress, dwtmp);
if (ptcb_desc->empkt_num <= 9) {
dwtmp = ptcb_desc->empkt_len[8];
} else {
dwtmp = ptcb_desc->empkt_len[8];
dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4;
dwtmp += ptcb_desc->empkt_len[9];
}
SET_EARLYMODE_LEN4(virtualaddress, dwtmp);
}
bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw,
struct rtl_stats *status,
struct ieee80211_rx_status *rx_status,
u8 *pdesc, struct sk_buff *skb)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rx_fwinfo_88e *p_drvinfo;
struct ieee80211_hdr *hdr;
u32 phystatus = GET_RX_DESC_PHYST(pdesc);
status->packet_report_type = (u8)GET_RX_STATUS_DESC_RPT_SEL(pdesc);
if (status->packet_report_type == TX_REPORT2)
status->length = (u16) GET_RX_RPT2_DESC_PKT_LEN(pdesc);
else
status->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
status->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) *
RX_DRV_INFO_SIZE_UNIT;
status->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03);
status->icv = (u16) GET_RX_DESC_ICV(pdesc);
status->crc = (u16) GET_RX_DESC_CRC32(pdesc);
status->hwerror = (status->crc | status->icv);
status->decrypted = !GET_RX_DESC_SWDEC(pdesc);
status->rate = (u8) GET_RX_DESC_RXMCS(pdesc);
status->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
status->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
status->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) &&
(GET_RX_DESC_FAGGR(pdesc) == 1));
if (status->packet_report_type == NORMAL_RX)
status->timestamp_low = GET_RX_DESC_TSFL(pdesc);
status->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc);
status->is_cck = RTL8188_RX_HAL_IS_CCK_RATE(status->rate);
status->macid = GET_RX_DESC_MACID(pdesc);
if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc))
status->wake_match = BIT(2);
else if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc))
status->wake_match = BIT(1);
else if (GET_RX_STATUS_DESC_UNICAST_MATCH(pdesc))
status->wake_match = BIT(0);
else
status->wake_match = 0;
if (status->wake_match)
RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD,
"Get Wakeup Packet!! WakeMatch =%d\n",
status->wake_match);
rx_status->freq = hw->conf.channel->center_freq;
rx_status->band = hw->conf.channel->band;
if (status->crc)
rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
if (status->rx_is40Mhzpacket)
rx_status->flag |= RX_FLAG_40MHZ;
if (status->is_ht)
rx_status->flag |= RX_FLAG_HT;
rx_status->flag |= RX_FLAG_MACTIME_START;
/* hw will set status->decrypted true, if it finds the
* frame is open data frame or mgmt frame.
* So hw will not decryption robust managment frame
* for IEEE80211w but still set status->decrypted
* true, so here we should set it back to undecrypted
* for IEEE80211w frame, and mac80211 sw will help
* to decrypt it
*/
if (status->decrypted) {
hdr = (struct ieee80211_hdr *)(skb->data +
status->rx_drvinfo_size + status->rx_bufshift);
if (!hdr) {
/* During testing, hdr was NULL */
return false;
}
if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
(ieee80211_has_protected(hdr->frame_control)))
rx_status->flag &= ~RX_FLAG_DECRYPTED;
else
rx_status->flag |= RX_FLAG_DECRYPTED;
}
/* rate_idx: index of data rate into band's
* supported rates or MCS index if HT rates
* are use (RX_FLAG_HT)
* Notice: this is diff with windows define
*/
rx_status->rate_idx = rtlwifi_rate_mapping(hw, status->is_ht,
status->rate, false);
rx_status->mactime = status->timestamp_low;
if (phystatus == true) {
p_drvinfo = (struct rx_fwinfo_88e *)(skb->data +
status->rx_bufshift);
_rtl88ee_translate_rx_signal_stuff(hw, skb, status, pdesc,
p_drvinfo);
}
/*rx_status->qual = status->signal; */
rx_status->signal = status->recvsignalpower + 10;
/*rx_status->noise = -status->noise; */
if (status->packet_report_type == TX_REPORT2) {
status->macid_valid_entry[0] =
GET_RX_RPT2_DESC_MACID_VALID_1(pdesc);
status->macid_valid_entry[1] =
GET_RX_RPT2_DESC_MACID_VALID_2(pdesc);
}
return true;
}
void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw,
struct ieee80211_hdr *hdr, u8 *pdesc_tx,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta,
struct sk_buff *skb,
u8 hw_queue, struct rtl_tcb_desc *ptcb_desc)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
u8 *pdesc = (u8 *)pdesc_tx;
u16 seq_number;
__le16 fc = hdr->frame_control;
unsigned int buf_len = 0;
unsigned int skb_len = skb->len;
u8 fw_qsel = _rtl88ee_map_hwqueue_to_fwqueue(skb, hw_queue);
bool firstseg = ((hdr->seq_ctrl &
cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0);
bool lastseg = ((hdr->frame_control &
cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0);
dma_addr_t mapping;
u8 bw_40 = 0;
u8 short_gi = 0;
if (mac->opmode == NL80211_IFTYPE_STATION) {
bw_40 = mac->bw_40;
} else if (mac->opmode == NL80211_IFTYPE_AP ||
mac->opmode == NL80211_IFTYPE_ADHOC) {
if (sta)
bw_40 = sta->ht_cap.cap &
IEEE80211_HT_CAP_SUP_WIDTH_20_40;
}
seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc);
/* reserve 8 byte for AMPDU early mode */
if (rtlhal->earlymode_enable) {
skb_push(skb, EM_HDR_LEN);
memset(skb->data, 0, EM_HDR_LEN);
}
buf_len = skb->len;
mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len,
PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
"DMA mapping error");
return;
}
CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_88e));
if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) {
firstseg = true;
lastseg = true;
}
if (firstseg) {
if (rtlhal->earlymode_enable) {
SET_TX_DESC_PKT_OFFSET(pdesc, 1);
SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN +
EM_HDR_LEN);
if (ptcb_desc->empkt_num) {
RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
"Insert 8 byte.pTcb->EMPktNum:%d\n",
ptcb_desc->empkt_num);
insert_em(ptcb_desc, (u8 *)(skb->data));
}
} else {
SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
}
ptcb_desc->use_driver_rate = true;
SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate);
if (ptcb_desc->hw_rate > DESC92C_RATEMCS0)
short_gi = (ptcb_desc->use_shortgi) ? 1 : 0;
else
short_gi = (ptcb_desc->use_shortpreamble) ? 1 : 0;
SET_TX_DESC_DATA_SHORTGI(pdesc, short_gi);
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
SET_TX_DESC_AGG_ENABLE(pdesc, 1);
SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14);
}
SET_TX_DESC_SEQ(pdesc, seq_number);
SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable &&
!ptcb_desc->cts_enable) ? 1 : 0));
SET_TX_DESC_HW_RTS_ENABLE(pdesc, 0);
SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0));
SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0));
SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate);
SET_TX_DESC_RTS_BW(pdesc, 0);
SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc);
SET_TX_DESC_RTS_SHORT(pdesc,
((ptcb_desc->rts_rate <= DESC92C_RATE54M) ?
(ptcb_desc->rts_use_shortpreamble ? 1 : 0) :
(ptcb_desc->rts_use_shortgi ? 1 : 0)));
if (ptcb_desc->btx_enable_sw_calc_duration)
SET_TX_DESC_NAV_USE_HDR(pdesc, 1);
if (bw_40) {
if (ptcb_desc->packet_bw) {
SET_TX_DESC_DATA_BW(pdesc, 1);
SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3);
} else {
SET_TX_DESC_DATA_BW(pdesc, 0);
SET_TX_DESC_TX_SUB_CARRIER(pdesc,
mac->cur_40_prime_sc);
}
} else {
SET_TX_DESC_DATA_BW(pdesc, 0);
SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0);
}
SET_TX_DESC_LINIP(pdesc, 0);
SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb_len);
if (sta) {
u8 ampdu_density = sta->ht_cap.ampdu_density;
SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density);
}
if (info->control.hw_key) {
struct ieee80211_key_conf *keyconf;
keyconf = info->control.hw_key;
switch (keyconf->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
case WLAN_CIPHER_SUITE_TKIP:
SET_TX_DESC_SEC_TYPE(pdesc, 0x1);
break;
case WLAN_CIPHER_SUITE_CCMP:
SET_TX_DESC_SEC_TYPE(pdesc, 0x3);
break;
default:
SET_TX_DESC_SEC_TYPE(pdesc, 0x0);
break;
}
}
SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel);
SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F);
SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF);
SET_TX_DESC_DISABLE_FB(pdesc, ptcb_desc->disable_ratefallback ?
1 : 0);
SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0);
/* Set TxRate and RTSRate in TxDesc */
/* This prevent Tx initial rate of new-coming packets */
/* from being overwritten by retried packet rate.*/
if (!ptcb_desc->use_driver_rate) {
/*SET_TX_DESC_RTS_RATE(pdesc, 0x08); */
/* SET_TX_DESC_TX_RATE(pdesc, 0x0b); */
}
if (ieee80211_is_data_qos(fc)) {
if (mac->rdg_en) {
RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
"Enable RDG function.\n");
SET_TX_DESC_RDG_ENABLE(pdesc, 1);
SET_TX_DESC_HTC(pdesc, 1);
}
}
}
SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0));
SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0));
SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) buf_len);
SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
if (rtlpriv->dm.useramask) {
SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index);
SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id);
} else {
SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index);
SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index);
}
if (ieee80211_is_data_qos(fc))
SET_TX_DESC_QOS(pdesc, 1);
if (!ieee80211_is_data_qos(fc))
SET_TX_DESC_HWSEQ_EN(pdesc, 1);
SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1));
if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
SET_TX_DESC_BMC(pdesc, 1);
rtl88e_dm_set_tx_ant_by_tx_info(hw, pdesc, ptcb_desc->mac_id);
RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n");
}
void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw,
u8 *pdesc, bool firstseg,
bool lastseg, struct sk_buff *skb)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
u8 fw_queue = QSLT_BEACON;
dma_addr_t mapping = pci_map_single(rtlpci->pdev,
skb->data, skb->len,
PCI_DMA_TODEVICE);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
__le16 fc = hdr->frame_control;
if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
"DMA mapping error");
return;
}
CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE);
if (firstseg)
SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M);
SET_TX_DESC_SEQ(pdesc, 0);
SET_TX_DESC_LINIP(pdesc, 0);
SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue);
SET_TX_DESC_FIRST_SEG(pdesc, 1);
SET_TX_DESC_LAST_SEG(pdesc, 1);
SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));
SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
SET_TX_DESC_RATE_ID(pdesc, 7);
SET_TX_DESC_MACID(pdesc, 0);
SET_TX_DESC_OWN(pdesc, 1);
SET_TX_DESC_PKT_SIZE((u8 *)pdesc, (u16)(skb->len));
SET_TX_DESC_FIRST_SEG(pdesc, 1);
SET_TX_DESC_LAST_SEG(pdesc, 1);
SET_TX_DESC_OFFSET(pdesc, 0x20);
SET_TX_DESC_USE_RATE(pdesc, 1);
if (!ieee80211_is_data_qos(fc))
SET_TX_DESC_HWSEQ_EN(pdesc, 1);
RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
"H2C Tx Cmd Content\n",
pdesc, TX_DESC_SIZE);
}
void rtl88ee_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
{
if (istx == true) {
switch (desc_name) {
case HW_DESC_OWN:
SET_TX_DESC_OWN(pdesc, 1);
break;
case HW_DESC_TX_NEXTDESC_ADDR:
SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *)val);
break;
default:
RT_ASSERT(false, "ERR txdesc :%d not processed\n",
desc_name);
break;
}
} else {
switch (desc_name) {
case HW_DESC_RXOWN:
SET_RX_DESC_OWN(pdesc, 1);
break;
case HW_DESC_RXBUFF_ADDR:
SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *)val);
break;
case HW_DESC_RXPKT_LEN:
SET_RX_DESC_PKT_LEN(pdesc, *(u32 *)val);
break;
case HW_DESC_RXERO:
SET_RX_DESC_EOR(pdesc, 1);
break;
default:
RT_ASSERT(false, "ERR rxdesc :%d not processed\n",
desc_name);
break;
}
}
}
u32 rtl88ee_get_desc(u8 *pdesc, bool istx, u8 desc_name)
{
u32 ret = 0;
if (istx == true) {
switch (desc_name) {
case HW_DESC_OWN:
ret = GET_TX_DESC_OWN(pdesc);
break;
case HW_DESC_TXBUFF_ADDR:
ret = GET_TX_DESC_TX_BUFFER_ADDRESS(pdesc);
break;
default:
RT_ASSERT(false, "ERR txdesc :%d not processed\n",
desc_name);
break;
}
} else {
switch (desc_name) {
case HW_DESC_OWN:
ret = GET_RX_DESC_OWN(pdesc);
break;
case HW_DESC_RXPKT_LEN:
ret = GET_RX_DESC_PKT_LEN(pdesc);
break;
default:
RT_ASSERT(false, "ERR rxdesc :%d not processed\n",
desc_name);
break;
}
}
return ret;
}
void rtl88ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
if (hw_queue == BEACON_QUEUE) {
rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4));
} else {
rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG,
BIT(0) << (hw_queue));
}
}
/******************************************************************************
*
* Copyright(c) 2009-2013 Realtek Corporation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __RTL92CE_TRX_H__
#define __RTL92CE_TRX_H__
#define TX_DESC_SIZE 64
#define TX_DESC_AGGR_SUBFRAME_SIZE 32
#define RX_DESC_SIZE 32
#define RX_DRV_INFO_SIZE_UNIT 8
#define TX_DESC_NEXT_DESC_OFFSET 40
#define USB_HWDESC_HEADER_LEN 32
#define CRCLENGTH 4
#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val)
#define SET_TX_DESC_OFFSET(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val)
#define SET_TX_DESC_BMC(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val)
#define SET_TX_DESC_HTC(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val)
#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val)
#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val)
#define SET_TX_DESC_LINIP(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val)
#define SET_TX_DESC_NO_ACM(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val)
#define SET_TX_DESC_GF(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val)
#define SET_TX_DESC_OWN(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val)
#define GET_TX_DESC_PKT_SIZE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 0, 16)
#define GET_TX_DESC_OFFSET(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 16, 8)
#define GET_TX_DESC_BMC(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 24, 1)
#define GET_TX_DESC_HTC(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 25, 1)
#define GET_TX_DESC_LAST_SEG(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 26, 1)
#define GET_TX_DESC_FIRST_SEG(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 27, 1)
#define GET_TX_DESC_LINIP(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 28, 1)
#define GET_TX_DESC_NO_ACM(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 29, 1)
#define GET_TX_DESC_GF(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 30, 1)
#define GET_TX_DESC_OWN(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 31, 1)
#define SET_TX_DESC_MACID(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 6, __val)
#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val)
#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val)
#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val)
#define SET_TX_DESC_PIFS(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val)
#define SET_TX_DESC_RATE_ID(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 4, __val)
#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+4, 20, 1, __val)
#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val)
#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val)
#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+4, 26, 5, __val)
#define SET_TX_DESC_PADDING_LEN(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 8, __val)
#define GET_TX_DESC_MACID(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 0, 5)
#define GET_TX_DESC_AGG_ENABLE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 5, 1)
#define GET_TX_DESC_AGG_BREAK(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 6, 1)
#define GET_TX_DESC_RDG_ENABLE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 7, 1)
#define GET_TX_DESC_QUEUE_SEL(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 8, 5)
#define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 13, 1)
#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 14, 1)
#define GET_TX_DESC_PIFS(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 15, 1)
#define GET_TX_DESC_RATE_ID(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 16, 4)
#define GET_TX_DESC_NAV_USE_HDR(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 20, 1)
#define GET_TX_DESC_EN_DESC_ID(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 21, 1)
#define GET_TX_DESC_SEC_TYPE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 22, 2)
#define GET_TX_DESC_PKT_OFFSET(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 24, 8)
#define SET_TX_DESC_RTS_RC(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 6, __val)
#define SET_TX_DESC_DATA_RC(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 6, 6, __val)
#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 12, 1, __val)
#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 13, 1, __val)
#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val)
#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 16, 1, __val)
#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val)
#define SET_TX_DESC_RAW(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val)
#define SET_TX_DESC_CCX(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val)
#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val)
#define SET_TX_DESC_BT_INT(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 23, 1, __val)
#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 1, __val)
#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 25, 1, __val)
#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 26, 2, __val)
#define SET_TX_DESC_TX_ANTL(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 28, 2, __val)
#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+8, 30, 2, __val)
#define GET_TX_DESC_RTS_RC(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+8, 0, 6)
#define GET_TX_DESC_DATA_RC(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+8, 6, 6)
#define GET_TX_DESC_BAR_RTY_TH(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+8, 14, 2)
#define GET_TX_DESC_MORE_FRAG(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+8, 17, 1)
#define GET_TX_DESC_RAW(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+8, 18, 1)
#define GET_TX_DESC_CCX(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+8, 19, 1)
#define GET_TX_DESC_AMPDU_DENSITY(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+8, 20, 3)
#define GET_TX_DESC_ANTSEL_A(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+8, 24, 1)
#define GET_TX_DESC_ANTSEL_B(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+8, 25, 1)
#define GET_TX_DESC_TX_ANT_CCK(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+8, 26, 2)
#define GET_TX_DESC_TX_ANTL(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+8, 28, 2)
#define GET_TX_DESC_TX_ANT_HT(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+8, 30, 2)
#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 8, __val)
#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 8, __val)
#define SET_TX_DESC_SEQ(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 12, __val)
#define SET_TX_DESC_CPU_HANDLE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+12, 28, 1, __val)
#define SET_TX_DESC_TAG1(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+12, 29, 1, __val)
#define SET_TX_DESC_TRIGGER_INT(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+12, 30, 1, __val)
#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+12, 31, 1, __val)
#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+12, 0, 8)
#define GET_TX_DESC_TAIL_PAGE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+12, 8, 8)
#define GET_TX_DESC_SEQ(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+12, 16, 12)
#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 5, __val)
#define SET_TX_DESC_AP_DCFE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 5, 1, __val)
#define SET_TX_DESC_QOS(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 6, 1, __val)
#define SET_TX_DESC_HWSEQ_SSN(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 7, 1, __val)
#define SET_TX_DESC_USE_RATE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 1, __val)
#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 9, 1, __val)
#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 10, 1, __val)
#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 11, 1, __val)
#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 12, 1, __val)
#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 1, __val)
#define SET_TX_DESC_PORT_ID(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 14, 1, __val)
#define SET_TX_DESC_PWR_STATUS(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 15, 3, __val)
#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 1, __val)
#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 19, 1, __val)
#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 20, 2, __val)
#define SET_TX_DESC_TX_STBC(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 22, 2, __val)
#define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 1, __val)
#define SET_TX_DESC_DATA_BW(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 25, 1, __val)
#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 26, 1, __val)
#define SET_TX_DESC_RTS_BW(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 27, 1, __val)
#define SET_TX_DESC_RTS_SC(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 28, 2, __val)
#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+16, 30, 2, __val)
#define GET_TX_DESC_RTS_RATE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 0, 5)
#define GET_TX_DESC_AP_DCFE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 5, 1)
#define GET_TX_DESC_QOS(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 6, 1)
#define GET_TX_DESC_HWSEQ_EN(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 7, 1)
#define GET_TX_DESC_USE_RATE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 8, 1)
#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 9, 1)
#define GET_TX_DESC_DISABLE_FB(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 10, 1)
#define GET_TX_DESC_CTS2SELF(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 11, 1)
#define GET_TX_DESC_RTS_ENABLE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 12, 1)
#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 13, 1)
#define GET_TX_DESC_PORT_ID(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 14, 1)
#define GET_TX_DESC_WAIT_DCTS(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 18, 1)
#define GET_TX_DESC_CTS2AP_EN(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 19, 1)
#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 20, 2)
#define GET_TX_DESC_TX_STBC(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 22, 2)
#define GET_TX_DESC_DATA_SHORT(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 24, 1)
#define GET_TX_DESC_DATA_BW(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 25, 1)
#define GET_TX_DESC_RTS_SHORT(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 26, 1)
#define GET_TX_DESC_RTS_BW(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 27, 1)
#define GET_TX_DESC_RTS_SC(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 28, 2)
#define GET_TX_DESC_RTS_STBC(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 30, 2)
#define SET_TX_DESC_TX_RATE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 6, __val)
#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+20, 6, 1, __val)
#define SET_TX_DESC_CCX_TAG(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val)
#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 5, __val)
#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val)
#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+20, 17, 1, __val)
#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+20, 18, 6, __val)
#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 8, __val)
#define GET_TX_DESC_TX_RATE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+20, 0, 6)
#define GET_TX_DESC_DATA_SHORTGI(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+20, 6, 1)
#define GET_TX_DESC_CCX_TAG(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+20, 7, 1)
#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+20, 8, 5)
#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+20, 13, 4)
#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+20, 17, 1)
#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+20, 18, 6)
#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+20, 24, 8)
#define SET_TX_DESC_TXAGC_A(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 5, __val)
#define SET_TX_DESC_TXAGC_B(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+24, 5, 5, __val)
#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+24, 10, 1, __val)
#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+24, 11, 5, __val)
#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 4, __val)
#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+24, 20, 4, __val)
#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+24, 24, 4, __val)
#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+24, 28, 4, __val)
#define GET_TX_DESC_TXAGC_A(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+24, 0, 5)
#define GET_TX_DESC_TXAGC_B(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+24, 5, 5)
#define GET_TX_DESC_USE_MAX_LEN(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+24, 10, 1)
#define GET_TX_DESC_MAX_AGG_NUM(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+24, 11, 5)
#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+24, 16, 4)
#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+24, 20, 4)
#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+24, 24, 4)
#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+24, 28, 4)
#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val)
#define SET_TX_DESC_SW_OFFSET30(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+28, 16, 8, __val)
#define SET_TX_DESC_SW_OFFSET31(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+28, 24, 4, __val)
#define SET_TX_DESC_ANTSEL_C(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+28, 29, 1, __val)
#define SET_TX_DESC_NULL_0(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+28, 30, 1, __val)
#define SET_TX_DESC_NULL_1(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+28, 30, 1, __val)
#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+28, 0, 16)
#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 32, __val)
#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 32, __val)
#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+32, 0, 32)
#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+36, 0, 32)
#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val)
#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+44, 0, 32, __val)
#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+40, 0, 32)
#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+44, 0, 32)
#define GET_RX_DESC_PKT_LEN(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 0, 14)
#define GET_RX_DESC_CRC32(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 14, 1)
#define GET_RX_DESC_ICV(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 15, 1)
#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 16, 4)
#define GET_RX_DESC_SECURITY(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 20, 3)
#define GET_RX_DESC_QOS(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 23, 1)
#define GET_RX_DESC_SHIFT(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 24, 2)
#define GET_RX_DESC_PHYST(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 26, 1)
#define GET_RX_DESC_SWDEC(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 27, 1)
#define GET_RX_DESC_LS(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 28, 1)
#define GET_RX_DESC_FS(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 29, 1)
#define GET_RX_DESC_EOR(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 30, 1)
#define GET_RX_DESC_OWN(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc, 31, 1)
#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val)
#define SET_RX_DESC_EOR(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val)
#define SET_RX_DESC_OWN(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val)
#define GET_RX_DESC_MACID(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 0, 6)
#define GET_RX_DESC_PAGGR(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 14, 1)
#define GET_RX_DESC_FAGGR(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 15, 1)
#define GET_RX_DESC_A1_FIT(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 16, 4)
#define GET_RX_DESC_A2_FIT(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 20, 4)
#define GET_RX_DESC_PAM(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 24, 1)
#define GET_RX_DESC_PWR(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 25, 1)
#define GET_RX_DESC_MD(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 26, 1)
#define GET_RX_DESC_MF(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 27, 1)
#define GET_RX_DESC_TYPE(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 28, 2)
#define GET_RX_DESC_MC(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 30, 1)
#define GET_RX_DESC_BC(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+4, 31, 1)
#define GET_RX_DESC_SEQ(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+8, 0, 12)
#define GET_RX_DESC_FRAG(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+8, 12, 4)
#define GET_RX_DESC_RXMCS(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+12, 0, 6)
#define GET_RX_DESC_RXHT(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+12, 6, 1)
#define GET_RX_STATUS_DESC_RX_GF(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+12, 7, 1)
#define GET_RX_DESC_SPLCP(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+12, 8, 1)
#define GET_RX_DESC_BW(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+12, 9, 1)
#define GET_RX_DESC_HTC(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+12, 10, 1)
#define GET_RX_STATUS_DESC_EOSP(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+12, 11, 1)
#define GET_RX_STATUS_DESC_BSSID_FIT(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+12, 12, 2)
#define GET_RX_STATUS_DESC_RPT_SEL(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+12, 14, 2)
#define GET_RX_STATUS_DESC_PATTERN_MATCH(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+12, 29, 1)
#define GET_RX_STATUS_DESC_UNICAST_MATCH(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+12, 30, 1)
#define GET_RX_STATUS_DESC_MAGIC_MATCH(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+12, 31, 1)
#define GET_RX_DESC_IV1(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+16, 0, 32)
#define GET_RX_DESC_TSFL(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+20, 0, 32)
#define GET_RX_DESC_BUFF_ADDR(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+24, 0, 32)
#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \
LE_BITS_TO_4BYTE(__pdesc+28, 0, 32)
#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val)
#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \
SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val)
/* TX report 2 format in Rx desc*/
#define GET_RX_RPT2_DESC_PKT_LEN(__status) \
LE_BITS_TO_4BYTE(__status, 0, 9)
#define GET_RX_RPT2_DESC_MACID_VALID_1(__status) \
LE_BITS_TO_4BYTE(__status+16, 0, 32)
#define GET_RX_RPT2_DESC_MACID_VALID_2(__status) \
LE_BITS_TO_4BYTE(__status+20, 0, 32)
#define SET_EARLYMODE_PKTNUM(__paddr, __value) \
SET_BITS_TO_LE_4BYTE(__paddr, 0, 4, __value)
#define SET_EARLYMODE_LEN0(__paddr, __value) \
SET_BITS_TO_LE_4BYTE(__paddr, 4, 12, __value)
#define SET_EARLYMODE_LEN1(__paddr, __value) \
SET_BITS_TO_LE_4BYTE(__paddr, 16, 12, __value)
#define SET_EARLYMODE_LEN2_1(__paddr, __value) \
SET_BITS_TO_LE_4BYTE(__paddr, 28, 4, __value)
#define SET_EARLYMODE_LEN2_2(__paddr, __value) \
SET_BITS_TO_LE_4BYTE(__paddr+4, 0, 8, __value)
#define SET_EARLYMODE_LEN3(__paddr, __value) \
SET_BITS_TO_LE_4BYTE(__paddr+4, 8, 12, __value)
#define SET_EARLYMODE_LEN4(__paddr, __value) \
SET_BITS_TO_LE_4BYTE(__paddr+4, 20, 12, __value)
#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \
do { \
if (_size > TX_DESC_NEXT_DESC_OFFSET) \
memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \
else \
memset(__pdesc, 0, _size); \
} while (0)
#define RTL8188_RX_HAL_IS_CCK_RATE(rxmcs)\
(rxmcs == DESC92C_RATE1M ||\
rxmcs == DESC92C_RATE2M ||\
rxmcs == DESC92C_RATE5_5M ||\
rxmcs == DESC92C_RATE11M)
struct phy_rx_agc_info_t {
#if __LITTLE_ENDIAN
u8 gain:7, trsw:1;
#else
u8 trsw:1, gain:7;
#endif
};
struct phy_status_rpt {
struct phy_rx_agc_info_t path_agc[2];
u8 ch_corr[2];
u8 cck_sig_qual_ofdm_pwdb_all;
u8 cck_agc_rpt_ofdm_cfosho_a;
u8 cck_rpt_b_ofdm_cfosho_b;
u8 rsvd_1;
u8 noise_power_db_msb;
u8 path_cfotail[2];
u8 pcts_mask[2];
u8 stream_rxevm[2];
u8 path_rxsnr[2];
u8 noise_power_db_lsb;
u8 rsvd_2[3];
u8 stream_csi[2];
u8 stream_target_csi[2];
u8 sig_evm;
u8 rsvd_3;
#if __LITTLE_ENDIAN
u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/
u8 sgi_en:1;
u8 rxsc:2;
u8 idle_long:1;
u8 r_ant_train_en:1;
u8 ant_sel_b:1;
u8 ant_sel:1;
#else /* _BIG_ENDIAN_ */
u8 ant_sel:1;
u8 ant_sel_b:1;
u8 r_ant_train_en:1;
u8 idle_long:1;
u8 rxsc:2;
u8 sgi_en:1;
u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/
#endif
} __packed;
struct rx_fwinfo_88e {
u8 gain_trsw[4];
u8 pwdb_all;
u8 cfosho[4];
u8 cfotail[4];
char rxevm[2];
char rxsnr[4];
u8 pdsnr[2];
u8 csi_current[2];
u8 csi_target[2];
u8 sigevm;
u8 max_ex_pwr;
u8 ex_intf_flag:1;
u8 sgi_en:1;
u8 rxsc:2;
u8 reserve:4;
} __packed;
struct tx_desc_88e {
u32 pktsize:16;
u32 offset:8;
u32 bmc:1;
u32 htc:1;
u32 lastseg:1;
u32 firstseg:1;
u32 linip:1;
u32 noacm:1;
u32 gf:1;
u32 own:1;
u32 macid:6;
u32 rsvd0:2;
u32 queuesel:5;
u32 rd_nav_ext:1;
u32 lsig_txop_en:1;
u32 pifs:1;
u32 rateid:4;
u32 nav_usehdr:1;
u32 en_descid:1;
u32 sectype:2;
u32 pktoffset:8;
u32 rts_rc:6;
u32 data_rc:6;
u32 agg_en:1;
u32 rdg_en:1;
u32 bar_retryht:2;
u32 agg_break:1;
u32 morefrag:1;
u32 raw:1;
u32 ccx:1;
u32 ampdudensity:3;
u32 bt_int:1;
u32 ant_sela:1;
u32 ant_selb:1;
u32 txant_cck:2;
u32 txant_l:2;
u32 txant_ht:2;
u32 nextheadpage:8;
u32 tailpage:8;
u32 seq:12;
u32 cpu_handle:1;
u32 tag1:1;
u32 trigger_int:1;
u32 hwseq_en:1;
u32 rtsrate:5;
u32 apdcfe:1;
u32 qos:1;
u32 hwseq_ssn:1;
u32 userrate:1;
u32 dis_rtsfb:1;
u32 dis_datafb:1;
u32 cts2self:1;
u32 rts_en:1;
u32 hwrts_en:1;
u32 portid:1;
u32 pwr_status:3;
u32 waitdcts:1;
u32 cts2ap_en:1;
u32 txsc:2;
u32 stbc:2;
u32 txshort:1;
u32 txbw:1;
u32 rtsshort:1;
u32 rtsbw:1;
u32 rtssc:2;
u32 rtsstbc:2;
u32 txrate:6;
u32 shortgi:1;
u32 ccxt:1;
u32 txrate_fb_lmt:5;
u32 rtsrate_fb_lmt:4;
u32 retrylmt_en:1;
u32 txretrylmt:6;
u32 usb_txaggnum:8;
u32 txagca:5;
u32 txagcb:5;
u32 usemaxlen:1;
u32 maxaggnum:5;
u32 mcsg1maxlen:4;
u32 mcsg2maxlen:4;
u32 mcsg3maxlen:4;
u32 mcs7sgimaxlen:4;
u32 txbuffersize:16;
u32 sw_offset30:8;
u32 sw_offset31:4;
u32 rsvd1:1;
u32 antsel_c:1;
u32 null_0:1;
u32 null_1:1;
u32 txbuffaddr;
u32 txbufferaddr64;
u32 nextdescaddress;
u32 nextdescaddress64;
u32 reserve_pass_pcie_mm_limit[4];
} __packed;
struct rx_desc_88e {
u32 length:14;
u32 crc32:1;
u32 icverror:1;
u32 drv_infosize:4;
u32 security:3;
u32 qos:1;
u32 shift:2;
u32 phystatus:1;
u32 swdec:1;
u32 lastseg:1;
u32 firstseg:1;
u32 eor:1;
u32 own:1;
u32 macid:6;
u32 tid:4;
u32 hwrsvd:5;
u32 paggr:1;
u32 faggr:1;
u32 a1_fit:4;
u32 a2_fit:4;
u32 pam:1;
u32 pwr:1;
u32 moredata:1;
u32 morefrag:1;
u32 type:2;
u32 mc:1;
u32 bc:1;
u32 seq:12;
u32 frag:4;
u32 nextpktlen:14;
u32 nextind:1;
u32 rsvd:1;
u32 rxmcs:6;
u32 rxht:1;
u32 amsdu:1;
u32 splcp:1;
u32 bandwidth:1;
u32 htc:1;
u32 tcpchk_rpt:1;
u32 ipcchk_rpt:1;
u32 tcpchk_valid:1;
u32 hwpcerr:1;
u32 hwpcind:1;
u32 iv0:16;
u32 iv1;
u32 tsfl;
u32 bufferaddress;
u32 bufferaddress64;
} __packed;
void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw,
struct ieee80211_hdr *hdr, u8 *pdesc_tx,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta,
struct sk_buff *skb,
u8 hw_queue, struct rtl_tcb_desc *ptcb_desc);
bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw,
struct rtl_stats *status,
struct ieee80211_rx_status *rx_status,
u8 *pdesc, struct sk_buff *skb);
void rtl88ee_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val);
u32 rtl88ee_get_desc(u8 *pdesc, bool istx, u8 desc_name);
void rtl88ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue);
void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
bool b_firstseg, bool b_lastseg,
struct sk_buff *skb);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment