diff options
24 files changed, 14998 insertions, 0 deletions
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/def.h b/drivers/net/wireless/rtlwifi/rtl8188ee/def.h new file mode 100644 index 00000000000..c764fff9ebe --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/def.h @@ -0,0 +1,324 @@ +/****************************************************************************** + * + * 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 diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c new file mode 100644 index 00000000000..0a338cccbdf --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c @@ -0,0 +1,1794 @@ +/****************************************************************************** + * + * 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); +	} +} diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h new file mode 100644 index 00000000000..0e07f72ea15 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h @@ -0,0 +1,326 @@ +/****************************************************************************** + * + * 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 diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c new file mode 100644 index 00000000000..66ff30ba28c --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c @@ -0,0 +1,830 @@ +/****************************************************************************** + * + * 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); +} diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h new file mode 100644 index 00000000000..854a9875cd5 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h @@ -0,0 +1,301 @@ +/****************************************************************************** + * + * 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 diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c new file mode 100644 index 00000000000..d734d19a066 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c @@ -0,0 +1,2529 @@ +/****************************************************************************** + * + * 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 *)(®_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 *)(®_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); +} diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h new file mode 100644 index 00000000000..b4460a41bd0 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h @@ -0,0 +1,68 @@ +/****************************************************************************** + * + * 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 diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/led.c b/drivers/net/wireless/rtlwifi/rtl8188ee/led.c new file mode 100644 index 00000000000..95d42afd771 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/led.c @@ -0,0 +1,157 @@ +/****************************************************************************** + * + * 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); +} diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/led.h b/drivers/net/wireless/rtlwifi/rtl8188ee/led.h new file mode 100644 index 00000000000..4073f6f847b --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/led.h @@ -0,0 +1,38 @@ +/****************************************************************************** + * + * 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 diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c new file mode 100644 index 00000000000..c2856315a8c --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c @@ -0,0 +1,2212 @@ +/****************************************************************************** + * + * 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; +} diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h new file mode 100644 index 00000000000..4f047c6ee09 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h @@ -0,0 +1,237 @@ +/****************************************************************************** + * + * 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 diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c new file mode 100644 index 00000000000..6dc4e3a954f --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c @@ -0,0 +1,109 @@ +/****************************************************************************** + * + * 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 +}; diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h new file mode 100644 index 00000000000..028ec6dd52b --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h @@ -0,0 +1,327 @@ +/****************************************************************************** + * + * 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 diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c new file mode 100644 index 00000000000..4798000ed53 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.c @@ -0,0 +1,140 @@ +/****************************************************************************** + * + * 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; +} diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.h b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.h new file mode 100644 index 00000000000..622ea7e72b2 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseqcmd.h @@ -0,0 +1,97 @@ +/****************************************************************************** + * + * 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 diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h b/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h new file mode 100644 index 00000000000..d849abf7d94 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h @@ -0,0 +1,2258 @@ +/****************************************************************************** + * + * 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 diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c new file mode 100644 index 00000000000..e62bcab6ed4 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c @@ -0,0 +1,467 @@ +/****************************************************************************** + * + * 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); +} diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h new file mode 100644 index 00000000000..a39a2a3dbcc --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h @@ -0,0 +1,46 @@ +/****************************************************************************** + * + * 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 diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c new file mode 100644 index 00000000000..e8ce1897f38 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c @@ -0,0 +1,400 @@ +/****************************************************************************** + * + * 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); diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h new file mode 100644 index 00000000000..85e02b3bdff --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h @@ -0,0 +1,36 @@ +/****************************************************************************** + * + * 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 diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/table.c b/drivers/net/wireless/rtlwifi/rtl8188ee/table.c new file mode 100644 index 00000000000..fad373f97b2 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/table.c @@ -0,0 +1,643 @@ +/****************************************************************************** + * + * 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, +}; diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/table.h b/drivers/net/wireless/rtlwifi/rtl8188ee/table.h new file mode 100644 index 00000000000..c1218e83512 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/table.h @@ -0,0 +1,47 @@ +/****************************************************************************** + * + * 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 diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c new file mode 100644 index 00000000000..251853178de --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c @@ -0,0 +1,817 @@ +/****************************************************************************** + * + * 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)); +	} +} diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h new file mode 100644 index 00000000000..d3a02e73f53 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h @@ -0,0 +1,795 @@ +/****************************************************************************** + * + * 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  |