Commit f7c92d2c authored by Larry Finger's avatar Larry Finger Committed by Greg Kroah-Hartman

staging: r8723au: Add source files for new driver - part 2

The Realtek USB device RTL8723AU is found in Lenovo Yoga 13 tablets.
A driver for it has been available in a GitHub repo for several months.
This commit contains the second part of the source files. The source
is arbitrarily split to avoid E-mail files that are too large.

Jes Sorensen at RedHat has made many improvements to the vendor code,
and he has been doing the testing. I do not have access to this device.
Signed-off-by: default avatarLarry Finger <Larry.Finger@lwfinger.net>
Cc: Jes Sorensen <Jes.Sorensen@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 5e93f352
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#include "Hal8723PwrSeq.h"
/*
drivers should parse below arrays and do the corresponding actions
*/
/* 3 Power on Array */
struct wlan_pwr_cfg rtl8723AU_power_on_flow[RTL8723A_TRANS_CARDEMU_TO_ACT_STEPS+RTL8723A_TRANS_END_STEPS] = {
RTL8723A_TRANS_CARDEMU_TO_ACT
RTL8723A_TRANS_END
};
/* 3 Radio off GPIO Array */
struct wlan_pwr_cfg rtl8723AU_radio_off_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_END_STEPS] = {
RTL8723A_TRANS_ACT_TO_CARDEMU
RTL8723A_TRANS_END
};
/* 3 Card Disable Array */
struct wlan_pwr_cfg rtl8723AU_card_disable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS] = {
RTL8723A_TRANS_ACT_TO_CARDEMU
RTL8723A_TRANS_CARDEMU_TO_CARDDIS
RTL8723A_TRANS_END
};
/* 3 Card Enable Array */
struct wlan_pwr_cfg rtl8723AU_card_enable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS] = {
RTL8723A_TRANS_CARDDIS_TO_CARDEMU
RTL8723A_TRANS_CARDEMU_TO_ACT
RTL8723A_TRANS_END
};
/* 3 Suspend Array */
struct wlan_pwr_cfg rtl8723AU_suspend_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS+RTL8723A_TRANS_END_STEPS] = {
RTL8723A_TRANS_ACT_TO_CARDEMU
RTL8723A_TRANS_CARDEMU_TO_SUS
RTL8723A_TRANS_END
};
/* 3 Resume Array */
struct wlan_pwr_cfg rtl8723AU_resume_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS+RTL8723A_TRANS_END_STEPS] = {
RTL8723A_TRANS_SUS_TO_CARDEMU
RTL8723A_TRANS_CARDEMU_TO_ACT
RTL8723A_TRANS_END
};
/* 3 HWPDN Array */
struct wlan_pwr_cfg rtl8723AU_hwpdn_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS] = {
RTL8723A_TRANS_ACT_TO_CARDEMU
RTL8723A_TRANS_CARDEMU_TO_PDN
RTL8723A_TRANS_END
};
/* 3 Enter LPS */
struct wlan_pwr_cfg rtl8723AU_enter_lps_flow[RTL8723A_TRANS_ACT_TO_LPS_STEPS+RTL8723A_TRANS_END_STEPS] = {
/* FW behavior */
RTL8723A_TRANS_ACT_TO_LPS
RTL8723A_TRANS_END
};
/* 3 Leave LPS */
struct wlan_pwr_cfg rtl8723AU_leave_lps_flow[RTL8723A_TRANS_LPS_TO_ACT_STEPS+RTL8723A_TRANS_END_STEPS] = {
/* FW behavior */
RTL8723A_TRANS_LPS_TO_ACT
RTL8723A_TRANS_END
};
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
/*Created on 2013/01/14, 15:51*/
#include "odm_precomp.h"
u32 Rtl8723UPHY_REG_Array_PG[Rtl8723UPHY_REG_Array_PGLength] = {
0xe00, 0xffffffff, 0x0a0c0c0c,
0xe04, 0xffffffff, 0x02040608,
0xe08, 0x0000ff00, 0x00000000,
0x86c, 0xffffff00, 0x00000000,
0xe10, 0xffffffff, 0x0a0c0d0e,
0xe14, 0xffffffff, 0x02040608,
0xe18, 0xffffffff, 0x0a0c0d0e,
0xe1c, 0xffffffff, 0x02040608,
0x830, 0xffffffff, 0x0a0c0c0c,
0x834, 0xffffffff, 0x02040608,
0x838, 0xffffff00, 0x00000000,
0x86c, 0x000000ff, 0x00000000,
0x83c, 0xffffffff, 0x0a0c0d0e,
0x848, 0xffffffff, 0x02040608,
0x84c, 0xffffffff, 0x0a0c0d0e,
0x868, 0xffffffff, 0x02040608,
0xe00, 0xffffffff, 0x00000000,
0xe04, 0xffffffff, 0x00000000,
0xe08, 0x0000ff00, 0x00000000,
0x86c, 0xffffff00, 0x00000000,
0xe10, 0xffffffff, 0x00000000,
0xe14, 0xffffffff, 0x00000000,
0xe18, 0xffffffff, 0x00000000,
0xe1c, 0xffffffff, 0x00000000,
0x830, 0xffffffff, 0x00000000,
0x834, 0xffffffff, 0x00000000,
0x838, 0xffffff00, 0x00000000,
0x86c, 0x000000ff, 0x00000000,
0x83c, 0xffffffff, 0x00000000,
0x848, 0xffffffff, 0x00000000,
0x84c, 0xffffffff, 0x00000000,
0x868, 0xffffffff, 0x00000000,
0xe00, 0xffffffff, 0x04040404,
0xe04, 0xffffffff, 0x00020204,
0xe08, 0x0000ff00, 0x00000000,
0x86c, 0xffffff00, 0x00000000,
0xe10, 0xffffffff, 0x06060606,
0xe14, 0xffffffff, 0x00020406,
0xe18, 0xffffffff, 0x00000000,
0xe1c, 0xffffffff, 0x00000000,
0x830, 0xffffffff, 0x04040404,
0x834, 0xffffffff, 0x00020204,
0x838, 0xffffff00, 0x00000000,
0x86c, 0x000000ff, 0x00000000,
0x83c, 0xffffffff, 0x06060606,
0x848, 0xffffffff, 0x00020406,
0x84c, 0xffffffff, 0x00000000,
0x868, 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,
0x830, 0xffffffff, 0x00000000,
0x834, 0xffffffff, 0x00000000,
0x838, 0xffffff00, 0x00000000,
0x86c, 0x000000ff, 0x00000000,
0x83c, 0xffffffff, 0x00000000,
0x848, 0xffffffff, 0x00000000,
0x84c, 0xffffffff, 0x00000000,
0x868, 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,
0x830, 0xffffffff, 0x00000000,
0x834, 0xffffffff, 0x00000000,
0x838, 0xffffff00, 0x00000000,
0x86c, 0x000000ff, 0x00000000,
0x83c, 0xffffffff, 0x00000000,
0x848, 0xffffffff, 0x00000000,
0x84c, 0xffffffff, 0x00000000,
0x868, 0xffffffff, 0x00000000,
0xe00, 0xffffffff, 0x04040404,
0xe04, 0xffffffff, 0x00020204,
0xe08, 0x0000ff00, 0x00000000,
0x86c, 0xffffff00, 0x00000000,
0xe10, 0xffffffff, 0x00000000,
0xe14, 0xffffffff, 0x00000000,
0xe18, 0xffffffff, 0x00000000,
0xe1c, 0xffffffff, 0x00000000,
0x830, 0xffffffff, 0x04040404,
0x834, 0xffffffff, 0x00020204,
0x838, 0xffffff00, 0x00000000,
0x86c, 0x000000ff, 0x00000000,
0x83c, 0xffffffff, 0x00000000,
0x848, 0xffffffff, 0x00000000,
0x84c, 0xffffffff, 0x00000000,
0x868, 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,
0x830, 0xffffffff, 0x00000000,
0x834, 0xffffffff, 0x00000000,
0x838, 0xffffff00, 0x00000000,
0x86c, 0x000000ff, 0x00000000,
0x83c, 0xffffffff, 0x00000000,
0x848, 0xffffffff, 0x00000000,
0x84c, 0xffffffff, 0x00000000,
0x868, 0xffffffff, 0x00000000,
};
u32 Rtl8723UMACPHY_Array_PG[Rtl8723UMACPHY_Array_PGLength] = {
0x0,
};
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
/* Description: */
/* This file is for 92CE/92CU dynamic mechanism only */
/* include files */
#include "odm_precomp.h"
#define DPK_DELTA_MAPPING_NUM 13
#define index_mapping_HP_NUM 15
/* 091212 chiyokolin */
static void
odm_TXPowerTrackingCallback_ThermalMeter_92C(
struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
u8 ThermalValue = 0, delta, delta_LCK, delta_IQK, delta_HP;
int ele_A, ele_D, TempCCk, X, value32;
int Y, ele_C;
s8 OFDM_index[2], CCK_index = 0, OFDM_index_old[2] = {0};
s8 CCK_index_old = 0;
int i = 0;
bool is2T = IS_92C_SERIAL(pHalData->VersionID);
u8 OFDM_min_index = 6, rf; /* OFDM BB Swing should be less than +3.0dB*/
u8 ThermalValue_HP_count = 0;
u32 ThermalValue_HP = 0;
s32 index_mapping_HP[index_mapping_HP_NUM] = {
0, 1, 3, 4, 6,
7, 9, 10, 12, 13,
15, 16, 18, 19, 21
};
s8 index_HP;
pdmpriv->TXPowerTrackingCallbackCnt++; /* cosa add for debug */
pdmpriv->bTXPowerTrackingInit = true;
if (pHalData->CurrentChannel == 14 && !pdmpriv->bCCKinCH14)
pdmpriv->bCCKinCH14 = true;
else if (pHalData->CurrentChannel != 14 && pdmpriv->bCCKinCH14)
pdmpriv->bCCKinCH14 = false;
ThermalValue = (u8)PHY_QueryRFReg(Adapter, RF_PATH_A, RF_T_METER,
0x1f);/* 0x24: RF Reg[4:0] */
rtl8723a_phy_ap_calibrate(Adapter, (ThermalValue -
pHalData->EEPROMThermalMeter));
if (is2T)
rf = 2;
else
rf = 1;
if (ThermalValue) {
/* Query OFDM path A default setting */
ele_D = PHY_QueryBBReg(Adapter, rOFDM0_XATxIQImbalance,
bMaskDWord)&bMaskOFDM_D;
for (i = 0; i < OFDM_TABLE_SIZE_92C; i++) {
/* find the index */
if (ele_D == (OFDMSwingTable23A[i]&bMaskOFDM_D)) {
OFDM_index_old[0] = (u8)i;
break;
}
}
/* Query OFDM path B default setting */
if (is2T) {
ele_D = PHY_QueryBBReg(Adapter, rOFDM0_XBTxIQImbalance,
bMaskDWord)&bMaskOFDM_D;
for (i = 0; i < OFDM_TABLE_SIZE_92C; i++) { /* find the index */
if (ele_D == (OFDMSwingTable23A[i]&bMaskOFDM_D)) {
OFDM_index_old[1] = (u8)i;
break;
}
}
}
/* Query CCK default setting From 0xa24 */
TempCCk = PHY_QueryBBReg(Adapter, rCCK0_TxFilter2,
bMaskDWord)&bMaskCCK;
for (i = 0 ; i < CCK_TABLE_SIZE ; i++) {
if (pdmpriv->bCCKinCH14) {
if (!memcmp(&TempCCk,
&CCKSwingTable_Ch1423A[i][2], 4)) {
CCK_index_old = (u8)i;
break;
}
} else {
if (!memcmp(&TempCCk,
&CCKSwingTable_Ch1_Ch1323A[i][2], 4)) {
CCK_index_old = (u8)i;
break;
}
}
}
if (!pdmpriv->ThermalValue) {
pdmpriv->ThermalValue = pHalData->EEPROMThermalMeter;
pdmpriv->ThermalValue_LCK = ThermalValue;
pdmpriv->ThermalValue_IQK = ThermalValue;
pdmpriv->ThermalValue_DPK = pHalData->EEPROMThermalMeter;
for (i = 0; i < rf; i++) {
pdmpriv->OFDM_index_HP[i] = OFDM_index_old[i];
pdmpriv->OFDM_index[i] = OFDM_index_old[i];
}
pdmpriv->CCK_index_HP = CCK_index_old;
pdmpriv->CCK_index = CCK_index_old;
}
if (pHalData->BoardType == BOARD_USB_High_PA) {
pdmpriv->ThermalValue_HP[pdmpriv->ThermalValue_HP_index] = ThermalValue;
pdmpriv->ThermalValue_HP_index++;
if (pdmpriv->ThermalValue_HP_index == HP_THERMAL_NUM)
pdmpriv->ThermalValue_HP_index = 0;
for (i = 0; i < HP_THERMAL_NUM; i++) {
if (pdmpriv->ThermalValue_HP[i]) {
ThermalValue_HP += pdmpriv->ThermalValue_HP[i];
ThermalValue_HP_count++;
}
}
if (ThermalValue_HP_count)
ThermalValue = (u8)(ThermalValue_HP / ThermalValue_HP_count);
}
delta = (ThermalValue > pdmpriv->ThermalValue) ?
(ThermalValue - pdmpriv->ThermalValue) :
(pdmpriv->ThermalValue - ThermalValue);
if (pHalData->BoardType == BOARD_USB_High_PA) {
if (pdmpriv->bDoneTxpower)
delta_HP = (ThermalValue > pdmpriv->ThermalValue) ?
(ThermalValue - pdmpriv->ThermalValue) :
(pdmpriv->ThermalValue - ThermalValue);
else
delta_HP = ThermalValue > pHalData->EEPROMThermalMeter ?
(ThermalValue - pHalData->EEPROMThermalMeter) :
(pHalData->EEPROMThermalMeter - ThermalValue);
} else {
delta_HP = 0;
}
delta_LCK = (ThermalValue > pdmpriv->ThermalValue_LCK) ?
(ThermalValue - pdmpriv->ThermalValue_LCK) :
(pdmpriv->ThermalValue_LCK - ThermalValue);
delta_IQK = (ThermalValue > pdmpriv->ThermalValue_IQK) ?
(ThermalValue - pdmpriv->ThermalValue_IQK) :
(pdmpriv->ThermalValue_IQK - ThermalValue);
if (delta_LCK > 1) {
pdmpriv->ThermalValue_LCK = ThermalValue;
rtl8723a_phy_lc_calibrate(Adapter);
}
if ((delta > 0 || delta_HP > 0) && pdmpriv->TxPowerTrackControl) {
if (pHalData->BoardType == BOARD_USB_High_PA) {
pdmpriv->bDoneTxpower = true;
delta_HP = ThermalValue > pHalData->EEPROMThermalMeter ?
(ThermalValue - pHalData->EEPROMThermalMeter) :
(pHalData->EEPROMThermalMeter - ThermalValue);
if (delta_HP > index_mapping_HP_NUM-1)
index_HP = index_mapping_HP[index_mapping_HP_NUM-1];
else
index_HP = index_mapping_HP[delta_HP];
if (ThermalValue > pHalData->EEPROMThermalMeter) {
/* set larger Tx power */
for (i = 0; i < rf; i++)
OFDM_index[i] = pdmpriv->OFDM_index_HP[i] - index_HP;
CCK_index = pdmpriv->CCK_index_HP - index_HP;
} else {
for (i = 0; i < rf; i++)
OFDM_index[i] = pdmpriv->OFDM_index_HP[i] + index_HP;
CCK_index = pdmpriv->CCK_index_HP + index_HP;
}
delta_HP = (ThermalValue > pdmpriv->ThermalValue) ?
(ThermalValue - pdmpriv->ThermalValue) :
(pdmpriv->ThermalValue - ThermalValue);
} else {
if (ThermalValue > pdmpriv->ThermalValue) {
for (i = 0; i < rf; i++)
pdmpriv->OFDM_index[i] -= delta;
pdmpriv->CCK_index -= delta;
} else {
for (i = 0; i < rf; i++)
pdmpriv->OFDM_index[i] += delta;
pdmpriv->CCK_index += delta;
}
}
/* no adjust */
if (pHalData->BoardType != BOARD_USB_High_PA) {
if (ThermalValue > pHalData->EEPROMThermalMeter) {
for (i = 0; i < rf; i++)
OFDM_index[i] = pdmpriv->OFDM_index[i]+1;
CCK_index = pdmpriv->CCK_index+1;
} else {
for (i = 0; i < rf; i++)
OFDM_index[i] = pdmpriv->OFDM_index[i];
CCK_index = pdmpriv->CCK_index;
}
}
for (i = 0; i < rf; i++) {
if (OFDM_index[i] > (OFDM_TABLE_SIZE_92C-1))
OFDM_index[i] = (OFDM_TABLE_SIZE_92C-1);
else if (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;
}
if (pdmpriv->TxPowerTrackControl && (delta != 0 || delta_HP != 0)) {
/* Adujst OFDM Ant_A according to IQK result */
ele_D = (OFDMSwingTable23A[OFDM_index[0]] & 0xFFC00000)>>22;
X = pdmpriv->RegE94;
Y = pdmpriv->RegE9C;
if (X != 0) {
if ((X & 0x00000200) != 0)
X = X | 0xFFFFFC00;
ele_A = ((X * ele_D)>>8)&0x000003FF;
/* new element C = element D x Y */
if ((Y & 0x00000200) != 0)
Y = Y | 0xFFFFFC00;
ele_C = ((Y * ele_D)>>8)&0x000003FF;
/* write new elements A, C, D to regC80 and regC94, element B is always 0 */
value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A;
PHY_SetBBReg(Adapter, rOFDM0_XATxIQImbalance, bMaskDWord, value32);
value32 = (ele_C&0x000003C0)>>6;
PHY_SetBBReg(Adapter, rOFDM0_XCTxAFE, bMaskH4Bits, value32);
value32 = ((X * ele_D)>>7)&0x01;
PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, BIT31, value32);
value32 = ((Y * ele_D)>>7)&0x01;
PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, BIT29, value32);
} else {
PHY_SetBBReg(Adapter, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable23A[OFDM_index[0]]);
PHY_SetBBReg(Adapter, rOFDM0_XCTxAFE, bMaskH4Bits, 0x00);
PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, BIT31|BIT29, 0x00);
}
/* Adjust CCK according to IQK result */
if (!pdmpriv->bCCKinCH14) {
rtw_write8(Adapter, 0xa22, CCKSwingTable_Ch1_Ch1323A[CCK_index][0]);
rtw_write8(Adapter, 0xa23, CCKSwingTable_Ch1_Ch1323A[CCK_index][1]);
rtw_write8(Adapter, 0xa24, CCKSwingTable_Ch1_Ch1323A[CCK_index][2]);
rtw_write8(Adapter, 0xa25, CCKSwingTable_Ch1_Ch1323A[CCK_index][3]);
rtw_write8(Adapter, 0xa26, CCKSwingTable_Ch1_Ch1323A[CCK_index][4]);
rtw_write8(Adapter, 0xa27, CCKSwingTable_Ch1_Ch1323A[CCK_index][5]);
rtw_write8(Adapter, 0xa28, CCKSwingTable_Ch1_Ch1323A[CCK_index][6]);
rtw_write8(Adapter, 0xa29, CCKSwingTable_Ch1_Ch1323A[CCK_index][7]);
} else {
rtw_write8(Adapter, 0xa22, CCKSwingTable_Ch1423A[CCK_index][0]);
rtw_write8(Adapter, 0xa23, CCKSwingTable_Ch1423A[CCK_index][1]);
rtw_write8(Adapter, 0xa24, CCKSwingTable_Ch1423A[CCK_index][2]);
rtw_write8(Adapter, 0xa25, CCKSwingTable_Ch1423A[CCK_index][3]);
rtw_write8(Adapter, 0xa26, CCKSwingTable_Ch1423A[CCK_index][4]);
rtw_write8(Adapter, 0xa27, CCKSwingTable_Ch1423A[CCK_index][5]);
rtw_write8(Adapter, 0xa28, CCKSwingTable_Ch1423A[CCK_index][6]);
rtw_write8(Adapter, 0xa29, CCKSwingTable_Ch1423A[CCK_index][7]);
}
if (is2T) {
ele_D = (OFDMSwingTable23A[(u8)OFDM_index[1]] & 0xFFC00000)>>22;
/* new element A = element D x X */
X = pdmpriv->RegEB4;
Y = pdmpriv->RegEBC;
if (X != 0) {
if ((X & 0x00000200) != 0) /* consider minus */
X = X | 0xFFFFFC00;
ele_A = ((X * ele_D)>>8)&0x000003FF;
/* new element C = element D x Y */
if ((Y & 0x00000200) != 0)
Y = Y | 0xFFFFFC00;
ele_C = ((Y * ele_D)>>8)&0x00003FF;
/* write new elements A, C, D to regC88 and regC9C, element B is always 0 */
value32 = (ele_D<<22)|((ele_C&0x3F)<<16) | ele_A;
PHY_SetBBReg(Adapter, rOFDM0_XBTxIQImbalance, bMaskDWord, value32);
value32 = (ele_C&0x000003C0)>>6;
PHY_SetBBReg(Adapter, rOFDM0_XDTxAFE, bMaskH4Bits, value32);
value32 = ((X * ele_D)>>7)&0x01;
PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, BIT27, value32);
value32 = ((Y * ele_D)>>7)&0x01;
PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, BIT25, value32);
} else {
PHY_SetBBReg(Adapter, rOFDM0_XBTxIQImbalance, bMaskDWord, OFDMSwingTable23A[OFDM_index[1]]);
PHY_SetBBReg(Adapter, rOFDM0_XDTxAFE, bMaskH4Bits, 0x00);
PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, BIT27|BIT25, 0x00);
}
}
}
if (delta_IQK > 3) {
pdmpriv->ThermalValue_IQK = ThermalValue;
rtl8723a_phy_iq_calibrate(Adapter, false);
}
/* update thermal meter value */
if (pdmpriv->TxPowerTrackControl)
pdmpriv->ThermalValue = ThermalValue;
}
pdmpriv->TXPowercount = 0;
}
/* Description: */
/* - Dispatch TxPower Tracking direct call ONLY for 92s. */
/* - We shall NOT schedule Workitem within PASSIVE LEVEL, which will cause system resource */
/* leakage under some platform. */
/* Assumption: */
/* PASSIVE_LEVEL when this routine is called. */
static void ODM_TXPowerTracking92CDirectCall(struct rtw_adapter *Adapter)
{
odm_TXPowerTrackingCallback_ThermalMeter_92C(Adapter);
}
static void odm_CheckTXPowerTracking_ThermalMeter(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
struct dm_odm_t *podmpriv = &pHalData->odmpriv;
if (!(podmpriv->SupportAbility & ODM_RF_TX_PWR_TRACK))
return;
if (!pdmpriv->TM_Trigger) { /* at least delay 1 sec */
PHY_SetRFReg(Adapter, RF_PATH_A, RF_T_METER, bRFRegOffsetMask, 0x60);
pdmpriv->TM_Trigger = 1;
return;
} else {
ODM_TXPowerTracking92CDirectCall(Adapter);
pdmpriv->TM_Trigger = 0;
}
}
void rtl8723a_odm_check_tx_power_tracking(struct rtw_adapter *Adapter)
{
odm_CheckTXPowerTracking_ThermalMeter(Adapter);
}
/* IQK */
#define MAX_TOLERANCE 5
#define IQK_DELAY_TIME 1 /* ms */
static u8 _PHY_PathA_IQK(struct rtw_adapter *pAdapter, bool configPathB)
{
u32 regEAC, regE94, regE9C, regEA4;
u8 result = 0x00;
struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
/* path-A IQK setting */
PHY_SetBBReg(pAdapter, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1f);
PHY_SetBBReg(pAdapter, rRx_IQK_Tone_A, bMaskDWord, 0x10008c1f);
PHY_SetBBReg(pAdapter, rTx_IQK_PI_A, bMaskDWord, 0x82140102);
PHY_SetBBReg(pAdapter, rRx_IQK_PI_A, bMaskDWord, configPathB ? 0x28160202 :
IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID)?0x28160202:0x28160502);
/* path-B IQK setting */
if (configPathB) {
PHY_SetBBReg(pAdapter, rTx_IQK_Tone_B, bMaskDWord, 0x10008c22);
PHY_SetBBReg(pAdapter, rRx_IQK_Tone_B, bMaskDWord, 0x10008c22);
PHY_SetBBReg(pAdapter, rTx_IQK_PI_B, bMaskDWord, 0x82140102);
PHY_SetBBReg(pAdapter, rRx_IQK_PI_B, bMaskDWord, 0x28160202);
}
/* LO calibration setting */
PHY_SetBBReg(pAdapter, rIQK_AGC_Rsp, bMaskDWord, 0x001028d1);
/* One shot, path A LOK & IQK */
PHY_SetBBReg(pAdapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
PHY_SetBBReg(pAdapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
/* delay x ms */
udelay(IQK_DELAY_TIME*1000);/* PlatformStallExecution(IQK_DELAY_TIME*1000); */
/* Check failed */
regEAC = PHY_QueryBBReg(pAdapter, rRx_Power_After_IQK_A_2, bMaskDWord);
regE94 = PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_A, bMaskDWord);
regE9C = PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_A, bMaskDWord);
regEA4 = PHY_QueryBBReg(pAdapter, rRx_Power_Before_IQK_A_2, bMaskDWord);
if (!(regEAC & BIT28) &&
(((regE94 & 0x03FF0000)>>16) != 0x142) &&
(((regE9C & 0x03FF0000)>>16) != 0x42))
result |= 0x01;
else /* if Tx not OK, ignore Rx */
return result;
if (!(regEAC & BIT27) && /* if Tx is OK, check whether Rx is OK */
(((regEA4 & 0x03FF0000)>>16) != 0x132) &&
(((regEAC & 0x03FF0000)>>16) != 0x36))
result |= 0x02;
else
DBG_8723A("Path A Rx IQK fail!!\n");
return result;
}
static u8 _PHY_PathB_IQK(struct rtw_adapter *pAdapter)
{
u32 regEAC, regEB4, regEBC, regEC4, regECC;
u8 result = 0x00;
/* One shot, path B LOK & IQK */
PHY_SetBBReg(pAdapter, rIQK_AGC_Cont, bMaskDWord, 0x00000002);
PHY_SetBBReg(pAdapter, rIQK_AGC_Cont, bMaskDWord, 0x00000000);
/* delay x ms */
udelay(IQK_DELAY_TIME*1000);
/* Check failed */
regEAC = PHY_QueryBBReg(pAdapter, rRx_Power_After_IQK_A_2, bMaskDWord);
regEB4 = PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_B, bMaskDWord);
regEBC = PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_B, bMaskDWord);
regEC4 = PHY_QueryBBReg(pAdapter, rRx_Power_Before_IQK_B_2, bMaskDWord);
regECC = PHY_QueryBBReg(pAdapter, rRx_Power_After_IQK_B_2, bMaskDWord);
if (!(regEAC & BIT31) &&
(((regEB4 & 0x03FF0000)>>16) != 0x142) &&
(((regEBC & 0x03FF0000)>>16) != 0x42))
result |= 0x01;
else
return result;
if (!(regEAC & BIT30) &&
(((regEC4 & 0x03FF0000)>>16) != 0x132) &&
(((regECC & 0x03FF0000)>>16) != 0x36))
result |= 0x02;
else
DBG_8723A("Path B Rx IQK fail!!\n");
return result;
}
static void _PHY_PathAFillIQKMatrix(struct rtw_adapter *pAdapter,
bool bIQKOK,
int result[][8],
u8 final_candidate,
bool bTxOnly
)
{
u32 Oldval_0, X, TX0_A, reg;
s32 Y, TX0_C;
DBG_8723A("Path A IQ Calibration %s !\n", (bIQKOK)?"Success":"Failed");
if (final_candidate == 0xFF) {
return;
} else if (bIQKOK) {
Oldval_0 = (PHY_QueryBBReg(pAdapter, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
X = result[final_candidate][0];
if ((X & 0x00000200) != 0)
X = X | 0xFFFFFC00;
TX0_A = (X * Oldval_0) >> 8;
PHY_SetBBReg(pAdapter, rOFDM0_XATxIQImbalance, 0x3FF, TX0_A);
PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(31), ((X * Oldval_0>>7) & 0x1));
Y = result[final_candidate][1];
if ((Y & 0x00000200) != 0)
Y = Y | 0xFFFFFC00;
TX0_C = (Y * Oldval_0) >> 8;
PHY_SetBBReg(pAdapter, rOFDM0_XCTxAFE, 0xF0000000, ((TX0_C&0x3C0)>>6));
PHY_SetBBReg(pAdapter, rOFDM0_XATxIQImbalance, 0x003F0000, (TX0_C&0x3F));
PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(29), ((Y * Oldval_0>>7) & 0x1));
if (bTxOnly) {
DBG_8723A("_PHY_PathAFillIQKMatrix only Tx OK\n");
return;
}
reg = result[final_candidate][2];
PHY_SetBBReg(pAdapter, rOFDM0_XARxIQImbalance, 0x3FF, reg);
reg = result[final_candidate][3] & 0x3F;
PHY_SetBBReg(pAdapter, rOFDM0_XARxIQImbalance, 0xFC00, reg);
reg = (result[final_candidate][3] >> 6) & 0xF;
PHY_SetBBReg(pAdapter, rOFDM0_RxIQExtAnta, 0xF0000000, reg);
}
}
static void _PHY_PathBFillIQKMatrix(struct rtw_adapter *pAdapter, bool bIQKOK, int result[][8], u8 final_candidate, bool bTxOnly)
{
u32 Oldval_1, X, TX1_A, reg;
s32 Y, TX1_C;
DBG_8723A("Path B IQ Calibration %s !\n", (bIQKOK)?"Success":"Failed");
if (final_candidate == 0xFF) {
return;
} else if (bIQKOK) {
Oldval_1 = (PHY_QueryBBReg(pAdapter, rOFDM0_XBTxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
X = result[final_candidate][4];
if ((X & 0x00000200) != 0)
X = X | 0xFFFFFC00;
TX1_A = (X * Oldval_1) >> 8;
PHY_SetBBReg(pAdapter, rOFDM0_XBTxIQImbalance, 0x3FF, TX1_A);
PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(27), ((X * Oldval_1>>7) & 0x1));
Y = result[final_candidate][5];
if ((Y & 0x00000200) != 0)
Y = Y | 0xFFFFFC00;
TX1_C = (Y * Oldval_1) >> 8;
PHY_SetBBReg(pAdapter, rOFDM0_XDTxAFE, 0xF0000000, ((TX1_C&0x3C0)>>6));
PHY_SetBBReg(pAdapter, rOFDM0_XBTxIQImbalance, 0x003F0000, (TX1_C&0x3F));
PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(25), ((Y * Oldval_1>>7) & 0x1));
if (bTxOnly)
return;
reg = result[final_candidate][6];
PHY_SetBBReg(pAdapter, rOFDM0_XBRxIQImbalance, 0x3FF, reg);
reg = result[final_candidate][7] & 0x3F;
PHY_SetBBReg(pAdapter, rOFDM0_XBRxIQImbalance, 0xFC00, reg);
reg = (result[final_candidate][7] >> 6) & 0xF;
PHY_SetBBReg(pAdapter, rOFDM0_AGCRSSITable, 0x0000F000, reg);
}
}
static void _PHY_SaveADDARegisters(struct rtw_adapter *pAdapter, u32 *ADDAReg, u32 *ADDABackup, u32 RegisterNum)
{
u32 i;
for (i = 0 ; i < RegisterNum ; i++) {
ADDABackup[i] = PHY_QueryBBReg(pAdapter, ADDAReg[i], bMaskDWord);
}
}
static void _PHY_SaveMACRegisters(struct rtw_adapter *pAdapter, u32 *MACReg, u32 *MACBackup)
{
u32 i;
for (i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++) {
MACBackup[i] = rtw_read8(pAdapter, MACReg[i]);
}
MACBackup[i] = rtw_read32(pAdapter, MACReg[i]);
}
static void _PHY_ReloadADDARegisters(struct rtw_adapter *pAdapter, u32 *ADDAReg, u32 *ADDABackup, u32 RegiesterNum)
{
u32 i;
for (i = 0 ; i < RegiesterNum ; i++) {
PHY_SetBBReg(pAdapter, ADDAReg[i], bMaskDWord, ADDABackup[i]);
}
}
static void _PHY_ReloadMACRegisters(struct rtw_adapter *pAdapter, u32 *MACReg, u32 *MACBackup)
{
u32 i;
for (i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++) {
rtw_write8(pAdapter, MACReg[i], (u8)MACBackup[i]);
}
rtw_write32(pAdapter, MACReg[i], MACBackup[i]);
}
static void _PHY_PathADDAOn(struct rtw_adapter *pAdapter, u32 *ADDAReg, bool isPathAOn, bool is2T)
{
u32 pathOn;
u32 i;
pathOn = isPathAOn ? 0x04db25a4 : 0x0b1b25a4;
if (false == is2T) {
pathOn = 0x0bdb25a0;
PHY_SetBBReg(pAdapter, ADDAReg[0], bMaskDWord, 0x0b1b25a0);
} else {
PHY_SetBBReg(pAdapter, ADDAReg[0], bMaskDWord, pathOn);
}
for (i = 1 ; i < IQK_ADDA_REG_NUM ; i++)
PHY_SetBBReg(pAdapter, ADDAReg[i], bMaskDWord, pathOn);
}
static void _PHY_MACSettingCalibration(struct rtw_adapter *pAdapter, u32 *MACReg, u32 *MACBackup)
{
u32 i = 0;
rtw_write8(pAdapter, MACReg[i], 0x3F);
for (i = 1 ; i < (IQK_MAC_REG_NUM - 1); i++) {
rtw_write8(pAdapter, MACReg[i], (u8)(MACBackup[i]&(~BIT3)));
}
rtw_write8(pAdapter, MACReg[i], (u8)(MACBackup[i]&(~BIT5)));
}
static void _PHY_PathAStandBy(struct rtw_adapter *pAdapter)
{
PHY_SetBBReg(pAdapter, rFPGA0_IQK, bMaskDWord, 0x0);
PHY_SetBBReg(pAdapter, 0x840, bMaskDWord, 0x00010000);
PHY_SetBBReg(pAdapter, rFPGA0_IQK, bMaskDWord, 0x80800000);
}
static void _PHY_PIModeSwitch(struct rtw_adapter *pAdapter, bool PIMode)
{
u32 mode;
mode = PIMode ? 0x01000100 : 0x01000000;
PHY_SetBBReg(pAdapter, 0x820, bMaskDWord, mode);
PHY_SetBBReg(pAdapter, 0x828, bMaskDWord, mode);
}
/*
return false => do IQK again
*/
static bool _PHY_SimularityCompare(struct rtw_adapter *pAdapter, int result[][8], u8 c1, u8 c2)
{
u32 i, j, diff, SimularityBitMap, bound = 0;
struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */
bool bResult = true, is2T = IS_92C_SERIAL(pHalData->VersionID);
if (is2T)
bound = 8;
else
bound = 4;
SimularityBitMap = 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) && !SimularityBitMap) {
if (result[c1][i]+result[c1][i+1] == 0)
final_candidate[(i/4)] = c2;
else if (result[c2][i]+result[c2][i+1] == 0)
final_candidate[(i/4)] = c1;
else
SimularityBitMap = SimularityBitMap|(1<<i);
} else {
SimularityBitMap = SimularityBitMap|(1<<i);
}
}
}
if (SimularityBitMap == 0) {
for (i = 0; i < (bound/4); i++) {
if (final_candidate[i] != 0xFF) {
for (j = i*4; j < (i+1)*4-2; j++)
result[3][j] = result[final_candidate[i]][j];
bResult = false;
}
}
return bResult;
} else if (!(SimularityBitMap & 0x0F)) {
/* path A OK */
for (i = 0; i < 4; i++)
result[3][i] = result[c1][i];
return false;
} else if (!(SimularityBitMap & 0xF0) && is2T) {
/* path B OK */
for (i = 4; i < 8; i++)
result[3][i] = result[c1][i];
return false;
} else {
return false;
}
}
static void _PHY_IQCalibrate(struct rtw_adapter *pAdapter, int result[][8], u8 t, bool is2T)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
u32 i;
u8 PathAOK, PathBOK;
u32 ADDA_REG[IQK_ADDA_REG_NUM] = {
rFPGA0_XCD_SwitchControl, rBlue_Tooth,
rRx_Wait_CCA, rTx_CCK_RFON,
rTx_CCK_BBON, rTx_OFDM_RFON,
rTx_OFDM_BBON, rTx_To_Rx,
rTx_To_Tx, rRx_CCK,
rRx_OFDM, rRx_Wait_RIFS,
rRx_TO_Rx, rStandby,
rSleep, rPMPD_ANAEN
};
u32 IQK_MAC_REG[IQK_MAC_REG_NUM] = {
REG_TXPAUSE, REG_BCN_CTRL,
REG_BCN_CTRL_1, REG_GPIO_MUXCFG
};
u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = {
rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar,
rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB,
rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE,
rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD
};
const u32 retryCount = 2;
/* Note: IQ calibration must be performed after loading */
/* PHY_REG.txt , and radio_a, radio_b.txt */
u32 bbvalue;
if (t == 0) {
bbvalue = PHY_QueryBBReg(pAdapter, rFPGA0_RFMOD, bMaskDWord);
/* Save ADDA parameters, turn Path A ADDA on */
_PHY_SaveADDARegisters(pAdapter, ADDA_REG, pdmpriv->ADDA_backup, IQK_ADDA_REG_NUM);
_PHY_SaveMACRegisters(pAdapter, IQK_MAC_REG, pdmpriv->IQK_MAC_backup);
_PHY_SaveADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup, IQK_BB_REG_NUM);
}
_PHY_PathADDAOn(pAdapter, ADDA_REG, true, is2T);
if (t == 0)
pdmpriv->bRfPiEnable = (u8)PHY_QueryBBReg(pAdapter, rFPGA0_XA_HSSIParameter1, BIT(8));
if (!pdmpriv->bRfPiEnable) {
/* Switch BB to PI mode to do IQ Calibration. */
_PHY_PIModeSwitch(pAdapter, true);
}
PHY_SetBBReg(pAdapter, rFPGA0_RFMOD, BIT24, 0x00);
PHY_SetBBReg(pAdapter, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
PHY_SetBBReg(pAdapter, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
PHY_SetBBReg(pAdapter, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT10, 0x01);
PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT26, 0x01);
PHY_SetBBReg(pAdapter, rFPGA0_XA_RFInterfaceOE, BIT10, 0x00);
PHY_SetBBReg(pAdapter, rFPGA0_XB_RFInterfaceOE, BIT10, 0x00);
if (is2T) {
PHY_SetBBReg(pAdapter, rFPGA0_XA_LSSIParameter, bMaskDWord, 0x00010000);
PHY_SetBBReg(pAdapter, rFPGA0_XB_LSSIParameter, bMaskDWord, 0x00010000);
}
/* MAC settings */
_PHY_MACSettingCalibration(pAdapter, IQK_MAC_REG, pdmpriv->IQK_MAC_backup);
/* Page B init */
PHY_SetBBReg(pAdapter, rConfig_AntA, bMaskDWord, 0x00080000);
if (is2T)
PHY_SetBBReg(pAdapter, rConfig_AntB, bMaskDWord, 0x00080000);
/* IQ calibration setting */
PHY_SetBBReg(pAdapter, rFPGA0_IQK, bMaskDWord, 0x80800000);
PHY_SetBBReg(pAdapter, rTx_IQK, bMaskDWord, 0x01007c00);
PHY_SetBBReg(pAdapter, rRx_IQK, bMaskDWord, 0x01004800);
for (i = 0 ; i < retryCount ; i++) {
PathAOK = _PHY_PathA_IQK(pAdapter, is2T);
if (PathAOK == 0x03) {
DBG_8723A("Path A IQK Success!!\n");
result[t][0] = (PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
result[t][1] = (PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
result[t][2] = (PHY_QueryBBReg(pAdapter, rRx_Power_Before_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
result[t][3] = (PHY_QueryBBReg(pAdapter, rRx_Power_After_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
break;
} else if (i == (retryCount-1) && PathAOK == 0x01) {
/* Tx IQK OK */
DBG_8723A("Path A IQK Only Tx Success!!\n");
result[t][0] = (PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
result[t][1] = (PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
}
}
if (0x00 == PathAOK) {
DBG_8723A("Path A IQK failed!!\n");
}
if (is2T) {
_PHY_PathAStandBy(pAdapter);
/* Turn Path B ADDA on */
_PHY_PathADDAOn(pAdapter, ADDA_REG, false, is2T);
for (i = 0 ; i < retryCount ; i++) {
PathBOK = _PHY_PathB_IQK(pAdapter);
if (PathBOK == 0x03) {
DBG_8723A("Path B IQK Success!!\n");
result[t][4] = (PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_B, bMaskDWord)&0x3FF0000)>>16;
result[t][5] = (PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_B, bMaskDWord)&0x3FF0000)>>16;
result[t][6] = (PHY_QueryBBReg(pAdapter, rRx_Power_Before_IQK_B_2, bMaskDWord)&0x3FF0000)>>16;
result[t][7] = (PHY_QueryBBReg(pAdapter, rRx_Power_After_IQK_B_2, bMaskDWord)&0x3FF0000)>>16;
break;
} else if (i == (retryCount - 1) && PathBOK == 0x01) {
/* Tx IQK OK */
DBG_8723A("Path B Only Tx IQK Success!!\n");
result[t][4] = (PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_B, bMaskDWord)&0x3FF0000)>>16;
result[t][5] = (PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_B, bMaskDWord)&0x3FF0000)>>16;
}
}
if (0x00 == PathBOK) {
DBG_8723A("Path B IQK failed!!\n");
}
}
/* Back to BB mode, load original value */
PHY_SetBBReg(pAdapter, rFPGA0_IQK, bMaskDWord, 0);
if (t != 0) {
if (!pdmpriv->bRfPiEnable) {
/* Switch back BB to SI mode after finish IQ Calibration. */
_PHY_PIModeSwitch(pAdapter, false);
}
/* Reload ADDA power saving parameters */
_PHY_ReloadADDARegisters(pAdapter, ADDA_REG, pdmpriv->ADDA_backup, IQK_ADDA_REG_NUM);
/* Reload MAC parameters */
_PHY_ReloadMACRegisters(pAdapter, IQK_MAC_REG, pdmpriv->IQK_MAC_backup);
/* Reload BB parameters */
_PHY_ReloadADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup, IQK_BB_REG_NUM);
/* Restore RX initial gain */
PHY_SetBBReg(pAdapter, rFPGA0_XA_LSSIParameter, bMaskDWord, 0x00032ed3);
if (is2T) {
PHY_SetBBReg(pAdapter, rFPGA0_XB_LSSIParameter, bMaskDWord, 0x00032ed3);
}
/* load 0xe30 IQC default value */
PHY_SetBBReg(pAdapter, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
PHY_SetBBReg(pAdapter, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
}
}
static void _PHY_LCCalibrate(struct rtw_adapter *pAdapter, bool is2T)
{
u8 tmpReg;
u32 RF_Amode = 0, RF_Bmode = 0, LC_Cal;
/* Check continuous TX and Packet TX */
tmpReg = rtw_read8(pAdapter, 0xd03);
if ((tmpReg&0x70) != 0) /* Deal with contisuous TX case */
rtw_write8(pAdapter, 0xd03, tmpReg&0x8F); /* disable all continuous TX */
else /* Deal with Packet TX case */
rtw_write8(pAdapter, REG_TXPAUSE, 0xFF); /* block all queues */
if ((tmpReg&0x70) != 0) {
/* 1. Read original RF mode */
/* Path-A */
RF_Amode = PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_AC, bMask12Bits);
/* Path-B */
if (is2T)
RF_Bmode = PHY_QueryRFReg(pAdapter, RF_PATH_B, RF_AC, bMask12Bits);
/* 2. Set RF mode = standby mode */
/* Path-A */
PHY_SetRFReg(pAdapter, RF_PATH_A, RF_AC, bMask12Bits, (RF_Amode&0x8FFFF)|0x10000);
/* Path-B */
if (is2T)
PHY_SetRFReg(pAdapter, RF_PATH_B, RF_AC, bMask12Bits, (RF_Bmode&0x8FFFF)|0x10000);
}
/* 3. Read RF reg18 */
LC_Cal = PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_CHNLBW, bMask12Bits);
/* 4. Set LC calibration begin */
PHY_SetRFReg(pAdapter, RF_PATH_A, RF_CHNLBW, bMask12Bits, LC_Cal|0x08000);
msleep(100);
/* Restore original situation */
if ((tmpReg&0x70) != 0) { /* Deal with contuous TX case */
/* Path-A */
rtw_write8(pAdapter, 0xd03, tmpReg);
PHY_SetRFReg(pAdapter, RF_PATH_A, RF_AC, bMask12Bits, RF_Amode);
/* Path-B */
if (is2T)
PHY_SetRFReg(pAdapter, RF_PATH_B, RF_AC, bMask12Bits, RF_Bmode);
} else { /* Deal with Packet TX case */
rtw_write8(pAdapter, REG_TXPAUSE, 0x00);
}
}
/* Analog Pre-distortion calibration */
#define APK_BB_REG_NUM 8
#define APK_CURVE_REG_NUM 4
#define PATH_NUM 2
void rtl8723a_phy_iq_calibrate(struct rtw_adapter *pAdapter, bool bReCovery)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
s32 result[4][8]; /* last is final result */
u8 i, final_candidate;
bool bPathAOK, bPathBOK;
s32 RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4;
s32 RegECC, RegTmp = 0;
bool is12simular, is13simular, is23simular;
bool bStartContTx = false, bSingleTone = false;
bool bCarrierSuppression = false;
u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = {
rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance,
rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable,
rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance,
rOFDM0_XCTxAFE, rOFDM0_XDTxAFE,
rOFDM0_RxIQExtAnta
};
/* ignore IQK when continuous Tx */
if (bStartContTx || bSingleTone || bCarrierSuppression)
return;
if (bReCovery) {
_PHY_ReloadADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup_recover, 9);
return;
}
DBG_8723A("IQK:Start!!!\n");
for (i = 0; i < 8; i++) {
result[0][i] = 0;
result[1][i] = 0;
result[2][i] = 0;
result[3][i] = 0;
}
final_candidate = 0xff;
bPathAOK = false;
bPathBOK = false;
is12simular = false;
is23simular = false;
is13simular = false;
for (i = 0; i < 3; i++) {
if (IS_92C_SERIAL(pHalData->VersionID)) {
_PHY_IQCalibrate(pAdapter, result, i, true);
} else {
/* For 88C 1T1R */
_PHY_IQCalibrate(pAdapter, result, i, false);
}
if (i == 1) {
is12simular = _PHY_SimularityCompare(pAdapter, result, 0, 1);
if (is12simular) {
final_candidate = 0;
break;
}
}
if (i == 2) {
is13simular = _PHY_SimularityCompare(pAdapter, result, 0, 2);
if (is13simular) {
final_candidate = 0;
break;
}
is23simular = _PHY_SimularityCompare(pAdapter, result, 1, 2);
if (is23simular) {
final_candidate = 1;
} else {
for (i = 0; i < 8; i++)
RegTmp += result[3][i];
if (RegTmp != 0)
final_candidate = 3;
else
final_candidate = 0xFF;
}
}
}
for (i = 0; i < 4; i++) {
RegE94 = result[i][0];
RegE9C = result[i][1];
RegEA4 = result[i][2];
RegEAC = result[i][3];
RegEB4 = result[i][4];
RegEBC = result[i][5];
RegEC4 = result[i][6];
RegECC = result[i][7];
}
if (final_candidate != 0xff) {
RegE94 = result[final_candidate][0];
pdmpriv->RegE94 = RegE94;
RegE9C = result[final_candidate][1];
pdmpriv->RegE9C = RegE9C;
RegEA4 = result[final_candidate][2];
RegEAC = result[final_candidate][3];
RegEB4 = result[final_candidate][4];
pdmpriv->RegEB4 = RegEB4;
RegEBC = result[final_candidate][5];
pdmpriv->RegEBC = RegEBC;
RegEC4 = result[final_candidate][6];
RegECC = result[final_candidate][7];
DBG_8723A("IQK: final_candidate is %x\n", final_candidate);
DBG_8723A("IQK: RegE94 =%x RegE9C =%x RegEA4 =%x RegEAC =%x RegEB4 =%x RegEBC =%x RegEC4 =%x RegECC =%x\n ",
RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4, RegECC);
bPathAOK = bPathBOK = true;
} else {
RegE94 = RegEB4 = pdmpriv->RegE94 = pdmpriv->RegEB4 = 0x100; /* X default value */
RegE9C = RegEBC = pdmpriv->RegE9C = pdmpriv->RegEBC = 0x0; /* Y default value */
}
if ((RegE94 != 0)/*&&(RegEA4 != 0)*/)
_PHY_PathAFillIQKMatrix(pAdapter, bPathAOK, result, final_candidate, (RegEA4 == 0));
if (IS_92C_SERIAL(pHalData->VersionID)) {
if ((RegEB4 != 0)/*&&(RegEC4 != 0)*/)
_PHY_PathBFillIQKMatrix(pAdapter, bPathBOK, result, final_candidate, (RegEC4 == 0));
}
_PHY_SaveADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup_recover, 9);
}
void rtl8723a_phy_lc_calibrate(struct rtw_adapter *pAdapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
struct mlme_ext_priv *pmlmeext = &pAdapter->mlmeextpriv;
bool bStartContTx = false, bSingleTone = false, bCarrierSuppression = false;
/* ignore IQK when continuous Tx */
if (bStartContTx || bSingleTone || bCarrierSuppression)
return;
if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
return;
if (IS_92C_SERIAL(pHalData->VersionID)) {
_PHY_LCCalibrate(pAdapter, true);
} else {
/* For 88C 1T1R */
_PHY_LCCalibrate(pAdapter, false);
}
}
void
rtl8723a_phy_ap_calibrate(struct rtw_adapter *pAdapter, char delta)
{
}
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#include "odm_precomp.h"
static bool CheckCondition(const u32 Condition, const u32 Hex)
{
u32 _board = (Hex & 0x000000FF);
u32 _interface = (Hex & 0x0000FF00) >> 8;
u32 _platform = (Hex & 0x00FF0000) >> 16;
u32 cond = Condition;
if (Condition == 0xCDCDCDCD)
return true;
cond = Condition & 0x000000FF;
if ((_board == cond) && cond != 0x00)
return false;
cond = Condition & 0x0000FF00;
cond = cond >> 8;
if ((_interface & cond) == 0 && cond != 0x07)
return false;
cond = Condition & 0x00FF0000;
cond = cond >> 16;
if ((_platform & cond) == 0 && cond != 0x0F)
return false;
return true;
}
/******************************************************************************
* AGC_TAB_1T.TXT
******************************************************************************/
static u32 Array_AGC_TAB_1T_8723A[] = {
0xC78, 0x7B000001,
0xC78, 0x7B010001,
0xC78, 0x7B020001,
0xC78, 0x7B030001,
0xC78, 0x7B040001,
0xC78, 0x7B050001,
0xC78, 0x7A060001,
0xC78, 0x79070001,
0xC78, 0x78080001,
0xC78, 0x77090001,
0xC78, 0x760A0001,
0xC78, 0x750B0001,
0xC78, 0x740C0001,
0xC78, 0x730D0001,
0xC78, 0x720E0001,
0xC78, 0x710F0001,
0xC78, 0x70100001,
0xC78, 0x6F110001,
0xC78, 0x6E120001,
0xC78, 0x6D130001,
0xC78, 0x6C140001,
0xC78, 0x6B150001,
0xC78, 0x6A160001,
0xC78, 0x69170001,
0xC78, 0x68180001,
0xC78, 0x67190001,
0xC78, 0x661A0001,
0xC78, 0x651B0001,
0xC78, 0x641C0001,
0xC78, 0x631D0001,
0xC78, 0x621E0001,
0xC78, 0x611F0001,
0xC78, 0x60200001,
0xC78, 0x49210001,
0xC78, 0x48220001,
0xC78, 0x47230001,
0xC78, 0x46240001,
0xC78, 0x45250001,
0xC78, 0x44260001,
0xC78, 0x43270001,
0xC78, 0x42280001,
0xC78, 0x41290001,
0xC78, 0x402A0001,
0xC78, 0x262B0001,
0xC78, 0x252C0001,
0xC78, 0x242D0001,
0xC78, 0x232E0001,
0xC78, 0x222F0001,
0xC78, 0x21300001,
0xC78, 0x20310001,
0xC78, 0x06320001,
0xC78, 0x05330001,
0xC78, 0x04340001,
0xC78, 0x03350001,
0xC78, 0x02360001,
0xC78, 0x01370001,
0xC78, 0x00380001,
0xC78, 0x00390001,
0xC78, 0x003A0001,
0xC78, 0x003B0001,
0xC78, 0x003C0001,
0xC78, 0x003D0001,
0xC78, 0x003E0001,
0xC78, 0x003F0001,
0xC78, 0x7B400001,
0xC78, 0x7B410001,
0xC78, 0x7B420001,
0xC78, 0x7B430001,
0xC78, 0x7B440001,
0xC78, 0x7B450001,
0xC78, 0x7A460001,
0xC78, 0x79470001,
0xC78, 0x78480001,
0xC78, 0x77490001,
0xC78, 0x764A0001,
0xC78, 0x754B0001,
0xC78, 0x744C0001,
0xC78, 0x734D0001,
0xC78, 0x724E0001,
0xC78, 0x714F0001,
0xC78, 0x70500001,
0xC78, 0x6F510001,
0xC78, 0x6E520001,
0xC78, 0x6D530001,
0xC78, 0x6C540001,
0xC78, 0x6B550001,
0xC78, 0x6A560001,
0xC78, 0x69570001,
0xC78, 0x68580001,
0xC78, 0x67590001,
0xC78, 0x665A0001,
0xC78, 0x655B0001,
0xC78, 0x645C0001,
0xC78, 0x635D0001,
0xC78, 0x625E0001,
0xC78, 0x615F0001,
0xC78, 0x60600001,
0xC78, 0x49610001,
0xC78, 0x48620001,
0xC78, 0x47630001,
0xC78, 0x46640001,
0xC78, 0x45650001,
0xC78, 0x44660001,
0xC78, 0x43670001,
0xC78, 0x42680001,
0xC78, 0x41690001,
0xC78, 0x406A0001,
0xC78, 0x266B0001,
0xC78, 0x256C0001,
0xC78, 0x246D0001,
0xC78, 0x236E0001,
0xC78, 0x226F0001,
0xC78, 0x21700001,
0xC78, 0x20710001,
0xC78, 0x06720001,
0xC78, 0x05730001,
0xC78, 0x04740001,
0xC78, 0x03750001,
0xC78, 0x02760001,
0xC78, 0x01770001,
0xC78, 0x00780001,
0xC78, 0x00790001,
0xC78, 0x007A0001,
0xC78, 0x007B0001,
0xC78, 0x007C0001,
0xC78, 0x007D0001,
0xC78, 0x007E0001,
0xC78, 0x007F0001,
0xC78, 0x3800001E,
0xC78, 0x3801001E,
0xC78, 0x3802001E,
0xC78, 0x3803001E,
0xC78, 0x3804001E,
0xC78, 0x3805001E,
0xC78, 0x3806001E,
0xC78, 0x3807001E,
0xC78, 0x3808001E,
0xC78, 0x3C09001E,
0xC78, 0x3E0A001E,
0xC78, 0x400B001E,
0xC78, 0x440C001E,
0xC78, 0x480D001E,
0xC78, 0x4C0E001E,
0xC78, 0x500F001E,
0xC78, 0x5210001E,
0xC78, 0x5611001E,
0xC78, 0x5A12001E,
0xC78, 0x5E13001E,
0xC78, 0x6014001E,
0xC78, 0x6015001E,
0xC78, 0x6016001E,
0xC78, 0x6217001E,
0xC78, 0x6218001E,
0xC78, 0x6219001E,
0xC78, 0x621A001E,
0xC78, 0x621B001E,
0xC78, 0x621C001E,
0xC78, 0x621D001E,
0xC78, 0x621E001E,
0xC78, 0x621F001E,
};
#define READ_NEXT_PAIR(v1, v2, i) \
do { \
i += 2; v1 = Array[i]; v2 = Array[i+1]; \
} while (0)
void ODM_ReadAndConfig_AGC_TAB_1T_8723A(struct dm_odm_t *pDM_Odm)
{
u32 hex;
u32 i;
u8 platform = 0x04;
u8 interfaceValue = pDM_Odm->SupportInterface;
u8 board = pDM_Odm->BoardType;
u32 ArrayLen = sizeof(Array_AGC_TAB_1T_8723A)/sizeof(u32);
u32 *Array = Array_AGC_TAB_1T_8723A;
hex = board;
hex += interfaceValue << 8;
hex += platform << 16;
hex += 0xFF000000;
for (i = 0; i < ArrayLen; i += 2) {
u32 v1 = Array[i];
u32 v2 = Array[i+1];
/* This (offset, data) pair meets the condition. */
if (v1 < 0xCDCDCDCD) {
odm_ConfigBB_AGC_8723A(pDM_Odm, v1, bMaskDWord, v2);
continue;
} else {
if (!CheckCondition(Array[i], hex)) {
/* Discard the following (offset, data) pairs. */
READ_NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < ArrayLen - 2)
READ_NEXT_PAIR(v1, v2, i);
i -= 2; /* prevent from for-loop += 2 */
} else {
/* Configure matched pairs and skip to end of if-else. */
READ_NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < ArrayLen - 2) {
odm_ConfigBB_AGC_8723A(pDM_Odm, v1, bMaskDWord, v2);
READ_NEXT_PAIR(v1, v2, i);
}
while (v2 != 0xDEAD && i < ArrayLen - 2)
READ_NEXT_PAIR(v1, v2, i);
}
}
}
}
/******************************************************************************
* PHY_REG_1T.TXT
******************************************************************************/
static u32 Array_PHY_REG_1T_8723A[] = {
0x800, 0x80040000,
0x804, 0x00000003,
0x808, 0x0000FC00,
0x80C, 0x0000000A,
0x810, 0x10001331,
0x814, 0x020C3D10,
0x818, 0x02200385,
0x81C, 0x00000000,
0x820, 0x01000100,
0x824, 0x00390004,
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, 0x569A569A,
0x85C, 0x001B25A4,
0x860, 0x66F60110,
0x864, 0x061F0130,
0x868, 0x00000000,
0x86C, 0x32323200,
0x870, 0x07000760,
0x874, 0x22004000,
0x878, 0x00000808,
0x87C, 0x00000000,
0x880, 0xC0083070,
0x884, 0x000004D5,
0x888, 0x00000000,
0x88C, 0xCCC000C0,
0x890, 0x00000800,
0x894, 0xFFFFFFFE,
0x898, 0x40302010,
0x89C, 0x00706050,
0x900, 0x00000000,
0x904, 0x00000023,
0x908, 0x00000000,
0x90C, 0x81121111,
0xA00, 0x00D047C8,
0xA04, 0x80FF000C,
0xA08, 0x8C838300,
0xA0C, 0x2E68120F,
0xA10, 0x9500BB78,
0xA14, 0x11144028,
0xA18, 0x00881117,
0xA1C, 0x89140F00,
0xA20, 0x1A1B0000,
0xA24, 0x090E1317,
0xA28, 0x00000204,
0xA2C, 0x00D30000,
0xA70, 0x101FBF00,
0xA74, 0x00000007,
0xA78, 0x00000900,
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, 0x69E9AC44,
0xFF0F011F, 0xABCD,
0xC34, 0x469652CF,
0xCDCDCDCD, 0xCDCD,
0xC34, 0x469652AF,
0xFF0F011F, 0xDEAD,
0xC38, 0x49795994,
0xC3C, 0x0A97971C,
0xC40, 0x1F7C403F,
0xC44, 0x000100B7,
0xC48, 0xEC020107,
0xC4C, 0x007F037F,
0xC50, 0x69543420,
0xC54, 0x43BC0094,
0xC58, 0x69543420,
0xC5C, 0x433C0094,
0xC60, 0x00000000,
0xFF0F011F, 0xABCD,
0xC64, 0x7116848B,
0xCDCDCDCD, 0xCDCD,
0xC64, 0x7112848B,
0xFF0F011F, 0xDEAD,
0xC68, 0x47C00BFF,
0xC6C, 0x00000036,
0xC70, 0x2C7F000D,
0xC74, 0x018610DB,
0xC78, 0x0000001F,
0xC7C, 0x00B91612,
0xC80, 0x40000100,
0xC84, 0x20F60000,
0xC88, 0x40000100,
0xC8C, 0x20200000,
0xC90, 0x00121820,
0xC94, 0x00000000,
0xC98, 0x00121820,
0xC9C, 0x00007F7F,
0xCA0, 0x00000000,
0xCA4, 0x00000080,
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, 0x00080740,
0xD04, 0x00020401,
0xD08, 0x0000907F,
0xD0C, 0x20010201,
0xD10, 0xA0633333,
0xD14, 0x3333BC43,
0xD18, 0x7A8F5B6B,
0xD2C, 0xCC979975,
0xD30, 0x00000000,
0xD34, 0x80608000,
0xD38, 0x00000000,
0xD3C, 0x00027293,
0xD40, 0x00000000,
0xD44, 0x00000000,
0xD48, 0x00000000,
0xD4C, 0x00000000,
0xD50, 0x6437140A,
0xD54, 0x00000000,
0xD58, 0x00000000,
0xD5C, 0x30032064,
0xD60, 0x4653DE68,
0xD64, 0x04518A3C,
0xD68, 0x00002101,
0xD6C, 0x2A201C16,
0xD70, 0x1812362E,
0xD74, 0x322C2220,
0xD78, 0x000E3C24,
0xE00, 0x2A2A2A2A,
0xE04, 0x2A2A2A2A,
0xE08, 0x03902A2A,
0xE10, 0x2A2A2A2A,
0xE14, 0x2A2A2A2A,
0xE18, 0x2A2A2A2A,
0xE1C, 0x2A2A2A2A,
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, 0x631B25A0,
0xE70, 0x631B25A0,
0xE74, 0x081B25A0,
0xE78, 0x081B25A0,
0xE7C, 0x081B25A0,
0xE80, 0x081B25A0,
0xE84, 0x631B25A0,
0xE88, 0x081B25A0,
0xE8C, 0x631B25A0,
0xED0, 0x631B25A0,
0xED4, 0x631B25A0,
0xED8, 0x631B25A0,
0xEDC, 0x001B25A0,
0xEE0, 0x001B25A0,
0xEEC, 0x6B1B25A0,
0xF14, 0x00000003,
0xF4C, 0x00000000,
0xF00, 0x00000300,
};
void ODM_ReadAndConfig_PHY_REG_1T_8723A(struct dm_odm_t *pDM_Odm)
{
u32 hex = 0;
u32 i = 0;
u8 platform = 0x04;
u8 interfaceValue = pDM_Odm->SupportInterface;
u8 board = pDM_Odm->BoardType;
u32 ArrayLen = sizeof(Array_PHY_REG_1T_8723A)/sizeof(u32);
u32 *Array = Array_PHY_REG_1T_8723A;
hex += board;
hex += interfaceValue << 8;
hex += platform << 16;
hex += 0xFF000000;
for (i = 0; i < ArrayLen; i += 2) {
u32 v1 = Array[i];
u32 v2 = Array[i+1];
/* This (offset, data) pair meets the condition. */
if (v1 < 0xCDCDCDCD) {
odm_ConfigBB_PHY_8723A(pDM_Odm, v1, bMaskDWord, v2);
continue;
} else {
if (!CheckCondition(Array[i], hex)) {
/* Discard the following (offset, data) pairs. */
READ_NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < ArrayLen - 2)
READ_NEXT_PAIR(v1, v2, i);
i -= 2; /* prevent from for-loop += 2 */
} else {
/* Configure matched pairs and skip to end of if-else. */
READ_NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < ArrayLen - 2) {
odm_ConfigBB_PHY_8723A(pDM_Odm, v1, bMaskDWord, v2);
READ_NEXT_PAIR(v1, v2, i);
}
while (v2 != 0xDEAD && i < ArrayLen - 2)
READ_NEXT_PAIR(v1, v2, i);
}
}
}
}
/******************************************************************************
* PHY_REG_MP.TXT
******************************************************************************/
static u32 Array_PHY_REG_MP_8723A[] = {
0xC30, 0x69E9AC4A,
0xC3C, 0x0A979718,
};
void ODM_ReadAndConfig_PHY_REG_MP_8723A(struct dm_odm_t *pDM_Odm)
{
u32 hex = 0;
u32 i = 0;
u8 platform = 0x04;
u8 interfaceValue = pDM_Odm->SupportInterface;
u8 board = pDM_Odm->BoardType;
u32 ArrayLen = sizeof(Array_PHY_REG_MP_8723A)/sizeof(u32);
u32 *Array = Array_PHY_REG_MP_8723A;
hex += board;
hex += interfaceValue << 8;
hex += platform << 16;
hex += 0xFF000000;
for (i = 0; i < ArrayLen; i += 2) {
u32 v1 = Array[i];
u32 v2 = Array[i+1];
/* This (offset, data) pair meets the condition. */
if (v1 < 0xCDCDCDCD) {
odm_ConfigBB_PHY_8723A(pDM_Odm, v1, bMaskDWord, v2);
continue;
} else {
if (!CheckCondition(Array[i], hex)) {
/* Discard the following (offset, data) pairs. */
READ_NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < ArrayLen - 2)
READ_NEXT_PAIR(v1, v2, i);
i -= 2; /* prevent from for-loop += 2 */
} else {
/* Configure matched pairs and skip to end of if-else. */
READ_NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < ArrayLen - 2) {
odm_ConfigBB_PHY_8723A(pDM_Odm, v1, bMaskDWord, v2);
READ_NEXT_PAIR(v1, v2, i);
}
while (v2 != 0xDEAD && i < ArrayLen - 2)
READ_NEXT_PAIR(v1, v2, i);
}
}
}
}
/******************************************************************************
* PHY_REG_PG.TXT
******************************************************************************/
static u32 Array_PHY_REG_PG_8723A[] = {
0xE00, 0xFFFFFFFF, 0x0A0C0C0C,
0xE04, 0xFFFFFFFF, 0x02040608,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x0A0C0D0E,
0xE14, 0xFFFFFFFF, 0x02040608,
0xE18, 0xFFFFFFFF, 0x0A0C0D0E,
0xE1C, 0xFFFFFFFF, 0x02040608,
0x830, 0xFFFFFFFF, 0x0A0C0C0C,
0x834, 0xFFFFFFFF, 0x02040608,
0x838, 0xFFFFFF00, 0x00000000,
0x86C, 0x000000FF, 0x00000000,
0x83C, 0xFFFFFFFF, 0x0A0C0D0E,
0x848, 0xFFFFFFFF, 0x02040608,
0x84C, 0xFFFFFFFF, 0x0A0C0D0E,
0x868, 0xFFFFFFFF, 0x02040608,
0xE00, 0xFFFFFFFF, 0x00000000,
0xE04, 0xFFFFFFFF, 0x00000000,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0x830, 0xFFFFFFFF, 0x00000000,
0x834, 0xFFFFFFFF, 0x00000000,
0x838, 0xFFFFFF00, 0x00000000,
0x86C, 0x000000FF, 0x00000000,
0x83C, 0xFFFFFFFF, 0x00000000,
0x848, 0xFFFFFFFF, 0x00000000,
0x84C, 0xFFFFFFFF, 0x00000000,
0x868, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x04040404,
0xE04, 0xFFFFFFFF, 0x00020204,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x06060606,
0xE14, 0xFFFFFFFF, 0x00020406,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0x830, 0xFFFFFFFF, 0x04040404,
0x834, 0xFFFFFFFF, 0x00020204,
0x838, 0xFFFFFF00, 0x00000000,
0x86C, 0x000000FF, 0x00000000,
0x83C, 0xFFFFFFFF, 0x06060606,
0x848, 0xFFFFFFFF, 0x00020406,
0x84C, 0xFFFFFFFF, 0x00000000,
0x868, 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,
0x830, 0xFFFFFFFF, 0x00000000,
0x834, 0xFFFFFFFF, 0x00000000,
0x838, 0xFFFFFF00, 0x00000000,
0x86C, 0x000000FF, 0x00000000,
0x83C, 0xFFFFFFFF, 0x00000000,
0x848, 0xFFFFFFFF, 0x00000000,
0x84C, 0xFFFFFFFF, 0x00000000,
0x868, 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,
0x830, 0xFFFFFFFF, 0x00000000,
0x834, 0xFFFFFFFF, 0x00000000,
0x838, 0xFFFFFF00, 0x00000000,
0x86C, 0x000000FF, 0x00000000,
0x83C, 0xFFFFFFFF, 0x00000000,
0x848, 0xFFFFFFFF, 0x00000000,
0x84C, 0xFFFFFFFF, 0x00000000,
0x868, 0xFFFFFFFF, 0x00000000,
0xE00, 0xFFFFFFFF, 0x04040404,
0xE04, 0xFFFFFFFF, 0x00020204,
0xE08, 0x0000FF00, 0x00000000,
0x86C, 0xFFFFFF00, 0x00000000,
0xE10, 0xFFFFFFFF, 0x00000000,
0xE14, 0xFFFFFFFF, 0x00000000,
0xE18, 0xFFFFFFFF, 0x00000000,
0xE1C, 0xFFFFFFFF, 0x00000000,
0x830, 0xFFFFFFFF, 0x04040404,
0x834, 0xFFFFFFFF, 0x00020204,
0x838, 0xFFFFFF00, 0x00000000,
0x86C, 0x000000FF, 0x00000000,
0x83C, 0xFFFFFFFF, 0x00000000,
0x848, 0xFFFFFFFF, 0x00000000,
0x84C, 0xFFFFFFFF, 0x00000000,
0x868, 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,
0x830, 0xFFFFFFFF, 0x00000000,
0x834, 0xFFFFFFFF, 0x00000000,
0x838, 0xFFFFFF00, 0x00000000,
0x86C, 0x000000FF, 0x00000000,
0x83C, 0xFFFFFFFF, 0x00000000,
0x848, 0xFFFFFFFF, 0x00000000,
0x84C, 0xFFFFFFFF, 0x00000000,
0x868, 0xFFFFFFFF, 0x00000000,
};
void ODM_ReadAndConfig_PHY_REG_PG_8723A(struct dm_odm_t *pDM_Odm)
{
u32 hex = 0;
u32 i = 0;
u8 platform = 0x04;
u8 interfaceValue = pDM_Odm->SupportInterface;
u8 board = pDM_Odm->BoardType;
u32 ArrayLen = sizeof(Array_PHY_REG_PG_8723A)/sizeof(u32);
u32 *Array = Array_PHY_REG_PG_8723A;
hex += board;
hex += interfaceValue << 8;
hex += platform << 16;
hex += 0xFF000000;
for (i = 0; i < ArrayLen; i += 3) {
u32 v1 = Array[i];
u32 v2 = Array[i+1];
u32 v3 = Array[i+2];
/* this line is a line of pure_body */
if (v1 < 0xCDCDCDCD) {
odm_ConfigBB_PHY_REG_PG_8723A(pDM_Odm, v1, v2, v3);
continue;
} else { /* this line is the start of branch */
if (!CheckCondition(Array[i], hex)) {
/* don't need the hw_body */
i += 2; /* skip the pair of expression */
v1 = Array[i];
v2 = Array[i+1];
v3 = Array[i+2];
while (v2 != 0xDEAD) {
i += 3;
v1 = Array[i];
v2 = Array[i+1];
v3 = Array[i+1];
}
}
}
}
}
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#include "odm_precomp.h"
static bool CheckCondition(const u32 Condition, const u32 Hex)
{
u32 _board = (Hex & 0x000000FF);
u32 _interface = (Hex & 0x0000FF00) >> 8;
u32 _platform = (Hex & 0x00FF0000) >> 16;
u32 cond = Condition;
if (Condition == 0xCDCDCDCD)
return true;
cond = Condition & 0x000000FF;
if ((_board == cond) && cond != 0x00)
return false;
cond = Condition & 0x0000FF00;
cond = cond >> 8;
if ((_interface & cond) == 0 && cond != 0x07)
return false;
cond = Condition & 0x00FF0000;
cond = cond >> 16;
if ((_platform & cond) == 0 && cond != 0x0F)
return false;
return true;
}
/******************************************************************************
* MAC_REG.TXT
******************************************************************************/
static u32 Array_MAC_REG_8723A[] = {
0x420, 0x00000080,
0x423, 0x00000000,
0x430, 0x00000000,
0x431, 0x00000000,
0x432, 0x00000000,
0x433, 0x00000001,
0x434, 0x00000004,
0x435, 0x00000005,
0x436, 0x00000006,
0x437, 0x00000007,
0x438, 0x00000000,
0x439, 0x00000000,
0x43A, 0x00000000,
0x43B, 0x00000001,
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,
0x462, 0x00000008,
0x463, 0x00000003,
0x4C8, 0x000000FF,
0x4C9, 0x00000008,
0x4CC, 0x000000FF,
0x4CD, 0x000000FF,
0x4CE, 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,
0x515, 0x00000010,
0x516, 0x0000000A,
0x517, 0x00000010,
0x51A, 0x00000016,
0x524, 0x0000000F,
0x525, 0x0000004F,
0x546, 0x00000040,
0x547, 0x00000000,
0x550, 0x00000010,
0x551, 0x00000010,
0x559, 0x00000002,
0x55A, 0x00000002,
0x55D, 0x000000FF,
0x605, 0x00000030,
0x608, 0x0000000E,
0x609, 0x0000002A,
0x652, 0x00000020,
0x63C, 0x0000000A,
0x63D, 0x0000000A,
0x63E, 0x0000000E,
0x63F, 0x0000000E,
0x66E, 0x00000005,
0x700, 0x00000021,
0x701, 0x00000043,
0x702, 0x00000065,
0x703, 0x00000087,
0x708, 0x00000021,
0x709, 0x00000043,
0x70A, 0x00000065,
0x70B, 0x00000087,
};
void ODM_ReadAndConfig_MAC_REG_8723A(struct dm_odm_t *pDM_Odm)
{
#define READ_NEXT_PAIR(v1, v2, i) \
do { \
i += 2; v1 = Array[i]; v2 = Array[i+1]; \
} while (0)
u32 hex = 0;
u32 i = 0;
u8 platform = 0x04;
u8 interfaceValue = pDM_Odm->SupportInterface;
u8 board = pDM_Odm->BoardType;
u32 ArrayLen = sizeof(Array_MAC_REG_8723A)/sizeof(u32);
u32 *Array = Array_MAC_REG_8723A;
hex += board;
hex += interfaceValue << 8;
hex += platform << 16;
hex += 0xFF000000;
for (i = 0; i < ArrayLen; i += 2) {
u32 v1 = Array[i];
u32 v2 = Array[i+1];
/* This (offset, data) pair meets the condition. */
if (v1 < 0xCDCDCDCD) {
odm_ConfigMAC_8723A(pDM_Odm, v1, (u8)v2);
continue;
} else {
if (!CheckCondition(Array[i], hex)) {
/* Discard the following (offset, data) pairs. */
READ_NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < ArrayLen - 2)
READ_NEXT_PAIR(v1, v2, i);
i -= 2; /* prevent from for-loop += 2 */
} else {
/* Configure matched pairs and skip to end of if-else. */
READ_NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < ArrayLen - 2) {
odm_ConfigMAC_8723A(pDM_Odm, v1, (u8)v2);
READ_NEXT_PAIR(v1, v2, i);
}
while (v2 != 0xDEAD && i < ArrayLen - 2)
READ_NEXT_PAIR(v1, v2, i);
}
}
}
}
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#include "odm_precomp.h"
static bool CheckCondition(const u32 Condition, const u32 Hex)
{
u32 _board = (Hex & 0x000000FF);
u32 _interface = (Hex & 0x0000FF00) >> 8;
u32 _platform = (Hex & 0x00FF0000) >> 16;
u32 cond = Condition;
if (Condition == 0xCDCDCDCD)
return true;
cond = Condition & 0x000000FF;
if ((_board == cond) && cond != 0x00)
return false;
cond = Condition & 0x0000FF00;
cond = cond >> 8;
if ((_interface & cond) == 0 && cond != 0x07)
return false;
cond = Condition & 0x00FF0000;
cond = cond >> 16;
if ((_platform & cond) == 0 && cond != 0x0F)
return false;
return true;
}
/******************************************************************************
* RadioA_1T.TXT
******************************************************************************/
static u32 Array_RadioA_1T_8723A[] = {
0x000, 0x00030159,
0x001, 0x00031284,
0x002, 0x00098000,
0xFF0F011F, 0xABCD,
0x003, 0x00018C63,
0xCDCDCDCD, 0xCDCD,
0x003, 0x00039C63,
0xFF0F011F, 0xDEAD,
0x004, 0x000210E7,
0x009, 0x0002044F,
0x00A, 0x0001A3F1,
0x00B, 0x00014787,
0x00C, 0x000896FE,
0x00D, 0x0000E02C,
0x00E, 0x00039CE7,
0x00F, 0x00000451,
0x019, 0x00000000,
0x01A, 0x00030355,
0x01B, 0x00060A00,
0x01C, 0x000FC378,
0x01D, 0x000A1250,
0x01E, 0x0000024F,
0x01F, 0x00000000,
0x020, 0x0000B614,
0x021, 0x0006C000,
0x022, 0x00000000,
0x023, 0x00001558,
0x024, 0x00000060,
0x025, 0x00000483,
0x026, 0x0004F000,
0x027, 0x000EC7D9,
0x028, 0x00057730,
0x029, 0x00004783,
0x02A, 0x00000001,
0x02B, 0x00021334,
0x02A, 0x00000000,
0x02B, 0x00000054,
0x02A, 0x00000001,
0x02B, 0x00000808,
0x02B, 0x00053333,
0x02C, 0x0000000C,
0x02A, 0x00000002,
0x02B, 0x00000808,
0x02B, 0x0005B333,
0x02C, 0x0000000D,
0x02A, 0x00000003,
0x02B, 0x00000808,
0x02B, 0x00063333,
0x02C, 0x0000000D,
0x02A, 0x00000004,
0x02B, 0x00000808,
0x02B, 0x0006B333,
0x02C, 0x0000000D,
0x02A, 0x00000005,
0x02B, 0x00000808,
0x02B, 0x00073333,
0x02C, 0x0000000D,
0x02A, 0x00000006,
0x02B, 0x00000709,
0x02B, 0x0005B333,
0x02C, 0x0000000D,
0x02A, 0x00000007,
0x02B, 0x00000709,
0x02B, 0x00063333,
0x02C, 0x0000000D,
0x02A, 0x00000008,
0x02B, 0x0000060A,
0x02B, 0x0004B333,
0x02C, 0x0000000D,
0x02A, 0x00000009,
0x02B, 0x0000060A,
0x02B, 0x00053333,
0x02C, 0x0000000D,
0x02A, 0x0000000A,
0x02B, 0x0000060A,
0x02B, 0x0005B333,
0x02C, 0x0000000D,
0x02A, 0x0000000B,
0x02B, 0x0000060A,
0x02B, 0x00063333,
0x02C, 0x0000000D,
0x02A, 0x0000000C,
0x02B, 0x0000060A,
0x02B, 0x0006B333,
0x02C, 0x0000000D,
0x02A, 0x0000000D,
0x02B, 0x0000060A,
0x02B, 0x00073333,
0x02C, 0x0000000D,
0x02A, 0x0000000E,
0x02B, 0x0000050B,
0x02B, 0x00066666,
0x02C, 0x0000001A,
0x02A, 0x000E0000,
0x010, 0x0004000F,
0x011, 0x000E31FC,
0x010, 0x0006000F,
0x011, 0x000FF9F8,
0x010, 0x0002000F,
0x011, 0x000203F9,
0x010, 0x0003000F,
0x011, 0x000FF500,
0x010, 0x00000000,
0x011, 0x00000000,
0x010, 0x0008000F,
0x011, 0x0003F100,
0x010, 0x0009000F,
0x011, 0x00023100,
0x012, 0x00032000,
0x012, 0x00071000,
0x012, 0x000B0000,
0x012, 0x000FC000,
0x013, 0x000287B3,
0x013, 0x000244B7,
0x013, 0x000204AB,
0x013, 0x0001C49F,
0x013, 0x00018493,
0x013, 0x0001429B,
0x013, 0x00010299,
0x013, 0x0000C29C,
0x013, 0x000081A0,
0x013, 0x000040AC,
0x013, 0x00000020,
0x014, 0x0001944C,
0x014, 0x00059444,
0x014, 0x0009944C,
0x014, 0x000D9444,
0xFF0F011F, 0xABCD,
0x015, 0x0000F424,
0x015, 0x0004F424,
0x015, 0x0008F424,
0x015, 0x000CF424,
0xCDCDCDCD, 0xCDCD,
0x015, 0x0000F474,
0x015, 0x0004F477,
0x015, 0x0008F455,
0x015, 0x000CF455,
0xFF0F011F, 0xDEAD,
0x016, 0x00000339,
0x016, 0x00040339,
0x016, 0x00080339,
0xFF0F011F, 0xABCD,
0x016, 0x000C0356,
0xCDCDCDCD, 0xCDCD,
0x016, 0x000C0366,
0xFF0F011F, 0xDEAD,
0x000, 0x00010159,
0x018, 0x0000F401,
0x0FE, 0x00000000,
0x0FE, 0x00000000,
0x01F, 0x00000003,
0x0FE, 0x00000000,
0x0FE, 0x00000000,
0x01E, 0x00000247,
0x01F, 0x00000000,
0x000, 0x00030159,
};
void ODM_ReadAndConfig_RadioA_1T_8723A(struct dm_odm_t *pDM_Odm)
{
#define READ_NEXT_PAIR(v1, v2, i) \
do { \
i += 2; v1 = Array[i]; v2 = Array[i+1];\
} while (0)
u32 hex = 0;
u32 i = 0;
u8 platform = 0x04;
u8 interfaceValue = pDM_Odm->SupportInterface;
u8 board = pDM_Odm->BoardType;
u32 ArrayLen = sizeof(Array_RadioA_1T_8723A)/sizeof(u32);
u32 *Array = Array_RadioA_1T_8723A;
hex += board;
hex += interfaceValue << 8;
hex += platform << 16;
hex += 0xFF000000;
for (i = 0; i < ArrayLen; i += 2) {
u32 v1 = Array[i];
u32 v2 = Array[i+1];
/* This (offset, data) pair meets the condition. */
if (v1 < 0xCDCDCDCD) {
odm_ConfigRF_RadioA_8723A(pDM_Odm, v1, v2);
continue;
} else {
if (!CheckCondition(Array[i], hex)) {
/* Discard the following (offset, data) pairs. */
READ_NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < ArrayLen - 2)
READ_NEXT_PAIR(v1, v2, i);
i -= 2; /* prevent from for-loop += 2 */
} else {
/* Configure matched pairs and skip to end of if-else. */
READ_NEXT_PAIR(v1, v2, i);
while (v2 != 0xDEAD &&
v2 != 0xCDEF &&
v2 != 0xCDCD && i < ArrayLen - 2) {
odm_ConfigRF_RadioA_8723A(pDM_Odm, v1, v2);
READ_NEXT_PAIR(v1, v2, i);
}
while (v2 != 0xDEAD && i < ArrayLen - 2)
READ_NEXT_PAIR(v1, v2, i);
}
}
}
}
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
/*++
Copyright (c) Realtek Semiconductor Corp. All rights reserved.
Module Name:
HalPwrSeqCmd.c
Abstract:
Implement HW Power sequence configuration CMD handling routine for
Realtek devices.
Major Change History:
When Who What
---------- --------------- -------------------------------
2011-10-26 Lucas Modify to be compatible with SD4-CE driver.
2011-07-07 Roger Create.
--*/
#include <HalPwrSeqCmd.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. */
/* */
u8 HalPwrSeqCmdParsing23a(struct rtw_adapter *padapter, u8 CutVersion,
u8 FabVersion, u8 InterfaceType,
struct wlan_pwr_cfg PwrSeqCmd[])
{
struct wlan_pwr_cfg PwrCfgCmd = { 0 };
u8 bPollingBit = false;
u32 AryIdx = 0;
u8 value = 0;
u32 offset = 0;
u32 pollingCount = 0; /* polling autoload done. */
u32 maxPollingCnt = 5000;
do {
PwrCfgCmd = PwrSeqCmd[AryIdx];
RT_TRACE(_module_hal_init_c_, _drv_info_,
("HalPwrSeqCmdParsing23a: offset(%#x) cut_msk(%#x) "
"fab_msk(%#x) interface_msk(%#x) base(%#x) cmd(%#x) "
"msk(%#x) value(%#x)\n",
GET_PWR_CFG_OFFSET(PwrCfgCmd),
GET_PWR_CFG_CUT_MASK(PwrCfgCmd),
GET_PWR_CFG_FAB_MASK(PwrCfgCmd),
GET_PWR_CFG_INTF_MASK(PwrCfgCmd),
GET_PWR_CFG_BASE(PwrCfgCmd),
GET_PWR_CFG_CMD(PwrCfgCmd),
GET_PWR_CFG_MASK(PwrCfgCmd),
GET_PWR_CFG_VALUE(PwrCfgCmd)));
/* 2 Only Handle the command whose FAB, CUT, and Interface are
matched */
if ((GET_PWR_CFG_FAB_MASK(PwrCfgCmd) & FabVersion) &&
(GET_PWR_CFG_CUT_MASK(PwrCfgCmd) & CutVersion) &&
(GET_PWR_CFG_INTF_MASK(PwrCfgCmd) & InterfaceType)) {
switch (GET_PWR_CFG_CMD(PwrCfgCmd)) {
case PWR_CMD_READ:
RT_TRACE(_module_hal_init_c_, _drv_info_,
("HalPwrSeqCmdParsing23a: "
"PWR_CMD_READ\n"));
break;
case PWR_CMD_WRITE:
RT_TRACE(_module_hal_init_c_, _drv_info_,
("HalPwrSeqCmdParsing23a: "
"PWR_CMD_WRITE\n"));
offset = GET_PWR_CFG_OFFSET(PwrCfgCmd);
/* Read the value from system register */
value = rtw_read8(padapter, offset);
value &= ~(GET_PWR_CFG_MASK(PwrCfgCmd));
value |= (GET_PWR_CFG_VALUE(PwrCfgCmd) &
GET_PWR_CFG_MASK(PwrCfgCmd));
/* Write the value back to sytem register */
rtw_write8(padapter, offset, value);
break;
case PWR_CMD_POLLING:
RT_TRACE(_module_hal_init_c_, _drv_info_,
("HalPwrSeqCmdParsing23a: "
"PWR_CMD_POLLING\n"));
bPollingBit = false;
offset = GET_PWR_CFG_OFFSET(PwrCfgCmd);
do {
value = rtw_read8(padapter, offset);
value &= GET_PWR_CFG_MASK(PwrCfgCmd);
if (value ==
(GET_PWR_CFG_VALUE(PwrCfgCmd) &
GET_PWR_CFG_MASK(PwrCfgCmd)))
bPollingBit = true;
else
udelay(10);
if (pollingCount++ > maxPollingCnt) {
DBG_8723A("Fail to polling "
"Offset[%#x]\n",
offset);
return false;
}
} while (!bPollingBit);
break;
case PWR_CMD_DELAY:
RT_TRACE(_module_hal_init_c_, _drv_info_,
("HalPwrSeqCmdParsing23a: "
"PWR_CMD_DELAY\n"));
if (GET_PWR_CFG_VALUE(PwrCfgCmd) ==
PWRSEQ_DELAY_US)
udelay(GET_PWR_CFG_OFFSET(PwrCfgCmd));
else
udelay(GET_PWR_CFG_OFFSET(PwrCfgCmd) *
1000);
break;
case PWR_CMD_END:
/* When this command is parsed, end
the process */
RT_TRACE(_module_hal_init_c_, _drv_info_,
("HalPwrSeqCmdParsing23a: "
"PWR_CMD_END\n"));
return true;
break;
default:
RT_TRACE(_module_hal_init_c_, _drv_err_,
("HalPwrSeqCmdParsing23a: "
"Unknown CMD!!\n"));
break;
}
}
AryIdx++; /* Add Array Index */
} while (1);
return true;
}
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#include <osdep_service.h>
#include <drv_types.h>
#include <hal_intf.h>
#include <hal_com.h>
#include <rtl8723a_hal.h>
#define _HAL_INIT_C_
void dump_chip_info23a(struct hal_version ChipVersion)
{
int cnt = 0;
u8 buf[128];
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8723A_");
cnt += sprintf((buf + cnt), "%s_", IS_NORMAL_CHIP(ChipVersion) ?
"Normal_Chip" : "Test_Chip");
cnt += sprintf((buf + cnt), "%s_",
IS_CHIP_VENDOR_TSMC(ChipVersion) ? "TSMC" : "UMC");
if (IS_A_CUT(ChipVersion))
cnt += sprintf((buf + cnt), "A_CUT_");
else if (IS_B_CUT(ChipVersion))
cnt += sprintf((buf + cnt), "B_CUT_");
else if (IS_C_CUT(ChipVersion))
cnt += sprintf((buf + cnt), "C_CUT_");
else if (IS_D_CUT(ChipVersion))
cnt += sprintf((buf + cnt), "D_CUT_");
else if (IS_E_CUT(ChipVersion))
cnt += sprintf((buf + cnt), "E_CUT_");
else
cnt += sprintf((buf + cnt), "UNKNOWN_CUT(%d)_",
ChipVersion.CUTVersion);
if (IS_1T1R(ChipVersion))
cnt += sprintf((buf + cnt), "1T1R_");
else if (IS_1T2R(ChipVersion))
cnt += sprintf((buf + cnt), "1T2R_");
else if (IS_2T2R(ChipVersion))
cnt += sprintf((buf + cnt), "2T2R_");
else
cnt += sprintf((buf + cnt), "UNKNOWN_RFTYPE(%d)_",
ChipVersion.RFType);
cnt += sprintf((buf + cnt), "RomVer(%d)\n", ChipVersion.ROMVer);
DBG_8723A("%s", buf);
}
#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80
/* return the final channel plan decision */
/* hw_channel_plan: channel plan from HW (efuse/eeprom) */
/* sw_channel_plan: channel plan from SW (registry/module param) */
/* def_channel_plan: channel plan used when the former two is invalid */
u8 hal_com_get_channel_plan23a(struct rtw_adapter *padapter, u8 hw_channel_plan,
u8 sw_channel_plan, u8 def_channel_plan,
bool AutoLoadFail)
{
u8 swConfig;
u8 chnlPlan;
swConfig = true;
if (!AutoLoadFail) {
if (!rtw_is_channel_plan_valid(sw_channel_plan))
swConfig = false;
if (hw_channel_plan & EEPROM_CHANNEL_PLAN_BY_HW_MASK)
swConfig = false;
}
if (swConfig == true)
chnlPlan = sw_channel_plan;
else
chnlPlan = hw_channel_plan & (~EEPROM_CHANNEL_PLAN_BY_HW_MASK);
if (!rtw_is_channel_plan_valid(chnlPlan))
chnlPlan = def_channel_plan;
return chnlPlan;
}
u8 MRateToHwRate23a(u8 rate)
{
u8 ret = DESC_RATE1M;
switch (rate) {
/* CCK and OFDM non-HT rates */
case IEEE80211_CCK_RATE_1MB:
ret = DESC_RATE1M;
break;
case IEEE80211_CCK_RATE_2MB:
ret = DESC_RATE2M;
break;
case IEEE80211_CCK_RATE_5MB:
ret = DESC_RATE5_5M;
break;
case IEEE80211_CCK_RATE_11MB:
ret = DESC_RATE11M;
break;
case IEEE80211_OFDM_RATE_6MB:
ret = DESC_RATE6M;
break;
case IEEE80211_OFDM_RATE_9MB:
ret = DESC_RATE9M;
break;
case IEEE80211_OFDM_RATE_12MB:
ret = DESC_RATE12M;
break;
case IEEE80211_OFDM_RATE_18MB:
ret = DESC_RATE18M;
break;
case IEEE80211_OFDM_RATE_24MB:
ret = DESC_RATE24M;
break;
case IEEE80211_OFDM_RATE_36MB:
ret = DESC_RATE36M;
break;
case IEEE80211_OFDM_RATE_48MB:
ret = DESC_RATE48M;
break;
case IEEE80211_OFDM_RATE_54MB:
ret = DESC_RATE54M;
break;
/* HT rates since here */
/* case MGN_MCS0: ret = DESC_RATEMCS0; break; */
/* case MGN_MCS1: ret = DESC_RATEMCS1; break; */
/* case MGN_MCS2: ret = DESC_RATEMCS2; break; */
/* case MGN_MCS3: ret = DESC_RATEMCS3; break; */
/* case MGN_MCS4: ret = DESC_RATEMCS4; break; */
/* case MGN_MCS5: ret = DESC_RATEMCS5; break; */
/* case MGN_MCS6: ret = DESC_RATEMCS6; break; */
/* case MGN_MCS7: ret = DESC_RATEMCS7; break; */
default:
break;
}
return ret;
}
void HalSetBrateCfg23a(struct rtw_adapter *padapter, u8 *mBratesOS)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
u8 i, is_brate, brate;
u16 brate_cfg = 0;
u8 rate_index;
for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
is_brate = mBratesOS[i] & IEEE80211_BASIC_RATE_MASK;
brate = mBratesOS[i] & 0x7f;
if (is_brate) {
switch (brate) {
case IEEE80211_CCK_RATE_1MB:
brate_cfg |= RATE_1M;
break;
case IEEE80211_CCK_RATE_2MB:
brate_cfg |= RATE_2M;
break;
case IEEE80211_CCK_RATE_5MB:
brate_cfg |= RATE_5_5M;
break;
case IEEE80211_CCK_RATE_11MB:
brate_cfg |= RATE_11M;
break;
case IEEE80211_OFDM_RATE_6MB:
brate_cfg |= RATE_6M;
break;
case IEEE80211_OFDM_RATE_9MB:
brate_cfg |= RATE_9M;
break;
case IEEE80211_OFDM_RATE_12MB:
brate_cfg |= RATE_12M;
break;
case IEEE80211_OFDM_RATE_18MB:
brate_cfg |= RATE_18M;
break;
case IEEE80211_OFDM_RATE_24MB:
brate_cfg |= RATE_24M;
break;
case IEEE80211_OFDM_RATE_36MB:
brate_cfg |= RATE_36M;
break;
case IEEE80211_OFDM_RATE_48MB:
brate_cfg |= RATE_48M;
break;
case IEEE80211_OFDM_RATE_54MB:
brate_cfg |= RATE_54M;
break;
}
}
}
/* 2007.01.16, by Emily */
/* Select RRSR (in Legacy-OFDM and CCK) */
/* For 8190, we select only 24M, 12M, 6M, 11M, 5.5M, 2M,
and 1M from the Basic rate. */
/* We do not use other rates. */
/* 2011.03.30 add by Luke Lee */
/* CCK 2M ACK should be disabled for some BCM and Atheros AP IOT */
/* because CCK 2M has poor TXEVM */
/* CCK 5.5M & 11M ACK should be enabled for better
performance */
brate_cfg = (brate_cfg | 0xd) & 0x15d;
pHalData->BasicRateSet = brate_cfg;
brate_cfg |= 0x01; /* default enable 1M ACK rate */
DBG_8723A("HW_VAR_BASIC_RATE: BrateCfg(%#x)\n", brate_cfg);
/* Set RRSR rate table. */
rtw_write8(padapter, REG_RRSR, brate_cfg & 0xff);
rtw_write8(padapter, REG_RRSR + 1, (brate_cfg >> 8) & 0xff);
rtw_write8(padapter, REG_RRSR + 2,
rtw_read8(padapter, REG_RRSR + 2) & 0xf0);
rate_index = 0;
/* Set RTS initial rate */
while (brate_cfg > 0x1) {
brate_cfg = (brate_cfg >> 1);
rate_index++;
}
/* Ziv - Check */
rtw_write8(padapter, REG_INIRTS_RATE_SEL, rate_index);
return;
}
static void _OneOutPipeMapping(struct rtw_adapter *pAdapter)
{
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[0]; /* BE */
pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0]; /* BK */
pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD */
}
static void _TwoOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg)
{
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
if (bWIFICfg) { /* WMM */
/* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
/* 0, 1, 0, 1, 0, 0, 0, 0, 0 }; */
/* 0:H, 1:L */
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[1]; /* VO */
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1]; /* BE */
pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0]; /* BK */
pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
} else { /* typical setting */
/* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
/* 1, 1, 0, 0, 0, 0, 0, 0, 0 }; */
/* 0:H, 1:L */
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1]; /* BE */
pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1]; /* BK */
pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
}
}
static void _ThreeOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg)
{
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
if (bWIFICfg) { /* for WMM */
/* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
/* 1, 2, 1, 0, 0, 0, 0, 0, 0 }; */
/* 0:H, 1:N, 2:L */
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1]; /* VI */
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2]; /* BE */
pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1]; /* BK */
pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
} else { /* typical setting */
/* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
/* 2, 2, 1, 0, 0, 0, 0, 0, 0 }; */
/* 0:H, 1:N, 2:L */
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1]; /* VI */
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2]; /* BE */
pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[2]; /* BK */
pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
}
}
bool Hal_MappingOutPipe23a(struct rtw_adapter *pAdapter, u8 NumOutPipe)
{
struct registry_priv *pregistrypriv = &pAdapter->registrypriv;
bool bWIFICfg = (pregistrypriv->wifi_spec) ? true : false;
bool result = true;
switch (NumOutPipe) {
case 2:
_TwoOutPipeMapping(pAdapter, bWIFICfg);
break;
case 3:
_ThreeOutPipeMapping(pAdapter, bWIFICfg);
break;
case 1:
_OneOutPipeMapping(pAdapter);
break;
default:
result = false;
break;
}
return result;
}
void hal_init_macaddr23a(struct rtw_adapter *adapter)
{
rtw_hal_set_hwreg23a(adapter, HW_VAR_MAC_ADDR,
adapter->eeprompriv.mac_addr);
}
/*
* C2H event format:
* Field TRIGGER CONTENT CMD_SEQ CMD_LEN CMD_ID
* BITS [127:120] [119:16] [15:8] [7:4] [3:0]
*/
void c2h_evt_clear23a(struct rtw_adapter *adapter)
{
rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
}
s32 c2h_evt_read23a(struct rtw_adapter *adapter, u8 *buf)
{
s32 ret = _FAIL;
struct c2h_evt_hdr *c2h_evt;
int i;
u8 trigger;
if (buf == NULL)
goto exit;
trigger = rtw_read8(adapter, REG_C2HEVT_CLEAR);
if (trigger == C2H_EVT_HOST_CLOSE)
goto exit; /* Not ready */
else if (trigger != C2H_EVT_FW_CLOSE)
goto clear_evt; /* Not a valid value */
c2h_evt = (struct c2h_evt_hdr *)buf;
memset(c2h_evt, 0, 16);
*buf = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL);
*(buf + 1) = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1);
RT_PRINT_DATA(_module_hal_init_c_, _drv_info_, "c2h_evt_read23a(): ",
&c2h_evt, sizeof(c2h_evt));
if (0) {
DBG_8723A("%s id:%u, len:%u, seq:%u, trigger:0x%02x\n",
__func__, c2h_evt->id, c2h_evt->plen, c2h_evt->seq,
trigger);
}
/* Read the content */
for (i = 0; i < c2h_evt->plen; i++)
c2h_evt->payload[i] = rtw_read8(adapter,
REG_C2HEVT_MSG_NORMAL +
sizeof(*c2h_evt) + i);
RT_PRINT_DATA(_module_hal_init_c_, _drv_info_,
"c2h_evt_read23a(): Command Content:\n", c2h_evt->payload,
c2h_evt->plen);
ret = _SUCCESS;
clear_evt:
/*
* Clear event to notify FW we have read the command.
* If this field isn't clear, the FW won't update the
* next command message.
*/
c2h_evt_clear23a(adapter);
exit:
return ret;
}
void
rtl8723a_set_ampdu_min_space(struct rtw_adapter *padapter, u8 MinSpacingToSet)
{
u8 SecMinSpace;
if (MinSpacingToSet <= 7) {
switch (padapter->securitypriv.dot11PrivacyAlgrthm) {
case _NO_PRIVACY_:
case _AES_:
SecMinSpace = 0;
break;
case _WEP40_:
case _WEP104_:
case _TKIP_:
case _TKIP_WTMIC_:
SecMinSpace = 6;
break;
default:
SecMinSpace = 7;
break;
}
if (MinSpacingToSet < SecMinSpace)
MinSpacingToSet = SecMinSpace;
/* RT_TRACE(COMP_MLME, DBG_LOUD,
("Set HW_VAR_AMPDU_MIN_SPACE: %#x\n",
padapter->MgntInfo.MinSpaceCfg)); */
MinSpacingToSet |=
rtw_read8(padapter, REG_AMPDU_MIN_SPACE) & 0xf8;
rtw_write8(padapter, REG_AMPDU_MIN_SPACE,
MinSpacingToSet);
}
}
void rtl8723a_set_ampdu_factor(struct rtw_adapter *padapter, u8 FactorToSet)
{
u8 RegToSet_Normal[4] = { 0x41, 0xa8, 0x72, 0xb9 };
u8 MaxAggNum;
u8 *pRegToSet;
u8 index = 0;
pRegToSet = RegToSet_Normal; /* 0xb972a841; */
#ifdef CONFIG_8723AU_BT_COEXIST
if ((BT_IsBtDisabled(padapter) == false) &&
(BT_1Ant(padapter) == true)) {
MaxAggNum = 0x8;
} else
#endif /* CONFIG_8723AU_BT_COEXIST */
{
MaxAggNum = 0xF;
}
if (FactorToSet <= 3) {
FactorToSet = (1 << (FactorToSet + 2));
if (FactorToSet > MaxAggNum)
FactorToSet = MaxAggNum;
for (index = 0; index < 4; index++) {
if ((pRegToSet[index] & 0xf0) > (FactorToSet << 4))
pRegToSet[index] = (pRegToSet[index] & 0x0f) |
(FactorToSet << 4);
if ((pRegToSet[index] & 0x0f) > FactorToSet)
pRegToSet[index] = (pRegToSet[index] & 0xf0) |
FactorToSet;
rtw_write8(padapter, REG_AGGLEN_LMT + index,
pRegToSet[index]);
}
/* RT_TRACE(COMP_MLME, DBG_LOUD,
("Set HW_VAR_AMPDU_FACTOR: %#x\n", FactorToSet)); */
}
}
void rtl8723a_set_acm_ctrl(struct rtw_adapter *padapter, u8 ctrl)
{
u8 hwctrl = 0;
if (ctrl != 0) {
hwctrl |= AcmHw_HwEn;
if (ctrl & BIT(1)) /* BE */
hwctrl |= AcmHw_BeqEn;
if (ctrl & BIT(2)) /* VI */
hwctrl |= AcmHw_ViqEn;
if (ctrl & BIT(3)) /* VO */
hwctrl |= AcmHw_VoqEn;
}
DBG_8723A("[HW_VAR_ACM_CTRL] Write 0x%02X\n", hwctrl);
rtw_write8(padapter, REG_ACMHWCTRL, hwctrl);
}
void rtl8723a_set_media_status(struct rtw_adapter *padapter, u8 status)
{
u8 val8;
val8 = rtw_read8(padapter, MSR) & 0x0c;
val8 |= status;
rtw_write8(padapter, MSR, val8);
}
void rtl8723a_set_media_status1(struct rtw_adapter *padapter, u8 status)
{
u8 val8;
val8 = rtw_read8(padapter, MSR) & 0x03;
val8 |= status << 2;
rtw_write8(padapter, MSR, val8);
}
void rtl8723a_set_bcn_func(struct rtw_adapter *padapter, u8 val)
{
if (val)
SetBcnCtrlReg23a(padapter, EN_BCN_FUNCTION | EN_TXBCN_RPT, 0);
else
SetBcnCtrlReg23a(padapter, 0, EN_BCN_FUNCTION | EN_TXBCN_RPT);
}
void rtl8723a_check_bssid(struct rtw_adapter *padapter, u8 val)
{
u32 val32;
val32 = rtw_read32(padapter, REG_RCR);
if (val)
val32 |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;
else
val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
rtw_write32(padapter, REG_RCR, val32);
}
void rtl8723a_mlme_sitesurvey(struct rtw_adapter *padapter, u8 flag)
{
if (flag) { /* under sitesurvey */
u32 v32;
/* config RCR to receive different BSSID & not
to receive data frame */
v32 = rtw_read32(padapter, REG_RCR);
v32 &= ~(RCR_CBSSID_BCN);
rtw_write32(padapter, REG_RCR, v32);
/* reject all data frame */
rtw_write16(padapter, REG_RXFLTMAP2, 0);
/* disable update TSF */
SetBcnCtrlReg23a(padapter, DIS_TSF_UDT, 0);
} else { /* sitesurvey done */
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo;
u32 v32;
pmlmeinfo = &pmlmeext->mlmext_info;
if ((is_client_associated_to_ap23a(padapter) == true) ||
((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
/* enable to rx data frame */
rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
/* enable update TSF */
SetBcnCtrlReg23a(padapter, 0, DIS_TSF_UDT);
}
v32 = rtw_read32(padapter, REG_RCR);
v32 |= RCR_CBSSID_BCN;
rtw_write32(padapter, REG_RCR, v32);
}
#ifdef CONFIG_8723AU_BT_COEXIST
BT_WifiScanNotify(padapter, flag ? true : false);
#endif
}
void rtl8723a_on_rcr_am(struct rtw_adapter *padapter)
{
rtw_write32(padapter, REG_RCR, rtw_read32(padapter, REG_RCR) | RCR_AM);
DBG_8723A("%s, %d, RCR = %x \n", __FUNCTION__, __LINE__,
rtw_read32(padapter, REG_RCR));
}
void rtl8723a_off_rcr_am(struct rtw_adapter *padapter)
{
rtw_write32(padapter, REG_RCR,
rtw_read32(padapter, REG_RCR) & (~RCR_AM));
DBG_8723A("%s, %d, RCR = %x \n", __FUNCTION__, __LINE__,
rtw_read32(padapter, REG_RCR));
}
void rtl8723a_set_slot_time(struct rtw_adapter *padapter, u8 slottime)
{
u8 u1bAIFS, aSifsTime;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
rtw_write8(padapter, REG_SLOT, slottime);
if (pmlmeinfo->WMM_enable == 0) {
if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
aSifsTime = 10;
else
aSifsTime = 16;
u1bAIFS = aSifsTime + (2 * pmlmeinfo->slotTime);
/* <Roger_EXP> Temporary removed, 2008.06.20. */
rtw_write8(padapter, REG_EDCA_VO_PARAM, u1bAIFS);
rtw_write8(padapter, REG_EDCA_VI_PARAM, u1bAIFS);
rtw_write8(padapter, REG_EDCA_BE_PARAM, u1bAIFS);
rtw_write8(padapter, REG_EDCA_BK_PARAM, u1bAIFS);
}
}
void rtl8723a_ack_preamble(struct rtw_adapter *padapter, u8 bShortPreamble)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
u8 regTmp;
/* Joseph marked out for Netgear 3500 TKIP
channel 7 issue.(Temporarily) */
regTmp = (pHalData->nCur40MhzPrimeSC) << 5;
/* regTmp = 0; */
if (bShortPreamble)
regTmp |= 0x80;
rtw_write8(padapter, REG_RRSR + 2, regTmp);
}
void rtl8723a_set_sec_cfg(struct rtw_adapter *padapter, u8 sec)
{
rtw_write8(padapter, REG_SECCFG, sec);
}
void rtl8723a_cam_empty_entry(struct rtw_adapter *padapter, u8 ucIndex)
{
u8 i;
u32 ulCommand = 0;
u32 ulContent = 0;
u32 ulEncAlgo = CAM_AES;
for (i = 0; i < CAM_CONTENT_COUNT; i++) {
/* filled id in CAM config 2 byte */
if (i == 0) {
ulContent |= (ucIndex & 0x03) |
((u16) (ulEncAlgo) << 2);
/* ulContent |= CAM_VALID; */
} else {
ulContent = 0;
}
/* polling bit, and No Write enable, and address */
ulCommand = CAM_CONTENT_COUNT * ucIndex + i;
ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE;
/* write content 0 is equall to mark invalid */
/* delay_ms(40); */
rtw_write32(padapter, WCAMI, ulContent);
/* RT_TRACE(COMP_SEC, DBG_LOUD,
("CAM_empty_entry23a(): WRITE A4: %lx \n", ulContent));*/
/* delay_ms(40); */
rtw_write32(padapter, RWCAM, ulCommand);
/* RT_TRACE(COMP_SEC, DBG_LOUD,
("CAM_empty_entry23a(): WRITE A0: %lx \n", ulCommand));*/
}
}
void rtl8723a_cam_invalid_all(struct rtw_adapter *padapter)
{
rtw_write32(padapter, RWCAM, BIT(31) | BIT(30));
}
void rtl8723a_cam_write(struct rtw_adapter *padapter, u32 val1, u32 val2)
{
u32 cmd;
rtw_write32(padapter, WCAMI, val1);
cmd = CAM_POLLINIG | CAM_WRITE | val2;
rtw_write32(padapter, RWCAM, cmd);
}
void rtl8723a_fifo_cleanup(struct rtw_adapter *padapter)
{
#define RW_RELEASE_EN BIT(18)
#define RXDMA_IDLE BIT(17)
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
u8 trycnt = 100;
/* pause tx */
rtw_write8(padapter, REG_TXPAUSE, 0xff);
/* keep sn */
padapter->xmitpriv.nqos_ssn = rtw_read16(padapter, REG_NQOS_SEQ);
if (pwrpriv->bkeepfwalive != true) {
u32 v32;
/* RX DMA stop */
v32 = rtw_read32(padapter, REG_RXPKT_NUM);
v32 |= RW_RELEASE_EN;
rtw_write32(padapter, REG_RXPKT_NUM, v32);
do {
v32 = rtw_read32(padapter, REG_RXPKT_NUM) & RXDMA_IDLE;
if (!v32)
break;
} while (trycnt--);
if (trycnt == 0) {
DBG_8723A("Stop RX DMA failed......\n");
}
/* RQPN Load 0 */
rtw_write16(padapter, REG_RQPN_NPQ, 0);
rtw_write32(padapter, REG_RQPN, 0x80000000);
mdelay(10);
}
}
void rtl8723a_set_apfm_on_mac(struct rtw_adapter *padapter, u8 val)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
pHalData->bMacPwrCtrlOn = val;
DBG_8723A("%s: bMacPwrCtrlOn =%d\n", __func__, pHalData->bMacPwrCtrlOn);
}
void rtl8723a_bcn_valid(struct rtw_adapter *padapter)
{
/* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2,
write 1 to clear, Clear by sw */
rtw_write8(padapter, REG_TDECTRL + 2,
rtw_read8(padapter, REG_TDECTRL + 2) | BIT0);
}
void rtl8723a_set_tx_pause(struct rtw_adapter *padapter, u8 pause)
{
rtw_write8(padapter, REG_TXPAUSE, pause);
}
void rtl8723a_set_beacon_interval(struct rtw_adapter *padapter, u16 interval)
{
rtw_write16(padapter, REG_BCN_INTERVAL, interval);
}
void rtl8723a_set_resp_sifs(struct rtw_adapter *padapter,
u8 r2t1, u8 r2t2, u8 t2t1, u8 t2t2)
{
/* SIFS_Timer = 0x0a0a0808; */
/* RESP_SIFS for CCK */
/* SIFS_T2T_CCK (0x08) */
rtw_write8(padapter, REG_R2T_SIFS, r2t1);
/* SIFS_R2T_CCK(0x08) */
rtw_write8(padapter, REG_R2T_SIFS + 1, r2t2);
/* RESP_SIFS for OFDM */
/* SIFS_T2T_OFDM (0x0a) */
rtw_write8(padapter, REG_T2T_SIFS, t2t1);
/* SIFS_R2T_OFDM(0x0a) */
rtw_write8(padapter, REG_T2T_SIFS + 1, t2t2);
}
void rtl8723a_set_ac_param_vo(struct rtw_adapter *padapter, u32 vo)
{
rtw_write32(padapter, REG_EDCA_VO_PARAM, vo);
}
void rtl8723a_set_ac_param_vi(struct rtw_adapter *padapter, u32 vi)
{
rtw_write32(padapter, REG_EDCA_VI_PARAM, vi);
}
void rtl8723a_set_ac_param_be(struct rtw_adapter *padapter, u32 be)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
pHalData->AcParam_BE = be;
rtw_write32(padapter, REG_EDCA_BE_PARAM, be);
}
void rtl8723a_set_ac_param_bk(struct rtw_adapter *padapter, u32 bk)
{
rtw_write32(padapter, REG_EDCA_BK_PARAM, bk);
}
void rtl8723a_set_rxdma_agg_pg_th(struct rtw_adapter *padapter, u8 val)
{
rtw_write8(padapter, REG_RXDMA_AGG_PG_TH, val);
}
void rtl8723a_set_nav_upper(struct rtw_adapter *padapter, u32 usNavUpper)
{
if (usNavUpper > HAL_8723A_NAV_UPPER_UNIT * 0xFF) {
RT_TRACE(_module_hal_init_c_, _drv_notice_,
("The setting value (0x%08X us) of NAV_UPPER "
"is larger than (%d * 0xFF)!!!\n",
usNavUpper, HAL_8723A_NAV_UPPER_UNIT));
return;
}
/* The value of ((usNavUpper + HAL_8723A_NAV_UPPER_UNIT - 1) /
HAL_8723A_NAV_UPPER_UNIT) */
/* is getting the upper integer. */
usNavUpper = (usNavUpper + HAL_8723A_NAV_UPPER_UNIT - 1) /
HAL_8723A_NAV_UPPER_UNIT;
rtw_write8(padapter, REG_NAV_UPPER, (u8) usNavUpper);
}
void rtl8723a_set_initial_gain(struct rtw_adapter *padapter, u32 rx_gain)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct dig_t *pDigTable = &pHalData->odmpriv.DM_DigTable;
if (rx_gain == 0xff) /* restore rx gain */
ODM_Write_DIG23a(&pHalData->odmpriv, pDigTable->BackupIGValue);
else {
pDigTable->BackupIGValue = pDigTable->CurIGValue;
ODM_Write_DIG23a(&pHalData->odmpriv, rx_gain);
}
}
void rtl8723a_odm_support_ability_write(struct rtw_adapter *padapter, u32 val)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
pHalData->odmpriv.SupportAbility = val;
}
void rtl8723a_odm_support_ability_backup(struct rtw_adapter *padapter, u8 val)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
if (val) /* save dm flag */
pHalData->odmpriv.BK_SupportAbility =
pHalData->odmpriv.SupportAbility;
else /* restore dm flag */
pHalData->odmpriv.SupportAbility =
pHalData->odmpriv.BK_SupportAbility;
}
void rtl8723a_odm_support_ability_set(struct rtw_adapter *padapter, u32 val)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
if (val == DYNAMIC_ALL_FUNC_ENABLE) {
pHalData->dmpriv.DMFlag = pHalData->dmpriv.InitDMFlag;
pHalData->odmpriv.SupportAbility = pHalData->dmpriv.InitODMFlag;
} else {
pHalData->odmpriv.SupportAbility |= val;
}
}
void rtl8723a_odm_support_ability_clr(struct rtw_adapter *padapter, u32 val)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
pHalData->odmpriv.SupportAbility &= val;
}
void rtl8723a_set_rpwm(struct rtw_adapter *padapter, u8 val)
{
rtw_write8(padapter, REG_USB_HRPWM, val);
}
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#define _HAL_INTF_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <hal_intf.h>
#include <usb_hal.h>
void rtw_hal_chip_configure23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.intf_chip_configure)
padapter->HalFunc.intf_chip_configure(padapter);
}
void rtw_hal_read_chip_info23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.read_adapter_info)
padapter->HalFunc.read_adapter_info(padapter);
}
void rtw_hal_read_chip_version23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.read_chip_version)
padapter->HalFunc.read_chip_version(padapter);
}
void rtw_hal_def_value_init23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.init_default_value)
padapter->HalFunc.init_default_value(padapter);
}
void rtw_hal_free_data23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.free_hal_data)
padapter->HalFunc.free_hal_data(padapter);
}
void rtw_hal_dm_init23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.dm_init)
padapter->HalFunc.dm_init(padapter);
}
void rtw_hal_dm_deinit23a(struct rtw_adapter *padapter)
{
/* cancel dm timer */
if (padapter->HalFunc.dm_deinit)
padapter->HalFunc.dm_deinit(padapter);
}
void rtw_hal_sw_led_init23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.InitSwLeds)
padapter->HalFunc.InitSwLeds(padapter);
}
void rtw_hal_sw_led_deinit23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.DeInitSwLeds)
padapter->HalFunc.DeInitSwLeds(padapter);
}
u32 rtw_hal_power_on23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.hal_power_on)
return padapter->HalFunc.hal_power_on(padapter);
return _FAIL;
}
uint rtw_hal_init23a(struct rtw_adapter *padapter)
{
uint status = _SUCCESS;
padapter->hw_init_completed = false;
status = padapter->HalFunc.hal_init(padapter);
if (status == _SUCCESS) {
padapter->hw_init_completed = true;
if (padapter->registrypriv.notch_filter == 1)
rtw_hal_notch_filter23a(padapter, 1);
rtw_hal_reset_security_engine23a(padapter);
} else {
padapter->hw_init_completed = false;
DBG_8723A("rtw_hal_init23a: hal__init fail\n");
}
RT_TRACE(_module_hal_init_c_, _drv_err_, ("-rtl871x_hal_init:status = 0x%x\n", status));
return status;
}
uint rtw_hal_deinit23a(struct rtw_adapter *padapter)
{
uint status = _SUCCESS;
status = padapter->HalFunc.hal_deinit(padapter);
if (status == _SUCCESS)
padapter->hw_init_completed = false;
else
DBG_8723A("\n rtw_hal_deinit23a: hal_init fail\n");
return status;
}
void rtw_hal_set_hwreg23a(struct rtw_adapter *padapter, u8 variable, u8 *val)
{
if (padapter->HalFunc.SetHwRegHandler)
padapter->HalFunc.SetHwRegHandler(padapter, variable, val);
}
void rtw23a_hal_get_hwreg(struct rtw_adapter *padapter, u8 variable, u8 *val)
{
if (padapter->HalFunc.GetHwRegHandler)
padapter->HalFunc.GetHwRegHandler(padapter, variable, val);
}
u8 rtw_hal_set_def_var23a(struct rtw_adapter *padapter, enum hal_def_variable eVariable, void *pValue)
{
if (padapter->HalFunc.SetHalDefVarHandler)
return padapter->HalFunc.SetHalDefVarHandler(padapter, eVariable, pValue);
return _FAIL;
}
u8 rtw_hal_get_def_var23a(struct rtw_adapter *padapter, enum hal_def_variable eVariable, void *pValue)
{
if (padapter->HalFunc.GetHalDefVarHandler)
return padapter->HalFunc.GetHalDefVarHandler(padapter, eVariable, pValue);
return _FAIL;
}
void rtw_hal_set_odm_var23a(struct rtw_adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
{
if (padapter->HalFunc.SetHalODMVarHandler)
padapter->HalFunc.SetHalODMVarHandler(padapter, eVariable, pValue1, bSet);
}
void rtw_hal_get_odm_var23a(struct rtw_adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
{
if (padapter->HalFunc.GetHalODMVarHandler)
padapter->HalFunc.GetHalODMVarHandler(padapter, eVariable, pValue1, bSet);
}
void rtw_hal_enable_interrupt23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.enable_interrupt)
padapter->HalFunc.enable_interrupt(padapter);
else
DBG_8723A("%s: HalFunc.enable_interrupt is NULL!\n", __FUNCTION__);
}
void rtw_hal_disable_interrupt23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.disable_interrupt)
padapter->HalFunc.disable_interrupt(padapter);
else
DBG_8723A("%s: HalFunc.disable_interrupt is NULL!\n", __FUNCTION__);
}
u32 rtw_hal_inirp_init23a(struct rtw_adapter *padapter)
{
u32 rst = _FAIL;
if (padapter->HalFunc.inirp_init)
rst = padapter->HalFunc.inirp_init(padapter);
else
DBG_8723A(" %s HalFunc.inirp_init is NULL!!!\n", __FUNCTION__);
return rst;
}
u32 rtw_hal_inirp_deinit23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.inirp_deinit)
return padapter->HalFunc.inirp_deinit(padapter);
return _FAIL;
}
u8 rtw_hal_intf_ps_func23a(struct rtw_adapter *padapter, enum hal_intf_ps_func efunc_id, u8 *val)
{
if (padapter->HalFunc.interface_ps_func)
return padapter->HalFunc.interface_ps_func(padapter, efunc_id, val);
return _FAIL;
}
s32 rtw_hal_xmit23aframe_enqueue(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
{
if (padapter->HalFunc.hal_xmitframe_enqueue)
return padapter->HalFunc.hal_xmitframe_enqueue(padapter, pxmitframe);
return false;
}
s32 rtw_hal_xmit23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
{
if (padapter->HalFunc.hal_xmit)
return padapter->HalFunc.hal_xmit(padapter, pxmitframe);
return false;
}
s32 rtw_hal_mgnt_xmit23a(struct rtw_adapter *padapter, struct xmit_frame *pmgntframe)
{
s32 ret = _FAIL;
if (padapter->HalFunc.mgnt_xmit)
ret = padapter->HalFunc.mgnt_xmit(padapter, pmgntframe);
return ret;
}
s32 rtw_hal_init23a_xmit_priv(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.init_xmit_priv != NULL)
return padapter->HalFunc.init_xmit_priv(padapter);
return _FAIL;
}
void rtw_hal_free_xmit_priv23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.free_xmit_priv != NULL)
padapter->HalFunc.free_xmit_priv(padapter);
}
s32 rtw_hal_init23a_recv_priv(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.init_recv_priv)
return padapter->HalFunc.init_recv_priv(padapter);
return _FAIL;
}
void rtw_hal_free_recv_priv23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.free_recv_priv)
padapter->HalFunc.free_recv_priv(padapter);
}
void rtw_hal_update_ra_mask23a(struct sta_info *psta, u8 rssi_level)
{
struct rtw_adapter *padapter;
struct mlme_priv *pmlmepriv;
if (!psta)
return;
padapter = psta->padapter;
pmlmepriv = &padapter->mlmepriv;
if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
add_RATid23a(padapter, psta, rssi_level);
} else {
if (padapter->HalFunc.UpdateRAMaskHandler)
padapter->HalFunc.UpdateRAMaskHandler(padapter, psta->mac_id, rssi_level);
}
}
void rtw_hal_add_ra_tid23a(struct rtw_adapter *padapter, u32 bitmap, u8 arg, u8 rssi_level)
{
if (padapter->HalFunc.Add_RateATid)
padapter->HalFunc.Add_RateATid(padapter, bitmap, arg, rssi_level);
}
/* Start specifical interface thread */
void rtw_hal_start_thread23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.run_thread)
padapter->HalFunc.run_thread(padapter);
}
/* Start specifical interface thread */
void rtw_hal_stop_thread23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.cancel_thread)
padapter->HalFunc.cancel_thread(padapter);
}
u32 rtw_hal_read_bbreg23a(struct rtw_adapter *padapter, u32 RegAddr, u32 BitMask)
{
u32 data = 0;
if (padapter->HalFunc.read_bbreg)
data = padapter->HalFunc.read_bbreg(padapter, RegAddr, BitMask);
return data;
}
void rtw_hal_write_bbreg23a(struct rtw_adapter *padapter, u32 RegAddr, u32 BitMask, u32 Data)
{
if (padapter->HalFunc.write_bbreg)
padapter->HalFunc.write_bbreg(padapter, RegAddr, BitMask, Data);
}
u32 rtw_hal_read_rfreg23a(struct rtw_adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask)
{
u32 data = 0;
if (padapter->HalFunc.read_rfreg)
data = padapter->HalFunc.read_rfreg(padapter, eRFPath, RegAddr, BitMask);
return data;
}
void rtw_hal_write_rfreg23a(struct rtw_adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask, u32 Data)
{
if (padapter->HalFunc.write_rfreg)
padapter->HalFunc.write_rfreg(padapter, eRFPath, RegAddr, BitMask, Data);
}
s32 rtw_hal_interrupt_handler23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.interrupt_handler)
return padapter->HalFunc.interrupt_handler(padapter);
return _FAIL;
}
void rtw_hal_set_bwmode23a(struct rtw_adapter *padapter,
enum ht_channel_width Bandwidth, u8 offset)
{
if (padapter->HalFunc.set_bwmode_handler)
padapter->HalFunc.set_bwmode_handler(padapter, Bandwidth,
offset);
}
void rtw_hal_set_chan23a(struct rtw_adapter *padapter, u8 channel)
{
if (padapter->HalFunc.set_channel_handler)
padapter->HalFunc.set_channel_handler(padapter, channel);
}
void rtw_hal_dm_watchdog23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.hal_dm_watchdog)
padapter->HalFunc.hal_dm_watchdog(padapter);
}
void rtw_hal_bcn_related_reg_setting23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.SetBeaconRelatedRegistersHandler)
padapter->HalFunc.SetBeaconRelatedRegistersHandler(padapter);
}
void rtw_hal_sreset_init23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.sreset_init_value23a)
padapter->HalFunc.sreset_init_value23a(padapter);
}
void rtw_hal_sreset_reset23a(struct rtw_adapter *padapter)
{
padapter = GET_PRIMARY_ADAPTER(padapter);
if (padapter->HalFunc.silentreset)
padapter->HalFunc.silentreset(padapter);
}
void rtw_hal_sreset_reset23a_value23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.sreset_reset_value23a)
padapter->HalFunc.sreset_reset_value23a(padapter);
}
void rtw_hal_sreset_xmit_status_check23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.sreset_xmit_status_check)
padapter->HalFunc.sreset_xmit_status_check(padapter);
}
void rtw_hal_sreset_linked_status_check23a(struct rtw_adapter *padapter)
{
if (padapter->HalFunc.sreset_linked_status_check)
padapter->HalFunc.sreset_linked_status_check(padapter);
}
u8 rtw_hal_sreset_get_wifi_status23a(struct rtw_adapter *padapter)
{
u8 status = 0;
if (padapter->HalFunc.sreset_get_wifi_status23a)
status = padapter->HalFunc.sreset_get_wifi_status23a(padapter);
return status;
}
bool rtw_hal_sreset_inprogress(struct rtw_adapter *padapter)
{
bool inprogress = false;
padapter = GET_PRIMARY_ADAPTER(padapter);
if (padapter->HalFunc.sreset_inprogress)
inprogress = padapter->HalFunc.sreset_inprogress(padapter);
return inprogress;
}
void rtw_hal_notch_filter23a(struct rtw_adapter *adapter, bool enable)
{
if (adapter->HalFunc.hal_notch_filter)
adapter->HalFunc.hal_notch_filter(adapter, enable);
}
void rtw_hal_reset_security_engine23a(struct rtw_adapter *adapter)
{
if (adapter->HalFunc.hal_reset_security_engine)
adapter->HalFunc.hal_reset_security_engine(adapter);
}
s32 rtw_hal_c2h_handler23a(struct rtw_adapter *adapter, struct c2h_evt_hdr *c2h_evt)
{
s32 ret = _FAIL;
if (adapter->HalFunc.c2h_handler)
ret = adapter->HalFunc.c2h_handler(adapter, c2h_evt);
return ret;
}
c2h_id_filter rtw_hal_c2h_id_filter_ccx23a(struct rtw_adapter *adapter)
{
return adapter->HalFunc.c2h_id_filter_ccx;
}
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#include "odm_precomp.h"
static const u16 dB_Invert_Table[8][12] = {
{1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4},
{4, 5, 6, 6, 7, 8, 9, 10, 11, 13, 14, 16},
{18, 20, 22, 25, 28, 32, 35, 40, 45, 50, 56, 63},
{71, 79, 89, 100, 112, 126, 141, 158, 178, 200, 224, 251},
{282, 316, 355, 398, 447, 501, 562, 631, 708, 794, 891, 1000},
{1122, 1259, 1413, 1585, 1778, 1995, 2239, 2512, 2818, 3162, 3548, 3981},
{4467, 5012, 5623, 6310, 7079, 7943, 8913, 10000, 11220, 12589, 14125, 15849},
{17783, 19953, 22387, 25119, 28184, 31623, 35481, 39811, 44668, 50119, 56234, 65535}
};
static u32 EDCAParam[HT_IOT_PEER_MAX][3] = { /* UL DL */
{0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 0:unknown AP */
{0xa44f, 0x5ea44f, 0x5e431c}, /* 1:realtek AP */
{0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 2:unknown AP => realtek_92SE */
{0x5ea32b, 0x5ea42b, 0x5e4322}, /* 3:broadcom AP */
{0x5ea422, 0x00a44f, 0x00a44f}, /* 4:ralink AP */
{0x5ea322, 0x00a630, 0x00a44f}, /* 5:atheros AP */
{0x5e4322, 0x5e4322, 0x5e4322},/* 6:cisco AP */
{0x5ea44f, 0x00a44f, 0x5ea42b}, /* 8:marvell AP */
{0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 10:unknown AP => 92U AP */
{0x5ea42b, 0xa630, 0x5e431c}, /* 11:airgocap AP */
};
/* EDCA Paramter for AP/ADSL by Mingzhi 2011-11-22 */
/* Global var */
u32 OFDMSwingTable23A[OFDM_TABLE_SIZE_92D] = {
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 */
};
u8 CCKSwingTable_Ch1_Ch1323A[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 */
};
u8 CCKSwingTable_Ch1423A[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 */
};
/* Local Function predefine. */
/* START------------COMMON INFO RELATED--------------- */
void odm_CommonInfoSelfInit23a(struct dm_odm_t *pDM_Odm);
void odm_CommonInfoSelfUpdate23a(struct dm_odm_t *pDM_Odm);
void odm_CmnInfoInit_Debug23a(struct dm_odm_t *pDM_Odm);
void odm_CmnInfoHook_Debug23a(struct dm_odm_t *pDM_Odm);
void odm_CmnInfoUpdate_Debug23a(struct dm_odm_t *pDM_Odm);
/* START---------------DIG--------------------------- */
void odm_FalseAlarmCounterStatistics23a(struct dm_odm_t *pDM_Odm);
void odm_DIG23aInit(struct dm_odm_t *pDM_Odm);
void odm_DIG23a(struct dm_odm_t *pDM_Odm);
void odm_CCKPacketDetectionThresh23a(struct dm_odm_t *pDM_Odm);
/* END---------------DIG--------------------------- */
/* START-------BB POWER SAVE----------------------- */
void odm23a_DynBBPSInit(struct dm_odm_t *pDM_Odm);
void odm_DynamicBBPowerSaving23a(struct dm_odm_t *pDM_Odm);
void odm_1R_CCA23a(struct dm_odm_t *pDM_Odm);
/* END---------BB POWER SAVE----------------------- */
void odm_RefreshRateAdaptiveMask23aMP23a(struct dm_odm_t *pDM_Odm);
void odm_RefreshRateAdaptiveMask23aCE23a(struct dm_odm_t *pDM_Odm);
void odm_RefreshRateAdaptiveMask23aAPADSL23a(struct dm_odm_t *pDM_Odm);
void odm_DynamicTxPower23aInit(struct dm_odm_t *pDM_Odm);
void odm_DynamicTxPower23aRestorePowerIndex(struct dm_odm_t *pDM_Odm);
void odm_DynamicTxPower23aSavePowerIndex(struct dm_odm_t *pDM_Odm);
void odm_DynamicTxPower23aWritePowerIndex(struct dm_odm_t *pDM_Odm,
u8 Value);
void odm_DynamicTxPower23a_92C(struct dm_odm_t *pDM_Odm);
void odm_DynamicTxPower23a_92D(struct dm_odm_t *pDM_Odm);
void odm_RSSIMonitorInit(struct dm_odm_t *pDM_Odm);
void odm_RSSIMonitorCheck23aMP(struct dm_odm_t *pDM_Odm);
void odm_RSSIMonitorCheck23aCE(struct dm_odm_t *pDM_Odm);
void odm_RSSIMonitorCheck23aAP(struct dm_odm_t *pDM_Odm);
void odm_RSSIMonitorCheck23a(struct dm_odm_t *pDM_Odm);
void odm_DynamicTxPower23a(struct dm_odm_t *pDM_Odm);
void odm_SwAntDivInit(struct dm_odm_t *pDM_Odm);
void odm_SwAntDivInit_NIC(struct dm_odm_t *pDM_Odm);
void odm_SwAntDivChkAntSwitch(struct dm_odm_t *pDM_Odm, u8 Step);
void odm_SwAntDivChkAntSwitchNIC(struct dm_odm_t *pDM_Odm,
u8 Step
);
void odm_SwAntDivChkAntSwitchCallback23a(unsigned long data);
void odm_GlobalAdapterCheck(void);
void odm_RefreshRateAdaptiveMask23a(struct dm_odm_t *pDM_Odm);
void ODM_TXPowerTrackingCheck23a(struct dm_odm_t *pDM_Odm);
void odm_TXPowerTrackingCheckAP(struct dm_odm_t *pDM_Odm);
void odm_RateAdaptiveMaskInit23a(struct dm_odm_t *pDM_Odm);
void odm_TXPowerTrackingThermalMeterInit23a(struct dm_odm_t *pDM_Odm);
void odm_TXPowerTrackingInit23a(struct dm_odm_t *pDM_Odm);
void odm_TXPowerTrackingCheckMP(struct dm_odm_t *pDM_Odm);
void odm_TXPowerTrackingCheckCE23a(struct dm_odm_t *pDM_Odm);
void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm);
void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm);
void odm_EdcaTurboCheck23aCE23a(struct dm_odm_t *pDM_Odm);
#define RxDefaultAnt1 0x65a9
#define RxDefaultAnt2 0x569a
void odm_InitHybridAntDiv23a(struct dm_odm_t *pDM_Odm);
bool odm_StaDefAntSel(struct dm_odm_t *pDM_Odm,
u32 OFDM_Ant1_Cnt,
u32 OFDM_Ant2_Cnt,
u32 CCK_Ant1_Cnt,
u32 CCK_Ant2_Cnt,
u8 *pDefAnt
);
void odm_SetRxIdleAnt(struct dm_odm_t *pDM_Odm,
u8 Ant,
bool bDualPath
);
void odm_HwAntDiv23a(struct dm_odm_t *pDM_Odm);
/* 3 Export Interface */
/* 2011/09/21 MH Add to describe different team necessary resource allocate?? */
void ODM23a_DMInit(struct dm_odm_t *pDM_Odm)
{
/* For all IC series */
odm_CommonInfoSelfInit23a(pDM_Odm);
odm_CmnInfoInit_Debug23a(pDM_Odm);
odm_DIG23aInit(pDM_Odm);
odm_RateAdaptiveMaskInit23a(pDM_Odm);
if (pDM_Odm->SupportICType & ODM_IC_11N_SERIES) {
odm23a_DynBBPSInit(pDM_Odm);
odm_DynamicTxPower23aInit(pDM_Odm);
odm_TXPowerTrackingInit23a(pDM_Odm);
ODM_EdcaTurboInit23a(pDM_Odm);
if ((pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) ||
(pDM_Odm->AntDivType == CGCS_RX_HW_ANTDIV) ||
(pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV))
odm_InitHybridAntDiv23a(pDM_Odm);
else if (pDM_Odm->AntDivType == CGCS_RX_SW_ANTDIV)
odm_SwAntDivInit(pDM_Odm);
}
}
/* 2011/09/20 MH This is the entry pointer for all team to execute HW out source DM. */
/* You can not add any dummy function here, be care, you can only use DM structure */
/* to perform any new ODM_DM. */
void ODM_DMWatchdog23a(struct dm_odm_t *pDM_Odm)
{
/* 2012.05.03 Luke: For all IC series */
odm_GlobalAdapterCheck();
odm_CmnInfoHook_Debug23a(pDM_Odm);
odm_CmnInfoUpdate_Debug23a(pDM_Odm);
odm_CommonInfoSelfUpdate23a(pDM_Odm);
odm_FalseAlarmCounterStatistics23a(pDM_Odm);
odm_RSSIMonitorCheck23a(pDM_Odm);
/* 8723A or 8189ES platform */
/* NeilChen--2012--08--24-- */
/* Fix Leave LPS issue */
if ((pDM_Odm->Adapter->pwrctrlpriv.pwr_mode != PS_MODE_ACTIVE) &&/* in LPS mode */
(pDM_Odm->SupportICType & (ODM_RTL8723A))) {
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("----Step1: odm_DIG23a is in LPS mode\n"));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("---Step2: 8723AS is in LPS mode\n"));
odm_DIG23abyRSSI_LPS(pDM_Odm);
} else {
odm_DIG23a(pDM_Odm);
}
odm_CCKPacketDetectionThresh23a(pDM_Odm);
if (*(pDM_Odm->pbPowerSaving))
return;
odm_RefreshRateAdaptiveMask23a(pDM_Odm);
odm_DynamicBBPowerSaving23a(pDM_Odm);
if ((pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) ||
(pDM_Odm->AntDivType == CGCS_RX_HW_ANTDIV) ||
(pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV))
odm_HwAntDiv23a(pDM_Odm);
else if (pDM_Odm->AntDivType == CGCS_RX_SW_ANTDIV)
odm_SwAntDivChkAntSwitch(pDM_Odm, SWAW_STEP_PEAK);
if (pDM_Odm->SupportICType & ODM_IC_11N_SERIES) {
ODM_TXPowerTrackingCheck23a(pDM_Odm);
odm_EdcaTurboCheck23a(pDM_Odm);
odm_DynamicTxPower23a(pDM_Odm);
}
odm_dtc(pDM_Odm);
}
/* */
/* Init /.. Fixed HW value. Only init time. */
/* */
void ODM_CmnInfoInit23a(struct dm_odm_t *pDM_Odm,
enum odm_cmninfo CmnInfo,
u32 Value
)
{
/* ODM_RT_TRACE(pDM_Odm,); */
/* */
/* This section is used for init value */
/* */
switch (CmnInfo) {
/* Fixed ODM value. */
case ODM_CMNINFO_ABILITY:
pDM_Odm->SupportAbility = (u32)Value;
break;
case ODM_CMNINFO_PLATFORM:
break;
case ODM_CMNINFO_INTERFACE:
pDM_Odm->SupportInterface = (u8)Value;
break;
case ODM_CMNINFO_MP_TEST_CHIP:
pDM_Odm->bIsMPChip = (u8)Value;
break;
case ODM_CMNINFO_IC_TYPE:
pDM_Odm->SupportICType = Value;
break;
case ODM_CMNINFO_CUT_VER:
pDM_Odm->CutVersion = (u8)Value;
break;
case ODM_CMNINFO_FAB_VER:
pDM_Odm->FabVersion = (u8)Value;
break;
case ODM_CMNINFO_RF_TYPE:
pDM_Odm->RFType = (u8)Value;
break;
case ODM_CMNINFO_RF_ANTENNA_TYPE:
pDM_Odm->AntDivType = (u8)Value;
break;
case ODM_CMNINFO_BOARD_TYPE:
pDM_Odm->BoardType = (u8)Value;
break;
case ODM_CMNINFO_EXT_LNA:
pDM_Odm->ExtLNA = (u8)Value;
break;
case ODM_CMNINFO_EXT_PA:
pDM_Odm->ExtPA = (u8)Value;
break;
case ODM_CMNINFO_EXT_TRSW:
pDM_Odm->ExtTRSW = (u8)Value;
break;
case ODM_CMNINFO_PATCH_ID:
pDM_Odm->PatchID = (u8)Value;
break;
case ODM_CMNINFO_BINHCT_TEST:
pDM_Odm->bInHctTest = (bool)Value;
break;
case ODM_CMNINFO_BWIFI_TEST:
pDM_Odm->bWIFITest = (bool)Value;
break;
case ODM_CMNINFO_SMART_CONCURRENT:
pDM_Odm->bDualMacSmartConcurrent = (bool)Value;
break;
/* To remove the compiler warning, must add an empty default statement to handle the other values. */
default:
/* do nothing */
break;
}
/* */
/* Tx power tracking BB swing table. */
/* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */
/* */
pDM_Odm->BbSwingIdxOfdm = 12; /* Set defalut value as index 12. */
pDM_Odm->BbSwingIdxOfdmCurrent = 12;
pDM_Odm->BbSwingFlagOfdm = false;
}
void ODM23a_CmnInfoHook(struct dm_odm_t *pDM_Odm,
enum odm_cmninfo CmnInfo,
void *pValue
)
{
/* Hook call by reference pointer. */
switch (CmnInfo) {
/* Dynamic call by reference pointer. */
case ODM_CMNINFO_MAC_PHY_MODE:
pDM_Odm->pMacPhyMode = (u8 *)pValue;
break;
case ODM_CMNINFO_TX_UNI:
pDM_Odm->pNumTxBytesUnicast = (u64 *)pValue;
break;
case ODM_CMNINFO_RX_UNI:
pDM_Odm->pNumRxBytesUnicast = (u64 *)pValue;
break;
case ODM_CMNINFO_WM_MODE:
pDM_Odm->pWirelessMode = (u8 *)pValue;
break;
case ODM_CMNINFO_BAND:
pDM_Odm->pBandType = (u8 *)pValue;
break;
case ODM_CMNINFO_SEC_CHNL_OFFSET:
pDM_Odm->pSecChOffset = (u8 *)pValue;
break;
case ODM_CMNINFO_SEC_MODE:
pDM_Odm->pSecurity = (u8 *)pValue;
break;
case ODM_CMNINFO_BW:
pDM_Odm->pBandWidth = (u8 *)pValue;
break;
case ODM_CMNINFO_CHNL:
pDM_Odm->pChannel = (u8 *)pValue;
break;
case ODM_CMNINFO_DMSP_GET_VALUE:
pDM_Odm->pbGetValueFromOtherMac = (bool *)pValue;
break;
case ODM_CMNINFO_BUDDY_ADAPTOR:
pDM_Odm->pBuddyAdapter = (struct rtw_adapter **)pValue;
break;
case ODM_CMNINFO_DMSP_IS_MASTER:
pDM_Odm->pbMasterOfDMSP = (bool *)pValue;
break;
case ODM_CMNINFO_SCAN:
pDM_Odm->pbScanInProcess = (bool *)pValue;
break;
case ODM_CMNINFO_POWER_SAVING:
pDM_Odm->pbPowerSaving = (bool *)pValue;
break;
case ODM_CMNINFO_ONE_PATH_CCA:
pDM_Odm->pOnePathCCA = (u8 *)pValue;
break;
case ODM_CMNINFO_DRV_STOP:
pDM_Odm->pbDriverStopped = (bool *)pValue;
break;
case ODM_CMNINFO_PNP_IN:
pDM_Odm->pbDriverIsGoingToPnpSetPowerSleep = (bool *)pValue;
break;
case ODM_CMNINFO_INIT_ON:
pDM_Odm->pinit_adpt_in_progress = (bool *)pValue;
break;
case ODM_CMNINFO_ANT_TEST:
pDM_Odm->pAntennaTest = (u8 *)pValue;
break;
case ODM_CMNINFO_NET_CLOSED:
pDM_Odm->pbNet_closed = (bool *)pValue;
break;
/* To remove the compiler warning, must add an empty default statement to handle the other values. */
default:
/* do nothing */
break;
}
}
void ODM_CmnInfoPtrArrayHook23a(struct dm_odm_t *pDM_Odm, enum odm_cmninfo CmnInfo,
u16 Index, void *pValue)
{
/* Hook call by reference pointer. */
switch (CmnInfo) {
/* Dynamic call by reference pointer. */
case ODM_CMNINFO_STA_STATUS:
pDM_Odm->pODM_StaInfo[Index] = (struct sta_info *)pValue;
break;
/* To remove the compiler warning, must add an empty default statement to handle the other values. */
default:
/* do nothing */
break;
}
}
/* Update Band/CHannel/.. The values are dynamic but non-per-packet. */
void ODM_CmnInfoUpdate23a(struct dm_odm_t *pDM_Odm, u32 CmnInfo, u64 Value)
{
/* This init variable may be changed in run time. */
switch (CmnInfo) {
case ODM_CMNINFO_ABILITY:
pDM_Odm->SupportAbility = (u32)Value;
break;
case ODM_CMNINFO_RF_TYPE:
pDM_Odm->RFType = (u8)Value;
break;
case ODM_CMNINFO_WIFI_DIRECT:
pDM_Odm->bWIFI_Direct = (bool)Value;
break;
case ODM_CMNINFO_WIFI_DISPLAY:
pDM_Odm->bWIFI_Display = (bool)Value;
break;
case ODM_CMNINFO_LINK:
pDM_Odm->bLinked = (bool)Value;
break;
case ODM_CMNINFO_RSSI_MIN:
pDM_Odm->RSSI_Min = (u8)Value;
break;
case ODM_CMNINFO_DBG_COMP:
pDM_Odm->DebugComponents = Value;
break;
case ODM_CMNINFO_DBG_LEVEL:
pDM_Odm->DebugLevel = (u32)Value;
break;
case ODM_CMNINFO_RA_THRESHOLD_HIGH:
pDM_Odm->RateAdaptive.HighRSSIThresh = (u8)Value;
break;
case ODM_CMNINFO_RA_THRESHOLD_LOW:
pDM_Odm->RateAdaptive.LowRSSIThresh = (u8)Value;
break;
}
}
void odm_CommonInfoSelfInit23a(struct dm_odm_t *pDM_Odm
)
{
pDM_Odm->bCckHighPower = (bool) ODM_GetBBReg(pDM_Odm, 0x824, BIT9);
pDM_Odm->RFPathRxEnable = (u8) ODM_GetBBReg(pDM_Odm, 0xc04, 0x0F);
if (pDM_Odm->SupportICType & (ODM_RTL8723A))
pDM_Odm->AntDivType = CGCS_RX_SW_ANTDIV;
ODM_InitDebugSetting23a(pDM_Odm);
}
void odm_CommonInfoSelfUpdate23a(struct dm_odm_t *pDM_Odm)
{
u8 EntryCnt = 0;
u8 i;
struct sta_info *pEntry;
if (*(pDM_Odm->pBandWidth) == ODM_BW40M) {
if (*(pDM_Odm->pSecChOffset) == 1)
pDM_Odm->ControlChannel = *(pDM_Odm->pChannel) - 2;
else if (*(pDM_Odm->pSecChOffset) == 2)
pDM_Odm->ControlChannel = *(pDM_Odm->pChannel) + 2;
} else {
pDM_Odm->ControlChannel = *(pDM_Odm->pChannel);
}
for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
pEntry = pDM_Odm->pODM_StaInfo[i];
if (IS_STA_VALID(pEntry))
EntryCnt++;
}
if (EntryCnt == 1)
pDM_Odm->bOneEntryOnly = true;
else
pDM_Odm->bOneEntryOnly = false;
}
void odm_CmnInfoInit_Debug23a(struct dm_odm_t *pDM_Odm)
{
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoInit_Debug23a ==>\n"));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportAbility = 0x%x\n", pDM_Odm->SupportAbility));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportInterface =%d\n", pDM_Odm->SupportInterface));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportICType = 0x%x\n", pDM_Odm->SupportICType));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("CutVersion =%d\n", pDM_Odm->CutVersion));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("FabVersion =%d\n", pDM_Odm->FabVersion));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("RFType =%d\n", pDM_Odm->RFType));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("BoardType =%d\n", pDM_Odm->BoardType));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtLNA =%d\n", pDM_Odm->ExtLNA));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtPA =%d\n", pDM_Odm->ExtPA));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtTRSW =%d\n", pDM_Odm->ExtTRSW));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("PatchID =%d\n", pDM_Odm->PatchID));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bInHctTest =%d\n", pDM_Odm->bInHctTest));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFITest =%d\n", pDM_Odm->bWIFITest));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bDualMacSmartConcurrent =%d\n", pDM_Odm->bDualMacSmartConcurrent));
}
void odm_CmnInfoHook_Debug23a(struct dm_odm_t *pDM_Odm)
{
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoHook_Debug23a ==>\n"));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pNumTxBytesUnicast =%llu\n", *(pDM_Odm->pNumTxBytesUnicast)));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pNumRxBytesUnicast =%llu\n", *(pDM_Odm->pNumRxBytesUnicast)));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pWirelessMode = 0x%x\n", *(pDM_Odm->pWirelessMode)));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pSecChOffset =%d\n", *(pDM_Odm->pSecChOffset)));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pSecurity =%d\n", *(pDM_Odm->pSecurity)));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pBandWidth =%d\n", *(pDM_Odm->pBandWidth)));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pChannel =%d\n", *(pDM_Odm->pChannel)));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pbScanInProcess =%d\n", *(pDM_Odm->pbScanInProcess)));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pbPowerSaving =%d\n", *(pDM_Odm->pbPowerSaving)));
}
void odm_CmnInfoUpdate_Debug23a(struct dm_odm_t *pDM_Odm)
{
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoUpdate_Debug23a ==>\n"));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFI_Direct =%d\n", pDM_Odm->bWIFI_Direct));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFI_Display =%d\n", pDM_Odm->bWIFI_Display));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bLinked =%d\n", pDM_Odm->bLinked));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("RSSI_Min =%d\n", pDM_Odm->RSSI_Min));
}
void ODM_Write_DIG23a(struct dm_odm_t *pDM_Odm,
u8 CurrentIGI
)
{
struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("ODM_REG(IGI_A, pDM_Odm) = 0x%x, ODM_BIT(IGI, pDM_Odm) = 0x%x \n",
ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm)));
if (pDM_DigTable->CurIGValue != CurrentIGI) {
ODM_SetBBReg(pDM_Odm, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("CurrentIGI(0x%02x). \n", CurrentIGI));
pDM_DigTable->CurIGValue = CurrentIGI;
}
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
("ODM_Write_DIG23a():CurrentIGI = 0x%x \n", CurrentIGI));
}
/* Need LPS mode for CE platform --2012--08--24--- */
/* 8723AS/8189ES */
void odm_DIG23abyRSSI_LPS(struct dm_odm_t *pDM_Odm)
{
struct rtw_adapter *pAdapter = pDM_Odm->Adapter;
struct false_alarm_stats *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
u8 RSSI_Lower = DM_DIG_MIN_NIC; /* 0x1E or 0x1C */
u8 bFwCurrentInPSMode = false;
u8 CurrentIGI = pDM_Odm->RSSI_Min;
if (!(pDM_Odm->SupportICType & (ODM_RTL8723A)))
return;
CurrentIGI = CurrentIGI+RSSI_OFFSET_DIG;
bFwCurrentInPSMode = pAdapter->pwrctrlpriv.bFwCurrentInPSMode;
/* ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG_LPS, ODM_DBG_LOUD, ("odm_DIG23a() ==>\n")); */
/* Using FW PS mode to make IGI */
if (bFwCurrentInPSMode) {
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("---Neil---odm_DIG23a is in LPS mode\n"));
/* Adjust by FA in LPS MODE */
if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2_LPS)
CurrentIGI = CurrentIGI+2;
else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1_LPS)
CurrentIGI = CurrentIGI+1;
else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0_LPS)
CurrentIGI = CurrentIGI-1;
} else {
CurrentIGI = RSSI_Lower;
}
/* Lower bound checking */
/* RSSI Lower bound check */
if ((pDM_Odm->RSSI_Min-10) > DM_DIG_MIN_NIC)
RSSI_Lower = (pDM_Odm->RSSI_Min-10);
else
RSSI_Lower = DM_DIG_MIN_NIC;
/* Upper and Lower Bound checking */
if (CurrentIGI > DM_DIG_MAX_NIC)
CurrentIGI = DM_DIG_MAX_NIC;
else if (CurrentIGI < RSSI_Lower)
CurrentIGI = RSSI_Lower;
ODM_Write_DIG23a(pDM_Odm, CurrentIGI);/* ODM_Write_DIG23a(pDM_Odm, pDM_DigTable->CurIGValue); */
}
void odm_DIG23aInit(struct dm_odm_t *pDM_Odm)
{
struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
pDM_DigTable->CurIGValue = (u8) ODM_GetBBReg(pDM_Odm, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm));
pDM_DigTable->RssiLowThresh = DM_DIG_THRESH_LOW;
pDM_DigTable->RssiHighThresh = DM_DIG_THRESH_HIGH;
pDM_DigTable->FALowThresh = DM_FALSEALARM_THRESH_LOW;
pDM_DigTable->FAHighThresh = DM_FALSEALARM_THRESH_HIGH;
if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) {
pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC;
} else {
pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC;
}
pDM_DigTable->BackoffVal = DM_DIG_BACKOFF_DEFAULT;
pDM_DigTable->BackoffVal_range_max = DM_DIG_BACKOFF_MAX;
pDM_DigTable->BackoffVal_range_min = DM_DIG_BACKOFF_MIN;
pDM_DigTable->PreCCK_CCAThres = 0xFF;
pDM_DigTable->CurCCK_CCAThres = 0x83;
pDM_DigTable->ForbiddenIGI = DM_DIG_MIN_NIC;
pDM_DigTable->LargeFAHit = 0;
pDM_DigTable->Recover_cnt = 0;
pDM_DigTable->DIG_Dynamic_MIN_0 = DM_DIG_MIN_NIC;
pDM_DigTable->DIG_Dynamic_MIN_1 = DM_DIG_MIN_NIC;
pDM_DigTable->bMediaConnect_0 = false;
pDM_DigTable->bMediaConnect_1 = false;
/* To Initialize pDM_Odm->bDMInitialGainEnable == false to avoid DIG error */
pDM_Odm->bDMInitialGainEnable = true;
}
void odm_DIG23a(struct dm_odm_t *pDM_Odm)
{
struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
struct false_alarm_stats *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
u8 DIG_Dynamic_MIN;
u8 DIG_MaxOfMin;
bool FirstConnect, FirstDisConnect;
u8 dm_dig_max, dm_dig_min;
u8 CurrentIGI = pDM_DigTable->CurIGValue;
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a() ==>\n"));
/* if (!(pDM_Odm->SupportAbility & (ODM_BB_DIG|ODM_BB_FA_CNT))) */
if ((!(pDM_Odm->SupportAbility&ODM_BB_DIG)) || (!(pDM_Odm->SupportAbility&ODM_BB_FA_CNT))) {
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
("odm_DIG23a() Return: SupportAbility ODM_BB_DIG or ODM_BB_FA_CNT is disabled\n"));
return;
}
if (*(pDM_Odm->pbScanInProcess)) {
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a() Return: In Scan Progress \n"));
return;
}
/* add by Neil Chen to avoid PSD is processing */
if (!pDM_Odm->bDMInitialGainEnable) {
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a() Return: PSD is Processing \n"));
return;
}
DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0;
FirstConnect = (pDM_Odm->bLinked) && (!pDM_DigTable->bMediaConnect_0);
FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0);
/* 1 Boundary Decision */
if ((pDM_Odm->SupportICType & (ODM_RTL8723A)) &&
((pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) || pDM_Odm->ExtLNA)) {
dm_dig_max = DM_DIG_MAX_NIC_HP;
dm_dig_min = DM_DIG_MIN_NIC_HP;
DIG_MaxOfMin = DM_DIG_MAX_AP_HP;
} else {
dm_dig_max = DM_DIG_MAX_NIC;
dm_dig_min = DM_DIG_MIN_NIC;
DIG_MaxOfMin = DM_DIG_MAX_AP;
}
if (pDM_Odm->bLinked) {
/* 2 8723A Series, offset need to be 10 */
if (pDM_Odm->SupportICType == (ODM_RTL8723A)) {
/* 2 Upper Bound */
if ((pDM_Odm->RSSI_Min + 10) > DM_DIG_MAX_NIC)
pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
else if ((pDM_Odm->RSSI_Min + 10) < DM_DIG_MIN_NIC)
pDM_DigTable->rx_gain_range_max = DM_DIG_MIN_NIC;
else
pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + 10;
/* 2 If BT is Concurrent, need to set Lower Bound */
DIG_Dynamic_MIN = DM_DIG_MIN_NIC;
} else {
/* 2 Modify DIG upper bound */
if ((pDM_Odm->RSSI_Min + 20) > dm_dig_max)
pDM_DigTable->rx_gain_range_max = dm_dig_max;
else if ((pDM_Odm->RSSI_Min + 20) < dm_dig_min)
pDM_DigTable->rx_gain_range_max = dm_dig_min;
else
pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + 20;
/* 2 Modify DIG lower bound */
if (pDM_Odm->bOneEntryOnly) {
if (pDM_Odm->RSSI_Min < dm_dig_min)
DIG_Dynamic_MIN = dm_dig_min;
else if (pDM_Odm->RSSI_Min > DIG_MaxOfMin)
DIG_Dynamic_MIN = DIG_MaxOfMin;
else
DIG_Dynamic_MIN = pDM_Odm->RSSI_Min;
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
("odm_DIG23a() : bOneEntryOnly = true, DIG_Dynamic_MIN = 0x%x\n",
DIG_Dynamic_MIN));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
("odm_DIG23a() : pDM_Odm->RSSI_Min =%d\n",
pDM_Odm->RSSI_Min));
} else {
DIG_Dynamic_MIN = dm_dig_min;
}
}
} else {
pDM_DigTable->rx_gain_range_max = dm_dig_max;
DIG_Dynamic_MIN = dm_dig_min;
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a() : No Link\n"));
}
/* 1 Modify DIG lower bound, deal with abnormally large false alarm */
if (pFalseAlmCnt->Cnt_all > 10000) {
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
("dm_DIG(): Abnornally false alarm case. \n"));
if (pDM_DigTable->LargeFAHit != 3)
pDM_DigTable->LargeFAHit++;
if (pDM_DigTable->ForbiddenIGI < CurrentIGI) {
pDM_DigTable->ForbiddenIGI = CurrentIGI;
pDM_DigTable->LargeFAHit = 1;
}
if (pDM_DigTable->LargeFAHit >= 3) {
if ((pDM_DigTable->ForbiddenIGI+1) > pDM_DigTable->rx_gain_range_max)
pDM_DigTable->rx_gain_range_min = pDM_DigTable->rx_gain_range_max;
else
pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1);
pDM_DigTable->Recover_cnt = 3600; /* 3600 = 2hr */
}
} else {
/* Recovery mechanism for IGI lower bound */
if (pDM_DigTable->Recover_cnt != 0) {
pDM_DigTable->Recover_cnt--;
} else {
if (pDM_DigTable->LargeFAHit < 3) {
if ((pDM_DigTable->ForbiddenIGI - 1) < DIG_Dynamic_MIN) {
pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
pDM_DigTable->rx_gain_range_min = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
("odm_DIG23a(): Normal Case: At Lower Bound\n"));
} else {
pDM_DigTable->ForbiddenIGI--;
pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
("odm_DIG23a(): Normal Case: Approach Lower Bound\n"));
}
} else {
pDM_DigTable->LargeFAHit = 0;
}
}
}
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): pDM_DigTable->LargeFAHit =%d\n", pDM_DigTable->LargeFAHit));
/* 1 Adjust initial gain by false alarm */
if (pDM_Odm->bLinked) {
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): DIG AfterLink\n"));
if (FirstConnect) {
CurrentIGI = pDM_Odm->RSSI_Min;
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("DIG: First Connect\n"));
} else {
if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2)
CurrentIGI = CurrentIGI + 4;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */
else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1)
CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */
else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0)
CurrentIGI = CurrentIGI - 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue-1; */
}
} else {
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): DIG BeforeLink\n"));
if (FirstDisConnect) {
CurrentIGI = pDM_DigTable->rx_gain_range_min;
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): First DisConnect \n"));
} else {
/* 2012.03.30 LukeLee: enable DIG before link but with very high thresholds */
if (pFalseAlmCnt->Cnt_all > 10000)
CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */
else if (pFalseAlmCnt->Cnt_all > 8000)
CurrentIGI = CurrentIGI + 1;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */
else if (pFalseAlmCnt->Cnt_all < 500)
CurrentIGI = CurrentIGI - 1;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue-1; */
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): England DIG \n"));
}
}
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): DIG End Adjust IGI\n"));
/* 1 Check initial gain by upper/lower bound */
if (CurrentIGI > pDM_DigTable->rx_gain_range_max)
CurrentIGI = pDM_DigTable->rx_gain_range_max;
if (CurrentIGI < pDM_DigTable->rx_gain_range_min)
CurrentIGI = pDM_DigTable->rx_gain_range_min;
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): rx_gain_range_max = 0x%x, rx_gain_range_min = 0x%x\n",
pDM_DigTable->rx_gain_range_max, pDM_DigTable->rx_gain_range_min));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): TotalFA =%d\n", pFalseAlmCnt->Cnt_all));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): CurIGValue = 0x%x\n", CurrentIGI));
/* 2 High power RSSI threshold */
ODM_Write_DIG23a(pDM_Odm, CurrentIGI);/* ODM_Write_DIG23a(pDM_Odm, pDM_DigTable->CurIGValue); */
pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked;
pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN;
}
/* 3 ============================================================ */
/* 3 FASLE ALARM CHECK */
/* 3 ============================================================ */
void odm_FalseAlarmCounterStatistics23a(struct dm_odm_t *pDM_Odm)
{
u32 ret_value;
struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT))
return;
if (pDM_Odm->SupportICType & ODM_IC_11N_SERIES) {
/* hold ofdm counter */
ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_HOLDC_11N, BIT31, 1); /* hold page C counter */
ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT31, 1); /* hold page D counter */
ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord);
FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff);
FalseAlmCnt->Cnt_SB_Search_fail = ((ret_value&0xffff0000)>>16);
ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord);
FalseAlmCnt->Cnt_OFDM_CCA = (ret_value&0xffff);
FalseAlmCnt->Cnt_Parity_Fail = ((ret_value&0xffff0000)>>16);
ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord);
FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff);
FalseAlmCnt->Cnt_Crc8_fail = ((ret_value&0xffff0000)>>16);
ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord);
FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff);
FalseAlmCnt->Cnt_Ofdm_fail = FalseAlmCnt->Cnt_Parity_Fail +
FalseAlmCnt->Cnt_Rate_Illegal +
FalseAlmCnt->Cnt_Crc8_fail +
FalseAlmCnt->Cnt_Mcs_fail +
FalseAlmCnt->Cnt_Fast_Fsync +
FalseAlmCnt->Cnt_SB_Search_fail;
/* hold cck counter */
ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT12, 1);
ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT14, 1);
ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_FA_LSB_11N, bMaskByte0);
FalseAlmCnt->Cnt_Cck_fail = ret_value;
ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_FA_MSB_11N, bMaskByte3);
FalseAlmCnt->Cnt_Cck_fail += (ret_value & 0xff) << 8;
ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord);
FalseAlmCnt->Cnt_CCK_CCA = ((ret_value&0xFF)<<8) | ((ret_value&0xFF00)>>8);
FalseAlmCnt->Cnt_all = (FalseAlmCnt->Cnt_Fast_Fsync +
FalseAlmCnt->Cnt_SB_Search_fail +
FalseAlmCnt->Cnt_Parity_Fail +
FalseAlmCnt->Cnt_Rate_Illegal +
FalseAlmCnt->Cnt_Crc8_fail +
FalseAlmCnt->Cnt_Mcs_fail +
FalseAlmCnt->Cnt_Cck_fail);
FalseAlmCnt->Cnt_CCA_all = FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA;
if (pDM_Odm->SupportICType >= ODM_RTL8723A) {
/* reset false alarm counter registers */
ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTC_11N, BIT31, 1);
ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTC_11N, BIT31, 0);
ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT27, 1);
ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT27, 0);
/* update ofdm counter */
ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_HOLDC_11N, BIT31, 0); /* update page C counter */
ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT31, 0); /* update page D counter */
/* reset CCK CCA counter */
ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT13|BIT12, 0);
ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT13|BIT12, 2);
/* reset CCK FA counter */
ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT15|BIT14, 0);
ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT15|BIT14, 2);
}
ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Enter odm_FalseAlarmCounterStatistics23a\n"));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Fast_Fsync =%d, Cnt_SB_Search_fail =%d\n",
FalseAlmCnt->Cnt_Fast_Fsync, FalseAlmCnt->Cnt_SB_Search_fail));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Parity_Fail =%d, Cnt_Rate_Illegal =%d\n",
FalseAlmCnt->Cnt_Parity_Fail, FalseAlmCnt->Cnt_Rate_Illegal));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Crc8_fail =%d, Cnt_Mcs_fail =%d\n",
FalseAlmCnt->Cnt_Crc8_fail, FalseAlmCnt->Cnt_Mcs_fail));
} else { /* FOR ODM_IC_11AC_SERIES */
/* read OFDM FA counter */
FalseAlmCnt->Cnt_Ofdm_fail = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_11AC, bMaskLWord);
FalseAlmCnt->Cnt_Cck_fail = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_FA_11AC, bMaskLWord);
FalseAlmCnt->Cnt_all = FalseAlmCnt->Cnt_Ofdm_fail + FalseAlmCnt->Cnt_Cck_fail;
/* reset OFDM FA coutner */
ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RST_11AC, BIT17, 1);
ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RST_11AC, BIT17, 0);
/* reset CCK FA counter */
ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11AC, BIT15, 0);
ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11AC, BIT15, 1);
}
ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Cck_fail =%d\n", FalseAlmCnt->Cnt_Cck_fail));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Ofdm_fail =%d\n", FalseAlmCnt->Cnt_Ofdm_fail));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Total False Alarm =%d\n", FalseAlmCnt->Cnt_all));
}
/* 3 ============================================================ */
/* 3 CCK Packet Detect Threshold */
/* 3 ============================================================ */
void odm_CCKPacketDetectionThresh23a(struct dm_odm_t *pDM_Odm)
{
struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
u8 CurCCK_CCAThres;
if (!(pDM_Odm->SupportAbility & (ODM_BB_CCK_PD|ODM_BB_FA_CNT)))
return;
if (pDM_Odm->ExtLNA)
return;
if (pDM_Odm->bLinked) {
if (pDM_Odm->RSSI_Min > 25) {
CurCCK_CCAThres = 0xcd;
} else if ((pDM_Odm->RSSI_Min <= 25) && (pDM_Odm->RSSI_Min > 10)) {
CurCCK_CCAThres = 0x83;
} else {
if (FalseAlmCnt->Cnt_Cck_fail > 1000)
CurCCK_CCAThres = 0x83;
else
CurCCK_CCAThres = 0x40;
}
} else {
if (FalseAlmCnt->Cnt_Cck_fail > 1000)
CurCCK_CCAThres = 0x83;
else
CurCCK_CCAThres = 0x40;
}
ODM_Write_CCK_CCA_Thres23a(pDM_Odm, CurCCK_CCAThres);
}
void ODM_Write_CCK_CCA_Thres23a(struct dm_odm_t *pDM_Odm, u8 CurCCK_CCAThres)
{
struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres)
ODM_Write1Byte(pDM_Odm, ODM_REG(CCK_CCA, pDM_Odm), CurCCK_CCAThres);
pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres;
pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres;
}
/* 3 ============================================================ */
/* 3 BB Power Save */
/* 3 ============================================================ */
void odm23a_DynBBPSInit(struct dm_odm_t *pDM_Odm)
{
struct dynamic_pwr_sav *pDM_PSTable = &pDM_Odm->DM_PSTable;
pDM_PSTable->PreCCAState = CCA_MAX;
pDM_PSTable->CurCCAState = CCA_MAX;
pDM_PSTable->PreRFState = RF_MAX;
pDM_PSTable->CurRFState = RF_MAX;
pDM_PSTable->Rssi_val_min = 0;
pDM_PSTable->initialize = 0;
}
void odm_DynamicBBPowerSaving23a(struct dm_odm_t *pDM_Odm)
{
return;
}
void odm_1R_CCA23a(struct dm_odm_t *pDM_Odm)
{
struct dynamic_pwr_sav *pDM_PSTable = &pDM_Odm->DM_PSTable;
if (pDM_Odm->RSSI_Min != 0xFF) {
if (pDM_PSTable->PreCCAState == CCA_2R) {
if (pDM_Odm->RSSI_Min >= 35)
pDM_PSTable->CurCCAState = CCA_1R;
else
pDM_PSTable->CurCCAState = CCA_2R;
} else {
if (pDM_Odm->RSSI_Min <= 30)
pDM_PSTable->CurCCAState = CCA_2R;
else
pDM_PSTable->CurCCAState = CCA_1R;
}
} else {
pDM_PSTable->CurCCAState = CCA_MAX;
}
if (pDM_PSTable->PreCCAState != pDM_PSTable->CurCCAState) {
if (pDM_PSTable->CurCCAState == CCA_1R) {
if (pDM_Odm->RFType == ODM_2T2R)
ODM_SetBBReg(pDM_Odm, 0xc04, bMaskByte0, 0x13);
else
ODM_SetBBReg(pDM_Odm, 0xc04, bMaskByte0, 0x23);
} else {
ODM_SetBBReg(pDM_Odm, 0xc04, bMaskByte0, 0x33);
/* PHY_SetBBReg(pAdapter, 0xe70, bMaskByte3, 0x63); */
}
pDM_PSTable->PreCCAState = pDM_PSTable->CurCCAState;
}
}
void ODM_RF_Saving23a(struct dm_odm_t *pDM_Odm, u8 bForceInNormal)
{
struct dynamic_pwr_sav *pDM_PSTable = &pDM_Odm->DM_PSTable;
u8 Rssi_Up_bound = 30 ;
u8 Rssi_Low_bound = 25;
if (pDM_Odm->PatchID == 40) { /* RT_CID_819x_FUNAI_TV */
Rssi_Up_bound = 50 ;
Rssi_Low_bound = 45;
}
if (pDM_PSTable->initialize == 0) {
pDM_PSTable->Reg874 = (ODM_GetBBReg(pDM_Odm, 0x874, bMaskDWord)&0x1CC000)>>14;
pDM_PSTable->RegC70 = (ODM_GetBBReg(pDM_Odm, 0xc70, bMaskDWord)&BIT3)>>3;
pDM_PSTable->Reg85C = (ODM_GetBBReg(pDM_Odm, 0x85c, bMaskDWord)&0xFF000000)>>24;
pDM_PSTable->RegA74 = (ODM_GetBBReg(pDM_Odm, 0xa74, bMaskDWord)&0xF000)>>12;
/* Reg818 = PHY_QueryBBReg(pAdapter, 0x818, bMaskDWord); */
pDM_PSTable->initialize = 1;
}
if (!bForceInNormal) {
if (pDM_Odm->RSSI_Min != 0xFF) {
if (pDM_PSTable->PreRFState == RF_Normal) {
if (pDM_Odm->RSSI_Min >= Rssi_Up_bound)
pDM_PSTable->CurRFState = RF_Save;
else
pDM_PSTable->CurRFState = RF_Normal;
} else {
if (pDM_Odm->RSSI_Min <= Rssi_Low_bound)
pDM_PSTable->CurRFState = RF_Normal;
else
pDM_PSTable->CurRFState = RF_Save;
}
} else {
pDM_PSTable->CurRFState = RF_MAX;
}
} else {
pDM_PSTable->CurRFState = RF_Normal;
}
if (pDM_PSTable->PreRFState != pDM_PSTable->CurRFState) {
if (pDM_PSTable->CurRFState == RF_Save) {
/* <tynli_note> 8723 RSSI report will be wrong. Set 0x874[5]= 1 when enter BB power saving mode. */
/* Suggested by SD3 Yu-Nan. 2011.01.20. */
if (pDM_Odm->SupportICType == ODM_RTL8723A)
ODM_SetBBReg(pDM_Odm, 0x874, BIT5, 0x1); /* Reg874[5]= 1b'1 */
ODM_SetBBReg(pDM_Odm, 0x874, 0x1C0000, 0x2); /* Reg874[20:18]= 3'b010 */
ODM_SetBBReg(pDM_Odm, 0xc70, BIT3, 0); /* RegC70[3]= 1'b0 */
ODM_SetBBReg(pDM_Odm, 0x85c, 0xFF000000, 0x63); /* Reg85C[31:24]= 0x63 */
ODM_SetBBReg(pDM_Odm, 0x874, 0xC000, 0x2); /* Reg874[15:14]= 2'b10 */
ODM_SetBBReg(pDM_Odm, 0xa74, 0xF000, 0x3); /* RegA75[7:4]= 0x3 */
ODM_SetBBReg(pDM_Odm, 0x818, BIT28, 0x0); /* Reg818[28]= 1'b0 */
ODM_SetBBReg(pDM_Odm, 0x818, BIT28, 0x1); /* Reg818[28]= 1'b1 */
} else {
ODM_SetBBReg(pDM_Odm, 0x874, 0x1CC000, pDM_PSTable->Reg874);
ODM_SetBBReg(pDM_Odm, 0xc70, BIT3, pDM_PSTable->RegC70);
ODM_SetBBReg(pDM_Odm, 0x85c, 0xFF000000, pDM_PSTable->Reg85C);
ODM_SetBBReg(pDM_Odm, 0xa74, 0xF000, pDM_PSTable->RegA74);
ODM_SetBBReg(pDM_Odm, 0x818, BIT28, 0x0);
if (pDM_Odm->SupportICType == ODM_RTL8723A)
ODM_SetBBReg(pDM_Odm, 0x874, BIT5, 0x0); /* Reg874[5]= 1b'0 */
}
pDM_PSTable->PreRFState = pDM_PSTable->CurRFState;
}
}
/* 3 ============================================================ */
/* 3 RATR MASK */
/* 3 ============================================================ */
/* 3 ============================================================ */
/* 3 Rate Adaptive */
/* 3 ============================================================ */
void odm_RateAdaptiveMaskInit23a(struct dm_odm_t *pDM_Odm)
{
struct odm_rate_adapt *pOdmRA = &pDM_Odm->RateAdaptive;
pOdmRA->Type = DM_Type_ByDriver;
if (pOdmRA->Type == DM_Type_ByDriver)
pDM_Odm->bUseRAMask = true;
else
pDM_Odm->bUseRAMask = false;
pOdmRA->RATRState = DM_RATR_STA_INIT;
pOdmRA->HighRSSIThresh = 50;
pOdmRA->LowRSSIThresh = 20;
}
u32 ODM_Get_Rate_Bitmap23a(struct dm_odm_t *pDM_Odm,
u32 macid,
u32 ra_mask,
u8 rssi_level)
{
struct sta_info *pEntry;
u32 rate_bitmap = 0x0fffffff;
u8 WirelessMode;
/* u8 WirelessMode =*(pDM_Odm->pWirelessMode); */
pEntry = pDM_Odm->pODM_StaInfo[macid];
if (!IS_STA_VALID(pEntry))
return ra_mask;
WirelessMode = pEntry->wireless_mode;
switch (WirelessMode) {
case ODM_WM_B:
if (ra_mask & 0x0000000c) /* 11M or 5.5M enable */
rate_bitmap = 0x0000000d;
else
rate_bitmap = 0x0000000f;
break;
case (ODM_WM_A|ODM_WM_G):
if (rssi_level == DM_RATR_STA_HIGH)
rate_bitmap = 0x00000f00;
else
rate_bitmap = 0x00000ff0;
break;
case (ODM_WM_B|ODM_WM_G):
if (rssi_level == DM_RATR_STA_HIGH)
rate_bitmap = 0x00000f00;
else if (rssi_level == DM_RATR_STA_MIDDLE)
rate_bitmap = 0x00000ff0;
else
rate_bitmap = 0x00000ff5;
break;
case (ODM_WM_B|ODM_WM_G|ODM_WM_N24G):
case (ODM_WM_A|ODM_WM_B|ODM_WM_G|ODM_WM_N24G):
if (pDM_Odm->RFType == ODM_1T2R || pDM_Odm->RFType == ODM_1T1R) {
if (rssi_level == DM_RATR_STA_HIGH) {
rate_bitmap = 0x000f0000;
} else if (rssi_level == DM_RATR_STA_MIDDLE) {
rate_bitmap = 0x000ff000;
} else {
if (*(pDM_Odm->pBandWidth) == ODM_BW40M)
rate_bitmap = 0x000ff015;
else
rate_bitmap = 0x000ff005;
}
} else {
if (rssi_level == DM_RATR_STA_HIGH) {
rate_bitmap = 0x0f8f0000;
} else if (rssi_level == DM_RATR_STA_MIDDLE) {
rate_bitmap = 0x0f8ff000;
} else {
if (*(pDM_Odm->pBandWidth) == ODM_BW40M)
rate_bitmap = 0x0f8ff015;
else
rate_bitmap = 0x0f8ff005;
}
}
break;
default:
/* case WIRELESS_11_24N: */
/* case WIRELESS_11_5N: */
if (pDM_Odm->RFType == RF_1T2R)
rate_bitmap = 0x000fffff;
else
rate_bitmap = 0x0fffffff;
break;
}
/* printk("%s ==> rssi_level:0x%02x, WirelessMode:0x%02x, rate_bitmap:0x%08x \n", __FUNCTION__, rssi_level, WirelessMode, rate_bitmap); */
ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, (" ==> rssi_level:0x%02x, WirelessMode:0x%02x, rate_bitmap:0x%08x \n", rssi_level, WirelessMode, rate_bitmap));
return rate_bitmap;
}
/*-----------------------------------------------------------------------------
* Function: odm_RefreshRateAdaptiveMask23a()
*
* Overview: Update rate table mask according to rssi
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
*When Who Remark
*05/27/2009 hpfan Create Version 0.
*
*---------------------------------------------------------------------------*/
void odm_RefreshRateAdaptiveMask23a(struct dm_odm_t *pDM_Odm)
{
if (!(pDM_Odm->SupportAbility & ODM_BB_RA_MASK))
return;
/* */
/* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
/* at the same time. In the stage2/3, we need to prive universal interface and merge all */
/* HW dynamic mechanism. */
/* */
odm_RefreshRateAdaptiveMask23aCE23a(pDM_Odm);
}
void odm_RefreshRateAdaptiveMask23aMP23a(struct dm_odm_t *pDM_Odm)
{
}
void odm_RefreshRateAdaptiveMask23aCE23a(struct dm_odm_t *pDM_Odm)
{
u8 i;
struct rtw_adapter *pAdapter = pDM_Odm->Adapter;
if (pAdapter->bDriverStopped) {
ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_TRACE,
("<---- odm_RefreshRateAdaptiveMask23a(): driver is going to unload\n"));
return;
}
if (!pDM_Odm->bUseRAMask) {
ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD,
("<---- odm_RefreshRateAdaptiveMask23a(): driver does not control rate adaptive mask\n"));
return;
}
/* printk("==> %s \n", __FUNCTION__); */
for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
struct sta_info *pstat = pDM_Odm->pODM_StaInfo[i];
if (IS_STA_VALID(pstat)) {
if (ODM_RAStateCheck23a(pDM_Odm, pstat->rssi_stat.UndecoratedSmoothedPWDB, false, &pstat->rssi_level)) {
ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD,
("RSSI:%d, RSSI_LEVEL:%d\n",
pstat->rssi_stat.UndecoratedSmoothedPWDB,
pstat->rssi_level));
rtw_hal_update_ra_mask23a(pstat, pstat->rssi_level);
}
}
}
}
void odm_RefreshRateAdaptiveMask23aAPADSL23a(struct dm_odm_t *pDM_Odm)
{
}
/* Return Value: bool */
/* - true: RATRState is changed. */
bool ODM_RAStateCheck23a(struct dm_odm_t *pDM_Odm, s32 RSSI, bool bForceUpdate,
u8 *pRATRState)
{
struct odm_rate_adapt *pRA = &pDM_Odm->RateAdaptive;
const u8 GoUpGap = 5;
u8 HighRSSIThreshForRA = pRA->HighRSSIThresh;
u8 LowRSSIThreshForRA = pRA->LowRSSIThresh;
u8 RATRState;
/* Threshold Adjustment: */
/* when RSSI state trends to go up one or two levels, make sure RSSI is high enough. */
/* Here GoUpGap is added to solve the boundary's level alternation issue. */
switch (*pRATRState) {
case DM_RATR_STA_INIT:
case DM_RATR_STA_HIGH:
break;
case DM_RATR_STA_MIDDLE:
HighRSSIThreshForRA += GoUpGap;
break;
case DM_RATR_STA_LOW:
HighRSSIThreshForRA += GoUpGap;
LowRSSIThreshForRA += GoUpGap;
break;
default:
ODM_RT_ASSERT(pDM_Odm, false, ("wrong rssi level setting %d !", *pRATRState));
break;
}
/* Decide RATRState by RSSI. */
if (RSSI > HighRSSIThreshForRA)
RATRState = DM_RATR_STA_HIGH;
else if (RSSI > LowRSSIThreshForRA)
RATRState = DM_RATR_STA_MIDDLE;
else
RATRState = DM_RATR_STA_LOW;
if (*pRATRState != RATRState || bForceUpdate) {
ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD,
("RSSI Level %d -> %d\n", *pRATRState, RATRState));
*pRATRState = RATRState;
return true;
}
return false;
}
/* 3 ============================================================ */
/* 3 Dynamic Tx Power */
/* 3 ============================================================ */
void odm_DynamicTxPower23aInit(struct dm_odm_t *pDM_Odm)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
pdmpriv->bDynamicTxPowerEnable = false;
pdmpriv->LastDTPLvl = TxHighPwrLevel_Normal;
pdmpriv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal;
}
void odm_DynamicTxPower23aSavePowerIndex(struct dm_odm_t *pDM_Odm)
{
u8 index;
u32 Power_Index_REG[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a};
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
for (index = 0; index < 6; index++)
pdmpriv->PowerIndex_backup[index] = rtw_read8(Adapter, Power_Index_REG[index]);
}
void odm_DynamicTxPower23aRestorePowerIndex(struct dm_odm_t *pDM_Odm)
{
u8 index;
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
u32 Power_Index_REG[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a};
struct dm_priv *pdmpriv = &pHalData->dmpriv;
for (index = 0; index < 6; index++)
rtw_write8(Adapter, Power_Index_REG[index], pdmpriv->PowerIndex_backup[index]);
}
void odm_DynamicTxPower23aWritePowerIndex(struct dm_odm_t *pDM_Odm,
u8 Value)
{
u8 index;
u32 Power_Index_REG[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a};
for (index = 0; index < 6; index++)
ODM_Write1Byte(pDM_Odm, Power_Index_REG[index], Value);
}
void odm_DynamicTxPower23a(struct dm_odm_t *pDM_Odm)
{
}
void odm_DynamicTxPower23a_92C(struct dm_odm_t *pDM_Odm)
{
}
void odm_DynamicTxPower23a_92D(struct dm_odm_t *pDM_Odm)
{
}
/* 3 ============================================================ */
/* 3 RSSI Monitor */
/* 3 ============================================================ */
void odm_RSSIMonitorInit(struct dm_odm_t *pDM_Odm)
{
}
void odm_RSSIMonitorCheck23a(struct dm_odm_t *pDM_Odm)
{
/* For AP/ADSL use struct rtl8723a_priv * */
/* For CE/NIC use struct rtw_adapter * */
if (!(pDM_Odm->SupportAbility & ODM_BB_RSSI_MONITOR))
return;
/* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
/* at the same time. In the stage2/3, we need to prive universal interface and merge all */
/* HW dynamic mechanism. */
odm_RSSIMonitorCheck23aCE(pDM_Odm);
} /* odm_RSSIMonitorCheck23a */
void odm_RSSIMonitorCheck23aMP(struct dm_odm_t *pDM_Odm)
{
}
static void
FindMinimumRSSI(
struct rtw_adapter *pAdapter
)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
/* 1 1.Determine the minimum RSSI */
if ((!pDM_Odm->bLinked) &&
(pdmpriv->EntryMinUndecoratedSmoothedPWDB == 0))
pdmpriv->MinUndecoratedPWDBForDM = 0;
else
pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB;
}
void odm_RSSIMonitorCheck23aCE(struct dm_odm_t *pDM_Odm)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
int i;
int tmpEntryMaxPWDB = 0, tmpEntryMinPWDB = 0xff;
u8 sta_cnt = 0;
u32 PWDB_rssi[NUM_STA] = {0};/* 0~15]:MACID, [16~31]:PWDB_rssi */
struct sta_info *psta;
if (!pDM_Odm->bLinked)
return;
for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
psta = pDM_Odm->pODM_StaInfo[i];
if (IS_STA_VALID(psta)) {
if (psta->rssi_stat.UndecoratedSmoothedPWDB < tmpEntryMinPWDB)
tmpEntryMinPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
if (psta->rssi_stat.UndecoratedSmoothedPWDB > tmpEntryMaxPWDB)
tmpEntryMaxPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
if (psta->rssi_stat.UndecoratedSmoothedPWDB != (-1))
PWDB_rssi[sta_cnt++] = (psta->mac_id | (psta->rssi_stat.UndecoratedSmoothedPWDB<<16));
}
}
for (i = 0; i < sta_cnt; i++) {
if (PWDB_rssi[i] != (0)) {
if (pHalData->fw_ractrl) /* Report every sta's RSSI to FW */
rtl8723a_set_rssi_cmd(Adapter, (u8 *)&PWDB_rssi[i]);
}
}
if (tmpEntryMaxPWDB != 0) /* If associated entry is found */
pdmpriv->EntryMaxUndecoratedSmoothedPWDB = tmpEntryMaxPWDB;
else
pdmpriv->EntryMaxUndecoratedSmoothedPWDB = 0;
if (tmpEntryMinPWDB != 0xff) /* If associated entry is found */
pdmpriv->EntryMinUndecoratedSmoothedPWDB = tmpEntryMinPWDB;
else
pdmpriv->EntryMinUndecoratedSmoothedPWDB = 0;
FindMinimumRSSI(Adapter);/* get pdmpriv->MinUndecoratedPWDBForDM */
ODM_CmnInfoUpdate23a(&pHalData->odmpriv, ODM_CMNINFO_RSSI_MIN, pdmpriv->MinUndecoratedPWDBForDM);
}
void odm_RSSIMonitorCheck23aAP(struct dm_odm_t *pDM_Odm)
{
}
void ODM_InitAllTimers(struct dm_odm_t *pDM_Odm)
{
setup_timer(&pDM_Odm->DM_SWAT_Table.SwAntennaSwitchTimer,
odm_SwAntDivChkAntSwitchCallback23a, (unsigned long)pDM_Odm);
}
void ODM_CancelAllTimers(struct dm_odm_t *pDM_Odm)
{
del_timer_sync(&pDM_Odm->DM_SWAT_Table.SwAntennaSwitchTimer);
}
void ODM_ReleaseAllTimers(struct dm_odm_t *pDM_Odm)
{
ODM_ReleaseTimer(pDM_Odm, &pDM_Odm->DM_SWAT_Table.SwAntennaSwitchTimer);
}
/* endif */
/* 3 ============================================================ */
/* 3 Tx Power Tracking */
/* 3 ============================================================ */
void odm_TXPowerTrackingInit23a(struct dm_odm_t *pDM_Odm)
{
odm_TXPowerTrackingThermalMeterInit23a(pDM_Odm);
}
void odm_TXPowerTrackingThermalMeterInit23a(struct dm_odm_t *pDM_Odm)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
pdmpriv->bTXPowerTracking = true;
pdmpriv->TXPowercount = 0;
pdmpriv->bTXPowerTrackingInit = false;
pdmpriv->TxPowerTrackControl = true;
MSG_8723A("pdmpriv->TxPowerTrackControl = %d\n", pdmpriv->TxPowerTrackControl);
pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = true;
}
void ODM_TXPowerTrackingCheck23a(struct dm_odm_t *pDM_Odm)
{
/* For AP/ADSL use struct rtl8723a_priv * */
/* For CE/NIC use struct rtw_adapter * */
/* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
/* at the same time. In the stage2/3, we need to prive universal interface and merge all */
/* HW dynamic mechanism. */
odm_TXPowerTrackingCheckCE23a(pDM_Odm);
}
void odm_TXPowerTrackingCheckCE23a(struct dm_odm_t *pDM_Odm)
{
}
void odm_TXPowerTrackingCheckMP(struct dm_odm_t *pDM_Odm)
{
}
void odm_TXPowerTrackingCheckAP(struct dm_odm_t *pDM_Odm)
{
}
/* antenna mapping info */
/* 1: right-side antenna */
/* 2/0: left-side antenna */
/* PpDM_SWAT_Table->CCK_Ant1_Cnt /OFDM_Ant1_Cnt: for right-side antenna: Ant:1 RxDefaultAnt1 */
/* PpDM_SWAT_Table->CCK_Ant2_Cnt /OFDM_Ant2_Cnt: for left-side antenna: Ant:0 RxDefaultAnt2 */
/* We select left antenna as default antenna in initial process, modify it as needed */
/* */
/* 3 ============================================================ */
/* 3 SW Antenna Diversity */
/* 3 ============================================================ */
void odm_SwAntDivInit(struct dm_odm_t *pDM_Odm)
{
}
void ODM_SwAntDivChkPerPktRssi(struct dm_odm_t *pDM_Odm, u8 StationID, struct odm_phy_info *pPhyInfo)
{
}
void odm_SwAntDivChkAntSwitch(struct dm_odm_t *pDM_Odm, u8 Step)
{
}
void ODM_SwAntDivRestAfterLink(struct dm_odm_t *pDM_Odm)
{
}
void odm_SwAntDivChkAntSwitchCallback23a(unsigned long data)
{
}
/* 3 ============================================================ */
/* 3 SW Antenna Diversity */
/* 3 ============================================================ */
void odm_InitHybridAntDiv23a(struct dm_odm_t *pDM_Odm)
{
}
void odm_HwAntDiv23a(struct dm_odm_t *pDM_Odm)
{
}
/* EDCA Turbo */
void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false;
pDM_Odm->DM_EDCA_Table.bIsCurRDLState = false;
Adapter->recvpriv.bIsAnyNonBEPkts = false;
ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial VO PARAM: 0x%x\n", ODM_Read4Byte(pDM_Odm, ODM_EDCA_VO_PARAM)));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial VI PARAM: 0x%x\n", ODM_Read4Byte(pDM_Odm, ODM_EDCA_VI_PARAM)));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial BE PARAM: 0x%x\n", ODM_Read4Byte(pDM_Odm, ODM_EDCA_BE_PARAM)));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial BK PARAM: 0x%x\n", ODM_Read4Byte(pDM_Odm, ODM_EDCA_BK_PARAM)));
} /* ODM_InitEdcaTurbo */
void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm)
{
/* For AP/ADSL use struct rtl8723a_priv * */
/* For CE/NIC use struct rtw_adapter * */
/* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
/* at the same time. In the stage2/3, we need to prive universal interface and merge all */
/* HW dynamic mechanism. */
ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("odm_EdcaTurboCheck23a ========================>\n"));
if (!(pDM_Odm->SupportAbility & ODM_MAC_EDCA_TURBO))
return;
odm_EdcaTurboCheck23aCE23a(pDM_Odm);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("<======================== odm_EdcaTurboCheck23a\n"));
} /* odm_CheckEdcaTurbo */
void odm_EdcaTurboCheck23aCE23a(struct dm_odm_t *pDM_Odm)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
u32 trafficIndex;
u32 edca_param;
u64 cur_tx_bytes = 0;
u64 cur_rx_bytes = 0;
u8 bbtchange = false;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct xmit_priv *pxmitpriv = &Adapter->xmitpriv;
struct recv_priv *precvpriv = &Adapter->recvpriv;
struct registry_priv *pregpriv = &Adapter->registrypriv;
struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
if ((pregpriv->wifi_spec == 1))/* (pmlmeinfo->HT_enable == 0)) */
goto dm_CheckEdcaTurbo_EXIT;
if (pmlmeinfo->assoc_AP_vendor >= HT_IOT_PEER_MAX)
goto dm_CheckEdcaTurbo_EXIT;
#ifdef CONFIG_8723AU_BT_COEXIST
if (BT_DisableEDCATurbo(Adapter))
goto dm_CheckEdcaTurbo_EXIT;
#endif
/* Check if the status needs to be changed. */
if ((bbtchange) || (!precvpriv->bIsAnyNonBEPkts)) {
cur_tx_bytes = pxmitpriv->tx_bytes - pxmitpriv->last_tx_bytes;
cur_rx_bytes = precvpriv->rx_bytes - precvpriv->last_rx_bytes;
/* traffic, TX or RX */
if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK) ||
(pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS)) {
if (cur_tx_bytes > (cur_rx_bytes << 2)) {
/* Uplink TP is present. */
trafficIndex = UP_LINK;
} else { /* Balance TP is present. */
trafficIndex = DOWN_LINK;
}
} else {
if (cur_rx_bytes > (cur_tx_bytes << 2)) {
/* Downlink TP is present. */
trafficIndex = DOWN_LINK;
} else { /* Balance TP is present. */
trafficIndex = UP_LINK;
}
}
if ((pDM_Odm->DM_EDCA_Table.prv_traffic_idx != trafficIndex) ||
(!pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA)) {
if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_CISCO) &&
(pmlmeext->cur_wireless_mode & WIRELESS_11_24N))
edca_param = EDCAParam[pmlmeinfo->assoc_AP_vendor][trafficIndex];
else
edca_param = EDCAParam[HT_IOT_PEER_UNKNOWN][trafficIndex];
rtw_write32(Adapter, REG_EDCA_BE_PARAM, edca_param);
pDM_Odm->DM_EDCA_Table.prv_traffic_idx = trafficIndex;
}
pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = true;
} else {
/* Turn Off EDCA turbo here. */
/* Restore original EDCA according to the declaration of AP. */
if (pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA) {
rtw_write32(Adapter, REG_EDCA_BE_PARAM, pHalData->AcParam_BE);
pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false;
}
}
dm_CheckEdcaTurbo_EXIT:
/* Set variables for next time. */
precvpriv->bIsAnyNonBEPkts = false;
pxmitpriv->last_tx_bytes = pxmitpriv->tx_bytes;
precvpriv->last_rx_bytes = precvpriv->rx_bytes;
}
u32 GetPSDData(struct dm_odm_t *pDM_Odm, unsigned int point, u8 initial_gain_psd)
{
u32 psd_report;
/* Set DCO frequency index, offset = (40MHz/SamplePts)*point */
ODM_SetBBReg(pDM_Odm, 0x808, 0x3FF, point);
/* Start PSD calculation, Reg808[22]= 0->1 */
ODM_SetBBReg(pDM_Odm, 0x808, BIT22, 1);
/* Need to wait for HW PSD report */
udelay(30);
ODM_SetBBReg(pDM_Odm, 0x808, BIT22, 0);
/* Read PSD report, Reg8B4[15:0] */
psd_report = ODM_GetBBReg(pDM_Odm, 0x8B4, bMaskDWord) & 0x0000FFFF;
psd_report = (u32)(ConvertTo_dB23a(psd_report))+(u32)(initial_gain_psd-0x1c);
return psd_report;
}
u32
ConvertTo_dB23a(
u32 Value)
{
u8 i;
u8 j;
u32 dB;
Value = Value & 0xFFFF;
for (i = 0; i < 8; i++) {
if (Value <= dB_Invert_Table[i][11])
break;
}
if (i >= 8)
return 96; /* maximum 96 dB */
for (j = 0; j < 12; j++) {
if (Value <= dB_Invert_Table[i][j])
break;
}
dB = i*12 + j + 1;
return dB;
}
/* */
/* 2011/09/22 MH Add for 92D global spin lock utilization. */
/* */
void
odm_GlobalAdapterCheck(
void
)
{
} /* odm_GlobalAdapterCheck */
/* */
/* Description: */
/*Set Single/Dual Antenna default setting for products that do not do detection in advance. */
/* */
/* Added by Joseph, 2012.03.22 */
/* */
void ODM_SingleDualAntennaDefaultSetting(struct dm_odm_t *pDM_Odm)
{
struct sw_ant_sw *pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table;
pDM_SWAT_Table->ANTA_ON = true;
pDM_SWAT_Table->ANTB_ON = true;
}
/* 2 8723A ANT DETECT */
static void odm_PHY_SaveAFERegisters(
struct dm_odm_t *pDM_Odm,
u32 *AFEReg,
u32 *AFEBackup,
u32 RegisterNum
)
{
u32 i;
/* RTPRINT(FINIT, INIT_IQK, ("Save ADDA parameters.\n")); */
for (i = 0 ; i < RegisterNum ; i++)
AFEBackup[i] = ODM_GetBBReg(pDM_Odm, AFEReg[i], bMaskDWord);
}
static void odm_PHY_ReloadAFERegisters(struct dm_odm_t *pDM_Odm, u32 *AFEReg,
u32 *AFEBackup, u32 RegiesterNum)
{
u32 i;
for (i = 0 ; i < RegiesterNum; i++)
ODM_SetBBReg(pDM_Odm, AFEReg[i], bMaskDWord, AFEBackup[i]);
}
/* 2 8723A ANT DETECT */
/* Description: */
/* Implement IQK single tone for RF DPK loopback and BB PSD scanning. */
/* This function is cooperated with BB team Neil. */
bool ODM_SingleDualAntennaDetection(struct dm_odm_t *pDM_Odm, u8 mode)
{
struct sw_ant_sw *pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table;
u32 CurrentChannel, RfLoopReg;
u8 n;
u32 Reg88c, Regc08, Reg874, Regc50;
u8 initial_gain = 0x5a;
u32 PSD_report_tmp;
u32 AntA_report = 0x0, AntB_report = 0x0, AntO_report = 0x0;
bool bResult = true;
u32 AFE_Backup[16];
u32 AFE_REG_8723A[16] = {
rRx_Wait_CCA, rTx_CCK_RFON,
rTx_CCK_BBON, rTx_OFDM_RFON,
rTx_OFDM_BBON, rTx_To_Rx,
rTx_To_Tx, rRx_CCK,
rRx_OFDM, rRx_Wait_RIFS,
rRx_TO_Rx, rStandby,
rSleep, rPMPD_ANAEN,
rFPGA0_XCD_SwitchControl, rBlue_Tooth};
if (!(pDM_Odm->SupportICType & (ODM_RTL8723A)))
return bResult;
if (!(pDM_Odm->SupportAbility&ODM_BB_ANT_DIV))
return bResult;
/* 1 Backup Current RF/BB Settings */
CurrentChannel = ODM_GetRFReg(pDM_Odm, RF_PATH_A, ODM_CHANNEL, bRFRegOffsetMask);
RfLoopReg = ODM_GetRFReg(pDM_Odm, RF_PATH_A, 0x00, bRFRegOffsetMask);
ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, ODM_DPDT, Antenna_A); /* change to Antenna A */
/* Step 1: USE IQK to transmitter single tone */
udelay(10);
/* Store A Path Register 88c, c08, 874, c50 */
Reg88c = ODM_GetBBReg(pDM_Odm, rFPGA0_AnalogParameter4, bMaskDWord);
Regc08 = ODM_GetBBReg(pDM_Odm, rOFDM0_TRMuxPar, bMaskDWord);
Reg874 = ODM_GetBBReg(pDM_Odm, rFPGA0_XCD_RFInterfaceSW, bMaskDWord);
Regc50 = ODM_GetBBReg(pDM_Odm, rOFDM0_XAAGCCore1, bMaskDWord);
/* Store AFE Registers */
odm_PHY_SaveAFERegisters(pDM_Odm, AFE_REG_8723A, AFE_Backup, 16);
/* Set PSD 128 pts */
ODM_SetBBReg(pDM_Odm, rFPGA0_PSDFunction, BIT14|BIT15, 0x0); /* 128 pts */
/* To SET CH1 to do */
ODM_SetRFReg(pDM_Odm, RF_PATH_A, ODM_CHANNEL, bRFRegOffsetMask, 0x01); /* Channel 1 */
/* AFE all on step */
ODM_SetBBReg(pDM_Odm, rRx_Wait_CCA, bMaskDWord, 0x6FDB25A4);
ODM_SetBBReg(pDM_Odm, rTx_CCK_RFON, bMaskDWord, 0x6FDB25A4);
ODM_SetBBReg(pDM_Odm, rTx_CCK_BBON, bMaskDWord, 0x6FDB25A4);
ODM_SetBBReg(pDM_Odm, rTx_OFDM_RFON, bMaskDWord, 0x6FDB25A4);
ODM_SetBBReg(pDM_Odm, rTx_OFDM_BBON, bMaskDWord, 0x6FDB25A4);
ODM_SetBBReg(pDM_Odm, rTx_To_Rx, bMaskDWord, 0x6FDB25A4);
ODM_SetBBReg(pDM_Odm, rTx_To_Tx, bMaskDWord, 0x6FDB25A4);
ODM_SetBBReg(pDM_Odm, rRx_CCK, bMaskDWord, 0x6FDB25A4);
ODM_SetBBReg(pDM_Odm, rRx_OFDM, bMaskDWord, 0x6FDB25A4);
ODM_SetBBReg(pDM_Odm, rRx_Wait_RIFS, bMaskDWord, 0x6FDB25A4);
ODM_SetBBReg(pDM_Odm, rRx_TO_Rx, bMaskDWord, 0x6FDB25A4);
ODM_SetBBReg(pDM_Odm, rStandby, bMaskDWord, 0x6FDB25A4);
ODM_SetBBReg(pDM_Odm, rSleep, bMaskDWord, 0x6FDB25A4);
ODM_SetBBReg(pDM_Odm, rPMPD_ANAEN, bMaskDWord, 0x6FDB25A4);
ODM_SetBBReg(pDM_Odm, rFPGA0_XCD_SwitchControl, bMaskDWord, 0x6FDB25A4);
ODM_SetBBReg(pDM_Odm, rBlue_Tooth, bMaskDWord, 0x6FDB25A4);
/* 3 wire Disable */
ODM_SetBBReg(pDM_Odm, rFPGA0_AnalogParameter4, bMaskDWord, 0xCCF000C0);
/* BB IQK Setting */
ODM_SetBBReg(pDM_Odm, rOFDM0_TRMuxPar, bMaskDWord, 0x000800E4);
ODM_SetBBReg(pDM_Odm, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22208000);
/* IQK setting tone@ 4.34Mhz */
ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_A, bMaskDWord, 0x10008C1C);
ODM_SetBBReg(pDM_Odm, rTx_IQK, bMaskDWord, 0x01007c00);
/* Page B init */
ODM_SetBBReg(pDM_Odm, rConfig_AntA, bMaskDWord, 0x00080000);
ODM_SetBBReg(pDM_Odm, rConfig_AntA, bMaskDWord, 0x0f600000);
ODM_SetBBReg(pDM_Odm, rRx_IQK, bMaskDWord, 0x01004800);
ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_A, bMaskDWord, 0x10008c1f);
ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_A, bMaskDWord, 0x82150008);
ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_A, bMaskDWord, 0x28150008);
ODM_SetBBReg(pDM_Odm, rIQK_AGC_Rsp, bMaskDWord, 0x001028d0);
/* RF loop Setting */
ODM_SetRFReg(pDM_Odm, RF_PATH_A, 0x0, 0xFFFFF, 0x50008);
/* IQK Single tone start */
ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskDWord, 0x80800000);
ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
udelay(1000);
PSD_report_tmp = 0x0;
for (n = 0; n < 2; n++) {
PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain);
if (PSD_report_tmp > AntA_report)
AntA_report = PSD_report_tmp;
}
PSD_report_tmp = 0x0;
ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, 0x300, Antenna_B); /* change to Antenna B */
udelay(10);
for (n = 0; n < 2; n++) {
PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain);
if (PSD_report_tmp > AntB_report)
AntB_report = PSD_report_tmp;
}
/* change to open case */
ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, 0x300, 0); /* change to Ant A and B all open case */
udelay(10);
for (n = 0; n < 2; n++) {
PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain);
if (PSD_report_tmp > AntO_report)
AntO_report = PSD_report_tmp;
}
/* Close IQK Single Tone function */
ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskDWord, 0x00000000);
PSD_report_tmp = 0x0;
/* 1 Return to antanna A */
ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, 0x300, Antenna_A);
ODM_SetBBReg(pDM_Odm, rFPGA0_AnalogParameter4, bMaskDWord, Reg88c);
ODM_SetBBReg(pDM_Odm, rOFDM0_TRMuxPar, bMaskDWord, Regc08);
ODM_SetBBReg(pDM_Odm, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, Reg874);
ODM_SetBBReg(pDM_Odm, rOFDM0_XAAGCCore1, 0x7F, 0x40);
ODM_SetBBReg(pDM_Odm, rOFDM0_XAAGCCore1, bMaskDWord, Regc50);
ODM_SetRFReg(pDM_Odm, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, CurrentChannel);
ODM_SetRFReg(pDM_Odm, RF_PATH_A, 0x00, bRFRegOffsetMask, RfLoopReg);
/* Reload AFE Registers */
odm_PHY_ReloadAFERegisters(pDM_Odm, AFE_REG_8723A, AFE_Backup, 16);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("psd_report_A[%d]= %d \n", 2416, AntA_report));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("psd_report_B[%d]= %d \n", 2416, AntB_report));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("psd_report_O[%d]= %d \n", 2416, AntO_report));
/* 2 Test Ant B based on Ant A is ON */
if (mode == ANTTESTB) {
if (AntA_report >= 100) {
if (AntB_report > (AntA_report+1)) {
pDM_SWAT_Table->ANTB_ON = false;
ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Single Antenna A\n"));
} else {
pDM_SWAT_Table->ANTB_ON = true;
ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Dual Antenna is A and B\n"));
}
} else {
ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Need to check again\n"));
pDM_SWAT_Table->ANTB_ON = false; /* Set Antenna B off as default */
bResult = false;
}
} else if (mode == ANTTESTALL) {
/* 2 Test Ant A and B based on DPDT Open */
if ((AntO_report >= 100) & (AntO_report < 118)) {
if (AntA_report > (AntO_report+1)) {
pDM_SWAT_Table->ANTA_ON = false;
ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Ant A is OFF"));
} else {
pDM_SWAT_Table->ANTA_ON = true;
ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Ant A is ON"));
}
if (AntB_report > (AntO_report+2)) {
pDM_SWAT_Table->ANTB_ON = false;
ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Ant B is OFF"));
} else {
pDM_SWAT_Table->ANTB_ON = true;
ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Ant B is ON"));
}
}
} else {
ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Need to check again\n"));
pDM_SWAT_Table->ANTA_ON = true; /* Set Antenna A on as default */
pDM_SWAT_Table->ANTB_ON = false; /* Set Antenna B off as default */
bResult = false;
}
return bResult;
}
/* Justin: According to the current RRSI to adjust Response Frame TX power, 2012/11/05 */
void odm_dtc(struct dm_odm_t *pDM_Odm)
{
}
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
/* */
/* include files */
/* */
#include "odm_precomp.h"
#define READ_AND_CONFIG READ_AND_CONFIG_MP
#define READ_AND_CONFIG_MP(ic, txt) (ODM_ReadAndConfig##txt##ic(pDM_Odm))
#define READ_AND_CONFIG_TC(ic, txt) (ODM_ReadAndConfig_TC##txt##ic(pDM_Odm))
static u8 odm_QueryRxPwrPercentage(s8 AntPower)
{
if ((AntPower <= -100) || (AntPower >= 20))
return 0;
else if (AntPower >= 0)
return 100;
else
return 100 + AntPower;
}
static s32 odm_SignalScaleMapping_92CSeries(struct dm_odm_t *pDM_Odm, s32 CurrSig)
{
s32 RetSig = 0;
if ((pDM_Odm->SupportInterface == ODM_ITRF_USB) || (pDM_Odm->SupportInterface == ODM_ITRF_SDIO)) {
if (CurrSig >= 51 && CurrSig <= 100)
RetSig = 100;
else if (CurrSig >= 41 && CurrSig <= 50)
RetSig = 80 + ((CurrSig - 40)*2);
else if (CurrSig >= 31 && CurrSig <= 40)
RetSig = 66 + (CurrSig - 30);
else if (CurrSig >= 21 && CurrSig <= 30)
RetSig = 54 + (CurrSig - 20);
else if (CurrSig >= 10 && CurrSig <= 20)
RetSig = 42 + (((CurrSig - 10) * 2) / 3);
else if (CurrSig >= 5 && CurrSig <= 9)
RetSig = 22 + (((CurrSig - 5) * 3) / 2);
else if (CurrSig >= 1 && CurrSig <= 4)
RetSig = 6 + (((CurrSig - 1) * 3) / 2);
else
RetSig = CurrSig;
}
return RetSig;
}
static s32 odm_SignalScaleMapping(struct dm_odm_t *pDM_Odm, s32 CurrSig)
{
return odm_SignalScaleMapping_92CSeries(pDM_Odm, CurrSig);
}
static u8
odm_EVMdbToPercentage(
s8 Value
)
{
/* */
/* -33dB~0dB to 0%~99% */
/* */
s8 ret_val;
ret_val = Value;
if (ret_val >= 0)
ret_val = 0;
if (ret_val <= -33)
ret_val = -33;
ret_val = 0 - ret_val;
ret_val *= 3;
if (ret_val == 99)
ret_val = 100;
return ret_val;
}
static void odm_RxPhyStatus92CSeries_Parsing(struct dm_odm_t *pDM_Odm,
struct odm_phy_info *pPhyInfo,
u8 *pPhyStatus,
struct odm_packet_info *pPktinfo)
{
struct phy_status_rpt *pPhyStaRpt = (struct phy_status_rpt *)pPhyStatus;
u8 i, Max_spatial_stream;
s8 rx_pwr[4], rx_pwr_all = 0;
u8 EVM, PWDB_ALL = 0, PWDB_ALL_BT;
u8 RSSI, total_rssi = 0;
u8 isCCKrate = 0;
u8 rf_rx_num = 0;
u8 cck_highpwr = 0;
isCCKrate = (pPktinfo->Rate <= DESC92C_RATE11M) ? true : false;
pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = -1;
pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1;
if (isCCKrate) {
u8 report;
u8 cck_agc_rpt;
pDM_Odm->PhyDbgInfo.NumQryPhyStatusCCK++;
/* (1)Hardware does not provide RSSI for CCK */
/* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */
cck_highpwr = pDM_Odm->bCckHighPower;
cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a ;
/* The RSSI formula should be modified according to the gain table */
if (!cck_highpwr) {
report = (cck_agc_rpt & 0xc0)>>6;
switch (report) {
/* Modify the RF RNA gain value to -40, -20, -2, 14 by Jenyu's suggestion */
/* Note: different RF with the different RNA gain. */
case 0x3:
rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
break;
case 0x2:
rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
break;
case 0x1:
rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
break;
case 0x0:
rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
break;
}
} else {
report = (cck_agc_rpt & 0x60)>>5;
switch (report) {
case 0x3:
rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f)<<1) ;
break;
case 0x2:
rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f)<<1);
break;
case 0x1:
rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f)<<1) ;
break;
case 0x0:
rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f)<<1) ;
break;
}
}
PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all);
/* Modification for ext-LNA board */
if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) {
if ((cck_agc_rpt>>7) == 0) {
PWDB_ALL = (PWDB_ALL > 94) ? 100 : (PWDB_ALL+6);
} else {
if (PWDB_ALL > 38)
PWDB_ALL -= 16;
else
PWDB_ALL = (PWDB_ALL <= 16) ? (PWDB_ALL>>2) : (PWDB_ALL-12);
}
/* CCK modification */
if (PWDB_ALL > 25 && PWDB_ALL <= 60)
PWDB_ALL += 6;
} else { /* Modification for int-LNA board */
if (PWDB_ALL > 99)
PWDB_ALL -= 8;
else if (PWDB_ALL > 50 && PWDB_ALL <= 68)
PWDB_ALL += 4;
}
pPhyInfo->RxPWDBAll = PWDB_ALL;
pPhyInfo->BTRxRSSIPercentage = PWDB_ALL;
pPhyInfo->RecvSignalPower = rx_pwr_all;
/* (3) Get Signal Quality (EVM) */
if (pPktinfo->bPacketMatchBSSID) {
u8 SQ, SQ_rpt;
SQ_rpt = pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all;
if (SQ_rpt > 64)
SQ = 0;
else if (SQ_rpt < 20)
SQ = 100;
else
SQ = ((64-SQ_rpt) * 100) / 44;
pPhyInfo->SignalQuality = SQ;
pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = SQ;
pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1;
}
} else { /* is OFDM rate */
pDM_Odm->PhyDbgInfo.NumQryPhyStatusOFDM++;
/* (1)Get RSSI for HT rate */
for (i = RF_PATH_A; i < RF_PATH_MAX; i++) {
/* 2008/01/30 MH we will judge RF RX path now. */
if (pDM_Odm->RFPathRxEnable & BIT(i))
rf_rx_num++;
rx_pwr[i] = ((pPhyStaRpt->path_agc[i].gain & 0x3F)*2) - 110;
pPhyInfo->RxPwr[i] = rx_pwr[i];
/* Translate DBM to percentage. */
RSSI = odm_QueryRxPwrPercentage(rx_pwr[i]);
total_rssi += RSSI;
/* Modification for ext-LNA board */
if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) {
if ((pPhyStaRpt->path_agc[i].trsw) == 1)
RSSI = (RSSI > 94) ? 100 : (RSSI+6);
else
RSSI = (RSSI <= 16) ? (RSSI>>3) : (RSSI-16);
if ((RSSI <= 34) && (RSSI >= 4))
RSSI -= 4;
}
pPhyInfo->RxMIMOSignalStrength[i] = (u8) RSSI;
/* Get Rx snr value in DB */
pPhyInfo->RxSNR[i] = pDM_Odm->PhyDbgInfo.RxSNRdB[i] = (s32)(pPhyStaRpt->path_rxsnr[i]/2);
}
/* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */
rx_pwr_all = (((pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all) >> 1) & 0x7f)-110;
PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all);
PWDB_ALL_BT = PWDB_ALL;
pPhyInfo->RxPWDBAll = PWDB_ALL;
pPhyInfo->BTRxRSSIPercentage = PWDB_ALL_BT;
pPhyInfo->RxPower = rx_pwr_all;
pPhyInfo->RecvSignalPower = rx_pwr_all;
/* (3)EVM of HT rate */
if (pPktinfo->Rate >= DESC92C_RATEMCS8 && pPktinfo->Rate <= DESC92C_RATEMCS15)
Max_spatial_stream = 2; /* both spatial stream make sense */
else
Max_spatial_stream = 1; /* only spatial stream 1 makes sense */
for (i = 0; i < Max_spatial_stream; i++) {
/* Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment */
/* fill most significant bit to "zero" when doing shifting operation which may change a negative */
/* value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore. */
EVM = odm_EVMdbToPercentage((pPhyStaRpt->stream_rxevm[i])); /* dbm */
if (pPktinfo->bPacketMatchBSSID) {
if (i == RF_PATH_A) {
/* Fill value in RFD, Get the first spatial stream only */
pPhyInfo->SignalQuality = (u8)(EVM & 0xff);
}
pPhyInfo->RxMIMOSignalQuality[i] = (u8)(EVM & 0xff);
}
}
}
/* UI BSS List signal strength(in percentage), make it good looking, from 0~100. */
/* It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp(). */
if (isCCKrate) {
pPhyInfo->SignalStrength = (u8)(odm_SignalScaleMapping(pDM_Odm, PWDB_ALL));/* PWDB_ALL; */
} else {
if (rf_rx_num != 0)
pPhyInfo->SignalStrength = (u8)(odm_SignalScaleMapping(pDM_Odm, total_rssi /= rf_rx_num));
}
}
void odm_Init_RSSIForDM23a(struct dm_odm_t *pDM_Odm)
{
}
static void odm_Process_RSSIForDM(struct dm_odm_t *pDM_Odm,
struct odm_phy_info *pPhyInfo,
struct odm_packet_info *pPktinfo)
{
s32 UndecoratedSmoothedPWDB, UndecoratedSmoothedCCK;
s32 UndecoratedSmoothedOFDM, RSSI_Ave;
u8 isCCKrate = 0;
u8 RSSI_max, RSSI_min, i;
u32 OFDM_pkt = 0;
u32 Weighting = 0;
struct sta_info *pEntry;
if (pPktinfo->StationID == 0xFF)
return;
pEntry = pDM_Odm->pODM_StaInfo[pPktinfo->StationID];
if (!IS_STA_VALID(pEntry))
return;
if ((!pPktinfo->bPacketMatchBSSID))
return;
isCCKrate = (pPktinfo->Rate <= DESC92C_RATE11M) ? true : false;
/* Smart Antenna Debug Message------------------*/
UndecoratedSmoothedCCK = pEntry->rssi_stat.UndecoratedSmoothedCCK;
UndecoratedSmoothedOFDM = pEntry->rssi_stat.UndecoratedSmoothedOFDM;
UndecoratedSmoothedPWDB = pEntry->rssi_stat.UndecoratedSmoothedPWDB;
if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon) {
if (!isCCKrate) { /* ofdm rate */
if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_B] == 0) {
RSSI_Ave = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
} else {
if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_A] > pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]) {
RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B];
} else {
RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B];
RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
}
if ((RSSI_max - RSSI_min) < 3)
RSSI_Ave = RSSI_max;
else if ((RSSI_max - RSSI_min) < 6)
RSSI_Ave = RSSI_max - 1;
else if ((RSSI_max - RSSI_min) < 10)
RSSI_Ave = RSSI_max - 2;
else
RSSI_Ave = RSSI_max - 3;
}
/* 1 Process OFDM RSSI */
if (UndecoratedSmoothedOFDM <= 0) {
/* initialize */
UndecoratedSmoothedOFDM = pPhyInfo->RxPWDBAll;
} else {
if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedOFDM) {
UndecoratedSmoothedOFDM =
(((UndecoratedSmoothedOFDM)*(Rx_Smooth_Factor-1)) +
(RSSI_Ave)) / (Rx_Smooth_Factor);
UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM + 1;
} else {
UndecoratedSmoothedOFDM =
(((UndecoratedSmoothedOFDM)*(Rx_Smooth_Factor-1)) +
(RSSI_Ave)) / (Rx_Smooth_Factor);
}
}
pEntry->rssi_stat.PacketMap = (pEntry->rssi_stat.PacketMap<<1) | BIT0;
} else {
RSSI_Ave = pPhyInfo->RxPWDBAll;
/* 1 Process CCK RSSI */
if (UndecoratedSmoothedCCK <= 0) {
/* initialize */
UndecoratedSmoothedCCK = pPhyInfo->RxPWDBAll;
} else {
if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedCCK) {
UndecoratedSmoothedCCK =
(((UndecoratedSmoothedCCK)*(Rx_Smooth_Factor-1)) +
(pPhyInfo->RxPWDBAll)) / (Rx_Smooth_Factor);
UndecoratedSmoothedCCK = UndecoratedSmoothedCCK + 1;
} else {
UndecoratedSmoothedCCK =
(((UndecoratedSmoothedCCK)*(Rx_Smooth_Factor-1)) +
(pPhyInfo->RxPWDBAll)) / (Rx_Smooth_Factor);
}
}
pEntry->rssi_stat.PacketMap = pEntry->rssi_stat.PacketMap<<1;
}
/* 2011.07.28 LukeLee: modified to prevent unstable CCK RSSI */
if (pEntry->rssi_stat.ValidBit >= 64)
pEntry->rssi_stat.ValidBit = 64;
else
pEntry->rssi_stat.ValidBit++;
for (i = 0; i < pEntry->rssi_stat.ValidBit; i++)
OFDM_pkt += (u8)(pEntry->rssi_stat.PacketMap>>i)&BIT0;
if (pEntry->rssi_stat.ValidBit == 64) {
Weighting = ((OFDM_pkt<<4) > 64)?64:(OFDM_pkt<<4);
UndecoratedSmoothedPWDB = (Weighting*UndecoratedSmoothedOFDM+(64-Weighting)*UndecoratedSmoothedCCK)>>6;
} else {
if (pEntry->rssi_stat.ValidBit != 0)
UndecoratedSmoothedPWDB = (OFDM_pkt*UndecoratedSmoothedOFDM+(pEntry->rssi_stat.ValidBit-OFDM_pkt)*UndecoratedSmoothedCCK)/pEntry->rssi_stat.ValidBit;
else
UndecoratedSmoothedPWDB = 0;
}
pEntry->rssi_stat.UndecoratedSmoothedCCK = UndecoratedSmoothedCCK;
pEntry->rssi_stat.UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM;
pEntry->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB;
}
}
/* Endianness before calling this API */
static void ODM_PhyStatusQuery23a_92CSeries(struct dm_odm_t *pDM_Odm,
struct odm_phy_info *pPhyInfo,
u8 *pPhyStatus,
struct odm_packet_info *pPktinfo)
{
odm_RxPhyStatus92CSeries_Parsing(pDM_Odm, pPhyInfo,
pPhyStatus, pPktinfo);
if (pDM_Odm->RSSI_test) {
/* Select the packets to do RSSI checking for antenna switching. */
if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon)
ODM_SwAntDivChkPerPktRssi(pDM_Odm, pPktinfo->StationID, pPhyInfo);
} else {
odm_Process_RSSIForDM(pDM_Odm, pPhyInfo, pPktinfo);
}
}
void ODM_PhyStatusQuery23a(struct dm_odm_t *pDM_Odm, struct odm_phy_info *pPhyInfo,
u8 *pPhyStatus, struct odm_packet_info *pPktinfo)
{
ODM_PhyStatusQuery23a_92CSeries(pDM_Odm, pPhyInfo, pPhyStatus, pPktinfo);
}
/* For future use. */
void ODM_MacStatusQuery23a(struct dm_odm_t *pDM_Odm, u8 *pMacStatus, u8 MacID,
bool bPacketMatchBSSID, bool bPacketToSelf,
bool bPacketBeacon)
{
/* 2011/10/19 Driver team will handle in the future. */
}
enum hal_status
ODM_ConfigRFWithHeaderFile23a(
struct dm_odm_t *pDM_Odm,
enum RF_RADIO_PATH Content,
enum RF_RADIO_PATH eRFPath
)
{
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
("===>ODM_ConfigRFWithHeaderFile23a\n"));
if (pDM_Odm->SupportICType == ODM_RTL8723A) {
if (eRFPath == RF_PATH_A)
READ_AND_CONFIG_MP(8723A, _RadioA_1T_);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
(" ===> ODM_ConfigRFWithHeaderFile23a() Radio_A:Rtl8723RadioA_1TArray\n"));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
(" ===> ODM_ConfigRFWithHeaderFile23a() Radio_B:Rtl8723RadioB_1TArray\n"));
}
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_TRACE,
("ODM_ConfigRFWithHeaderFile23a: Radio No %x\n", eRFPath));
return HAL_STATUS_SUCCESS;
}
enum hal_status
ODM_ConfigBBWithHeaderFile23a(
struct dm_odm_t *pDM_Odm,
enum odm_bb_config_type ConfigType
)
{
if (pDM_Odm->SupportICType == ODM_RTL8723A) {
if (ConfigType == CONFIG_BB_PHY_REG)
READ_AND_CONFIG_MP(8723A, _PHY_REG_1T_);
else if (ConfigType == CONFIG_BB_AGC_TAB)
READ_AND_CONFIG_MP(8723A, _AGC_TAB_1T_);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
(" ===> phy_ConfigBBWithHeaderFile() phy:Rtl8723AGCTAB_1TArray\n"));
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
(" ===> phy_ConfigBBWithHeaderFile() agc:Rtl8723PHY_REG_1TArray\n"));
}
return HAL_STATUS_SUCCESS;
}
enum hal_status
ODM_ConfigMACWithHeaderFile23a(
struct dm_odm_t *pDM_Odm
)
{
u8 result = HAL_STATUS_SUCCESS;
if (pDM_Odm->SupportICType == ODM_RTL8723A)
READ_AND_CONFIG_MP(8723A, _MAC_REG_);
return result;
}
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#include "odm_precomp.h"
void
odm_ConfigRFReg_8723A(
struct dm_odm_t *pDM_Odm,
u32 Addr,
u32 Data,
enum RF_RADIO_PATH RF_PATH,
u32 RegAddr
)
{
if (Addr == 0xfe) {
msleep(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 {
ODM_SetRFReg(pDM_Odm, RF_PATH, RegAddr, bRFRegOffsetMask, Data);
/* Add 1us delay between BB/RF register setting. */
udelay(1);
}
}
void odm_ConfigRF_RadioA_8723A(struct dm_odm_t *pDM_Odm,
u32 Addr,
u32 Data
)
{
u32 content = 0x1000; /* RF_Content: radioa_txt */
u32 maskforPhySet = (u32)(content&0xE000);
odm_ConfigRFReg_8723A(pDM_Odm, Addr, Data, RF_PATH_A,
Addr|maskforPhySet);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
("===> ODM_ConfigRFWithHeaderFile23a: [RadioA] %08X %08X\n",
Addr, Data));
}
void odm_ConfigRF_RadioB_8723A(struct dm_odm_t *pDM_Odm,
u32 Addr,
u32 Data
)
{
u32 content = 0x1001; /* RF_Content: radiob_txt */
u32 maskforPhySet = (u32)(content&0xE000);
odm_ConfigRFReg_8723A(pDM_Odm, Addr, Data, RF_PATH_B,
Addr|maskforPhySet);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
("===> ODM_ConfigRFWithHeaderFile23a: [RadioB] %08X %08X\n",
Addr, Data));
}
void odm_ConfigMAC_8723A(struct dm_odm_t *pDM_Odm,
u32 Addr,
u8 Data
)
{
ODM_Write1Byte(pDM_Odm, Addr, Data);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
("===> ODM_ConfigMACWithHeaderFile23a: [MAC_REG] %08X %08X\n",
Addr, Data));
}
void
odm_ConfigBB_AGC_8723A(
struct dm_odm_t *pDM_Odm,
u32 Addr,
u32 Bitmask,
u32 Data
)
{
ODM_SetBBReg(pDM_Odm, Addr, Bitmask, Data);
/* Add 1us delay between BB/RF register setting. */
udelay(1);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
("===> ODM_ConfigBBWithHeaderFile23a: [AGC_TAB] %08X %08X\n",
Addr, Data));
}
void
odm_ConfigBB_PHY_REG_PG_8723A(
struct dm_odm_t *pDM_Odm,
u32 Addr,
u32 Bitmask,
u32 Data
)
{
if (Addr == 0xfe)
msleep(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);
/* TODO: ODM_StorePwrIndexDiffRateOffset(...) */
/* storePwrIndexDiffRateOffset(Adapter, Addr, Bitmask, Data); */
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
("===> ODM_ConfigBBWithHeaderFile23a: [PHY_REG] %08X %08X %08X\n",
Addr, Bitmask, Data));
}
void
odm_ConfigBB_PHY_8723A(
struct dm_odm_t *pDM_Odm,
u32 Addr,
u32 Bitmask,
u32 Data
)
{
if (Addr == 0xfe)
msleep(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 if (Addr == 0xa24)
pDM_Odm->RFCalibrateInfo.RegA24 = Data;
ODM_SetBBReg(pDM_Odm, Addr, Bitmask, Data);
/* Add 1us delay between BB/RF register setting. */
udelay(1);
ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
("===> ODM_ConfigBBWithHeaderFile23a: [PHY_REG] %08X %08X\n",
Addr, Data));
}
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#include "odm_precomp.h"
void ODM_InitDebugSetting23a(struct dm_odm_t *pDM_Odm)
{
pDM_Odm->DebugLevel = ODM_DBG_TRACE;
pDM_Odm->DebugComponents = 0;
}
u32 GlobalDebugLevel23A;
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
/* */
/* include files */
/* */
#include "odm_precomp.h"
/* */
/* ODM IO Relative API. */
/* */
u8 ODM_Read1Byte(struct dm_odm_t *pDM_Odm,
u32 RegAddr
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
return rtw_read8(Adapter, RegAddr);
}
u16 ODM_Read2Byte(struct dm_odm_t *pDM_Odm,
u32 RegAddr
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
return rtw_read16(Adapter, RegAddr);
}
u32 ODM_Read4Byte(struct dm_odm_t *pDM_Odm,
u32 RegAddr
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
return rtw_read32(Adapter, RegAddr);
}
void ODM_Write1Byte(
struct dm_odm_t *pDM_Odm,
u32 RegAddr,
u8 Data
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
rtw_write8(Adapter, RegAddr, Data);
}
void ODM_Write2Byte(
struct dm_odm_t *pDM_Odm,
u32 RegAddr,
u16 Data
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
rtw_write16(Adapter, RegAddr, Data);
}
void ODM_Write4Byte(
struct dm_odm_t *pDM_Odm,
u32 RegAddr,
u32 Data
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
rtw_write32(Adapter, RegAddr, Data);
}
void ODM_SetMACReg(
struct dm_odm_t *pDM_Odm,
u32 RegAddr,
u32 BitMask,
u32 Data
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
PHY_SetBBReg(Adapter, RegAddr, BitMask, Data);
}
u32 ODM_GetMACReg(
struct dm_odm_t *pDM_Odm,
u32 RegAddr,
u32 BitMask
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
return PHY_QueryBBReg(Adapter, RegAddr, BitMask);
}
void ODM_SetBBReg(
struct dm_odm_t *pDM_Odm,
u32 RegAddr,
u32 BitMask,
u32 Data
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
PHY_SetBBReg(Adapter, RegAddr, BitMask, Data);
}
u32 ODM_GetBBReg(
struct dm_odm_t *pDM_Odm,
u32 RegAddr,
u32 BitMask
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
return PHY_QueryBBReg(Adapter, RegAddr, BitMask);
}
void ODM_SetRFReg(
struct dm_odm_t *pDM_Odm,
enum RF_RADIO_PATH eRFPath,
u32 RegAddr,
u32 BitMask,
u32 Data
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
PHY_SetRFReg(Adapter, eRFPath, RegAddr, BitMask, Data);
}
u32 ODM_GetRFReg(
struct dm_odm_t *pDM_Odm,
enum RF_RADIO_PATH eRFPath,
u32 RegAddr,
u32 BitMask
)
{
struct rtw_adapter *Adapter = pDM_Odm->Adapter;
return PHY_QueryRFReg(Adapter, eRFPath, RegAddr, BitMask);
}
/* */
/* ODM Memory relative API. */
/* */
void ODM_AllocateMemory(
struct dm_odm_t *pDM_Odm,
void **pPtr,
u32 length
)
{
*pPtr = rtw_zvmalloc(length);
}
/* length could be ignored, used to detect memory leakage. */
void ODM_FreeMemory(
struct dm_odm_t *pDM_Odm,
void *pPtr,
u32 length
)
{
rtw_vmfree(pPtr, length);
}
/* */
/* ODM MISC relative API. */
/* */
void
ODM_AcquireSpinLock(
struct dm_odm_t *pDM_Odm,
enum rt_spinlock_type type
)
{
}
void ODM_ReleaseSpinLock(
struct dm_odm_t *pDM_Odm,
enum rt_spinlock_type type
)
{
}
/* */
/* Work item relative API. FOr MP driver only~! */
/* */
void ODM_InitializeWorkItem(
struct dm_odm_t *pDM_Odm,
void *pRtWorkItem,
RT_WORKITEM_CALL_BACK RtWorkItemCallback,
void *pContext,
const char *szID
)
{
}
/* */
/* ODM Timer relative API. */
/* */
void ODM_SetTimer(struct dm_odm_t *pDM_Odm, struct timer_list *pTimer, u32 msDelay)
{
mod_timer(pTimer, jiffies + msecs_to_jiffies(msDelay)); /* ms */
}
void ODM_ReleaseTimer(struct dm_odm_t *pDM_Odm, struct timer_list *pTimer)
{
}
/* */
/* ODM FW relative API. */
/* */
u32 ODM_FillH2CCmd(
u8 *pH2CBuffer,
u32 H2CBufferLen,
u32 CmdNum,
u32 *pElementID,
u32 *pCmdLen,
u8 **pCmbBuffer,
u8 *CmdStartSeq
)
{
return true;
}
This source diff could not be displayed because it is too large. You can view the blob instead.
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#define _RTL8723A_CMD_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <recv_osdep.h>
#include <cmd_osdep.h>
#include <mlme_osdep.h>
#include <rtw_ioctl_set.h>
#include <rtl8723a_hal.h>
#define RTL92C_MAX_H2C_BOX_NUMS 4
#define RTL92C_MAX_CMD_LEN 5
#define MESSAGE_BOX_SIZE 4
#define EX_MESSAGE_BOX_SIZE 2
static u8 _is_fw_read_cmd_down(struct rtw_adapter *padapter, u8 msgbox_num)
{
u8 read_down = false;
int retry_cnts = 100;
u8 valid;
do {
valid = rtw_read8(padapter, REG_HMETFR) & BIT(msgbox_num);
if (0 == valid)
read_down = true;
} while ((!read_down) && (retry_cnts--));
return read_down;
}
/*****************************************
* H2C Msg format :
*| 31 - 8 |7 | 6 - 0 |
*| h2c_msg |Ext_bit |CMD_ID |
*
******************************************/
s32 FillH2CCmd(struct rtw_adapter *padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer)
{
u8 bcmd_down = false;
s32 retry_cnts = 100;
u8 h2c_box_num;
u32 msgbox_addr;
u32 msgbox_ex_addr;
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
u32 h2c_cmd = 0;
u16 h2c_cmd_ex = 0;
s32 ret = _FAIL;
padapter = GET_PRIMARY_ADAPTER(padapter);
pHalData = GET_HAL_DATA(padapter);
mutex_lock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex);
if (!pCmdBuffer)
goto exit;
if (CmdLen > RTL92C_MAX_CMD_LEN)
goto exit;
if (padapter->bSurpriseRemoved == true)
goto exit;
/* pay attention to if race condition happened in H2C cmd setting. */
do {
h2c_box_num = pHalData->LastHMEBoxNum;
if (!_is_fw_read_cmd_down(padapter, h2c_box_num)) {
DBG_8723A(" fw read cmd failed...\n");
goto exit;
}
if (CmdLen <= 3) {
memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, CmdLen);
} else {
memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer, EX_MESSAGE_BOX_SIZE);
memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer+2, (CmdLen-EX_MESSAGE_BOX_SIZE));
*(u8 *)(&h2c_cmd) |= BIT(7);
}
*(u8 *)(&h2c_cmd) |= ElementID;
if (h2c_cmd & BIT(7)) {
msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num * EX_MESSAGE_BOX_SIZE);
h2c_cmd_ex = le16_to_cpu(h2c_cmd_ex);
rtw_write16(padapter, msgbox_ex_addr, h2c_cmd_ex);
}
msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * MESSAGE_BOX_SIZE);
h2c_cmd = le32_to_cpu(h2c_cmd);
rtw_write32(padapter, msgbox_addr, h2c_cmd);
bcmd_down = true;
pHalData->LastHMEBoxNum = (h2c_box_num+1) % RTL92C_MAX_H2C_BOX_NUMS;
} while ((!bcmd_down) && (retry_cnts--));
ret = _SUCCESS;
exit:
mutex_unlock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex);
return ret;
}
u8 rtl8723a_set_rssi_cmd(struct rtw_adapter *padapter, u8 *param)
{
u8 res = _SUCCESS;
*((u32 *)param) = cpu_to_le32(*((u32 *)param));
FillH2CCmd(padapter, RSSI_SETTING_EID, 3, param);
return res;
}
u8 rtl8723a_set_raid_cmd(struct rtw_adapter *padapter, u32 mask, u8 arg)
{
u8 buf[5];
u8 res = _SUCCESS;
memset(buf, 0, 5);
mask = cpu_to_le32(mask);
memcpy(buf, &mask, 4);
buf[4] = arg;
FillH2CCmd(padapter, MACID_CONFIG_EID, 5, buf);
return res;
}
/* bitmap[0:27] = tx_rate_bitmap */
/* bitmap[28:31]= Rate Adaptive id */
/* arg[0:4] = macid */
/* arg[5] = Short GI */
void rtl8723a_add_rateatid(struct rtw_adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
u8 macid = arg&0x1f;
u8 raid = (bitmap>>28) & 0x0f;
bitmap &= 0x0fffffff;
if (rssi_level != DM_RATR_STA_INIT)
bitmap = ODM_Get_Rate_Bitmap23a(&pHalData->odmpriv, macid, bitmap, rssi_level);
bitmap |= ((raid<<28)&0xf0000000);
if (pHalData->fw_ractrl == true) {
rtl8723a_set_raid_cmd(pAdapter, bitmap, arg);
} else {
u8 init_rate, shortGIrate = false;
init_rate = get_highest_rate_idx23a(bitmap&0x0fffffff)&0x3f;
shortGIrate = (arg&BIT(5)) ? true:false;
if (shortGIrate == true)
init_rate |= BIT(6);
rtw_write8(pAdapter, (REG_INIDATA_RATE_SEL+macid), (u8)init_rate);
}
}
void rtl8723a_set_FwPwrMode_cmd(struct rtw_adapter *padapter, u8 Mode)
{
struct setpwrmode_parm H2CSetPwrMode;
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
DBG_8723A("%s: Mode =%d SmartPS =%d UAPSD =%d BcnMode = 0x%02x\n", __FUNCTION__,
Mode, pwrpriv->smart_ps, padapter->registrypriv.uapsd_enable, pwrpriv->bcn_ant_mode);
/* Forece leave RF low power mode for 1T1R to
prevent conficting setting in Fw power */
/* saving sequence. 2010.06.07. Added by tynli.
Suggested by SD3 yschang. */
if ((Mode != PS_MODE_ACTIVE) &&
(!IS_92C_SERIAL(pHalData->VersionID))) {
ODM_RF_Saving23a(&pHalData->odmpriv, true);
}
H2CSetPwrMode.Mode = Mode;
H2CSetPwrMode.SmartPS = pwrpriv->smart_ps;
H2CSetPwrMode.AwakeInterval = 1;
H2CSetPwrMode.bAllQueueUAPSD = padapter->registrypriv.uapsd_enable;
H2CSetPwrMode.BcnAntMode = pwrpriv->bcn_ant_mode;
FillH2CCmd(padapter, SET_PWRMODE_EID, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode);
}
static void ConstructBeacon(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength)
{
struct ieee80211_hdr *pwlanhdr;
u16 *fctrl;
u32 rate_len, pktlen;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
/* DBG_8723A("%s\n", __FUNCTION__); */
pwlanhdr = (struct ieee80211_hdr *)pframe;
fctrl = &pwlanhdr->frame_control;
*(fctrl) = 0;
memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
memcpy(pwlanhdr->addr3, get_my_bssid23a(cur_network), ETH_ALEN);
SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
/* pmlmeext->mgnt_seq++; */
SetFrameSubType(pframe, WIFI_BEACON);
pframe += sizeof(struct ieee80211_hdr_3addr);
pktlen = sizeof (struct ieee80211_hdr_3addr);
/* timestamp will be inserted by hardware */
pframe += 8;
pktlen += 8;
/* beacon interval: 2 bytes */
memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval23a_from_ie(cur_network->IEs)), 2);
pframe += 2;
pktlen += 2;
/* capability info: 2 bytes */
memcpy(pframe, (unsigned char *)(rtw_get_capability23a_from_ie(cur_network->IEs)), 2);
pframe += 2;
pktlen += 2;
if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
/* DBG_8723A("ie len =%d\n", cur_network->IELength); */
pktlen += cur_network->IELength - sizeof(struct ndis_802_11_fixed_ies);
memcpy(pframe, cur_network->IEs+sizeof(struct ndis_802_11_fixed_ies), pktlen);
goto _ConstructBeacon;
}
/* below for ad-hoc mode */
/* SSID */
pframe = rtw_set_ie23a(pframe, _SSID_IE_, cur_network->Ssid.ssid_len,
cur_network->Ssid.ssid, &pktlen);
/* supported rates... */
rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ?
8 : rate_len), cur_network->SupportedRates, &pktlen);
/* DS parameter set */
pframe = rtw_set_ie23a(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pktlen);
if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
u32 ATIMWindow;
/* IBSS Parameter Set... */
/* ATIMWindow = cur->Configuration.ATIMWindow; */
ATIMWindow = 0;
pframe = rtw_set_ie23a(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
}
/* todo: ERP IE */
/* EXTERNDED SUPPORTED RATE */
if (rate_len > 8)
pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
/* todo:HT for adhoc */
_ConstructBeacon:
if ((pktlen + TXDESC_SIZE) > 512) {
DBG_8723A("beacon frame too large\n");
return;
}
*pLength = pktlen;
/* DBG_8723A("%s bcn_sz =%d\n", __FUNCTION__, pktlen); */
}
static void ConstructPSPoll(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength)
{
struct ieee80211_hdr *pwlanhdr;
u16 *fctrl;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
pwlanhdr = (struct ieee80211_hdr *)pframe;
/* Frame control. */
fctrl = &pwlanhdr->frame_control;
*(fctrl) = 0;
SetPwrMgt(fctrl);
SetFrameSubType(pframe, WIFI_PSPOLL);
/* AID. */
SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
/* BSSID. */
memcpy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
/* TA. */
memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
*pLength = 16;
}
static void ConstructNullFunctionData(
struct rtw_adapter *padapter,
u8 *pframe,
u32 *pLength,
u8 *StaAddr,
u8 bQoS,
u8 AC,
u8 bEosp,
u8 bForcePowerSave)
{
struct ieee80211_hdr *pwlanhdr;
u16 *fctrl;
u32 pktlen;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct wlan_network *cur_network = &pmlmepriv->cur_network;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
pwlanhdr = (struct ieee80211_hdr *)pframe;
fctrl = &pwlanhdr->frame_control;
*(fctrl) = 0;
if (bForcePowerSave)
SetPwrMgt(fctrl);
switch (cur_network->network.InfrastructureMode) {
case Ndis802_11Infrastructure:
SetToDs(fctrl);
memcpy(pwlanhdr->addr1,
get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv),
ETH_ALEN);
memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
break;
case Ndis802_11APMode:
SetFrDs(fctrl);
memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
memcpy(pwlanhdr->addr2,
get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv),
ETH_ALEN);
break;
case Ndis802_11IBSS:
default:
memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
memcpy(pwlanhdr->addr3,
get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
break;
}
SetSeqNum(pwlanhdr, 0);
if (bQoS == true) {
struct ieee80211_qos_hdr *pwlanqoshdr;
SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe;
SetPriority(&pwlanqoshdr->qos_ctrl, AC);
SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp);
pktlen = sizeof(struct ieee80211_qos_hdr);
} else {
SetFrameSubType(pframe, WIFI_DATA_NULL);
pktlen = sizeof(struct ieee80211_hdr_3addr);
}
*pLength = pktlen;
}
static void ConstructProbeRsp(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength, u8 *StaAddr, bool bHideSSID)
{
struct ieee80211_hdr *pwlanhdr;
u16 *fctrl;
u8 *mac, *bssid;
u32 pktlen;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
/* DBG_8723A("%s\n", __FUNCTION__); */
pwlanhdr = (struct ieee80211_hdr *)pframe;
mac = myid(&padapter->eeprompriv);
bssid = cur_network->MacAddress;
fctrl = &pwlanhdr->frame_control;
*(fctrl) = 0;
memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
SetSeqNum(pwlanhdr, 0);
SetFrameSubType(fctrl, WIFI_PROBERSP);
pktlen = sizeof(struct ieee80211_hdr_3addr);
pframe += pktlen;
if (cur_network->IELength > MAX_IE_SZ)
return;
memcpy(pframe, cur_network->IEs, cur_network->IELength);
pframe += cur_network->IELength;
pktlen += cur_network->IELength;
*pLength = pktlen;
}
/* To check if reserved page content is destroyed by beacon beacuse beacon is too large. */
void CheckFwRsvdPageContent23a(struct rtw_adapter *Adapter)
{
}
/* */
/* Description: Fill the reserved packets that FW will use to RSVD page. */
/* Now we just send 4 types packet to rsvd page. */
/* (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp. */
/* Input: */
/* bDLFinished - false: At the first time we will send all the packets as a large packet to Hw, */
/* so we need to set the packet length to total lengh. */
/* true: At the second time, we should send the first packet (default:beacon) */
/* to Hw again and set the lengh in descriptor to the real beacon lengh. */
/* 2009.10.15 by tynli. */
static void SetFwRsvdPagePkt(struct rtw_adapter *padapter, bool bDLFinished)
{
struct hal_data_8723a *pHalData;
struct xmit_frame *pmgntframe;
struct pkt_attrib *pattrib;
struct xmit_priv *pxmitpriv;
struct mlme_ext_priv *pmlmeext;
struct mlme_ext_info *pmlmeinfo;
u32 BeaconLength = 0, ProbeRspLength = 0, PSPollLength;
u32 NullDataLength, QosNullLength, BTQosNullLength;
u8 *ReservedPagePacket;
u8 PageNum, PageNeed, TxDescLen;
u16 BufIndex;
u32 TotalPacketLen;
struct rsvdpage_loc RsvdPageLoc;
DBG_8723A("%s\n", __FUNCTION__);
ReservedPagePacket = kzalloc(1000, GFP_KERNEL);
if (ReservedPagePacket == NULL) {
DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
return;
}
pHalData = GET_HAL_DATA(padapter);
pxmitpriv = &padapter->xmitpriv;
pmlmeext = &padapter->mlmeextpriv;
pmlmeinfo = &pmlmeext->mlmext_info;
TxDescLen = TXDESC_SIZE;
PageNum = 0;
/* 3 (1) beacon */
BufIndex = TXDESC_OFFSET;
ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);
/* When we count the first page size, we need to reserve description size for the RSVD */
/* packet, it will be filled in front of the packet in TXPKTBUF. */
PageNeed = (u8)PageNum_128(TxDescLen + BeaconLength);
/* To reserved 2 pages for beacon buffer. 2010.06.24. */
if (PageNeed == 1)
PageNeed += 1;
PageNum += PageNeed;
pHalData->FwRsvdPageStartOffset = PageNum;
BufIndex += PageNeed*128;
/* 3 (2) ps-poll */
RsvdPageLoc.LocPsPoll = PageNum;
ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength);
rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, true, false);
PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength);
PageNum += PageNeed;
BufIndex += PageNeed*128;
/* 3 (3) null data */
RsvdPageLoc.LocNullData = PageNum;
ConstructNullFunctionData(
padapter,
&ReservedPagePacket[BufIndex],
&NullDataLength,
get_my_bssid23a(&pmlmeinfo->network),
false, 0, 0, false);
rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false);
PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
PageNum += PageNeed;
BufIndex += PageNeed*128;
/* 3 (4) probe response */
RsvdPageLoc.LocProbeRsp = PageNum;
ConstructProbeRsp(
padapter,
&ReservedPagePacket[BufIndex],
&ProbeRspLength,
get_my_bssid23a(&pmlmeinfo->network),
false);
rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, false, false);
PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength);
PageNum += PageNeed;
BufIndex += PageNeed*128;
/* 3 (5) Qos null data */
RsvdPageLoc.LocQosNull = PageNum;
ConstructNullFunctionData(
padapter,
&ReservedPagePacket[BufIndex],
&QosNullLength,
get_my_bssid23a(&pmlmeinfo->network),
true, 0, 0, false);
rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false);
PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength);
PageNum += PageNeed;
BufIndex += PageNeed*128;
/* 3 (6) BT Qos null data */
RsvdPageLoc.LocBTQosNull = PageNum;
ConstructNullFunctionData(
padapter,
&ReservedPagePacket[BufIndex],
&BTQosNullLength,
get_my_bssid23a(&pmlmeinfo->network),
true, 0, 0, false);
rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true);
TotalPacketLen = BufIndex + BTQosNullLength;
pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
if (pmgntframe == NULL)
goto exit;
/* update attribute */
pattrib = &pmgntframe->attrib;
update_mgntframe_attrib23a(padapter, pattrib);
pattrib->qsel = 0x10;
pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;
memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
rtw_hal_mgnt_xmit23a(padapter, pmgntframe);
DBG_8723A("%s: Set RSVD page location to Fw\n", __FUNCTION__);
FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
exit:
kfree(ReservedPagePacket);
}
void rtl8723a_set_FwJoinBssReport_cmd(struct rtw_adapter *padapter, u8 mstatus)
{
struct joinbssrpt_parm JoinBssRptParm;
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
DBG_8723A("%s mstatus(%x)\n", __FUNCTION__, mstatus);
if (mstatus == 1) {
bool bRecover = false;
u8 v8;
/* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */
/* Suggested by filen. Added by tynli. */
rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
/* Do not set TSF again here or vWiFi beacon DMA INT will not work. */
/* correct_TSF23a(padapter, pmlmeext); */
/* Hw sequende enable by dedault. 2010.06.23. by tynli. */
/* rtw_write16(padapter, REG_NQOS_SEQ, ((pmlmeext->mgnt_seq+100)&0xFFF)); */
/* rtw_write8(padapter, REG_HWSEQ_CTRL, 0xFF); */
/* set REG_CR bit 8 */
v8 = rtw_read8(padapter, REG_CR+1);
v8 |= BIT(0); /* ENSWBCN */
rtw_write8(padapter, REG_CR+1, v8);
/* Disable Hw protection for a time which revserd for Hw sending beacon. */
/* Fix download reserved page packet fail that access collision with the protection time. */
/* 2010.05.11. Added by tynli. */
/* SetBcnCtrlReg23a(padapter, 0, BIT(3)); */
/* SetBcnCtrlReg23a(padapter, BIT(4), 0); */
SetBcnCtrlReg23a(padapter, BIT(4), BIT(3));
/* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
if (pHalData->RegFwHwTxQCtrl & BIT(6))
bRecover = true;
/* To tell Hw the packet is not a real beacon frame. */
/* U1bTmp = rtw_read8(padapter, REG_FWHW_TXQ_CTRL+2); */
rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl & ~BIT(6));
pHalData->RegFwHwTxQCtrl &= ~BIT(6);
SetFwRsvdPagePkt(padapter, 0);
/* 2010.05.11. Added by tynli. */
SetBcnCtrlReg23a(padapter, BIT(3), BIT(4));
/* To make sure that if there exists an adapter which would like to send beacon. */
/* If exists, the origianl value of 0x422[6] will be 1, we should check this to */
/* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
/* the beacon cannot be sent by HW. */
/* 2010.06.23. Added by tynli. */
if (bRecover) {
rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl | BIT(6));
pHalData->RegFwHwTxQCtrl |= BIT(6);
}
/* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
v8 = rtw_read8(padapter, REG_CR+1);
v8 &= ~BIT(0); /* ~ENSWBCN */
rtw_write8(padapter, REG_CR+1, v8);
}
JoinBssRptParm.OpMode = mstatus;
FillH2CCmd(padapter, JOINBSS_RPT_EID, sizeof(JoinBssRptParm), (u8 *)&JoinBssRptParm);
}
#ifdef CONFIG_8723AU_BT_COEXIST
static void SetFwRsvdPagePkt_BTCoex(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData;
struct xmit_frame *pmgntframe;
struct pkt_attrib *pattrib;
struct xmit_priv *pxmitpriv;
struct mlme_ext_priv *pmlmeext;
struct mlme_ext_info *pmlmeinfo;
u8 fakemac[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x00};
u32 NullDataLength, BTQosNullLength;
u8 *ReservedPagePacket;
u8 PageNum, PageNeed, TxDescLen;
u16 BufIndex;
u32 TotalPacketLen;
struct rsvdpage_loc RsvdPageLoc;
DBG_8723A("+%s\n", __FUNCTION__);
ReservedPagePacket = kzalloc(1024, GFP_KERNEL);
if (ReservedPagePacket == NULL) {
DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
return;
}
pHalData = GET_HAL_DATA(padapter);
pxmitpriv = &padapter->xmitpriv;
pmlmeext = &padapter->mlmeextpriv;
pmlmeinfo = &pmlmeext->mlmext_info;
TxDescLen = TXDESC_SIZE;
PageNum = 0;
/* 3 (1) beacon */
BufIndex = TXDESC_OFFSET;
/* skip Beacon Packet */
PageNeed = 3;
PageNum += PageNeed;
pHalData->FwRsvdPageStartOffset = PageNum;
BufIndex += PageNeed*128;
/* 3 (3) null data */
RsvdPageLoc.LocNullData = PageNum;
ConstructNullFunctionData(
padapter,
&ReservedPagePacket[BufIndex],
&NullDataLength,
fakemac,
false, 0, 0, false);
rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false);
PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
PageNum += PageNeed;
BufIndex += PageNeed*128;
/* 3 (6) BT Qos null data */
RsvdPageLoc.LocBTQosNull = PageNum;
ConstructNullFunctionData(
padapter,
&ReservedPagePacket[BufIndex],
&BTQosNullLength,
fakemac,
true, 0, 0, false);
rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true);
TotalPacketLen = BufIndex + BTQosNullLength;
pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
if (pmgntframe == NULL)
goto exit;
/* update attribute */
pattrib = &pmgntframe->attrib;
update_mgntframe_attrib23a(padapter, pattrib);
pattrib->qsel = 0x10;
pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;
memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
rtw_hal_mgnt_xmit23a(padapter, pmgntframe);
DBG_8723A("%s: Set RSVD page location to Fw\n", __FUNCTION__);
FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
exit:
kfree(ReservedPagePacket);
}
void rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData;
u8 bRecover = false;
DBG_8723A("+%s\n", __FUNCTION__);
pHalData = GET_HAL_DATA(padapter);
/* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
if (pHalData->RegFwHwTxQCtrl & BIT(6))
bRecover = true;
/* To tell Hw the packet is not a real beacon frame. */
pHalData->RegFwHwTxQCtrl &= ~BIT(6);
rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
SetFwRsvdPagePkt_BTCoex(padapter);
/* To make sure that if there exists an adapter which would like to send beacon. */
/* If exists, the origianl value of 0x422[6] will be 1, we should check this to */
/* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
/* the beacon cannot be sent by HW. */
/* 2010.06.23. Added by tynli. */
if (bRecover) {
pHalData->RegFwHwTxQCtrl |= BIT(6);
rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
}
}
#endif
#ifdef CONFIG_8723AU_P2P
void rtl8723a_set_p2p_ps_offload_cmd(struct rtw_adapter *padapter, u8 p2p_ps_state)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
struct P2P_PS_Offload_t *p2p_ps_offload = &pHalData->p2p_ps_offload;
u8 i;
switch (p2p_ps_state) {
case P2P_PS_DISABLE:
DBG_8723A("P2P_PS_DISABLE \n");
memset(p2p_ps_offload, 0, 1);
break;
case P2P_PS_ENABLE:
DBG_8723A("P2P_PS_ENABLE \n");
/* update CTWindow value. */
if (pwdinfo->ctwindow > 0) {
p2p_ps_offload->CTWindow_En = 1;
rtw_write8(padapter, REG_P2P_CTWIN, pwdinfo->ctwindow);
}
/* hw only support 2 set of NoA */
for (i = 0; i < pwdinfo->noa_num; i++) {
/* To control the register setting for which NOA */
rtw_write8(padapter, REG_NOA_DESC_SEL, (i << 4));
if (i == 0)
p2p_ps_offload->NoA0_En = 1;
else
p2p_ps_offload->NoA1_En = 1;
/* config P2P NoA Descriptor Register */
rtw_write32(padapter, REG_NOA_DESC_DURATION, pwdinfo->noa_duration[i]);
rtw_write32(padapter, REG_NOA_DESC_INTERVAL, pwdinfo->noa_interval[i]);
rtw_write32(padapter, REG_NOA_DESC_START, pwdinfo->noa_start_time[i]);
rtw_write8(padapter, REG_NOA_DESC_COUNT, pwdinfo->noa_count[i]);
}
if ((pwdinfo->opp_ps == 1) || (pwdinfo->noa_num > 0)) {
/* rst p2p circuit */
rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(4));
p2p_ps_offload->Offload_En = 1;
if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
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:
DBG_8723A("P2P_PS_SCAN \n");
p2p_ps_offload->discovery = 1;
break;
case P2P_PS_SCAN_DONE:
DBG_8723A("P2P_PS_SCAN_DONE \n");
p2p_ps_offload->discovery = 0;
pwdinfo->p2p_ps_state = P2P_PS_ENABLE;
break;
default:
break;
}
FillH2CCmd(padapter, P2P_PS_OFFLOAD_EID, 1, (u8 *)p2p_ps_offload);
}
#endif /* CONFIG_8723AU_P2P */
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
/* */
/* Description: */
/* */
/* This file is for 92CE/92CU dynamic mechanism only */
/* */
/* */
/* */
#define _RTL8723A_DM_C_
/* */
/* include files */
/* */
#include <osdep_service.h>
#include <drv_types.h>
#include <rtl8723a_hal.h>
/* */
/* Global var */
/* */
static void dm_CheckStatistics(struct rtw_adapter *Adapter)
{
}
static void dm_CheckPbcGPIO(struct rtw_adapter *padapter)
{
u8 tmp1byte;
u8 bPbcPressed = false;
if (!padapter->registrypriv.hw_wps_pbc)
return;
tmp1byte = rtw_read8(padapter, GPIO_IO_SEL);
tmp1byte |= (HAL_8192C_HW_GPIO_WPS_BIT);
rtw_write8(padapter, GPIO_IO_SEL, tmp1byte); /* enable GPIO[2] as output mode */
tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT);
rtw_write8(padapter, GPIO_IN, tmp1byte); /* reset the floating voltage level */
tmp1byte = rtw_read8(padapter, GPIO_IO_SEL);
tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT);
rtw_write8(padapter, GPIO_IO_SEL, tmp1byte); /* enable GPIO[2] as input mode */
tmp1byte = rtw_read8(padapter, GPIO_IN);
if (tmp1byte == 0xff)
return;
if (tmp1byte&HAL_8192C_HW_GPIO_WPS_BIT)
bPbcPressed = true;
if (bPbcPressed) {
/* Here we only set bPbcPressed to true */
/* After trigger PBC, the variable will be set to false */
DBG_8723A("CheckPbcGPIO - PBC is pressed\n");
if (padapter->pid[0] == 0) {
/* 0 is the default value and it means the application
* monitors the HW PBC doesn't privde its pid to driver.
*/
return;
}
rtw_signal_process(padapter->pid[0], SIGUSR1);
}
}
/* Initialize GPIO setting registers */
/* functions */
static void Init_ODM_ComInfo_8723a(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
u8 cut_ver, fab_ver;
/* */
/* Init Value */
/* */
memset(pDM_Odm, 0, sizeof(*pDM_Odm));
pDM_Odm->Adapter = Adapter;
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_PLATFORM, 0x04);
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_INTERFACE, RTW_USB);/* RTL871X_HCI_TYPE */
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_IC_TYPE, ODM_RTL8723A);
if (IS_8723A_A_CUT(pHalData->VersionID)) {
fab_ver = ODM_UMC;
cut_ver = ODM_CUT_A;
} else if (IS_8723A_B_CUT(pHalData->VersionID)) {
fab_ver = ODM_UMC;
cut_ver = ODM_CUT_B;
} else {
fab_ver = ODM_TSMC;
cut_ver = ODM_CUT_A;
}
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_FAB_VER, fab_ver);
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_CUT_VER, cut_ver);
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_MP_TEST_CHIP, IS_NORMAL_CHIP(pHalData->VersionID));
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_BOARD_TYPE, pHalData->BoardType);
if (pHalData->BoardType == BOARD_USB_High_PA) {
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_EXT_LNA, true);
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_EXT_PA, true);
}
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_PATCH_ID, pHalData->CustomerID);
ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_BWIFI_TEST, Adapter->registrypriv.wifi_spec);
if (pHalData->rf_type == RF_1T1R)
ODM_CmnInfoUpdate23a(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_1T1R);
else if (pHalData->rf_type == RF_2T2R)
ODM_CmnInfoUpdate23a(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_2T2R);
else if (pHalData->rf_type == RF_1T2R)
ODM_CmnInfoUpdate23a(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_1T2R);
}
static void Update_ODM_ComInfo_8723a(struct rtw_adapter *Adapter)
{
struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
struct dm_priv *pdmpriv = &pHalData->dmpriv;
int i;
pdmpriv->InitODMFlag = ODM_BB_DIG |
ODM_BB_RA_MASK |
ODM_BB_DYNAMIC_TXPWR |
ODM_BB_FA_CNT |
ODM_BB_RSSI_MONITOR |
ODM_BB_CCK_PD |
ODM_BB_PWR_SAVE |
ODM_MAC_EDCA_TURBO |
ODM_RF_TX_PWR_TRACK |
ODM_RF_CALIBRATION;
/* Pointer reference */
ODM_CmnInfoUpdate23a(pDM_Odm, ODM_CMNINFO_ABILITY, pdmpriv->InitODMFlag);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_TX_UNI,
&Adapter->xmitpriv.tx_bytes);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_RX_UNI,
&Adapter->recvpriv.rx_bytes);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_WM_MODE,
&pmlmeext->cur_wireless_mode);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SEC_CHNL_OFFSET,
&pHalData->nCur40MhzPrimeSC);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SEC_MODE,
&Adapter->securitypriv.dot11PrivacyAlgrthm);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_BW,
&pHalData->CurrentChannelBW);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_CHNL,
&pHalData->CurrentChannel);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_NET_CLOSED, &Adapter->net_closed);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SCAN, &pmlmepriv->bScanInProcess);
ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_POWER_SAVING,
&pwrctrlpriv->bpower_saving);
for (i = 0; i < NUM_STA; i++)
ODM_CmnInfoPtrArrayHook23a(pDM_Odm, ODM_CMNINFO_STA_STATUS, i, NULL);
}
void rtl8723a_InitHalDm(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
u8 i;
pdmpriv->DM_Type = DM_Type_ByDriver;
pdmpriv->DMFlag = DYNAMIC_FUNC_DISABLE;
#ifdef CONFIG_8723AU_BT_COEXIST
pdmpriv->DMFlag |= DYNAMIC_FUNC_BT;
#endif
pdmpriv->InitDMFlag = pdmpriv->DMFlag;
Update_ODM_ComInfo_8723a(Adapter);
ODM23a_DMInit(pDM_Odm);
/* Save REG_INIDATA_RATE_SEL value for TXDESC. */
for (i = 0; i < 32; i++)
pdmpriv->INIDATA_RATE[i] = rtw_read8(Adapter, REG_INIDATA_RATE_SEL+i) & 0x3f;
}
void
rtl8723a_HalDmWatchDog(
struct rtw_adapter *Adapter
)
{
bool bFwCurrentInPSMode = false;
bool bFwPSAwake = true;
u8 hw_init_completed = false;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
hw_init_completed = Adapter->hw_init_completed;
if (hw_init_completed == false)
goto skip_dm;
bFwCurrentInPSMode = Adapter->pwrctrlpriv.bFwCurrentInPSMode;
rtw23a_hal_get_hwreg(Adapter, HW_VAR_FWLPS_RF_ON, (u8 *)(&bFwPSAwake));
#ifdef CONFIG_8723AU_P2P
/* Fw is under p2p powersaving mode, driver should stop dynamic mechanism. */
/* modifed by thomas. 2011.06.11. */
if (Adapter->wdinfo.p2p_ps_mode)
bFwPSAwake = false;
#endif /* CONFIG_8723AU_P2P */
if ((hw_init_completed) && ((!bFwCurrentInPSMode) && bFwPSAwake)) {
/* Calculate Tx/Rx statistics. */
dm_CheckStatistics(Adapter);
/* Read REG_INIDATA_RATE_SEL value for TXDESC. */
if (check_fwstate(&Adapter->mlmepriv, WIFI_STATION_STATE)) {
pdmpriv->INIDATA_RATE[0] = rtw_read8(Adapter, REG_INIDATA_RATE_SEL) & 0x3f;
} else {
u8 i;
for (i = 1 ; i < (Adapter->stapriv.asoc_sta_count + 1); i++)
pdmpriv->INIDATA_RATE[i] = rtw_read8(Adapter, (REG_INIDATA_RATE_SEL+i)) & 0x3f;
}
}
/* ODM */
if (hw_init_completed == true) {
u8 bLinked = false;
if (rtw_linked_check(Adapter))
bLinked = true;
ODM_CmnInfoUpdate23a(&pHalData->odmpriv, ODM_CMNINFO_LINK,
bLinked);
ODM_DMWatchdog23a(&pHalData->odmpriv);
}
skip_dm:
/* Check GPIO to determine current RF on/off and Pbc status. */
/* Check Hardware Radio ON/OFF or not */
dm_CheckPbcGPIO(Adapter);
}
void rtl8723a_init_dm_priv(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
memset(pdmpriv, 0, sizeof(struct dm_priv));
Init_ODM_ComInfo_8723a(Adapter);
}
void rtl8723a_deinit_dm_priv(struct rtw_adapter *Adapter)
{
}
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#define _HAL_INIT_C_
#include <linux/firmware.h>
#include <drv_types.h>
#include <rtw_efuse.h>
#include <rtl8723a_hal.h>
static void _FWDownloadEnable(struct rtw_adapter *padapter, bool enable)
{
u8 tmp;
if (enable) {
/* 8051 enable */
tmp = rtw_read8(padapter, REG_SYS_FUNC_EN + 1);
rtw_write8(padapter, REG_SYS_FUNC_EN + 1, tmp | 0x04);
/* MCU firmware download enable. */
tmp = rtw_read8(padapter, REG_MCUFWDL);
rtw_write8(padapter, REG_MCUFWDL, tmp | 0x01);
/* 8051 reset */
tmp = rtw_read8(padapter, REG_MCUFWDL + 2);
rtw_write8(padapter, REG_MCUFWDL + 2, tmp & 0xf7);
} else {
/* MCU firmware download disable. */
tmp = rtw_read8(padapter, REG_MCUFWDL);
rtw_write8(padapter, REG_MCUFWDL, tmp & 0xfe);
/* Reserved for fw extension. */
rtw_write8(padapter, REG_MCUFWDL + 1, 0x00);
}
}
static int _BlockWrite(struct rtw_adapter *padapter, void *buffer, u32 buffSize)
{
int ret = _SUCCESS;
/* (Default) Phase #1 : PCI muse use 4-byte write to download FW */
u32 blockSize_p1 = 4;
/* Phase #2 : Use 8-byte, if Phase#1 use big size to write FW. */
u32 blockSize_p2 = 8;
/* Phase #3 : Use 1-byte, the remnant of FW image. */
u32 blockSize_p3 = 1;
u32 blockCount_p1 = 0, blockCount_p2 = 0, blockCount_p3 = 0;
u32 remainSize_p1 = 0, remainSize_p2 = 0;
u8 *bufferPtr = (u8 *) buffer;
u32 i = 0, offset = 0;
blockSize_p1 = 254;
/* 3 Phase #1 */
blockCount_p1 = buffSize / blockSize_p1;
remainSize_p1 = buffSize % blockSize_p1;
if (blockCount_p1) {
RT_TRACE(_module_hal_init_c_, _drv_notice_,
("_BlockWrite: [P1] buffSize(%d) blockSize_p1(%d) "
"blockCount_p1(%d) remainSize_p1(%d)\n",
buffSize, blockSize_p1, blockCount_p1,
remainSize_p1));
}
for (i = 0; i < blockCount_p1; i++) {
ret = rtw_writeN(padapter,
(FW_8723A_START_ADDRESS + i * blockSize_p1),
blockSize_p1, (bufferPtr + i * blockSize_p1));
if (ret == _FAIL)
goto exit;
}
/* 3 Phase #2 */
if (remainSize_p1) {
offset = blockCount_p1 * blockSize_p1;
blockCount_p2 = remainSize_p1 / blockSize_p2;
remainSize_p2 = remainSize_p1 % blockSize_p2;
if (blockCount_p2) {
RT_TRACE(_module_hal_init_c_, _drv_notice_,
("_BlockWrite: [P2] buffSize_p2(%d) "
"blockSize_p2(%d) blockCount_p2(%d) "
"remainSize_p2(%d)\n",
(buffSize - offset), blockSize_p2,
blockCount_p2, remainSize_p2));
}
for (i = 0; i < blockCount_p2; i++) {
ret = rtw_writeN(padapter,
(FW_8723A_START_ADDRESS + offset +
i * blockSize_p2), blockSize_p2,
(bufferPtr + offset +
i * blockSize_p2));
if (ret == _FAIL)
goto exit;
}
}
/* 3 Phase #3 */
if (remainSize_p2) {
offset = (blockCount_p1 * blockSize_p1) +
(blockCount_p2 * blockSize_p2);
blockCount_p3 = remainSize_p2 / blockSize_p3;
RT_TRACE(_module_hal_init_c_, _drv_notice_,
("_BlockWrite: [P3] buffSize_p3(%d) blockSize_p3(%d) "
"blockCount_p3(%d)\n",
(buffSize - offset), blockSize_p3, blockCount_p3));
for (i = 0; i < blockCount_p3; i++) {
ret = rtw_write8(padapter,
(FW_8723A_START_ADDRESS + offset + i),
*(bufferPtr + offset + i));
if (ret == _FAIL)
goto exit;
}
}
exit:
return ret;
}
static int
_PageWrite(struct rtw_adapter *padapter, u32 page, void *buffer, u32 size)
{
u8 value8;
u8 u8Page = (u8) (page & 0x07);
value8 = (rtw_read8(padapter, REG_MCUFWDL + 2) & 0xF8) | u8Page;
rtw_write8(padapter, REG_MCUFWDL + 2, value8);
return _BlockWrite(padapter, buffer, size);
}
static int _WriteFW(struct rtw_adapter *padapter, void *buffer, u32 size)
{
/* Since we need dynamic decide method of dwonload fw, so we
call this function to get chip version. */
/* We can remove _ReadChipVersion from ReadpadapterInfo8192C later. */
int ret = _SUCCESS;
u32 pageNums, remainSize;
u32 page, offset;
u8 *bufferPtr = (u8 *) buffer;
pageNums = size / MAX_PAGE_SIZE;
/* RT_ASSERT((pageNums <= 4),
("Page numbers should not greater then 4 \n")); */
remainSize = size % MAX_PAGE_SIZE;
for (page = 0; page < pageNums; page++) {
offset = page * MAX_PAGE_SIZE;
ret = _PageWrite(padapter, page, bufferPtr + offset,
MAX_PAGE_SIZE);
if (ret == _FAIL)
goto exit;
}
if (remainSize) {
offset = pageNums * MAX_PAGE_SIZE;
page = pageNums;
ret = _PageWrite(padapter, page, bufferPtr + offset,
remainSize);
if (ret == _FAIL)
goto exit;
}
RT_TRACE(_module_hal_init_c_, _drv_info_,
("_WriteFW Done- for Normal chip.\n"));
exit:
return ret;
}
static s32 _FWFreeToGo(struct rtw_adapter *padapter)
{
u32 counter = 0;
u32 value32;
/* polling CheckSum report */
do {
value32 = rtw_read32(padapter, REG_MCUFWDL);
if (value32 & FWDL_ChkSum_rpt)
break;
} while (counter++ < POLLING_READY_TIMEOUT_COUNT);
if (counter >= POLLING_READY_TIMEOUT_COUNT) {
RT_TRACE(_module_hal_init_c_, _drv_err_,
("%s: chksum report fail! REG_MCUFWDL:0x%08x\n",
__func__, value32));
return _FAIL;
}
RT_TRACE(_module_hal_init_c_, _drv_info_,
("%s: Checksum report OK! REG_MCUFWDL:0x%08x\n", __func__,
value32));
value32 = rtw_read32(padapter, REG_MCUFWDL);
value32 |= MCUFWDL_RDY;
value32 &= ~WINTINI_RDY;
rtw_write32(padapter, REG_MCUFWDL, value32);
/* polling for FW ready */
counter = 0;
do {
value32 = rtw_read32(padapter, REG_MCUFWDL);
if (value32 & WINTINI_RDY) {
RT_TRACE(_module_hal_init_c_, _drv_info_,
("%s: Polling FW ready success!! "
"REG_MCUFWDL:0x%08x\n",
__func__, value32));
return _SUCCESS;
}
udelay(5);
} while (counter++ < POLLING_READY_TIMEOUT_COUNT);
RT_TRACE(_module_hal_init_c_, _drv_err_,
("%s: Polling FW ready fail!! REG_MCUFWDL:0x%08x\n",
__func__, value32));
return _FAIL;
}
#define IS_FW_81xxC(padapter) (((GET_HAL_DATA(padapter))->FirmwareSignature & 0xFFF0) == 0x88C0)
void rtl8723a_FirmwareSelfReset(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
u8 u1bTmp;
u8 Delay = 100;
if (!(IS_FW_81xxC(padapter) &&
((pHalData->FirmwareVersion < 0x21) ||
(pHalData->FirmwareVersion == 0x21 &&
pHalData->FirmwareSubVersion < 0x01)))) {
/* after 88C Fw v33.1 */
/* 0x1cf = 0x20. Inform 8051 to reset. 2009.12.25. tynli_test */
rtw_write8(padapter, REG_HMETFR + 3, 0x20);
u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN + 1);
while (u1bTmp & BIT2) {
Delay--;
if (Delay == 0)
break;
udelay(50);
u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN + 1);
}
RT_TRACE(_module_hal_init_c_, _drv_info_,
("-%s: 8051 reset success (%d)\n", __func__,
Delay));
if ((Delay == 0)) {
/* force firmware reset */
u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN + 1);
rtw_write8(padapter, REG_SYS_FUNC_EN + 1,
u1bTmp & (~BIT2));
}
}
}
/* */
/* Description: */
/* Download 8192C firmware code. */
/* */
/* */
s32 rtl8723a_FirmwareDownload(struct rtw_adapter *padapter)
{
s32 rtStatus = _SUCCESS;
u8 writeFW_retry = 0;
unsigned long fwdl_start_time;
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
struct device *device = dvobj_to_dev(dvobj);
struct rt_8723a_firmware_hdr *pFwHdr = NULL;
const struct firmware *fw;
char *fw_name;
u8 *firmware_buf = NULL;
u8 *buf;
int fw_size;
static int log_version;
RT_TRACE(_module_hal_init_c_, _drv_info_, ("+%s\n", __func__));
if (IS_8723A_A_CUT(pHalData->VersionID)) {
fw_name = "rtlwifi/rtl8723aufw.bin";
RT_TRACE(_module_hal_init_c_, _drv_info_,
("rtl8723a_FirmwareDownload: R8723FwImageArray_UMC "
"for RTL8723A A CUT\n"));
} else if (IS_8723A_B_CUT(pHalData->VersionID)) {
/* WLAN Fw. */
if (padapter->registrypriv.wifi_spec == 1) {
fw_name = "rtlwifi/rtl8723aufw_B_NoBT.bin";
DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithoutBT for "
"RTL8723A B CUT\n");
} else {
#ifdef CONFIG_8723AU_BT_COEXIST
fw_name = "rtlwifi/rtl8723aufw_B.bin";
DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithBT for "
"RTL8723A B CUT\n");
#else
fw_name = "rtlwifi/rtl8723aufw_B_NoBT.bin";
DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithoutBT for "
"RTL8723A B CUT\n");
#endif
}
} else {
/* <Roger_TODO> We should download proper RAM Code here
to match the ROM code. */
RT_TRACE(_module_hal_init_c_, _drv_err_,
("%s: unknow version!\n", __func__));
rtStatus = _FAIL;
goto Exit;
}
pr_info("rtl8723au: Loading firmware %s\n", fw_name);
if (request_firmware(&fw, fw_name, device)) {
pr_err("rtl8723au: request_firmware load failed\n");
rtStatus = _FAIL;
goto Exit;
}
if (!fw) {
pr_err("rtl8723au: Firmware %s not available\n", fw_name);
rtStatus = _FAIL;
goto Exit;
}
firmware_buf = kzalloc(fw->size, GFP_KERNEL);
if (!firmware_buf) {
rtStatus = _FAIL;
goto Exit;
}
memcpy(firmware_buf, fw->data, fw->size);
buf = firmware_buf;
fw_size = fw->size;
release_firmware(fw);
/* To Check Fw header. Added by tynli. 2009.12.04. */
pFwHdr = (struct rt_8723a_firmware_hdr *)firmware_buf;
pHalData->FirmwareVersion = le16_to_cpu(pFwHdr->Version);
pHalData->FirmwareSubVersion = pFwHdr->Subversion;
pHalData->FirmwareSignature = le16_to_cpu(pFwHdr->Signature);
DBG_8723A("%s: fw_ver =%d fw_subver =%d sig = 0x%x\n",
__func__, pHalData->FirmwareVersion,
pHalData->FirmwareSubVersion, pHalData->FirmwareSignature);
if (!log_version++)
pr_info("%sFirmware Version %d, SubVersion %d, Signature "
"0x%x\n", DRIVER_PREFIX, pHalData->FirmwareVersion,
pHalData->FirmwareSubVersion,
pHalData->FirmwareSignature);
if (IS_FW_HEADER_EXIST(pFwHdr)) {
/* Shift 32 bytes for FW header */
buf = buf + 32;
fw_size = fw_size - 32;
}
/* Suggested by Filen. If 8051 is running in RAM code, driver should
inform Fw to reset by itself, */
/* or it will cause download Fw fail. 2010.02.01. by tynli. */
if (rtw_read8(padapter, REG_MCUFWDL) & RAM_DL_SEL) {
/* 8051 RAM code */
rtl8723a_FirmwareSelfReset(padapter);
rtw_write8(padapter, REG_MCUFWDL, 0x00);
}
_FWDownloadEnable(padapter, true);
fwdl_start_time = jiffies;
while (1) {
/* reset the FWDL chksum */
rtw_write8(padapter, REG_MCUFWDL,
rtw_read8(padapter, REG_MCUFWDL) | FWDL_ChkSum_rpt);
rtStatus = _WriteFW(padapter, buf, fw_size);
if (rtStatus == _SUCCESS ||
(rtw_get_passing_time_ms23a(fwdl_start_time) > 500 &&
writeFW_retry++ >= 3))
break;
DBG_8723A("%s writeFW_retry:%u, time after fwdl_start_time:"
"%ums\n", __func__, writeFW_retry,
jiffies_to_msecs(jiffies - fwdl_start_time));
}
_FWDownloadEnable(padapter, false);
if (_SUCCESS != rtStatus) {
DBG_8723A("DL Firmware failed!\n");
goto Exit;
}
rtStatus = _FWFreeToGo(padapter);
if (_SUCCESS != rtStatus) {
RT_TRACE(_module_hal_init_c_, _drv_err_,
("DL Firmware failed!\n"));
goto Exit;
}
RT_TRACE(_module_hal_init_c_, _drv_info_,
("Firmware is ready to run!\n"));
Exit:
kfree(firmware_buf);
return rtStatus;
}
void rtl8723a_InitializeFirmwareVars(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
/* Init Fw LPS related. */
padapter->pwrctrlpriv.bFwCurrentInPSMode = false;
/* Init H2C counter. by tynli. 2009.12.09. */
pHalData->LastHMEBoxNum = 0;
}
static void rtl8723a_free_hal_data(struct rtw_adapter *padapter)
{
kfree(padapter->HalData);
padapter->HalData = NULL;
}
/* */
/* Efuse related code */
/* */
static u8
hal_EfuseSwitchToBank(struct rtw_adapter *padapter, u8 bank)
{
u8 bRet = false;
u32 value32 = 0;
DBG_8723A("%s: Efuse switch bank to %d\n", __func__, bank);
value32 = rtw_read32(padapter, EFUSE_TEST);
bRet = true;
switch (bank) {
case 0:
value32 = (value32 & ~EFUSE_SEL_MASK) |
EFUSE_SEL(EFUSE_WIFI_SEL_0);
break;
case 1:
value32 = (value32 & ~EFUSE_SEL_MASK) |
EFUSE_SEL(EFUSE_BT_SEL_0);
break;
case 2:
value32 = (value32 & ~EFUSE_SEL_MASK) |
EFUSE_SEL(EFUSE_BT_SEL_1);
break;
case 3:
value32 = (value32 & ~EFUSE_SEL_MASK) |
EFUSE_SEL(EFUSE_BT_SEL_2);
break;
default:
value32 = (value32 & ~EFUSE_SEL_MASK) |
EFUSE_SEL(EFUSE_WIFI_SEL_0);
bRet = false;
break;
}
rtw_write32(padapter, EFUSE_TEST, value32);
return bRet;
}
static void
Hal_GetEfuseDefinition(struct rtw_adapter *padapter,
u8 efuseType, u8 type, void *pOut)
{
u8 *pu1Tmp;
u16 *pu2Tmp;
u8 *pMax_section;
switch (type) {
case TYPE_EFUSE_MAX_SECTION:
pMax_section = (u8 *) pOut;
if (efuseType == EFUSE_WIFI)
*pMax_section = EFUSE_MAX_SECTION_8723A;
else
*pMax_section = EFUSE_BT_MAX_SECTION;
break;
case TYPE_EFUSE_REAL_CONTENT_LEN:
pu2Tmp = (u16 *) pOut;
if (efuseType == EFUSE_WIFI)
*pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A;
else
*pu2Tmp = EFUSE_BT_REAL_CONTENT_LEN;
break;
case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
pu2Tmp = (u16 *) pOut;
if (efuseType == EFUSE_WIFI)
*pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A -
EFUSE_OOB_PROTECT_BYTES);
else
*pu2Tmp = (EFUSE_BT_REAL_BANK_CONTENT_LEN -
EFUSE_PROTECT_BYTES_BANK);
break;
case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
pu2Tmp = (u16 *) pOut;
if (efuseType == EFUSE_WIFI)
*pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A -
EFUSE_OOB_PROTECT_BYTES);
else
*pu2Tmp = (EFUSE_BT_REAL_CONTENT_LEN -
(EFUSE_PROTECT_BYTES_BANK * 3));
break;
case TYPE_EFUSE_MAP_LEN:
pu2Tmp = (u16 *) pOut;
if (efuseType == EFUSE_WIFI)
*pu2Tmp = EFUSE_MAP_LEN_8723A;
else
*pu2Tmp = EFUSE_BT_MAP_LEN;
break;
case TYPE_EFUSE_PROTECT_BYTES_BANK:
pu1Tmp = (u8 *) pOut;
if (efuseType == EFUSE_WIFI)
*pu1Tmp = EFUSE_OOB_PROTECT_BYTES;
else
*pu1Tmp = EFUSE_PROTECT_BYTES_BANK;
break;
case TYPE_EFUSE_CONTENT_LEN_BANK:
pu2Tmp = (u16 *) pOut;
if (efuseType == EFUSE_WIFI)
*pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A;
else
*pu2Tmp = EFUSE_BT_REAL_BANK_CONTENT_LEN;
break;
default:
pu1Tmp = (u8 *) pOut;
*pu1Tmp = 0;
break;
}
}
#define VOLTAGE_V25 0x03
#define LDOE25_SHIFT 28
static void
Hal_EfusePowerSwitch(struct rtw_adapter *padapter, u8 bWrite, u8 PwrState)
{
u8 tempval;
u16 tmpV16;
if (PwrState == true) {
rtw_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
/* 1.2V Power: From VDDON with Power
Cut(0x0000h[15]), defualt valid */
tmpV16 = rtw_read16(padapter, REG_SYS_ISO_CTRL);
if (!(tmpV16 & PWC_EV12V)) {
tmpV16 |= PWC_EV12V;
rtw_write16(padapter, REG_SYS_ISO_CTRL, tmpV16);
}
/* Reset: 0x0000h[28], default valid */
tmpV16 = rtw_read16(padapter, REG_SYS_FUNC_EN);
if (!(tmpV16 & FEN_ELDR)) {
tmpV16 |= FEN_ELDR;
rtw_write16(padapter, REG_SYS_FUNC_EN, tmpV16);
}
/* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock
from ANA, default valid */
tmpV16 = rtw_read16(padapter, REG_SYS_CLKR);
if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) {
tmpV16 |= (LOADER_CLK_EN | ANA8M);
rtw_write16(padapter, REG_SYS_CLKR, tmpV16);
}
if (bWrite == true) {
/* Enable LDO 2.5V before read/write action */
tempval = rtw_read8(padapter, EFUSE_TEST + 3);
tempval &= 0x0F;
tempval |= (VOLTAGE_V25 << 4);
rtw_write8(padapter, EFUSE_TEST + 3, (tempval | 0x80));
}
} else {
rtw_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
if (bWrite == true) {
/* Disable LDO 2.5V after read/write action */
tempval = rtw_read8(padapter, EFUSE_TEST + 3);
rtw_write8(padapter, EFUSE_TEST + 3, (tempval & 0x7F));
}
}
}
static void
hal_ReadEFuse_WiFi(struct rtw_adapter *padapter,
u16 _offset, u16 _size_byte, u8 *pbuf)
{
u8 *efuseTbl = NULL;
u16 eFuse_Addr = 0;
u8 offset, wden;
u8 efuseHeader, efuseExtHdr, efuseData;
u16 i, total, used;
/* Do NOT excess total size of EFuse table.
Added by Roger, 2008.11.10. */
if ((_offset + _size_byte) > EFUSE_MAP_LEN_8723A) {
DBG_8723A("%s: Invalid offset(%#x) with read bytes(%#x)!!\n",
__func__, _offset, _size_byte);
return;
}
efuseTbl = (u8 *) kmalloc(EFUSE_MAP_LEN_8723A, GFP_KERNEL);
if (efuseTbl == NULL) {
DBG_8723A("%s: alloc efuseTbl fail!\n", __func__);
return;
}
/* 0xff will be efuse default value instead of 0x00. */
memset(efuseTbl, 0xFF, EFUSE_MAP_LEN_8723A);
/* switch bank back to bank 0 for later BT and wifi use. */
hal_EfuseSwitchToBank(padapter, 0);
while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseHeader);
if (efuseHeader == 0xFF) {
DBG_8723A("%s: data end at address =%#x\n", __func__,
eFuse_Addr);
break;
}
/* Check PG header for section num. */
if (EXT_HEADER(efuseHeader)) { /* extended header */
offset = GET_HDR_OFFSET_2_0(efuseHeader);
ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseExtHdr);
if (ALL_WORDS_DISABLED(efuseExtHdr)) {
continue;
}
offset |= ((efuseExtHdr & 0xF0) >> 1);
wden = (efuseExtHdr & 0x0F);
} else {
offset = ((efuseHeader >> 4) & 0x0f);
wden = (efuseHeader & 0x0f);
}
if (offset < EFUSE_MAX_SECTION_8723A) {
u16 addr;
/* Get word enable value from PG header */
addr = offset * PGPKT_DATA_SIZE;
for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
/* Check word enable condition in the section */
if (!(wden & (0x01 << i))) {
ReadEFuseByte23a(padapter, eFuse_Addr++,
&efuseData);
efuseTbl[addr] = efuseData;
ReadEFuseByte23a(padapter, eFuse_Addr++,
&efuseData);
efuseTbl[addr + 1] = efuseData;
}
addr += 2;
}
} else {
DBG_8723A(KERN_ERR "%s: offset(%d) is illegal!!\n",
__func__, offset);
eFuse_Addr += Efuse_CalculateWordCnts23a(wden) * 2;
}
}
/* Copy from Efuse map to output pointer memory!!! */
for (i = 0; i < _size_byte; i++)
pbuf[i] = efuseTbl[_offset + i];
/* Calculate Efuse utilization */
EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total);
used = eFuse_Addr - 1;
rtw_hal_set_hwreg23a(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&used);
kfree(efuseTbl);
}
static void
hal_ReadEFuse_BT(struct rtw_adapter *padapter,
u16 _offset, u16 _size_byte, u8 *pbuf)
{
u8 *efuseTbl;
u8 bank;
u16 eFuse_Addr;
u8 efuseHeader, efuseExtHdr, efuseData;
u8 offset, wden;
u16 i, total, used;
/* Do NOT excess total size of EFuse table.
Added by Roger, 2008.11.10. */
if ((_offset + _size_byte) > EFUSE_BT_MAP_LEN) {
DBG_8723A("%s: Invalid offset(%#x) with read bytes(%#x)!!\n",
__func__, _offset, _size_byte);
return;
}
efuseTbl = kmalloc(EFUSE_BT_MAP_LEN, GFP_KERNEL);
if (efuseTbl == NULL) {
DBG_8723A("%s: efuseTbl malloc fail!\n", __func__);
return;
}
/* 0xff will be efuse default value instead of 0x00. */
memset(efuseTbl, 0xFF, EFUSE_BT_MAP_LEN);
EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
TYPE_AVAILABLE_EFUSE_BYTES_BANK, &total);
for (bank = 1; bank < EFUSE_MAX_BANK; bank++) {
if (hal_EfuseSwitchToBank(padapter, bank) == false) {
DBG_8723A("%s: hal_EfuseSwitchToBank Fail!!\n",
__func__);
goto exit;
}
eFuse_Addr = 0;
while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseHeader);
if (efuseHeader == 0xFF)
break;
/* Check PG header for section num. */
if (EXT_HEADER(efuseHeader)) { /* extended header */
offset = GET_HDR_OFFSET_2_0(efuseHeader);
ReadEFuseByte23a(padapter, eFuse_Addr++,
&efuseExtHdr);
if (ALL_WORDS_DISABLED(efuseExtHdr)) {
continue;
}
offset |= ((efuseExtHdr & 0xF0) >> 1);
wden = (efuseExtHdr & 0x0F);
} else {
offset = ((efuseHeader >> 4) & 0x0f);
wden = (efuseHeader & 0x0f);
}
if (offset < EFUSE_BT_MAX_SECTION) {
u16 addr;
/* Get word enable value from PG header */
addr = offset * PGPKT_DATA_SIZE;
for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
/* Check word enable condition in
the section */
if (!(wden & (0x01 << i))) {
ReadEFuseByte23a(padapter,
eFuse_Addr++,
&efuseData);
efuseTbl[addr] = efuseData;
ReadEFuseByte23a(padapter,
eFuse_Addr++,
&efuseData);
efuseTbl[addr + 1] = efuseData;
}
addr += 2;
}
} else {
DBG_8723A(KERN_ERR
"%s: offset(%d) is illegal!!\n",
__func__, offset);
eFuse_Addr += Efuse_CalculateWordCnts23a(wden) * 2;
}
}
if ((eFuse_Addr - 1) < total) {
DBG_8723A("%s: bank(%d) data end at %#x\n",
__func__, bank, eFuse_Addr - 1);
break;
}
}
/* switch bank back to bank 0 for later BT and wifi use. */
hal_EfuseSwitchToBank(padapter, 0);
/* Copy from Efuse map to output pointer memory!!! */
for (i = 0; i < _size_byte; i++)
pbuf[i] = efuseTbl[_offset + i];
/* */
/* Calculate Efuse utilization. */
/* */
EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total);
used = (EFUSE_BT_REAL_BANK_CONTENT_LEN * (bank - 1)) + eFuse_Addr - 1;
rtw_hal_set_hwreg23a(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *) &used);
exit:
kfree(efuseTbl);
}
static void
Hal_ReadEFuse(struct rtw_adapter *padapter,
u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf)
{
if (efuseType == EFUSE_WIFI)
hal_ReadEFuse_WiFi(padapter, _offset, _size_byte, pbuf);
else
hal_ReadEFuse_BT(padapter, _offset, _size_byte, pbuf);
}
static u16
hal_EfuseGetCurrentSize_WiFi(struct rtw_adapter *padapter)
{
u16 efuse_addr = 0;
u8 hoffset = 0, hworden = 0;
u8 efuse_data, word_cnts = 0;
rtw23a_hal_get_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *) &efuse_addr);
DBG_8723A("%s: start_efuse_addr = 0x%X\n", __func__, efuse_addr);
/* switch bank back to bank 0 for later BT and wifi use. */
hal_EfuseSwitchToBank(padapter, 0);
while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
if (efuse_OneByteRead23a(padapter, efuse_addr, &efuse_data) ==
false) {
DBG_8723A(KERN_ERR "%s: efuse_OneByteRead23a Fail! "
"addr = 0x%X !!\n", __func__, efuse_addr);
break;
}
if (efuse_data == 0xFF)
break;
if (EXT_HEADER(efuse_data)) {
hoffset = GET_HDR_OFFSET_2_0(efuse_data);
efuse_addr++;
efuse_OneByteRead23a(padapter, efuse_addr, &efuse_data);
if (ALL_WORDS_DISABLED(efuse_data)) {
continue;
}
hoffset |= ((efuse_data & 0xF0) >> 1);
hworden = efuse_data & 0x0F;
} else {
hoffset = (efuse_data >> 4) & 0x0F;
hworden = efuse_data & 0x0F;
}
word_cnts = Efuse_CalculateWordCnts23a(hworden);
efuse_addr += (word_cnts * 2) + 1;
}
rtw_hal_set_hwreg23a(padapter, HW_VAR_EFUSE_BYTES, (u8 *) &efuse_addr);
DBG_8723A("%s: CurrentSize =%d\n", __func__, efuse_addr);
return efuse_addr;
}
static u16
hal_EfuseGetCurrentSize_BT(struct rtw_adapter *padapter)
{
u16 btusedbytes;
u16 efuse_addr;
u8 bank, startBank;
u8 hoffset = 0, hworden = 0;
u8 efuse_data, word_cnts = 0;
u16 retU2 = 0;
rtw23a_hal_get_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *) &btusedbytes);
efuse_addr = (u16) ((btusedbytes % EFUSE_BT_REAL_BANK_CONTENT_LEN));
startBank = (u8) (1 + (btusedbytes / EFUSE_BT_REAL_BANK_CONTENT_LEN));
DBG_8723A("%s: start from bank =%d addr = 0x%X\n", __func__, startBank,
efuse_addr);
EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
TYPE_AVAILABLE_EFUSE_BYTES_BANK, &retU2);
for (bank = startBank; bank < EFUSE_MAX_BANK; bank++) {
if (hal_EfuseSwitchToBank(padapter, bank) == false) {
DBG_8723A(KERN_ERR "%s: switch bank(%d) Fail!!\n",
__func__, bank);
bank = EFUSE_MAX_BANK;
break;
}
/* only when bank is switched we have to reset
the efuse_addr. */
if (bank != startBank)
efuse_addr = 0;
while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
if (efuse_OneByteRead23a(padapter, efuse_addr,
&efuse_data) == false) {
DBG_8723A(KERN_ERR "%s: efuse_OneByteRead23a Fail!"
" addr = 0x%X !!\n",
__func__, efuse_addr);
bank = EFUSE_MAX_BANK;
break;
}
if (efuse_data == 0xFF)
break;
if (EXT_HEADER(efuse_data)) {
hoffset = GET_HDR_OFFSET_2_0(efuse_data);
efuse_addr++;
efuse_OneByteRead23a(padapter, efuse_addr,
&efuse_data);
if (ALL_WORDS_DISABLED(efuse_data)) {
efuse_addr++;
continue;
}
hoffset |= ((efuse_data & 0xF0) >> 1);
hworden = efuse_data & 0x0F;
} else {
hoffset = (efuse_data >> 4) & 0x0F;
hworden = efuse_data & 0x0F;
}
word_cnts = Efuse_CalculateWordCnts23a(hworden);
/* read next header */
efuse_addr += (word_cnts * 2) + 1;
}
/* Check if we need to check next bank efuse */
if (efuse_addr < retU2) {
break; /* don't need to check next bank. */
}
}
retU2 = ((bank - 1) * EFUSE_BT_REAL_BANK_CONTENT_LEN) + efuse_addr;
rtw_hal_set_hwreg23a(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *)&retU2);
DBG_8723A("%s: CurrentSize =%d\n", __func__, retU2);
return retU2;
}
static u16
Hal_EfuseGetCurrentSize(struct rtw_adapter *pAdapter, u8 efuseType)
{
u16 ret = 0;
if (efuseType == EFUSE_WIFI)
ret = hal_EfuseGetCurrentSize_WiFi(pAdapter);
else
ret = hal_EfuseGetCurrentSize_BT(pAdapter);
return ret;
}
static u8
Hal_EfuseWordEnableDataWrite(struct rtw_adapter *padapter,
u16 efuse_addr, u8 word_en, u8 *data)
{
u16 tmpaddr = 0;
u16 start_addr = efuse_addr;
u8 badworden = 0x0F;
u8 tmpdata[PGPKT_DATA_SIZE];
memset(tmpdata, 0xFF, PGPKT_DATA_SIZE);
if (!(word_en & BIT(0))) {
tmpaddr = start_addr;
efuse_OneByteWrite23a(padapter, start_addr++, data[0]);
efuse_OneByteWrite23a(padapter, start_addr++, data[1]);
efuse_OneByteRead23a(padapter, tmpaddr, &tmpdata[0]);
efuse_OneByteRead23a(padapter, tmpaddr + 1, &tmpdata[1]);
if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) {
badworden &= (~BIT(0));
}
}
if (!(word_en & BIT(1))) {
tmpaddr = start_addr;
efuse_OneByteWrite23a(padapter, start_addr++, data[2]);
efuse_OneByteWrite23a(padapter, start_addr++, data[3]);
efuse_OneByteRead23a(padapter, tmpaddr, &tmpdata[2]);
efuse_OneByteRead23a(padapter, tmpaddr + 1, &tmpdata[3]);
if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) {
badworden &= (~BIT(1));
}
}
if (!(word_en & BIT(2))) {
tmpaddr = start_addr;
efuse_OneByteWrite23a(padapter, start_addr++, data[4]);
efuse_OneByteWrite23a(padapter, start_addr++, data[5]);
efuse_OneByteRead23a(padapter, tmpaddr, &tmpdata[4]);
efuse_OneByteRead23a(padapter, tmpaddr + 1, &tmpdata[5]);
if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) {
badworden &= (~BIT(2));
}
}
if (!(word_en & BIT(3))) {
tmpaddr = start_addr;
efuse_OneByteWrite23a(padapter, start_addr++, data[6]);
efuse_OneByteWrite23a(padapter, start_addr++, data[7]);
efuse_OneByteRead23a(padapter, tmpaddr, &tmpdata[6]);
efuse_OneByteRead23a(padapter, tmpaddr + 1, &tmpdata[7]);
if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) {
badworden &= (~BIT(3));
}
}
return badworden;
}
static s32
Hal_EfusePgPacketRead(struct rtw_adapter *padapter, u8 offset, u8 *data)
{
u8 efuse_data, word_cnts = 0;
u16 efuse_addr = 0;
u8 hoffset = 0, hworden = 0;
u8 i;
u8 max_section = 0;
s32 ret;
if (data == NULL)
return false;
EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION,
&max_section);
if (offset > max_section) {
DBG_8723A("%s: Packet offset(%d) is illegal(>%d)!\n",
__func__, offset, max_section);
return false;
}
memset(data, 0xFF, PGPKT_DATA_SIZE);
ret = true;
/* */
/* <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the
end of Efuse by CP. */
/* Skip dummy parts to prevent unexpected data read from Efuse. */
/* By pass right now. 2009.02.19. */
/* */
while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
if (efuse_OneByteRead23a(padapter, efuse_addr++, &efuse_data) ==
false) {
ret = false;
break;
}
if (efuse_data == 0xFF)
break;
if (EXT_HEADER(efuse_data)) {
hoffset = GET_HDR_OFFSET_2_0(efuse_data);
efuse_OneByteRead23a(padapter, efuse_addr++, &efuse_data);
if (ALL_WORDS_DISABLED(efuse_data)) {
DBG_8723A("%s: Error!! All words disabled!\n",
__func__);
continue;
}
hoffset |= ((efuse_data & 0xF0) >> 1);
hworden = efuse_data & 0x0F;
} else {
hoffset = (efuse_data >> 4) & 0x0F;
hworden = efuse_data & 0x0F;
}
if (hoffset == offset) {
for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
/* Check word enable condition in the section */
if (!(hworden & (0x01 << i))) {
ReadEFuseByte23a(padapter, efuse_addr++,
&efuse_data);
data[i * 2] = efuse_data;
ReadEFuseByte23a(padapter, efuse_addr++,
&efuse_data);
data[(i * 2) + 1] = efuse_data;
}
}
} else {
word_cnts = Efuse_CalculateWordCnts23a(hworden);
efuse_addr += word_cnts * 2;
}
}
return ret;
}
static u8
hal_EfusePgCheckAvailableAddr(struct rtw_adapter *pAdapter, u8 efuseType)
{
u16 max_available = 0;
u16 current_size;
EFUSE_GetEfuseDefinition23a(pAdapter, efuseType,
TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
&max_available);
current_size = Efuse_GetCurrentSize23a(pAdapter, efuseType);
if (current_size >= max_available) {
DBG_8723A("%s: Error!! current_size(%d)>max_available(%d)\n",
__func__, current_size, max_available);
return false;
}
return true;
}
static void
hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData,
struct pg_pkt_struct *pTargetPkt)
{
memset(pTargetPkt->data, 0xFF, PGPKT_DATA_SIZE);
pTargetPkt->offset = offset;
pTargetPkt->word_en = word_en;
efuse_WordEnableDataRead23a(word_en, pData, pTargetPkt->data);
pTargetPkt->word_cnts = Efuse_CalculateWordCnts23a(pTargetPkt->word_en);
}
static u8
hal_EfusePartialWriteCheck(struct rtw_adapter *padapter, u8 efuseType,
u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
{
u8 bRet = false;
u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0;
u8 efuse_data = 0;
EFUSE_GetEfuseDefinition23a(padapter, efuseType,
TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
&efuse_max_available_len);
EFUSE_GetEfuseDefinition23a(padapter, efuseType,
TYPE_EFUSE_CONTENT_LEN_BANK, &efuse_max);
if (efuseType == EFUSE_WIFI) {
rtw23a_hal_get_hwreg(padapter, HW_VAR_EFUSE_BYTES,
(u8 *) &startAddr);
} else {
rtw23a_hal_get_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES,
(u8 *) &startAddr);
}
startAddr %= efuse_max;
while (1) {
if (startAddr >= efuse_max_available_len) {
bRet = false;
DBG_8723A("%s: startAddr(%d) >= efuse_max_available_"
"len(%d)\n", __func__, startAddr,
efuse_max_available_len);
break;
}
if (efuse_OneByteRead23a(padapter, startAddr, &efuse_data) &&
(efuse_data != 0xFF)) {
bRet = false;
DBG_8723A("%s: Something Wrong! last bytes(%#X = 0x%02X) "
"is not 0xFF\n", __func__,
startAddr, efuse_data);
break;
} else {
/* not used header, 0xff */
*pAddr = startAddr;
bRet = true;
break;
}
}
return bRet;
}
static u8
hal_EfusePgPacketWrite1ByteHeader(struct rtw_adapter *pAdapter, u8 efuseType,
u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
{
u8 pg_header = 0, tmp_header = 0;
u16 efuse_addr = *pAddr;
u8 repeatcnt = 0;
pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
do {
efuse_OneByteWrite23a(pAdapter, efuse_addr, pg_header);
efuse_OneByteRead23a(pAdapter, efuse_addr, &tmp_header);
if (tmp_header != 0xFF)
break;
if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
DBG_8723A("%s: Repeat over limit for pg_header!!\n",
__func__);
return false;
}
} while (1);
if (tmp_header != pg_header) {
DBG_8723A(KERN_ERR "%s: PG Header Fail!!(pg = 0x%02X "
"read = 0x%02X)\n", __func__,
pg_header, tmp_header);
return false;
}
*pAddr = efuse_addr;
return true;
}
static u8
hal_EfusePgPacketWrite2ByteHeader(struct rtw_adapter *padapter, u8 efuseType,
u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
{
u16 efuse_addr, efuse_max_available_len = 0;
u8 pg_header = 0, tmp_header = 0;
u8 repeatcnt = 0;
EFUSE_GetEfuseDefinition23a(padapter, efuseType,
TYPE_AVAILABLE_EFUSE_BYTES_BANK,
&efuse_max_available_len);
efuse_addr = *pAddr;
if (efuse_addr >= efuse_max_available_len) {
DBG_8723A("%s: addr(%d) over avaliable(%d)!!\n", __func__,
efuse_addr, efuse_max_available_len);
return false;
}
pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
do {
efuse_OneByteWrite23a(padapter, efuse_addr, pg_header);
efuse_OneByteRead23a(padapter, efuse_addr, &tmp_header);
if (tmp_header != 0xFF)
break;
if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
DBG_8723A("%s: Repeat over limit for pg_header!!\n",
__func__);
return false;
}
} while (1);
if (tmp_header != pg_header) {
DBG_8723A(KERN_ERR
"%s: PG Header Fail!!(pg = 0x%02X read = 0x%02X)\n",
__func__, pg_header, tmp_header);
return false;
}
/* to write ext_header */
efuse_addr++;
pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
do {
efuse_OneByteWrite23a(padapter, efuse_addr, pg_header);
efuse_OneByteRead23a(padapter, efuse_addr, &tmp_header);
if (tmp_header != 0xFF)
break;
if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
DBG_8723A("%s: Repeat over limit for ext_header!!\n",
__func__);
return false;
}
} while (1);
if (tmp_header != pg_header) { /* offset PG fail */
DBG_8723A(KERN_ERR
"%s: PG EXT Header Fail!!(pg = 0x%02X read = 0x%02X)\n",
__func__, pg_header, tmp_header);
return false;
}
*pAddr = efuse_addr;
return true;
}
static u8
hal_EfusePgPacketWriteHeader(struct rtw_adapter *padapter, u8 efuseType,
u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
{
u8 bRet = false;
if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE) {
bRet = hal_EfusePgPacketWrite2ByteHeader(padapter, efuseType,
pAddr, pTargetPkt);
} else {
bRet = hal_EfusePgPacketWrite1ByteHeader(padapter, efuseType,
pAddr, pTargetPkt);
}
return bRet;
}
static u8
hal_EfusePgPacketWriteData(struct rtw_adapter *pAdapter, u8 efuseType,
u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
{
u16 efuse_addr;
u8 badworden;
efuse_addr = *pAddr;
badworden =
Efuse_WordEnableDataWrite23a(pAdapter, efuse_addr + 1,
pTargetPkt->word_en, pTargetPkt->data);
if (badworden != 0x0F) {
DBG_8723A("%s: Fail!!\n", __func__);
return false;
}
return true;
}
static s32
Hal_EfusePgPacketWrite(struct rtw_adapter *padapter,
u8 offset, u8 word_en, u8 *pData)
{
struct pg_pkt_struct targetPkt;
u16 startAddr = 0;
u8 efuseType = EFUSE_WIFI;
if (!hal_EfusePgCheckAvailableAddr(padapter, efuseType))
return false;
hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
if (!hal_EfusePartialWriteCheck(padapter, efuseType,
&startAddr, &targetPkt))
return false;
if (!hal_EfusePgPacketWriteHeader(padapter, efuseType,
&startAddr, &targetPkt))
return false;
if (!hal_EfusePgPacketWriteData(padapter, efuseType,
&startAddr, &targetPkt))
return false;
return true;
}
static bool
Hal_EfusePgPacketWrite_BT(struct rtw_adapter *pAdapter,
u8 offset, u8 word_en, u8 *pData)
{
struct pg_pkt_struct targetPkt;
u16 startAddr = 0;
u8 efuseType = EFUSE_BT;
if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType))
return false;
hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
if (!hal_EfusePartialWriteCheck(pAdapter, efuseType,
&startAddr, &targetPkt))
return false;
if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType,
&startAddr, &targetPkt))
return false;
if (!hal_EfusePgPacketWriteData(pAdapter, efuseType,
&startAddr, &targetPkt))
return false;
return true;
}
static struct hal_version ReadChipVersion8723A(struct rtw_adapter *padapter)
{
u32 value32;
struct hal_version ChipVersion;
struct hal_data_8723a *pHalData;
pHalData = GET_HAL_DATA(padapter);
value32 = rtw_read32(padapter, REG_SYS_CFG);
ChipVersion.ICType = CHIP_8723A;
ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
ChipVersion.RFType = RF_TYPE_1T1R;
ChipVersion.VendorType =
((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC);
ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK) >> CHIP_VER_RTL_SHIFT; /* IC version (CUT) */
/* For regulator mode. by tynli. 2011.01.14 */
pHalData->RegulatorMode = ((value32 & SPS_SEL) ?
RT_LDO_REGULATOR : RT_SWITCHING_REGULATOR);
value32 = rtw_read32(padapter, REG_GPIO_OUTSTS);
/* ROM code version. */
ChipVersion.ROMVer = ((value32 & RF_RL_ID) >> 20);
/* For multi-function consideration. Added by Roger, 2010.10.06. */
pHalData->MultiFunc = RT_MULTI_FUNC_NONE;
value32 = rtw_read32(padapter, REG_MULTI_FUNC_CTRL);
pHalData->MultiFunc |=
((value32 & WL_FUNC_EN) ? RT_MULTI_FUNC_WIFI : 0);
pHalData->MultiFunc |= ((value32 & BT_FUNC_EN) ? RT_MULTI_FUNC_BT : 0);
pHalData->MultiFunc |=
((value32 & GPS_FUNC_EN) ? RT_MULTI_FUNC_GPS : 0);
pHalData->PolarityCtl =
((value32 & WL_HWPDN_SL) ? RT_POLARITY_HIGH_ACT :
RT_POLARITY_LOW_ACT);
dump_chip_info23a(ChipVersion);
pHalData->VersionID = ChipVersion;
if (IS_1T2R(ChipVersion))
pHalData->rf_type = RF_1T2R;
else if (IS_2T2R(ChipVersion))
pHalData->rf_type = RF_2T2R;
else
pHalData->rf_type = RF_1T1R;
MSG_8723A("RF_Type is %x!!\n", pHalData->rf_type);
return ChipVersion;
}
static void rtl8723a_read_chip_version(struct rtw_adapter *padapter)
{
ReadChipVersion8723A(padapter);
}
/* */
/* */
/* 20100209 Joseph: */
/* This function is used only for 92C to set REG_BCN_CTRL(0x550) register. */
/* We just reserve the value of the register in variable
pHalData->RegBcnCtrlVal and then operate */
/* the value of the register via atomic operation. */
/* This prevents from race condition when setting this register. */
/* The value of pHalData->RegBcnCtrlVal is initialized in
HwConfigureRTL8192CE() function. */
/* */
void SetBcnCtrlReg23a(struct rtw_adapter *padapter, u8 SetBits, u8 ClearBits)
{
struct hal_data_8723a *pHalData;
u32 addr;
u8 *pRegBcnCtrlVal;
pHalData = GET_HAL_DATA(padapter);
pRegBcnCtrlVal = (u8 *)&pHalData->RegBcnCtrlVal;
addr = REG_BCN_CTRL;
*pRegBcnCtrlVal = rtw_read8(padapter, addr);
*pRegBcnCtrlVal |= SetBits;
*pRegBcnCtrlVal &= ~ClearBits;
rtw_write8(padapter, addr, *pRegBcnCtrlVal);
}
void rtl8723a_InitBeaconParameters(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
rtw_write16(padapter, REG_BCN_CTRL, 0x1010);
pHalData->RegBcnCtrlVal = 0x1010;
/* TODO: Remove these magic number */
rtw_write16(padapter, REG_TBTT_PROHIBIT, 0x6404); /* ms */
/* Firmware will control REG_DRVERLYINT when power saving is enable, */
/* so don't set this register on STA mode. */
if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == false)
rtw_write8(padapter, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);
/* 2ms */
rtw_write8(padapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
/* Suggested by designer timchen. Change beacon AIFS to the
largest number beacause test chip does not contension before
sending beacon. by tynli. 2009.11.03 */
rtw_write16(padapter, REG_BCNTCFG, 0x660F);
}
static void ResumeTxBeacon(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
/* 2010.03.01. Marked by tynli. No need to call workitem beacause
we record the value */
/* which should be read from register to a global variable. */
RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("+ResumeTxBeacon\n"));
pHalData->RegFwHwTxQCtrl |= BIT(6);
rtw_write8(padapter, REG_FWHW_TXQ_CTRL + 2, pHalData->RegFwHwTxQCtrl);
rtw_write8(padapter, REG_TBTT_PROHIBIT + 1, 0xff);
pHalData->RegReg542 |= BIT(0);
rtw_write8(padapter, REG_TBTT_PROHIBIT + 2, pHalData->RegReg542);
}
static void StopTxBeacon(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
/* 2010.03.01. Marked by tynli. No need to call workitem beacause
we record the value */
/* which should be read from register to a global variable. */
RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("+StopTxBeacon\n"));
pHalData->RegFwHwTxQCtrl &= ~BIT(6);
rtw_write8(padapter, REG_FWHW_TXQ_CTRL + 2, pHalData->RegFwHwTxQCtrl);
rtw_write8(padapter, REG_TBTT_PROHIBIT + 1, 0x64);
pHalData->RegReg542 &= ~BIT(0);
rtw_write8(padapter, REG_TBTT_PROHIBIT + 2, pHalData->RegReg542);
CheckFwRsvdPageContent23a(padapter); /* 2010.06.23. Added by tynli. */
}
static void _BeaconFunctionEnable(struct rtw_adapter *padapter, u8 Enable,
u8 Linked)
{
SetBcnCtrlReg23a(padapter, DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB,
0);
rtw_write8(padapter, REG_RD_CTRL + 1, 0x6F);
}
static void rtl8723a_SetBeaconRelatedRegisters(struct rtw_adapter *padapter)
{
u32 value32;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
/* reset TSF, enable update TSF, correcting TSF On Beacon */
/* REG_BCN_INTERVAL */
/* REG_BCNDMATIM */
/* REG_ATIMWND */
/* REG_TBTT_PROHIBIT */
/* REG_DRVERLYINT */
/* REG_BCN_MAX_ERR */
/* REG_BCNTCFG (0x510) */
/* REG_DUAL_TSF_RST */
/* REG_BCN_CTRL (0x550) */
/* */
/* ATIM window */
/* */
rtw_write16(padapter, REG_ATIMWND, 2);
/* */
/* Beacon interval (in unit of TU). */
/* */
rtw_write16(padapter, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval);
rtl8723a_InitBeaconParameters(padapter);
rtw_write8(padapter, REG_SLOT, 0x09);
/* */
/* Reset TSF Timer to zero, added by Roger. 2008.06.24 */
/* */
value32 = rtw_read32(padapter, REG_TCR);
value32 &= ~TSFRST;
rtw_write32(padapter, REG_TCR, value32);
value32 |= TSFRST;
rtw_write32(padapter, REG_TCR, value32);
/* NOTE: Fix test chip's bug (about contention windows's randomness) */
if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE |
WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE) == true) {
rtw_write8(padapter, REG_RXTSF_OFFSET_CCK, 0x50);
rtw_write8(padapter, REG_RXTSF_OFFSET_OFDM, 0x50);
}
_BeaconFunctionEnable(padapter, true, true);
ResumeTxBeacon(padapter);
SetBcnCtrlReg23a(padapter, DIS_BCNQ_SUB, 0);
}
static void rtl8723a_GetHalODMVar(struct rtw_adapter *Adapter,
enum hal_odm_variable eVariable,
void *pValue1, bool bSet)
{
switch (eVariable) {
case HAL_ODM_STA_INFO:
break;
default:
break;
}
}
static void rtl8723a_SetHalODMVar(struct rtw_adapter *Adapter,
enum hal_odm_variable eVariable,
void *pValue1, bool bSet)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_odm_t *podmpriv = &pHalData->odmpriv;
switch (eVariable) {
case HAL_ODM_STA_INFO:
{
struct sta_info *psta = (struct sta_info *)pValue1;
if (bSet) {
DBG_8723A("Set STA_(%d) info\n", psta->mac_id);
ODM_CmnInfoPtrArrayHook23a(podmpriv,
ODM_CMNINFO_STA_STATUS,
psta->mac_id, psta);
} else {
DBG_8723A("Clean STA_(%d) info\n", psta->mac_id);
ODM_CmnInfoPtrArrayHook23a(podmpriv,
ODM_CMNINFO_STA_STATUS,
psta->mac_id, NULL);
}
}
break;
case HAL_ODM_P2P_STATE:
ODM_CmnInfoUpdate23a(podmpriv, ODM_CMNINFO_WIFI_DIRECT, bSet);
break;
case HAL_ODM_WIFI_DISPLAY_STATE:
ODM_CmnInfoUpdate23a(podmpriv, ODM_CMNINFO_WIFI_DISPLAY, bSet);
break;
default:
break;
}
}
static void hal_notch_filter_8723a(struct rtw_adapter *adapter, bool enable)
{
if (enable) {
DBG_8723A("Enable notch filter\n");
rtw_write8(adapter, rOFDM0_RxDSP + 1,
rtw_read8(adapter, rOFDM0_RxDSP + 1) | BIT1);
} else {
DBG_8723A("Disable notch filter\n");
rtw_write8(adapter, rOFDM0_RxDSP + 1,
rtw_read8(adapter, rOFDM0_RxDSP + 1) & ~BIT1);
}
}
s32 c2h_id_filter_ccx_8723a(u8 id)
{
s32 ret = false;
if (id == C2H_CCX_TX_RPT)
ret = true;
return ret;
}
static s32 c2h_handler_8723a(struct rtw_adapter *padapter,
struct c2h_evt_hdr *c2h_evt)
{
s32 ret = _SUCCESS;
u8 i = 0;
if (c2h_evt == NULL) {
DBG_8723A("%s c2h_evt is NULL\n", __func__);
ret = _FAIL;
goto exit;
}
switch (c2h_evt->id) {
case C2H_DBG:
RT_TRACE(_module_hal_init_c_, _drv_info_,
("C2HCommandHandler: %s\n", c2h_evt->payload));
break;
case C2H_CCX_TX_RPT:
handle_txrpt_ccx_8723a(padapter, c2h_evt->payload);
break;
case C2H_EXT_RA_RPT:
break;
case C2H_HW_INFO_EXCH:
RT_TRACE(_module_hal_init_c_, _drv_info_,
("[BT], C2H_HW_INFO_EXCH\n"));
for (i = 0; i < c2h_evt->plen; i++) {
RT_TRACE(_module_hal_init_c_, _drv_info_,
("[BT], tmpBuf[%d]= 0x%x\n", i,
c2h_evt->payload[i]));
}
break;
case C2H_C2H_H2C_TEST:
RT_TRACE(_module_hal_init_c_, _drv_info_,
("[BT], C2H_H2C_TEST\n"));
RT_TRACE(_module_hal_init_c_, _drv_info_,
("[BT], tmpBuf[0]/[1]/[2]/[3]/[4]= 0x%x/ 0x%x/ "
"0x%x/ 0x%x/ 0x%x\n", c2h_evt->payload[0],
c2h_evt->payload[1], c2h_evt->payload[2],
c2h_evt->payload[3], c2h_evt->payload[4]));
break;
#ifdef CONFIG_8723AU_BT_COEXIST
case C2H_BT_INFO:
DBG_8723A("%s , Got C2H_BT_INFO \n", __func__);
BT_FwC2hBtInfo(padapter, c2h_evt->payload, c2h_evt->plen);
break;
#endif
default:
ret = _FAIL;
break;
}
exit:
return ret;
}
void rtl8723a_set_hal_ops(struct hal_ops *pHalFunc)
{
pHalFunc->free_hal_data = &rtl8723a_free_hal_data;
pHalFunc->dm_init = &rtl8723a_init_dm_priv;
pHalFunc->dm_deinit = &rtl8723a_deinit_dm_priv;
pHalFunc->read_chip_version = &rtl8723a_read_chip_version;
pHalFunc->set_bwmode_handler = &PHY_SetBWMode23a8723A;
pHalFunc->set_channel_handler = &PHY_SwChnl8723A;
pHalFunc->hal_dm_watchdog = &rtl8723a_HalDmWatchDog;
pHalFunc->SetBeaconRelatedRegistersHandler =
&rtl8723a_SetBeaconRelatedRegisters;
pHalFunc->Add_RateATid = &rtl8723a_add_rateatid;
pHalFunc->run_thread = &rtl8723a_start_thread;
pHalFunc->cancel_thread = &rtl8723a_stop_thread;
pHalFunc->read_bbreg = &PHY_QueryBBReg;
pHalFunc->write_bbreg = &PHY_SetBBReg;
pHalFunc->read_rfreg = &PHY_QueryRFReg;
pHalFunc->write_rfreg = &PHY_SetRFReg;
/* Efuse related function */
pHalFunc->EfusePowerSwitch = &Hal_EfusePowerSwitch;
pHalFunc->ReadEFuse = &Hal_ReadEFuse;
pHalFunc->EFUSEGetEfuseDefinition = &Hal_GetEfuseDefinition;
pHalFunc->EfuseGetCurrentSize = &Hal_EfuseGetCurrentSize;
pHalFunc->Efuse_PgPacketRead23a = &Hal_EfusePgPacketRead;
pHalFunc->Efuse_PgPacketWrite23a = &Hal_EfusePgPacketWrite;
pHalFunc->Efuse_WordEnableDataWrite23a = &Hal_EfuseWordEnableDataWrite;
pHalFunc->Efuse_PgPacketWrite23a_BT = &Hal_EfusePgPacketWrite_BT;
pHalFunc->sreset_init_value23a = &sreset_init_value23a;
pHalFunc->sreset_reset_value23a = &sreset_reset_value23a;
pHalFunc->silentreset = &sreset_reset;
pHalFunc->sreset_xmit_status_check = &rtl8723a_sreset_xmit_status_check;
pHalFunc->sreset_linked_status_check =
&rtl8723a_sreset_linked_status_check;
pHalFunc->sreset_get_wifi_status23a = &sreset_get_wifi_status23a;
pHalFunc->sreset_inprogress = &sreset_inprogress;
pHalFunc->GetHalODMVarHandler = &rtl8723a_GetHalODMVar;
pHalFunc->SetHalODMVarHandler = &rtl8723a_SetHalODMVar;
pHalFunc->hal_notch_filter = &hal_notch_filter_8723a;
pHalFunc->c2h_handler = c2h_handler_8723a;
pHalFunc->c2h_id_filter_ccx = c2h_id_filter_ccx_8723a;
}
void rtl8723a_InitAntenna_Selection(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData;
u8 val;
pHalData = GET_HAL_DATA(padapter);
val = rtw_read8(padapter, REG_LEDCFG2);
/* Let 8051 take control antenna settting */
val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */
rtw_write8(padapter, REG_LEDCFG2, val);
}
void rtl8723a_CheckAntenna_Selection(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData;
u8 val;
pHalData = GET_HAL_DATA(padapter);
val = rtw_read8(padapter, REG_LEDCFG2);
/* Let 8051 take control antenna settting */
if (!(val & BIT(7))) {
val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */
rtw_write8(padapter, REG_LEDCFG2, val);
}
}
void rtl8723a_DeinitAntenna_Selection(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData;
u8 val;
pHalData = GET_HAL_DATA(padapter);
val = rtw_read8(padapter, REG_LEDCFG2);
/* Let 8051 take control antenna settting */
val &= ~BIT(7); /* DPDT_SEL_EN, clear 0x4C[23] */
rtw_write8(padapter, REG_LEDCFG2, val);
}
void rtl8723a_init_default_value(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData;
struct dm_priv *pdmpriv;
u8 i;
pHalData = GET_HAL_DATA(padapter);
pdmpriv = &pHalData->dmpriv;
/* init default value */
pHalData->fw_ractrl = false;
pHalData->bIQKInitialized = false;
if (!padapter->pwrctrlpriv.bkeepfwalive)
pHalData->LastHMEBoxNum = 0;
pHalData->bIQKInitialized = false;
/* init dm default value */
pdmpriv->TM_Trigger = 0; /* for IQK */
/* pdmpriv->binitialized = false; */
/* pdmpriv->prv_traffic_idx = 3; */
/* pdmpriv->initialize = 0; */
pdmpriv->ThermalValue_HP_index = 0;
for (i = 0; i < HP_THERMAL_NUM; i++)
pdmpriv->ThermalValue_HP[i] = 0;
/* init Efuse variables */
pHalData->EfuseUsedBytes = 0;
pHalData->BTEfuseUsedBytes = 0;
}
u8 GetEEPROMSize8723A(struct rtw_adapter *padapter)
{
u8 size = 0;
u32 cr;
cr = rtw_read16(padapter, REG_9346CR);
/* 6: EEPROM used is 93C46, 4: boot from E-Fuse. */
size = (cr & BOOT_FROM_EEPROM) ? 6 : 4;
MSG_8723A("EEPROM type is %s\n", size == 4 ? "E-FUSE" : "93C46");
return size;
}
/* */
/* */
/* LLT R/W/Init function */
/* */
/* */
static s32 _LLTWrite(struct rtw_adapter *padapter, u32 address, u32 data)
{
s32 status = _SUCCESS;
s32 count = 0;
u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) |
_LLT_OP(_LLT_WRITE_ACCESS);
u16 LLTReg = REG_LLT_INIT;
rtw_write32(padapter, LLTReg, value);
/* polling */
do {
value = rtw_read32(padapter, LLTReg);
if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) {
break;
}
if (count > POLLING_LLT_THRESHOLD) {
RT_TRACE(_module_hal_init_c_, _drv_err_,
("Failed to polling write LLT done at "
"address %d!\n", address));
status = _FAIL;
break;
}
} while (count++);
return status;
}
s32 InitLLTTable23a(struct rtw_adapter *padapter, u32 boundary)
{
s32 status = _SUCCESS;
u32 i;
u32 txpktbuf_bndy = boundary;
u32 Last_Entry_Of_TxPktBuf = LAST_ENTRY_OF_TX_PKT_BUFFER;
for (i = 0; i < (txpktbuf_bndy - 1); i++) {
status = _LLTWrite(padapter, i, i + 1);
if (_SUCCESS != status) {
return status;
}
}
/* end of list */
status = _LLTWrite(padapter, (txpktbuf_bndy - 1), 0xFF);
if (_SUCCESS != status) {
return status;
}
/* Make the other pages as ring buffer */
/* This ring buffer is used as beacon buffer if we config this
MAC as two MAC transfer. */
/* Otherwise used as local loopback buffer. */
for (i = txpktbuf_bndy; i < Last_Entry_Of_TxPktBuf; i++) {
status = _LLTWrite(padapter, i, (i + 1));
if (_SUCCESS != status) {
return status;
}
}
/* Let last entry point to the start entry of ring buffer */
status = _LLTWrite(padapter, Last_Entry_Of_TxPktBuf, txpktbuf_bndy);
if (_SUCCESS != status) {
return status;
}
return status;
}
static void _DisableGPIO(struct rtw_adapter *padapter)
{
/***************************************
j. GPIO_PIN_CTRL 0x44[31:0]= 0x000
k.Value = GPIO_PIN_CTRL[7:0]
l. GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); write external PIN level
m. GPIO_MUXCFG 0x42 [15:0] = 0x0780
n. LEDCFG 0x4C[15:0] = 0x8080
***************************************/
u32 value32;
u32 u4bTmp;
/* 1. Disable GPIO[7:0] */
rtw_write16(padapter, REG_GPIO_PIN_CTRL + 2, 0x0000);
value32 = rtw_read32(padapter, REG_GPIO_PIN_CTRL) & 0xFFFF00FF;
u4bTmp = value32 & 0x000000FF;
value32 |= ((u4bTmp << 8) | 0x00FF0000);
rtw_write32(padapter, REG_GPIO_PIN_CTRL, value32);
/* */
/* <Roger_Notes> For RTL8723u multi-function configuration which
was autoload from Efuse offset 0x0a and 0x0b, */
/* WLAN HW GPIO[9], GPS HW GPIO[10] and BT HW GPIO[11]. */
/* Added by Roger, 2010.10.07. */
/* */
/* 2. Disable GPIO[8] and GPIO[12] */
/* Configure all pins as input mode. */
rtw_write16(padapter, REG_GPIO_IO_SEL_2, 0x0000);
value32 = rtw_read32(padapter, REG_GPIO_PIN_CTRL_2) & 0xFFFF001F;
u4bTmp = value32 & 0x0000001F;
/* Set pin 8, 10, 11 and pin 12 to output mode. */
value32 |= ((u4bTmp << 8) | 0x001D0000);
rtw_write32(padapter, REG_GPIO_PIN_CTRL_2, value32);
/* 3. Disable LED0 & 1 */
rtw_write16(padapter, REG_LEDCFG0, 0x8080);
} /* end of _DisableGPIO() */
static void _DisableRFAFEAndResetBB8192C(struct rtw_adapter *padapter)
{
/**************************************
a. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue
b. RF path 0 offset 0x00 = 0x00 disable RF
c. APSD_CTRL 0x600[7:0] = 0x40
d. SYS_FUNC_EN 0x02[7:0] = 0x16 reset BB state machine
e. SYS_FUNC_EN 0x02[7:0] = 0x14 reset BB state machine
***************************************/
u8 eRFPath = 0, value8 = 0;
rtw_write8(padapter, REG_TXPAUSE, 0xFF);
PHY_SetRFReg(padapter, (enum RF_RADIO_PATH) eRFPath, 0x0, bMaskByte0, 0x0);
value8 |= APSDOFF;
rtw_write8(padapter, REG_APSD_CTRL, value8); /* 0x40 */
/* Set BB reset at first */
value8 = 0;
value8 |= (FEN_USBD | FEN_USBA | FEN_BB_GLB_RSTn);
rtw_write8(padapter, REG_SYS_FUNC_EN, value8); /* 0x16 */
/* Set global reset. */
value8 &= ~FEN_BB_GLB_RSTn;
rtw_write8(padapter, REG_SYS_FUNC_EN, value8); /* 0x14 */
/* 2010/08/12 MH We need to set BB/GLBAL reset to save power
for SS mode. */
/* RT_TRACE(COMP_INIT, DBG_LOUD, ("======> RF off and reset BB.\n")); */
}
static void _DisableRFAFEAndResetBB(struct rtw_adapter *padapter)
{
_DisableRFAFEAndResetBB8192C(padapter);
}
static void _ResetDigitalProcedure1_92C(struct rtw_adapter *padapter,
bool bWithoutHWSM)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
if (IS_FW_81xxC(padapter) && (pHalData->FirmwareVersion <= 0x20)) {
/*****************************
f. MCUFWDL 0x80[7:0]= 0 reset MCU ready status
g. SYS_FUNC_EN 0x02[10]= 0 reset MCU register, (8051 reset)
h. SYS_FUNC_EN 0x02[15-12]= 5 reset MAC register, DCORE
i. SYS_FUNC_EN 0x02[10]= 1 enable MCU register,
(8051 enable)
******************************/
u16 valu16 = 0;
rtw_write8(padapter, REG_MCUFWDL, 0);
valu16 = rtw_read16(padapter, REG_SYS_FUNC_EN);
/* reset MCU , 8051 */
rtw_write16(padapter, REG_SYS_FUNC_EN, (valu16 & (~FEN_CPUEN)));
valu16 = rtw_read16(padapter, REG_SYS_FUNC_EN) & 0x0FFF;
rtw_write16(padapter, REG_SYS_FUNC_EN,
(valu16 | (FEN_HWPDN | FEN_ELDR))); /* reset MAC */
valu16 = rtw_read16(padapter, REG_SYS_FUNC_EN);
/* enable MCU , 8051 */
rtw_write16(padapter, REG_SYS_FUNC_EN, (valu16 | FEN_CPUEN));
} else {
u8 retry_cnts = 0;
/* 2010/08/12 MH For USB SS, we can not stop 8051 when we
are trying to enter IPS/HW&SW radio off. For
S3/S4/S5/Disable, we can stop 8051 because */
/* we will init FW when power on again. */
/* if (!pDevice->RegUsbSS) */
/* If we want to SS mode, we can not reset 8051. */
if (rtw_read8(padapter, REG_MCUFWDL) & BIT1) {
/* IF fw in RAM code, do reset */
if (padapter->bFWReady) {
/* 2010/08/25 MH Accordign to RD alfred's
suggestion, we need to disable other */
/* HRCV INT to influence 8051 reset. */
rtw_write8(padapter, REG_FWIMR, 0x20);
/* 2011/02/15 MH According to Alex's
suggestion, close mask to prevent
incorrect FW write operation. */
rtw_write8(padapter, REG_FTIMR, 0x00);
rtw_write8(padapter, REG_FSIMR, 0x00);
/* 8051 reset by self */
rtw_write8(padapter, REG_HMETFR + 3, 0x20);
while ((retry_cnts++ < 100) &&
(FEN_CPUEN &
rtw_read16(padapter, REG_SYS_FUNC_EN))) {
udelay(50); /* us */
}
if (retry_cnts >= 100) {
/* Reset MAC and Enable 8051 */
rtw_write8(padapter,
REG_SYS_FUNC_EN + 1, 0x50);
mdelay(10);
}
}
}
/* Reset MAC and Enable 8051 */
rtw_write8(padapter, REG_SYS_FUNC_EN + 1, 0x54);
rtw_write8(padapter, REG_MCUFWDL, 0);
}
if (bWithoutHWSM) {
/*****************************
Without HW auto state machine
g. SYS_CLKR 0x08[15:0] = 0x30A3 disable MAC clock
h. AFE_PLL_CTRL 0x28[7:0] = 0x80 disable AFE PLL
i. AFE_XTAL_CTRL 0x24[15:0] = 0x880F gated AFE DIG_CLOCK
j. SYS_ISO_CTRL 0x00[7:0] = 0xF9 isolated digital to PON
******************************/
/* modify to 0x70A3 by Scott. */
rtw_write16(padapter, REG_SYS_CLKR, 0x70A3);
rtw_write8(padapter, REG_AFE_PLL_CTRL, 0x80);
rtw_write16(padapter, REG_AFE_XTAL_CTRL, 0x880F);
rtw_write8(padapter, REG_SYS_ISO_CTRL, 0xF9);
} else {
/* Disable all RF/BB power */
rtw_write8(padapter, REG_RF_CTRL, 0x00);
}
}
static void _ResetDigitalProcedure1(struct rtw_adapter *padapter,
bool bWithoutHWSM)
{
_ResetDigitalProcedure1_92C(padapter, bWithoutHWSM);
}
static void _ResetDigitalProcedure2(struct rtw_adapter *padapter)
{
/*****************************
k. SYS_FUNC_EN 0x03[7:0] = 0x44 disable ELDR runction
l. SYS_CLKR 0x08[15:0] = 0x3083 disable ELDR clock
m. SYS_ISO_CTRL 0x01[7:0] = 0x83 isolated ELDR to PON
******************************/
/* modify to 0x70a3 by Scott. */
rtw_write16(padapter, REG_SYS_CLKR, 0x70a3);
/* modify to 0x82 by Scott. */
rtw_write8(padapter, REG_SYS_ISO_CTRL + 1, 0x82);
}
static void _DisableAnalog(struct rtw_adapter *padapter, bool bWithoutHWSM)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
u16 value16 = 0;
u8 value8 = 0;
if (bWithoutHWSM) {
/*****************************
n. LDOA15_CTRL 0x20[7:0] = 0x04 disable A15 power
o. LDOV12D_CTRL 0x21[7:0] = 0x54 disable digital core power
r. When driver call disable, the ASIC will turn off remaining
clock automatically
******************************/
rtw_write8(padapter, REG_LDOA15_CTRL, 0x04);
/* rtw_write8(padapter, REG_LDOV12D_CTRL, 0x54); */
value8 = rtw_read8(padapter, REG_LDOV12D_CTRL);
value8 &= (~LDV12_EN);
rtw_write8(padapter, REG_LDOV12D_CTRL, value8);
/* RT_TRACE(COMP_INIT, DBG_LOUD,
(" REG_LDOV12D_CTRL Reg0x21:0x%02x.\n", value8)); */
}
/*****************************
h. SPS0_CTRL 0x11[7:0] = 0x23 enter PFM mode
i. APS_FSMCO 0x04[15:0] = 0x4802 set USB suspend
******************************/
value8 = 0x23;
if (IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID))
value8 |= BIT3;
rtw_write8(padapter, REG_SPS0_CTRL, value8);
if (bWithoutHWSM) {
/* value16 |= (APDM_HOST | FSM_HSUS |/PFM_ALDN); */
/* 2010/08/31 According to Filen description, we need to
use HW to shut down 8051 automatically. */
/* Becasue suspend operatione need the asistance of 8051
to wait for 3ms. */
value16 |= (APDM_HOST | AFSM_HSUS | PFM_ALDN);
} else {
value16 |= (APDM_HOST | AFSM_HSUS | PFM_ALDN);
}
rtw_write16(padapter, REG_APS_FSMCO, value16); /* 0x4802 */
rtw_write8(padapter, REG_RSV_CTRL, 0x0e);
}
/* HW Auto state machine */
s32 CardDisableHWSM(struct rtw_adapter *padapter, u8 resetMCU)
{
int rtStatus = _SUCCESS;
if (padapter->bSurpriseRemoved) {
return rtStatus;
}
/* RF Off Sequence ==== */
_DisableRFAFEAndResetBB(padapter);
/* ==== Reset digital sequence ====== */
_ResetDigitalProcedure1(padapter, false);
/* ==== Pull GPIO PIN to balance level and LED control ====== */
_DisableGPIO(padapter);
/* ==== Disable analog sequence === */
_DisableAnalog(padapter, false);
RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
("======> Card disable finished.\n"));
return rtStatus;
}
/* without HW Auto state machine */
s32 CardDisableWithoutHWSM(struct rtw_adapter *padapter)
{
s32 rtStatus = _SUCCESS;
/* RT_TRACE(COMP_INIT, DBG_LOUD,
("======> Card Disable Without HWSM .\n")); */
if (padapter->bSurpriseRemoved) {
return rtStatus;
}
/* RF Off Sequence ==== */
_DisableRFAFEAndResetBB(padapter);
/* ==== Reset digital sequence ====== */
_ResetDigitalProcedure1(padapter, true);
/* ==== Pull GPIO PIN to balance level and LED control ====== */
_DisableGPIO(padapter);
/* ==== Reset digital sequence ====== */
_ResetDigitalProcedure2(padapter);
/* ==== Disable analog sequence === */
_DisableAnalog(padapter, true);
/* RT_TRACE(COMP_INIT, DBG_LOUD,
("<====== Card Disable Without HWSM .\n")); */
return rtStatus;
}
void Hal_InitPGData(struct rtw_adapter *padapter, u8 *PROMContent)
{
struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
if (false == pEEPROM->bautoload_fail_flag) { /* autoload OK. */
if (!pEEPROM->EepromOrEfuse) {
/* Read EFUSE real map to shadow. */
EFUSE_ShadowMapUpdate23a(padapter, EFUSE_WIFI);
memcpy((void *)PROMContent,
(void *)pEEPROM->efuse_eeprom_data,
HWSET_MAX_SIZE);
}
} else { /* autoload fail */
RT_TRACE(_module_hci_hal_init_c_, _drv_notice_,
("AutoLoad Fail reported from CR9346!!\n"));
/* pHalData->AutoloadFailFlag = true; */
/* update to default value 0xFF */
if (false == pEEPROM->EepromOrEfuse)
EFUSE_ShadowMapUpdate23a(padapter, EFUSE_WIFI);
memcpy((void *)PROMContent, (void *)pEEPROM->efuse_eeprom_data,
HWSET_MAX_SIZE);
}
}
void Hal_EfuseParseIDCode(struct rtw_adapter *padapter, u8 *hwinfo)
{
struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
/* struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); */
u16 EEPROMId;
/* Checl 0x8129 again for making sure autoload status!! */
EEPROMId = le16_to_cpu(*((u16 *) hwinfo));
if (EEPROMId != RTL_EEPROM_ID) {
DBG_8723A("EEPROM ID(%#x) is invalid!!\n", EEPROMId);
pEEPROM->bautoload_fail_flag = true;
} else {
pEEPROM->bautoload_fail_flag = false;
}
RT_TRACE(_module_hal_init_c_, _drv_info_,
("EEPROM ID = 0x%04x\n", EEPROMId));
}
static void Hal_EEValueCheck(u8 EEType, void *pInValue, void *pOutValue)
{
switch (EEType) {
case EETYPE_TX_PWR:
{
u8 *pIn, *pOut;
pIn = (u8 *) pInValue;
pOut = (u8 *) pOutValue;
if (*pIn >= 0 && *pIn <= 63) {
*pOut = *pIn;
} else {
RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
("EETYPE_TX_PWR, value =%d is invalid, set "
"to default = 0x%x\n",
*pIn, EEPROM_Default_TxPowerLevel));
*pOut = EEPROM_Default_TxPowerLevel;
}
}
break;
default:
break;
}
}
static void
Hal_ReadPowerValueFromPROM_8723A(struct txpowerinfo *pwrInfo,
u8 *PROMContent, bool AutoLoadFail)
{
u32 rfPath, eeAddr, group, rfPathMax = 1;
memset(pwrInfo, 0, sizeof(*pwrInfo));
if (AutoLoadFail) {
for (group = 0; group < MAX_CHNL_GROUP; group++) {
for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
pwrInfo->CCKIndex[rfPath][group] =
EEPROM_Default_TxPowerLevel;
pwrInfo->HT40_1SIndex[rfPath][group] =
EEPROM_Default_TxPowerLevel;
pwrInfo->HT40_2SIndexDiff[rfPath][group] =
EEPROM_Default_HT40_2SDiff;
pwrInfo->HT20IndexDiff[rfPath][group] =
EEPROM_Default_HT20_Diff;
pwrInfo->OFDMIndexDiff[rfPath][group] =
EEPROM_Default_LegacyHTTxPowerDiff;
pwrInfo->HT40MaxOffset[rfPath][group] =
EEPROM_Default_HT40_PwrMaxOffset;
pwrInfo->HT20MaxOffset[rfPath][group] =
EEPROM_Default_HT20_PwrMaxOffset;
}
}
pwrInfo->TSSI_A[0] = EEPROM_Default_TSSI;
return;
}
for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
for (group = 0; group < MAX_CHNL_GROUP; group++) {
eeAddr =
EEPROM_CCK_TX_PWR_INX_8723A + (rfPath * 3) + group;
/* pwrInfo->CCKIndex[rfPath][group] =
PROMContent[eeAddr]; */
Hal_EEValueCheck(EETYPE_TX_PWR, &PROMContent[eeAddr],
&pwrInfo->CCKIndex[rfPath][group]);
eeAddr = EEPROM_HT40_1S_TX_PWR_INX_8723A +
(rfPath * 3) + group;
/* pwrInfo->HT40_1SIndex[rfPath][group] =
PROMContent[eeAddr]; */
Hal_EEValueCheck(EETYPE_TX_PWR, &PROMContent[eeAddr],
&pwrInfo->HT40_1SIndex[rfPath][group]);
}
}
for (group = 0; group < MAX_CHNL_GROUP; group++) {
for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
pwrInfo->HT40_2SIndexDiff[rfPath][group] = 0;
pwrInfo->HT20IndexDiff[rfPath][group] =
(PROMContent
[EEPROM_HT20_TX_PWR_INX_DIFF_8723A +
group] >> (rfPath * 4)) & 0xF;
/* 4bit sign number to 8 bit sign number */
if (pwrInfo->HT20IndexDiff[rfPath][group] & BIT3)
pwrInfo->HT20IndexDiff[rfPath][group] |= 0xF0;
pwrInfo->OFDMIndexDiff[rfPath][group] =
(PROMContent[EEPROM_OFDM_TX_PWR_INX_DIFF_8723A +
group] >> (rfPath * 4)) & 0xF;
pwrInfo->HT40MaxOffset[rfPath][group] =
(PROMContent[EEPROM_HT40_MAX_PWR_OFFSET_8723A +
group] >> (rfPath * 4)) & 0xF;
pwrInfo->HT20MaxOffset[rfPath][group] =
(PROMContent[EEPROM_HT20_MAX_PWR_OFFSET_8723A +
group] >> (rfPath * 4)) & 0xF;
}
}
pwrInfo->TSSI_A[0] = PROMContent[EEPROM_TSSI_A_8723A];
}
static u8 Hal_GetChnlGroup(u8 chnl)
{
u8 group = 0;
if (chnl < 3) /* Cjanel 1-3 */
group = 0;
else if (chnl < 9) /* Channel 4-9 */
group = 1;
else /* Channel 10-14 */
group = 2;
return group;
}
void
Hal_EfuseParsetxpowerinfo_8723A(struct rtw_adapter *padapter,
u8 *PROMContent, bool AutoLoadFail)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct txpowerinfo pwrInfo;
u8 rfPath, ch, group, rfPathMax = 1;
u8 pwr, diff;
Hal_ReadPowerValueFromPROM_8723A(&pwrInfo, PROMContent, AutoLoadFail);
for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
group = Hal_GetChnlGroup(ch);
pHalData->TxPwrLevelCck[rfPath][ch] =
pwrInfo.CCKIndex[rfPath][group];
pHalData->TxPwrLevelHT40_1S[rfPath][ch] =
pwrInfo.HT40_1SIndex[rfPath][group];
pHalData->TxPwrHt20Diff[rfPath][ch] =
pwrInfo.HT20IndexDiff[rfPath][group];
pHalData->TxPwrLegacyHtDiff[rfPath][ch] =
pwrInfo.OFDMIndexDiff[rfPath][group];
pHalData->PwrGroupHT20[rfPath][ch] =
pwrInfo.HT20MaxOffset[rfPath][group];
pHalData->PwrGroupHT40[rfPath][ch] =
pwrInfo.HT40MaxOffset[rfPath][group];
pwr = pwrInfo.HT40_1SIndex[rfPath][group];
diff = pwrInfo.HT40_2SIndexDiff[rfPath][group];
pHalData->TxPwrLevelHT40_2S[rfPath][ch] =
(pwr > diff) ? (pwr - diff) : 0;
}
}
for (rfPath = 0; rfPath < RF_PATH_MAX; rfPath++) {
for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
("RF(%u)-Ch(%u) [CCK / HT40_1S / HT40_2S] = "
"[0x%x / 0x%x / 0x%x]\n",
rfPath, ch,
pHalData->TxPwrLevelCck[rfPath][ch],
pHalData->TxPwrLevelHT40_1S[rfPath][ch],
pHalData->TxPwrLevelHT40_2S[rfPath][ch]));
}
}
for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
("RF-A Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch,
pHalData->TxPwrHt20Diff[RF_PATH_A][ch],
pHalData->TxPwrHt20Diff[RF_PATH_A][ch]));
}
for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++)
RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
("RF-A Legacy to Ht40 Diff[%u] = 0x%x\n", ch,
pHalData->TxPwrLegacyHtDiff[RF_PATH_A][ch]));
for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
("RF-B Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch,
pHalData->TxPwrHt20Diff[RF_PATH_B][ch],
pHalData->TxPwrHt20Diff[RF_PATH_B][ch]));
}
for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++)
RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
("RF-B Legacy to HT40 Diff[%u] = 0x%x\n", ch,
pHalData->TxPwrLegacyHtDiff[RF_PATH_B][ch]));
if (!AutoLoadFail) {
struct registry_priv *registry_par = &padapter->registrypriv;
if (registry_par->regulatory_tid == 0xff) {
if (PROMContent[RF_OPTION1_8723A] == 0xff)
pHalData->EEPROMRegulatory = 0;
else
pHalData->EEPROMRegulatory =
PROMContent[RF_OPTION1_8723A] & 0x7;
} else {
pHalData->EEPROMRegulatory =
registry_par->regulatory_tid;
}
} else {
pHalData->EEPROMRegulatory = 0;
}
RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
("EEPROMRegulatory = 0x%x\n", pHalData->EEPROMRegulatory));
if (!AutoLoadFail)
pHalData->bTXPowerDataReadFromEEPORM = true;
}
void
Hal_EfuseParseBTCoexistInfo_8723A(struct rtw_adapter *padapter,
u8 *hwinfo, bool AutoLoadFail)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
u8 tempval;
u32 tmpu4;
if (!AutoLoadFail) {
tmpu4 = rtw_read32(padapter, REG_MULTI_FUNC_CTRL);
if (tmpu4 & BT_FUNC_EN)
pHalData->EEPROMBluetoothCoexist = 1;
else
pHalData->EEPROMBluetoothCoexist = 0;
pHalData->EEPROMBluetoothType = BT_RTL8723A;
/* The following need to be checked with newer version of */
/* eeprom spec */
tempval = hwinfo[RF_OPTION4_8723A];
pHalData->EEPROMBluetoothAntNum = (tempval & 0x1);
pHalData->EEPROMBluetoothAntIsolation = ((tempval & 0x10) >> 4);
pHalData->EEPROMBluetoothRadioShared = ((tempval & 0x20) >> 5);
} else {
pHalData->EEPROMBluetoothCoexist = 0;
pHalData->EEPROMBluetoothType = BT_RTL8723A;
pHalData->EEPROMBluetoothAntNum = Ant_x2;
pHalData->EEPROMBluetoothAntIsolation = 0;
pHalData->EEPROMBluetoothRadioShared = BT_Radio_Shared;
}
#ifdef CONFIG_8723AU_BT_COEXIST
BT_InitHalVars(padapter);
#endif
}
void
Hal_EfuseParseEEPROMVer(struct rtw_adapter *padapter,
u8 *hwinfo, bool AutoLoadFail)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
if (!AutoLoadFail)
pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_8723A];
else
pHalData->EEPROMVersion = 1;
RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
("Hal_EfuseParseEEPROMVer(), EEVer = %d\n",
pHalData->EEPROMVersion));
}
void
rtl8723a_EfuseParseChnlPlan(struct rtw_adapter *padapter,
u8 *hwinfo, bool AutoLoadFail)
{
padapter->mlmepriv.ChannelPlan =
hal_com_get_channel_plan23a(padapter, hwinfo ?
hwinfo[EEPROM_ChannelPlan_8723A]:0xFF,
padapter->registrypriv.channel_plan,
RT_CHANNEL_DOMAIN_WORLD_WIDE_13,
AutoLoadFail);
DBG_8723A("mlmepriv.ChannelPlan = 0x%02x\n",
padapter->mlmepriv.ChannelPlan);
}
void
Hal_EfuseParseCustomerID(struct rtw_adapter *padapter,
u8 *hwinfo, bool AutoLoadFail)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
if (!AutoLoadFail) {
pHalData->EEPROMCustomerID = hwinfo[EEPROM_CustomID_8723A];
pHalData->EEPROMSubCustomerID =
hwinfo[EEPROM_SubCustomID_8723A];
} else {
pHalData->EEPROMCustomerID = 0;
pHalData->EEPROMSubCustomerID = 0;
}
RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
("EEPROM Customer ID: 0x%2x\n", pHalData->EEPROMCustomerID));
RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
("EEPROM SubCustomer ID: 0x%02x\n",
pHalData->EEPROMSubCustomerID));
}
void
Hal_EfuseParseAntennaDiversity(struct rtw_adapter *padapter,
u8 *hwinfo, bool AutoLoadFail)
{
}
void
Hal_EfuseParseRateIndicationOption(struct rtw_adapter *padapter,
u8 *hwinfo, bool AutoLoadFail)
{
}
void
Hal_EfuseParseXtal_8723A(struct rtw_adapter *pAdapter,
u8 *hwinfo, u8 AutoLoadFail)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
if (!AutoLoadFail) {
pHalData->CrystalCap = hwinfo[EEPROM_XTAL_K_8723A];
if (pHalData->CrystalCap == 0xFF)
pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723A;
} else {
pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723A;
}
RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
("%s: CrystalCap = 0x%2x\n", __func__,
pHalData->CrystalCap));
}
void
Hal_EfuseParseThermalMeter_8723A(struct rtw_adapter *padapter,
u8 *PROMContent, u8 AutoloadFail)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
/* */
/* ThermalMeter from EEPROM */
/* */
if (false == AutoloadFail)
pHalData->EEPROMThermalMeter =
PROMContent[EEPROM_THERMAL_METER_8723A];
else
pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
if ((pHalData->EEPROMThermalMeter == 0xff) || (true == AutoloadFail)) {
pHalData->bAPKThermalMeterIgnore = true;
pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
}
DBG_8723A("%s: ThermalMeter = 0x%x\n", __func__,
pHalData->EEPROMThermalMeter);
}
void Hal_InitChannelPlan23a(struct rtw_adapter *padapter)
{
}
static void rtl8723a_cal_txdesc_chksum(struct tx_desc *ptxdesc)
{
u16 *usPtr = (u16 *) ptxdesc;
u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */
u32 index;
u16 checksum = 0;
/* Clear first */
ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
for (index = 0; index < count; index++) {
checksum ^= le16_to_cpu(*(usPtr + index));
}
ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff);
}
static void fill_txdesc_sectype(struct pkt_attrib *pattrib,
struct txdesc_8723a *ptxdesc)
{
if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
switch (pattrib->encrypt) {
/* SEC_TYPE */
case _WEP40_:
case _WEP104_:
case _TKIP_:
case _TKIP_WTMIC_:
ptxdesc->sectype = 1;
break;
case _AES_:
ptxdesc->sectype = 3;
break;
case _NO_PRIVACY_:
default:
break;
}
}
}
static void fill_txdesc_vcs(struct pkt_attrib *pattrib,
struct txdesc_8723a *ptxdesc)
{
/* DBG_8723A("cvs_mode =%d\n", pattrib->vcs_mode); */
switch (pattrib->vcs_mode) {
case RTS_CTS:
ptxdesc->rtsen = 1;
break;
case CTS_TO_SELF:
ptxdesc->cts2self = 1;
break;
case NONE_VCS:
default:
break;
}
if (pattrib->vcs_mode) {
ptxdesc->hw_rts_en = 1; /* ENABLE HW RTS */
/* Set RTS BW */
if (pattrib->ht_en) {
if (pattrib->bwmode & HT_CHANNEL_WIDTH_40)
ptxdesc->rts_bw = 1;
switch (pattrib->ch_offset) {
case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
ptxdesc->rts_sc = 0;
break;
case HAL_PRIME_CHNL_OFFSET_LOWER:
ptxdesc->rts_sc = 1;
break;
case HAL_PRIME_CHNL_OFFSET_UPPER:
ptxdesc->rts_sc = 2;
break;
default:
ptxdesc->rts_sc = 3; /* Duplicate */
break;
}
}
}
}
static void fill_txdesc_phy(struct pkt_attrib *pattrib,
struct txdesc_8723a *ptxdesc)
{
if (pattrib->ht_en) {
if (pattrib->bwmode & HT_CHANNEL_WIDTH_40)
ptxdesc->data_bw = 1;
switch (pattrib->ch_offset) {
case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
ptxdesc->data_sc = 0;
break;
case HAL_PRIME_CHNL_OFFSET_LOWER:
ptxdesc->data_sc = 1;
break;
case HAL_PRIME_CHNL_OFFSET_UPPER:
ptxdesc->data_sc = 2;
break;
default:
ptxdesc->data_sc = 3; /* Duplicate */
break;
}
}
}
static void rtl8723a_fill_default_txdesc(struct xmit_frame *pxmitframe,
u8 *pbuf)
{
struct rtw_adapter *padapter;
struct hal_data_8723a *pHalData;
struct dm_priv *pdmpriv;
struct mlme_ext_priv *pmlmeext;
struct mlme_ext_info *pmlmeinfo;
struct pkt_attrib *pattrib;
struct txdesc_8723a *ptxdesc;
s32 bmcst;
padapter = pxmitframe->padapter;
pHalData = GET_HAL_DATA(padapter);
pdmpriv = &pHalData->dmpriv;
pmlmeext = &padapter->mlmeextpriv;
pmlmeinfo = &pmlmeext->mlmext_info;
pattrib = &pxmitframe->attrib;
bmcst = is_multicast_ether_addr(pattrib->ra);
ptxdesc = (struct txdesc_8723a *)pbuf;
if (pxmitframe->frame_tag == DATA_FRAMETAG) {
ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
if (pattrib->ampdu_en == true)
ptxdesc->agg_en = 1; /* AGG EN */
else
ptxdesc->bk = 1; /* AGG BK */
ptxdesc->qsel = pattrib->qsel;
ptxdesc->rate_id = pattrib->raid;
fill_txdesc_sectype(pattrib, ptxdesc);
ptxdesc->seq = pattrib->seqnum;
if ((pattrib->ether_type != 0x888e) &&
(pattrib->ether_type != 0x0806) &&
(pattrib->dhcp_pkt != 1)) {
/* Non EAP & ARP & DHCP type data packet */
fill_txdesc_vcs(pattrib, ptxdesc);
fill_txdesc_phy(pattrib, ptxdesc);
ptxdesc->rtsrate = 8; /* RTS Rate = 24M */
ptxdesc->data_ratefb_lmt = 0x1F;
ptxdesc->rts_ratefb_lmt = 0xF;
/* use REG_INIDATA_RATE_SEL value */
ptxdesc->datarate =
pdmpriv->INIDATA_RATE[pattrib->mac_id];
} else {
/* EAP data packet and ARP packet. */
/* Use the 1M data rate to send the EAP/ARP packet. */
/* This will maybe make the handshake smooth. */
ptxdesc->bk = 1; /* AGG BK */
ptxdesc->userate = 1; /* driver uses rate */
if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
ptxdesc->data_short = 1;
ptxdesc->datarate = MRateToHwRate23a(pmlmeext->tx_rate);
}
} else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
/* RT_TRACE(_module_hal_xmit_c_, _drv_notice_,
("%s: MGNT_FRAMETAG\n", __func__)); */
ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
ptxdesc->qsel = pattrib->qsel;
ptxdesc->rate_id = pattrib->raid; /* Rate ID */
ptxdesc->seq = pattrib->seqnum;
ptxdesc->userate = 1; /* driver uses rate, 1M */
ptxdesc->rty_lmt_en = 1; /* retry limit enable */
ptxdesc->data_rt_lmt = 6; /* retry limit = 6 */
/* CCX-TXRPT ack for xmit mgmt frames. */
if (pxmitframe->ack_report)
ptxdesc->ccx = 1;
ptxdesc->datarate = MRateToHwRate23a(pmlmeext->tx_rate);
} else if (pxmitframe->frame_tag == TXAGG_FRAMETAG) {
RT_TRACE(_module_hal_xmit_c_, _drv_warning_,
("%s: TXAGG_FRAMETAG\n", __func__));
} else {
RT_TRACE(_module_hal_xmit_c_, _drv_warning_,
("%s: frame_tag = 0x%x\n", __func__,
pxmitframe->frame_tag));
ptxdesc->macid = 4; /* CAM_ID(MAC_ID) */
ptxdesc->rate_id = 6; /* Rate ID */
ptxdesc->seq = pattrib->seqnum;
ptxdesc->userate = 1; /* driver uses rate */
ptxdesc->datarate = MRateToHwRate23a(pmlmeext->tx_rate);
}
ptxdesc->pktlen = pattrib->last_txcmdsz;
ptxdesc->offset = TXDESC_SIZE + OFFSET_SZ;
if (bmcst)
ptxdesc->bmc = 1;
ptxdesc->ls = 1;
ptxdesc->fs = 1;
ptxdesc->own = 1;
/* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. */
/* (1) The sequence number of each non-Qos frame / broadcast /
* multicast / mgnt frame should be controled by Hw because Fw
* will also send null data which we cannot control when Fw LPS enable.
* --> default enable non-Qos data sequense number.
2010.06.23. by tynli. */
/* (2) Enable HW SEQ control for beacon packet,
* because we use Hw beacon. */
/* (3) Use HW Qos SEQ to control the seq num of Ext port
* non-Qos packets. */
/* 2010.06.23. Added by tynli. */
if (!pattrib->qos_en) {
/* Hw set sequence number */
ptxdesc->hwseq_en = 1; /* HWSEQ_EN */
ptxdesc->hwseq_sel = 0; /* HWSEQ_SEL */
}
}
/*
* Description:
*
* Parameters:
* pxmitframe xmitframe
* pbuf where to fill tx desc
*/
void rtl8723a_update_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf)
{
struct tx_desc *pdesc;
pdesc = (struct tx_desc *)pbuf;
memset(pdesc, 0, sizeof(struct tx_desc));
rtl8723a_fill_default_txdesc(pxmitframe, pbuf);
pdesc->txdw0 = cpu_to_le32(pdesc->txdw0);
pdesc->txdw1 = cpu_to_le32(pdesc->txdw1);
pdesc->txdw2 = cpu_to_le32(pdesc->txdw2);
pdesc->txdw3 = cpu_to_le32(pdesc->txdw3);
pdesc->txdw4 = cpu_to_le32(pdesc->txdw4);
pdesc->txdw5 = cpu_to_le32(pdesc->txdw5);
pdesc->txdw6 = cpu_to_le32(pdesc->txdw6);
pdesc->txdw7 = cpu_to_le32(pdesc->txdw7);
rtl8723a_cal_txdesc_chksum(pdesc);
}
/*
* Description: In normal chip, we should send some packet to Hw which
* will be used by Fw in FW LPS mode. The function is to fill the Tx
* descriptor of this packets, then
*/
/* Fw can tell Hw to send these packet derectly. */
/* Added by tynli. 2009.10.15. */
/* */
void rtl8723a_fill_fake_txdesc(struct rtw_adapter *padapter, u8 *pDesc,
u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull)
{
struct tx_desc *ptxdesc;
/* Clear all status */
ptxdesc = (struct tx_desc *)pDesc;
memset(pDesc, 0, TXDESC_SIZE);
/* offset 0 */
/* own, bFirstSeg, bLastSeg; */
ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
/* 32 bytes for TX Desc */
ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) <<
OFFSET_SHT) & 0x00ff0000);
/* Buffer size + command header */
ptxdesc->txdw0 |= cpu_to_le32(BufferLen & 0x0000ffff);
/* offset 4 */
/* Fixed queue of Mgnt queue */
ptxdesc->txdw1 |= cpu_to_le32((QSLT_MGNT << QSEL_SHT) & 0x00001f00);
/* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed
to error vlaue by Hw. */
if (IsPsPoll) {
ptxdesc->txdw1 |= cpu_to_le32(NAVUSEHDR);
} else {
/* Hw set sequence number */
ptxdesc->txdw4 |= cpu_to_le32(BIT(7));
/* set bit3 to 1. Suugested by TimChen. 2009.12.29. */
ptxdesc->txdw3 |= cpu_to_le32((8 << 28));
}
if (true == IsBTQosNull) {
ptxdesc->txdw2 |= cpu_to_le32(BIT(23)); /* BT NULL */
}
/* offset 16 */
ptxdesc->txdw4 |= cpu_to_le32(BIT(8)); /* driver uses rate */
/* USB interface drop packet if the checksum of descriptor isn't
correct. */
/* Using this checksum can let hardware recovery from packet bulk
out error (e.g. Cancel URC, Bulk out error.). */
rtl8723a_cal_txdesc_chksum(ptxdesc);
}
static void hw_var_set_opmode(struct rtw_adapter *padapter, u8 mode)
{
u8 val8;
if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) {
StopTxBeacon(padapter);
/* disable atim wnd */
val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_ATIM;
SetBcnCtrlReg23a(padapter, val8, ~val8);
} else if ((mode == _HW_STATE_ADHOC_) /*|| (mode == _HW_STATE_AP_) */) {
ResumeTxBeacon(padapter);
val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB;
SetBcnCtrlReg23a(padapter, val8, ~val8);
} else if (mode == _HW_STATE_AP_) {
#ifdef CONFIG_8723AU_BT_COEXIST
/* add NULL Data and BT NULL Data Packets to FW RSVD Page */
rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(padapter);
#endif
ResumeTxBeacon(padapter);
val8 = DIS_TSF_UDT | DIS_BCNQ_SUB;
SetBcnCtrlReg23a(padapter, val8, ~val8);
/* Set RCR */
/* rtw_write32(padapter, REG_RCR, 0x70002a8e);
CBSSID_DATA must set to 0 */
/* CBSSID_DATA must set to 0 */
rtw_write32(padapter, REG_RCR, 0x7000228e);
/* enable to rx data frame */
rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
/* enable to rx ps-poll */
rtw_write16(padapter, REG_RXFLTMAP1, 0x0400);
/* Beacon Control related register for first time */
rtw_write8(padapter, REG_BCNDMATIM, 0x02); /* 2ms */
rtw_write8(padapter, REG_DRVERLYINT, 0x05); /* 5ms */
rtw_write8(padapter, REG_ATIMWND, 0x0a); /* 10ms for port0 */
rtw_write16(padapter, REG_BCNTCFG, 0x00);
rtw_write16(padapter, REG_TBTT_PROHIBIT, 0xff04);
/* +32767 (~32ms) */
rtw_write16(padapter, REG_TSFTR_SYN_OFFSET, 0x7fff);
/* reset TSF */
rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(0));
/* enable BCN Function */
/* don't enable update TSF (due to TSF update when
beacon/probe rsp are received) */
val8 = DIS_TSF_UDT | EN_BCN_FUNCTION |
EN_TXBCN_RPT | DIS_BCNQ_SUB;
SetBcnCtrlReg23a(padapter, val8, ~val8);
}
val8 = rtw_read8(padapter, MSR);
val8 = (val8 & 0xC) | mode;
rtw_write8(padapter, MSR, val8);
}
static void hw_var_set_macaddr(struct rtw_adapter *padapter, u8 *val)
{
u8 idx = 0;
u32 reg_macid;
reg_macid = REG_MACID;
for (idx = 0; idx < 6; idx++)
rtw_write8(padapter, (reg_macid + idx), val[idx]);
}
static void hw_var_set_bssid(struct rtw_adapter *padapter, u8 *val)
{
u8 idx = 0;
u32 reg_bssid;
reg_bssid = REG_BSSID;
for (idx = 0; idx < 6; idx++)
rtw_write8(padapter, (reg_bssid + idx), val[idx]);
}
static void hw_var_set_correct_tsf(struct rtw_adapter *padapter)
{
u64 tsf;
u32 reg_tsftr;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
/* tsf = pmlmeext->TSFValue - ((u32)pmlmeext->TSFValue %
(pmlmeinfo->bcn_interval*1024)) - 1024; us */
tsf = pmlmeext->TSFValue -
rtw_modular6423a(pmlmeext->TSFValue,
(pmlmeinfo->bcn_interval * 1024)) - 1024; /* us */
if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
/* pHalData->RegTxPause |= STOP_BCNQ;BIT(6) */
/* rtw_write8(padapter, REG_TXPAUSE,
(rtw_read8(Adapter, REG_TXPAUSE)|BIT(6))); */
StopTxBeacon(padapter);
}
reg_tsftr = REG_TSFTR;
/* disable related TSF function */
SetBcnCtrlReg23a(padapter, 0, EN_BCN_FUNCTION);
rtw_write32(padapter, reg_tsftr, tsf);
rtw_write32(padapter, reg_tsftr + 4, tsf >> 32);
/* enable related TSF function */
SetBcnCtrlReg23a(padapter, EN_BCN_FUNCTION, 0);
if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
ResumeTxBeacon(padapter);
}
static void hw_var_set_mlme_disconnect(struct rtw_adapter *padapter)
{
/* reject all data frames */
rtw_write16(padapter, REG_RXFLTMAP2, 0);
/* reset TSF */
rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(0));
/* disable update TSF */
SetBcnCtrlReg23a(padapter, DIS_TSF_UDT, 0);
}
static void hw_var_set_mlme_join(struct rtw_adapter *padapter, u8 type)
{
u8 RetryLimit = 0x30;
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
if (type == 0) { /* prepare to join */
u32 v32;
/* enable to rx data frame.Accept all data frame */
/* rtw_write32(padapter, REG_RCR,
rtw_read32(padapter, REG_RCR)|RCR_ADF); */
rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
v32 = rtw_read32(padapter, REG_RCR);
v32 |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;
rtw_write32(padapter, REG_RCR, v32);
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
RetryLimit =
(pHalData->CustomerID == RT_CID_CCX) ? 7 : 48;
else /* Ad-hoc Mode */
RetryLimit = 0x7;
} else if (type == 1) { /* joinbss_event callback when join res < 0 */
/* config RCR to receive different BSSID & not to
receive data frame during linking */
rtw_write16(padapter, REG_RXFLTMAP2, 0);
} else if (type == 2) { /* sta add event callback */
/* enable update TSF */
SetBcnCtrlReg23a(padapter, 0, DIS_TSF_UDT);
if (check_fwstate(pmlmepriv,
WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) {
/* fixed beacon issue for 8191su........... */
rtw_write8(padapter, 0x542, 0x02);
RetryLimit = 0x7;
}
}
rtw_write16(padapter, REG_RL,
RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit <<
RETRY_LIMIT_LONG_SHIFT);
#ifdef CONFIG_8723AU_BT_COEXIST
switch (type) {
case 0:
/* prepare to join */
BT_WifiAssociateNotify(padapter, true);
break;
case 1:
/* joinbss_event callback when join res < 0 */
BT_WifiAssociateNotify(padapter, false);
break;
case 2:
/* sta add event callback */
/* BT_WifiMediaStatusNotify(padapter, RT_MEDIA_CONNECT); */
break;
}
#endif
}
void SetHwReg8723A(struct rtw_adapter *padapter, u8 variable, u8 *val)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
u32 *val32 = (u32 *)val;
switch (variable) {
case HW_VAR_MEDIA_STATUS:
rtl8723a_set_media_status(padapter, *val);
break;
case HW_VAR_MEDIA_STATUS1:
rtl8723a_set_media_status1(padapter, *val);
break;
case HW_VAR_SET_OPMODE:
hw_var_set_opmode(padapter, *val);
break;
case HW_VAR_MAC_ADDR:
hw_var_set_macaddr(padapter, val);
break;
case HW_VAR_BSSID:
hw_var_set_bssid(padapter, val);
break;
case HW_VAR_BASIC_RATE:
HalSetBrateCfg23a(padapter, val);
break;
case HW_VAR_TXPAUSE:
rtl8723a_set_tx_pause(padapter, *val);
break;
case HW_VAR_BCN_FUNC:
rtl8723a_set_bcn_func(padapter, *val);
break;
case HW_VAR_CORRECT_TSF:
hw_var_set_correct_tsf(padapter);
break;
case HW_VAR_CHECK_BSSID:
rtl8723a_check_bssid(padapter, *val);
break;
case HW_VAR_MLME_DISCONNECT:
hw_var_set_mlme_disconnect(padapter);
break;
case HW_VAR_MLME_SITESURVEY:
rtl8723a_mlme_sitesurvey(padapter, *val);
break;
case HW_VAR_MLME_JOIN:
hw_var_set_mlme_join(padapter, *val);
break;
case HW_VAR_ON_RCR_AM:
rtl8723a_on_rcr_am(padapter);
break;
case HW_VAR_OFF_RCR_AM:
rtl8723a_off_rcr_am(padapter);
break;
case HW_VAR_BEACON_INTERVAL:
rtl8723a_set_beacon_interval(padapter, *((u16 *) val));
break;
case HW_VAR_SLOT_TIME:
rtl8723a_set_slot_time(padapter, *val);
break;
case HW_VAR_RESP_SIFS:
rtl8723a_set_resp_sifs(padapter, val[0], val[1],
val[2], val[3]);
break;
case HW_VAR_ACK_PREAMBLE:
rtl8723a_ack_preamble(padapter, *val);
break;
case HW_VAR_SEC_CFG:
rtl8723a_set_sec_cfg(padapter, *val);
break;
case HW_VAR_DM_FLAG:
rtl8723a_odm_support_ability_write(padapter, *val32);
break;
case HW_VAR_DM_FUNC_OP:
rtl8723a_odm_support_ability_backup(padapter, *val);
break;
case HW_VAR_DM_FUNC_SET:
rtl8723a_odm_support_ability_set(padapter, *val32);
break;
case HW_VAR_DM_FUNC_CLR:
rtl8723a_odm_support_ability_clr(padapter, *val32);
break;
case HW_VAR_CAM_EMPTY_ENTRY:
rtl8723a_cam_empty_entry(padapter, *val);
break;
case HW_VAR_CAM_INVALID_ALL:
rtl8723a_cam_invalid_all(padapter);
break;
case HW_VAR_CAM_WRITE:
rtl8723a_cam_write(padapter, val32[0], val32[1]);
break;
case HW_VAR_AC_PARAM_VO:
rtl8723a_set_ac_param_vo(padapter, *val32);
break;
case HW_VAR_AC_PARAM_VI:
rtl8723a_set_ac_param_vi(padapter, *val32);
break;
case HW_VAR_AC_PARAM_BE:
rtl8723a_set_ac_param_be(padapter, *val32);
break;
case HW_VAR_AC_PARAM_BK:
rtl8723a_set_ac_param_bk(padapter, *val32);
break;
case HW_VAR_ACM_CTRL:
rtl8723a_set_acm_ctrl(padapter, *val);
break;
case HW_VAR_AMPDU_MIN_SPACE:
rtl8723a_set_ampdu_min_space(padapter, *val);
break;
case HW_VAR_AMPDU_FACTOR:
rtl8723a_set_ampdu_factor(padapter, *val);
break;
case HW_VAR_RXDMA_AGG_PG_TH:
rtl8723a_set_rxdma_agg_pg_th(padapter, *val);
break;
case HW_VAR_H2C_FW_PWRMODE:
rtl8723a_set_FwPwrMode_cmd(padapter, *val);
break;
case HW_VAR_H2C_FW_JOINBSSRPT:
rtl8723a_set_FwJoinBssReport_cmd(padapter, *val);
break;
#ifdef CONFIG_8723AU_P2P
case HW_VAR_H2C_FW_P2P_PS_OFFLOAD:
rtl8723a_set_p2p_ps_offload_cmd(padapter, *val);
break;
#endif /* CONFIG_8723AU_P2P */
case HW_VAR_INITIAL_GAIN:
rtl8723a_set_initial_gain(padapter, *val32);
break;
case HW_VAR_EFUSE_BYTES:
pHalData->EfuseUsedBytes = *((u16 *) val);
break;
case HW_VAR_EFUSE_BT_BYTES:
pHalData->BTEfuseUsedBytes = *((u16 *) val);
break;
case HW_VAR_FIFO_CLEARN_UP:
rtl8723a_fifo_cleanup(padapter);
break;
case HW_VAR_CHECK_TXBUF:
break;
case HW_VAR_APFM_ON_MAC:
rtl8723a_set_apfm_on_mac(padapter, *val);
break;
case HW_VAR_NAV_UPPER:
rtl8723a_set_nav_upper(padapter, *val32);
break;
case HW_VAR_BCN_VALID:
rtl8723a_bcn_valid(padapter);
break;
default:
break;
}
}
void GetHwReg8723A(struct rtw_adapter *padapter, u8 variable, u8 *val)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
switch (variable) {
case HW_VAR_BASIC_RATE:
*((u16 *) val) = pHalData->BasicRateSet;
break;
case HW_VAR_TXPAUSE:
*val = rtw_read8(padapter, REG_TXPAUSE);
break;
case HW_VAR_BCN_VALID:
/* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */
val[0] = (BIT0 & rtw_read8(padapter, REG_TDECTRL + 2)) ? true :
false;
break;
case HW_VAR_RF_TYPE:
*val = pHalData->rf_type;
break;
case HW_VAR_DM_FLAG:
{
struct dm_odm_t *podmpriv = &pHalData->odmpriv;
*((u32 *) val) = podmpriv->SupportAbility;
}
break;
case HW_VAR_FWLPS_RF_ON:
{
/* When we halt NIC, we should check if FW LPS is leave. */
u32 valRCR;
if ((padapter->bSurpriseRemoved == true) ||
(padapter->pwrctrlpriv.rf_pwrstate == rf_off)) {
/* If it is in HW/SW Radio OFF or IPS state, we do
not check Fw LPS Leave, because Fw is unload. */
*val = true;
} else {
valRCR = rtw_read32(padapter, REG_RCR);
valRCR &= 0x00070000;
if (valRCR)
*val = false;
else
*val = true;
}
}
break;
case HW_VAR_EFUSE_BYTES:
*((u16 *) val) = pHalData->EfuseUsedBytes;
break;
case HW_VAR_EFUSE_BT_BYTES:
*((u16 *) val) = pHalData->BTEfuseUsedBytes;
break;
case HW_VAR_APFM_ON_MAC:
*val = pHalData->bMacPwrCtrlOn;
break;
case HW_VAR_CHK_HI_QUEUE_EMPTY:
*val =
((rtw_read32(padapter, REG_HGQ_INFORMATION) & 0x0000ff00) ==
0) ? true : false;
break;
}
}
#ifdef CONFIG_8723AU_BT_COEXIST
void rtl8723a_SingleDualAntennaDetection(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData;
struct dm_odm_t *pDM_Odm;
struct sw_ant_sw *pDM_SWAT_Table;
u8 i;
pHalData = GET_HAL_DATA(padapter);
pDM_Odm = &pHalData->odmpriv;
pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table;
/* */
/* <Roger_Notes> RTL8723A Single and Dual antenna dynamic detection
mechanism when RF power state is on. */
/* We should take power tracking, IQK, LCK, RCK RF read/write
operation into consideration. */
/* 2011.12.15. */
/* */
if (!pHalData->bAntennaDetected) {
u8 btAntNum = BT_GetPGAntNum(padapter);
/* Set default antenna B status */
if (btAntNum == Ant_x2)
pDM_SWAT_Table->ANTB_ON = true;
else if (btAntNum == Ant_x1)
pDM_SWAT_Table->ANTB_ON = false;
else
pDM_SWAT_Table->ANTB_ON = true;
if (pHalData->CustomerID != RT_CID_TOSHIBA) {
for (i = 0; i < MAX_ANTENNA_DETECTION_CNT; i++) {
if (ODM_SingleDualAntennaDetection
(&pHalData->odmpriv, ANTTESTALL) == true)
break;
}
/* Set default antenna number for BT coexistence */
if (btAntNum == Ant_x2)
BT_SetBtCoexCurrAntNum(padapter,
pDM_SWAT_Table->
ANTB_ON ? 2 : 1);
}
pHalData->bAntennaDetected = true;
}
}
#endif /* CONFIG_8723AU_BT_COEXIST */
void rtl8723a_clone_haldata(struct rtw_adapter *dst_adapter,
struct rtw_adapter *src_adapter)
{
memcpy(dst_adapter->HalData, src_adapter->HalData,
dst_adapter->hal_data_sz);
}
void rtl8723a_start_thread(struct rtw_adapter *padapter)
{
}
void rtl8723a_stop_thread(struct rtw_adapter *padapter)
{
}
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#define _RTL8723A_PHYCFG_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <rtl8723a_hal.h>
/*---------------------------Define Local Constant---------------------------*/
/* Channel switch:The size of command tables for switch channel*/
#define MAX_PRECMD_CNT 16
#define MAX_RFDEPENDCMD_CNT 16
#define MAX_POSTCMD_CNT 16
#define MAX_DOZE_WAITING_TIMES_9x 64
/*---------------------------Define Local Constant---------------------------*/
/*------------------------Define global variable-----------------------------*/
/*------------------------Define local variable------------------------------*/
/*--------------------Define export function prototype-----------------------*/
/* Please refer to header file */
/*--------------------Define export function prototype-----------------------*/
/*----------------------------Function Body----------------------------------*/
/* */
/* 1. BB register R/W API */
/* */
/**
* Function: phy_CalculateBitShift
*
* OverView: Get shifted position of the BitMask
*
* Input:
* u32 BitMask,
*
* Output: none
* Return: u32 Return the shift bit bit position of the mask
*/
static u32 phy_CalculateBitShift(u32 BitMask)
{
u32 i;
for (i = 0; i <= 31; i++) {
if (((BitMask>>i) & 0x1) == 1)
break;
}
return i;
}
/**
* Function: PHY_QueryBBReg
*
* OverView: Read "sepcific bits" from BB register
*
* Input:
* struct rtw_adapter * Adapter,
* u32 RegAddr, Target address to be readback
* u32 BitMask Target bit position in the
* target address to be readback
* Output:
* None
* Return:
* u32 Data The readback register value
* Note:
* This function is equal to "GetRegSetting" in PHY programming guide
*/
u32
PHY_QueryBBReg(struct rtw_adapter *Adapter, u32 RegAddr, u32 BitMask)
{
u32 ReturnValue = 0, OriginalValue, BitShift;
OriginalValue = rtw_read32(Adapter, RegAddr);
BitShift = phy_CalculateBitShift(BitMask);
ReturnValue = (OriginalValue & BitMask) >> BitShift;
return ReturnValue;
}
/**
* Function: PHY_SetBBReg
*
* OverView: Write "Specific bits" to BB register (page 8~)
*
* Input:
* struct rtw_adapter * Adapter,
* u32 RegAddr, Target address to be modified
* u32 BitMask Target bit position in the
* target address to be modified
* u32 Data The new register value in the
* target bit position of the
* target address
*
* Output:
* None
* Return:
* None
* Note:
* This function is equal to "PutRegSetting" in PHY programming guide
*/
void
PHY_SetBBReg(struct rtw_adapter *Adapter, u32 RegAddr, u32 BitMask, u32 Data)
{
u32 OriginalValue, BitShift;
/* RT_TRACE(COMP_RF, DBG_TRACE, ("--->PHY_SetBBReg(): RegAddr(%#lx), BitMask(%#lx), Data(%#lx)\n", RegAddr, BitMask, Data)); */
if (BitMask != bMaskDWord) {/* if not "double word" write */
OriginalValue = rtw_read32(Adapter, RegAddr);
BitShift = phy_CalculateBitShift(BitMask);
Data = ((OriginalValue & (~BitMask)) | (Data << BitShift));
}
rtw_write32(Adapter, RegAddr, Data);
/* RTPRINT(FPHY, PHY_BBW, ("BBW MASK = 0x%lx Addr[0x%lx]= 0x%lx\n", BitMask, RegAddr, Data)); */
/* RT_TRACE(COMP_RF, DBG_TRACE, ("<---PHY_SetBBReg(): RegAddr(%#lx), BitMask(%#lx), Data(%#lx)\n", RegAddr, BitMask, Data)); */
}
/* */
/* 2. RF register R/W API */
/* */
/**
* Function: phy_RFSerialRead
*
* OverView: Read regster from RF chips
*
* Input:
* struct rtw_adapter * Adapter,
* enum RF_RADIO_PATH eRFPath, Radio path of A/B/C/D
* u32 Offset, The target address to be read
*
* Output: None
* Return: u32 reback value
* Note: Threre are three types of serial operations:
* 1. Software serial write
* 2. Hardware LSSI-Low Speed Serial Interface
* 3. Hardware HSSI-High speed
* serial write. Driver need to implement (1) and (2).
* This function is equal to the combination of RF_ReadReg() and
* RFLSSIRead()
*/
static u32
phy_RFSerialRead(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath,
u32 Offset)
{
u32 retValue = 0;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct bb_reg_define *pPhyReg = &pHalData->PHYRegDef[eRFPath];
u32 NewOffset;
u32 tmplong, tmplong2;
u8 RfPiEnable = 0;
/* */
/* Make sure RF register offset is correct */
/* */
Offset &= 0x3f;
/* */
/* Switch page for 8256 RF IC */
/* */
NewOffset = Offset;
/* 2009/06/17 MH We can not execute IO for power save or
other accident mode. */
/* if (RT_CANNOT_IO(Adapter)) */
/* */
/* RTPRINT(FPHY, PHY_RFR, ("phy_RFSerialRead return all one\n")); */
/* return 0xFFFFFFFF; */
/* */
/* For 92S LSSI Read RFLSSIRead */
/* For RF A/B write 0x824/82c(does not work in the future) */
/* We must use 0x824 for RF A and B to execute read trigger */
tmplong = PHY_QueryBBReg(Adapter, rFPGA0_XA_HSSIParameter2, bMaskDWord);
if (eRFPath == RF_PATH_A)
tmplong2 = tmplong;
else
tmplong2 = PHY_QueryBBReg(Adapter, pPhyReg->rfHSSIPara2,
bMaskDWord);
tmplong2 = (tmplong2 & ~bLSSIReadAddress) |
(NewOffset << 23) | bLSSIReadEdge; /* T65 RF */
PHY_SetBBReg(Adapter, rFPGA0_XA_HSSIParameter2,
bMaskDWord, tmplong & (~bLSSIReadEdge));
udelay(10);/* PlatformStallExecution(10); */
PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, bMaskDWord, tmplong2);
udelay(100);/* PlatformStallExecution(100); */
PHY_SetBBReg(Adapter, rFPGA0_XA_HSSIParameter2, bMaskDWord,
tmplong | bLSSIReadEdge);
udelay(10);/* PlatformStallExecution(10); */
if (eRFPath == RF_PATH_A)
RfPiEnable = (u8)PHY_QueryBBReg(Adapter,
rFPGA0_XA_HSSIParameter1, BIT8);
else if (eRFPath == RF_PATH_B)
RfPiEnable = (u8)PHY_QueryBBReg(Adapter,
rFPGA0_XB_HSSIParameter1, BIT8);
if (RfPiEnable) {
/* Read from BBreg8b8, 12 bits for 8190, 20bits for T65 RF */
retValue = PHY_QueryBBReg(Adapter, pPhyReg->rfLSSIReadBackPi,
bLSSIReadBackData);
/* DBG_8723A("Readback from RF-PI : 0x%x\n", retValue); */
} else {
/* Read from BBreg8a0, 12 bits for 8190, 20 bits for T65 RF */
retValue = PHY_QueryBBReg(Adapter, pPhyReg->rfLSSIReadBack,
bLSSIReadBackData);
/* DBG_8723A("Readback from RF-SI : 0x%x\n", retValue); */
}
/* DBG_8723A("RFR-%d Addr[0x%x]= 0x%x\n", eRFPath, pPhyReg->rfLSSIReadBack, retValue); */
return retValue;
}
/**
* Function: phy_RFSerialWrite
*
* OverView: Write data to RF register (page 8~)
*
* Input:
* struct rtw_adapter * Adapter,
* enum RF_RADIO_PATH eRFPath, Radio path of A/B/C/D
* u32 Offset, The target address to be read
* u32 Data The new register Data in the target
* bit position of the target to be read
*
* Output:
* None
* Return:
* None
* Note:
* Threre are three types of serial operations:
* 1. Software serial write
* 2. Hardware LSSI-Low Speed Serial Interface
* 3. Hardware HSSI-High speed
* serial write. Driver need to implement (1) and (2).
* This function is equal to the combination of RF_ReadReg() and
* RFLSSIRead()
*
* Note: For RF8256 only
* The total count of RTL8256(Zebra4) register is around 36 bit it only employs
* 4-bit RF address. RTL8256 uses "register mode control bit"
* (Reg00[12], Reg00[10]) to access register address bigger than 0xf.
* See "Appendix-4 in PHY Configuration programming guide" for more details.
* Thus, we define a sub-finction for RTL8526 register address conversion
* ===========================================================
* Register Mode: RegCTL[1] RegCTL[0] Note
* (Reg00[12]) (Reg00[10])
* ===========================================================
* Reg_Mode0 0 x Reg 0 ~15(0x0 ~ 0xf)
* ------------------------------------------------------------------
* Reg_Mode1 1 0 Reg 16 ~30(0x1 ~ 0xf)
* ------------------------------------------------------------------
* Reg_Mode2 1 1 Reg 31 ~ 45(0x1 ~ 0xf)
* ------------------------------------------------------------------
*
* 2008/09/02 MH Add 92S RF definition
*/
static void
phy_RFSerialWrite(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath,
u32 Offset, u32 Data)
{
u32 DataAndAddr = 0;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct bb_reg_define *pPhyReg = &pHalData->PHYRegDef[eRFPath];
u32 NewOffset;
/* 2009/06/17 MH We can not execute IO for power save or
other accident mode. */
/* if (RT_CANNOT_IO(Adapter)) */
/* */
/* RTPRINT(FPHY, PHY_RFW, ("phy_RFSerialWrite stop\n")); */
/* return; */
/* */
Offset &= 0x3f;
/* */
/* Shadow Update */
/* */
/* PHY_RFShadowWrite(Adapter, eRFPath, Offset, Data); */
/* */
/* Switch page for 8256 RF IC */
/* */
NewOffset = Offset;
/* */
/* Put write addr in [5:0] and write data in [31:16] */
/* */
/* DataAndAddr = (Data<<16) | (NewOffset&0x3f); */
/* T65 RF */
DataAndAddr = ((NewOffset<<20) | (Data&0x000fffff)) & 0x0fffffff;
/* */
/* Write Operation */
/* */
PHY_SetBBReg(Adapter, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr);
/* RTPRINT(FPHY, PHY_RFW, ("RFW-%d Addr[0x%lx]= 0x%lx\n", eRFPath, pPhyReg->rf3wireOffset, DataAndAddr)); */
}
/**
* Function: PHY_QueryRFReg
*
* OverView: Query "Specific bits" to RF register (page 8~)
*
* Input:
* struct rtw_adapter * Adapter,
* enum RF_RADIO_PATH eRFPath, Radio path of A/B/C/D
* u32 RegAddr, The target address to be read
* u32BitMask The target bit position in the target
* address to be read
*
* Output:
* None
* Return:
* u32 Readback value
* Note:
* This function is equal to "GetRFRegSetting" in PHY programming guide
*/
u32
PHY_QueryRFReg(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath,
u32 RegAddr, u32 BitMask)
{
u32 Original_Value, Readback_Value, BitShift;
/* struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); */
/* u8 RFWaitCounter = 0; */
/* _irqL irqL; */
Original_Value = phy_RFSerialRead(Adapter, eRFPath, RegAddr);
BitShift = phy_CalculateBitShift(BitMask);
Readback_Value = (Original_Value & BitMask) >> BitShift;
return Readback_Value;
}
/**
* Function: PHY_SetRFReg
*
* OverView: Write "Specific bits" to RF register (page 8~)
*
* Input:
* struct rtw_adapter * Adapter,
* enum RF_RADIO_PATH eRFPath, Radio path of A/B/C/D
* u32 RegAddr, The target address to be modified
* u32 BitMask The target bit position in the target
* address to be modified
* u32 Data The new register Data in the target
* bit position of the target address
*
* Output:
* None
* Return:
* None
* Note: This function is equal to "PutRFRegSetting" in PHY programming guide
*/
void
PHY_SetRFReg(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath,
u32 RegAddr, u32 BitMask, u32 Data)
{
/* struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); */
/* u8 RFWaitCounter = 0; */
u32 Original_Value, BitShift;
/* RF data is 12 bits only */
if (BitMask != bRFRegOffsetMask) {
Original_Value = phy_RFSerialRead(Adapter, eRFPath, RegAddr);
BitShift = phy_CalculateBitShift(BitMask);
Data = ((Original_Value & (~BitMask)) | (Data << BitShift));
}
phy_RFSerialWrite(Adapter, eRFPath, RegAddr, Data);
}
/* 3. Initial MAC/BB/RF config by reading MAC/BB/RF txt. */
/*-----------------------------------------------------------------------------
* Function: PHY_MACConfig8723A
*
* Overview: Condig MAC by header file or parameter file.
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 08/12/2008 MHC Create Version 0.
*
*---------------------------------------------------------------------------*/
s32 PHY_MACConfig8723A(struct rtw_adapter *Adapter)
{
int rtStatus = _SUCCESS;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
s8 *pszMACRegFile;
s8 sz8723MACRegFile[] = RTL8723_PHY_MACREG;
bool is92C = IS_92C_SERIAL(pHalData->VersionID);
pszMACRegFile = sz8723MACRegFile;
/* */
/* Config MAC */
/* */
if (HAL_STATUS_FAILURE ==
ODM_ConfigMACWithHeaderFile23a(&pHalData->odmpriv))
rtStatus = _FAIL;
/* 2010.07.13 AMPDU aggregation number 9 */
/* rtw_write16(Adapter, REG_MAX_AGGR_NUM, MAX_AGGR_NUM); */
rtw_write8(Adapter, REG_MAX_AGGR_NUM, 0x0A); /* By tynli. 2010.11.18. */
if (is92C && (BOARD_USB_DONGLE == pHalData->BoardType))
rtw_write8(Adapter, 0x40, 0x04);
return rtStatus;
}
/**
* Function: phy_InitBBRFRegisterDefinition
*
* OverView: Initialize Register definition offset for Radio Path A/B/C/D
*
* Input:
* struct rtw_adapter * Adapter,
*
* Output: None
* Return: None
* Note:
* The initialization value is constant and it should never be changes
*/
static void
phy_InitBBRFRegisterDefinition(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
/* RF Interface Sowrtware Control */
/* 16 LSBs if read 32-bit from 0x870 */
pHalData->PHYRegDef[RF_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW;
/* 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) */
pHalData->PHYRegDef[RF_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW;
/* 16 LSBs if read 32-bit from 0x874 */
pHalData->PHYRegDef[RF_PATH_C].rfintfs = rFPGA0_XCD_RFInterfaceSW;
/* 16 MSBs if read 32-bit from 0x874 (16-bit for 0x876) */
pHalData->PHYRegDef[RF_PATH_D].rfintfs = rFPGA0_XCD_RFInterfaceSW;
/* RF Interface Readback Value */
/* 16 LSBs if read 32-bit from 0x8E0 */
pHalData->PHYRegDef[RF_PATH_A].rfintfi = rFPGA0_XAB_RFInterfaceRB;
/* 16 MSBs if read 32-bit from 0x8E0 (16-bit for 0x8E2) */
pHalData->PHYRegDef[RF_PATH_B].rfintfi = rFPGA0_XAB_RFInterfaceRB;
/* 16 LSBs if read 32-bit from 0x8E4 */
pHalData->PHYRegDef[RF_PATH_C].rfintfi = rFPGA0_XCD_RFInterfaceRB;
/* 16 MSBs if read 32-bit from 0x8E4 (16-bit for 0x8E6) */
pHalData->PHYRegDef[RF_PATH_D].rfintfi = rFPGA0_XCD_RFInterfaceRB;
/* RF Interface Output (and Enable) */
/* 16 LSBs if read 32-bit from 0x860 */
pHalData->PHYRegDef[RF_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE;
/* 16 LSBs if read 32-bit from 0x864 */
pHalData->PHYRegDef[RF_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE;
/* RF Interface (Output and) Enable */
/* 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) */
pHalData->PHYRegDef[RF_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE;
/* 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) */
pHalData->PHYRegDef[RF_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE;
/* Addr of LSSI. Wirte RF register by driver */
pHalData->PHYRegDef[RF_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter;
pHalData->PHYRegDef[RF_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter;
/* RF parameter */
/* BB Band Select */
pHalData->PHYRegDef[RF_PATH_A].rfLSSI_Select = rFPGA0_XAB_RFParameter;
pHalData->PHYRegDef[RF_PATH_B].rfLSSI_Select = rFPGA0_XAB_RFParameter;
pHalData->PHYRegDef[RF_PATH_C].rfLSSI_Select = rFPGA0_XCD_RFParameter;
pHalData->PHYRegDef[RF_PATH_D].rfLSSI_Select = rFPGA0_XCD_RFParameter;
/* Tx AGC Gain Stage (same for all path. Should we remove this?) */
pHalData->PHYRegDef[RF_PATH_A].rfTxGainStage = rFPGA0_TxGainStage;
pHalData->PHYRegDef[RF_PATH_B].rfTxGainStage = rFPGA0_TxGainStage;
pHalData->PHYRegDef[RF_PATH_C].rfTxGainStage = rFPGA0_TxGainStage;
pHalData->PHYRegDef[RF_PATH_D].rfTxGainStage = rFPGA0_TxGainStage;
/* Tranceiver A~D HSSI Parameter-1 */
/* wire control parameter1 */
pHalData->PHYRegDef[RF_PATH_A].rfHSSIPara1 = rFPGA0_XA_HSSIParameter1;
/* wire control parameter1 */
pHalData->PHYRegDef[RF_PATH_B].rfHSSIPara1 = rFPGA0_XB_HSSIParameter1;
/* Tranceiver A~D HSSI Parameter-2 */
/* wire control parameter2 */
pHalData->PHYRegDef[RF_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2;
/* wire control parameter2 */
pHalData->PHYRegDef[RF_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2;
/* RF switch Control */
pHalData->PHYRegDef[RF_PATH_A].rfSwitchControl =
rFPGA0_XAB_SwitchControl; /* TR/Ant switch control */
pHalData->PHYRegDef[RF_PATH_B].rfSwitchControl =
rFPGA0_XAB_SwitchControl;
pHalData->PHYRegDef[RF_PATH_C].rfSwitchControl =
rFPGA0_XCD_SwitchControl;
pHalData->PHYRegDef[RF_PATH_D].rfSwitchControl =
rFPGA0_XCD_SwitchControl;
/* AGC control 1 */
pHalData->PHYRegDef[RF_PATH_A].rfAGCControl1 = rOFDM0_XAAGCCore1;
pHalData->PHYRegDef[RF_PATH_B].rfAGCControl1 = rOFDM0_XBAGCCore1;
pHalData->PHYRegDef[RF_PATH_C].rfAGCControl1 = rOFDM0_XCAGCCore1;
pHalData->PHYRegDef[RF_PATH_D].rfAGCControl1 = rOFDM0_XDAGCCore1;
/* AGC control 2 */
pHalData->PHYRegDef[RF_PATH_A].rfAGCControl2 = rOFDM0_XAAGCCore2;
pHalData->PHYRegDef[RF_PATH_B].rfAGCControl2 = rOFDM0_XBAGCCore2;
pHalData->PHYRegDef[RF_PATH_C].rfAGCControl2 = rOFDM0_XCAGCCore2;
pHalData->PHYRegDef[RF_PATH_D].rfAGCControl2 = rOFDM0_XDAGCCore2;
/* RX AFE control 1 */
pHalData->PHYRegDef[RF_PATH_A].rfRxIQImbalance = rOFDM0_XARxIQImbalance;
pHalData->PHYRegDef[RF_PATH_B].rfRxIQImbalance = rOFDM0_XBRxIQImbalance;
pHalData->PHYRegDef[RF_PATH_C].rfRxIQImbalance = rOFDM0_XCRxIQImbalance;
pHalData->PHYRegDef[RF_PATH_D].rfRxIQImbalance = rOFDM0_XDRxIQImbalance;
/* RX AFE control 1 */
pHalData->PHYRegDef[RF_PATH_A].rfRxAFE = rOFDM0_XARxAFE;
pHalData->PHYRegDef[RF_PATH_B].rfRxAFE = rOFDM0_XBRxAFE;
pHalData->PHYRegDef[RF_PATH_C].rfRxAFE = rOFDM0_XCRxAFE;
pHalData->PHYRegDef[RF_PATH_D].rfRxAFE = rOFDM0_XDRxAFE;
/* Tx AFE control 1 */
pHalData->PHYRegDef[RF_PATH_A].rfTxIQImbalance = rOFDM0_XATxIQImbalance;
pHalData->PHYRegDef[RF_PATH_B].rfTxIQImbalance = rOFDM0_XBTxIQImbalance;
pHalData->PHYRegDef[RF_PATH_C].rfTxIQImbalance = rOFDM0_XCTxIQImbalance;
pHalData->PHYRegDef[RF_PATH_D].rfTxIQImbalance = rOFDM0_XDTxIQImbalance;
/* Tx AFE control 2 */
pHalData->PHYRegDef[RF_PATH_A].rfTxAFE = rOFDM0_XATxAFE;
pHalData->PHYRegDef[RF_PATH_B].rfTxAFE = rOFDM0_XBTxAFE;
pHalData->PHYRegDef[RF_PATH_C].rfTxAFE = rOFDM0_XCTxAFE;
pHalData->PHYRegDef[RF_PATH_D].rfTxAFE = rOFDM0_XDTxAFE;
/* Tranceiver LSSI Readback SI mode */
pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack;
pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack;
pHalData->PHYRegDef[RF_PATH_C].rfLSSIReadBack = rFPGA0_XC_LSSIReadBack;
pHalData->PHYRegDef[RF_PATH_D].rfLSSIReadBack = rFPGA0_XD_LSSIReadBack;
/* Tranceiver LSSI Readback PI mode */
pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBackPi =
TransceiverA_HSPI_Readback;
pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBackPi =
TransceiverB_HSPI_Readback;
/* pHalData->PHYRegDef[RF_PATH_C].rfLSSIReadBackPi =
rFPGA0_XC_LSSIReadBack; */
/* pHalData->PHYRegDef[RF_PATH_D].rfLSSIReadBackPi =
rFPGA0_XD_LSSIReadBack; */
}
/* The following is for High Power PA */
static void
storePwrIndexDiffRateOffset(struct rtw_adapter *Adapter, u32 RegAddr,
u32 BitMask, u32 Data)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
if (RegAddr == rTxAGC_A_Rate18_06) {
pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][0] = Data;
/* RT_TRACE(COMP_INIT, DBG_TRACE,
("MCSTxPowerLevelOriginalOffset[%d][0] = 0x%lx\n",
pHalData->pwrGroupCnt, */
/* pHalData->MCSTxPowerLevelOriginalOffset[
pHalData->pwrGroupCnt][0])); */
}
if (RegAddr == rTxAGC_A_Rate54_24) {
pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][1] = Data;
/* RT_TRACE(COMP_INIT, DBG_TRACE,
("MCSTxPowerLevelOriginalOffset[%d][1] = 0x%lx\n",
pHalData->pwrGroupCnt, */
/* pHalData->MCSTxPowerLevelOriginalOffset[
pHalData->pwrGroupCnt][1])); */
}
if (RegAddr == rTxAGC_A_CCK1_Mcs32) {
pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][6] = Data;
/* RT_TRACE(COMP_INIT, DBG_TRACE,
("MCSTxPowerLevelOriginalOffset[%d][6] = 0x%lx\n",
pHalData->pwrGroupCnt, */
/* pHalData->MCSTxPowerLevelOriginalOffset[
pHalData->pwrGroupCnt][6])); */
}
if (RegAddr == rTxAGC_B_CCK11_A_CCK2_11 && BitMask == 0xffffff00) {
pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][7] = Data;
/* RT_TRACE(COMP_INIT, DBG_TRACE,
("MCSTxPowerLevelOriginalOffset[%d][7] = 0x%lx\n",
pHalData->pwrGroupCnt, */
/* pHalData->MCSTxPowerLevelOriginalOffset[
pHalData->pwrGroupCnt][7])); */
}
if (RegAddr == rTxAGC_A_Mcs03_Mcs00) {
pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][2] = Data;
/* RT_TRACE(COMP_INIT, DBG_TRACE,
("MCSTxPowerLevelOriginalOffset[%d][2] = 0x%lx\n",
pHalData->pwrGroupCnt, */
/* pHalData->MCSTxPowerLevelOriginalOffset[
pHalData->pwrGroupCnt][2])); */
}
if (RegAddr == rTxAGC_A_Mcs07_Mcs04) {
pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][3] = Data;
/* RT_TRACE(COMP_INIT, DBG_TRACE,
("MCSTxPowerLevelOriginalOffset[%d][3] = 0x%lx\n",
pHalData->pwrGroupCnt, */
/* pHalData->MCSTxPowerLevelOriginalOffset[
pHalData->pwrGroupCnt][3])); */
}
if (RegAddr == rTxAGC_A_Mcs11_Mcs08) {
pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][4] = Data;
/* RT_TRACE(COMP_INIT, DBG_TRACE,
("MCSTxPowerLevelOriginalOffset[%d][4] = 0x%lx\n",
pHalData->pwrGroupCnt, */
/* pHalData->MCSTxPowerLevelOriginalOffset[
pHalData->pwrGroupCnt][4])); */
}
if (RegAddr == rTxAGC_A_Mcs15_Mcs12) {
pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][5] = Data;
/* RT_TRACE(COMP_INIT, DBG_TRACE,
("MCSTxPowerLevelOriginalOffset[%d][5] = 0x%lx\n",
pHalData->pwrGroupCnt, */
/* pHalData->MCSTxPowerLevelOriginalOffset[
pHalData->pwrGroupCnt][5])); */
}
if (RegAddr == rTxAGC_B_Rate18_06) {
pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][8] = Data;
/* RT_TRACE(COMP_INIT, DBG_TRACE,
("MCSTxPowerLevelOriginalOffset[%d][8] = 0x%lx\n",
pHalData->pwrGroupCnt, */
/* pHalData->MCSTxPowerLevelOriginalOffset[
pHalData->pwrGroupCnt][8])); */
}
if (RegAddr == rTxAGC_B_Rate54_24) {
pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][9] = Data;
/* RT_TRACE(COMP_INIT, DBG_TRACE,
("MCSTxPowerLevelOriginalOffset[%d][9] = 0x%lx\n",
pHalData->pwrGroupCnt, */
/* pHalData->MCSTxPowerLevelOriginalOffset[
pHalData->pwrGroupCnt][9])); */
}
if (RegAddr == rTxAGC_B_CCK1_55_Mcs32) {
pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][14] = Data;
/* RT_TRACE(COMP_INIT, DBG_TRACE,
("MCSTxPowerLevelOriginalOffset[%d][14] = 0x%lx\n",
pHalData->pwrGroupCnt, */
/* pHalData->MCSTxPowerLevelOriginalOffset[
pHalData->pwrGroupCnt][14])); */
}
if (RegAddr == rTxAGC_B_CCK11_A_CCK2_11 && BitMask == 0x000000ff) {
pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][15] = Data;
/* RT_TRACE(COMP_INIT, DBG_TRACE,
("MCSTxPowerLevelOriginalOffset[%d][15] = 0x%lx\n",
pHalData->pwrGroupCnt, */
/* pHalData->MCSTxPowerLevelOriginalOffset[
pHalData->pwrGroupCnt][15])); */
}
if (RegAddr == rTxAGC_B_Mcs03_Mcs00) {
pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][10] = Data;
/* RT_TRACE(COMP_INIT, DBG_TRACE,
("MCSTxPowerLevelOriginalOffset[%d][10] = 0x%lx\n",
pHalData->pwrGroupCnt, */
/* pHalData->MCSTxPowerLevelOriginalOffset[
pHalData->pwrGroupCnt][10])); */
}
if (RegAddr == rTxAGC_B_Mcs07_Mcs04) {
pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][11] = Data;
/* RT_TRACE(COMP_INIT, DBG_TRACE,
("MCSTxPowerLevelOriginalOffset[%d][11] = 0x%lx\n",
pHalData->pwrGroupCnt, */
/* pHalData->MCSTxPowerLevelOriginalOffset[
pHalData->pwrGroupCnt][11])); */
}
if (RegAddr == rTxAGC_B_Mcs11_Mcs08) {
pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][12] = Data;
/* RT_TRACE(COMP_INIT, DBG_TRACE,
("MCSTxPowerLevelOriginalOffset[%d][12] = 0x%lx\n",
pHalData->pwrGroupCnt, */
/* pHalData->MCSTxPowerLevelOriginalOffset[
pHalData->pwrGroupCnt][12])); */
}
if (RegAddr == rTxAGC_B_Mcs15_Mcs12) {
pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][13] = Data;
/* RT_TRACE(COMP_INIT, DBG_TRACE,
("MCSTxPowerLevelOriginalOffset[%d][13] = 0x%lx\n",
pHalData->pwrGroupCnt, */
/* pHalData->MCSTxPowerLevelOriginalOffset[
pHalData->pwrGroupCnt][13])); */
pHalData->pwrGroupCnt++;
}
}
/*-----------------------------------------------------------------------------
* Function: phy_ConfigBBWithPgHeaderFile
*
* Overview: Config PHY_REG_PG array
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 11/06/2008 MHC Add later!!!!!!.. Please modify for new files!!!!
* 11/10/2008 tynli Modify to mew files.
*---------------------------------------------------------------------------*/
static int
phy_ConfigBBWithPgHeaderFile(struct rtw_adapter *Adapter, u8 ConfigType)
{
int i;
u32 *Rtl819XPHY_REGArray_Table_PG;
u16 PHY_REGArrayPGLen;
PHY_REGArrayPGLen = Rtl8723_PHY_REG_Array_PGLength;
Rtl819XPHY_REGArray_Table_PG = (u32 *)Rtl8723_PHY_REG_Array_PG;
if (ConfigType == BaseBand_Config_PHY_REG) {
for (i = 0; i < PHY_REGArrayPGLen; i = i + 3) {
storePwrIndexDiffRateOffset(Adapter,
Rtl819XPHY_REGArray_Table_PG[i],
Rtl819XPHY_REGArray_Table_PG[i+1],
Rtl819XPHY_REGArray_Table_PG[i+2]);
}
}
return _SUCCESS;
} /* phy_ConfigBBWithPgHeaderFile */
static void
phy_BB8192C_Config_1T(struct rtw_adapter *Adapter)
{
/* for path - B */
PHY_SetBBReg(Adapter, rFPGA0_TxInfo, 0x3, 0x2);
PHY_SetBBReg(Adapter, rFPGA1_TxInfo, 0x300033, 0x200022);
/* 20100519 Joseph: Add for 1T2R config. Suggested by Kevin,
Jenyu and Yunan. */
PHY_SetBBReg(Adapter, rCCK0_AFESetting, bMaskByte3, 0x45);
PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, bMaskByte0, 0x23);
/* B path first AGC */
PHY_SetBBReg(Adapter, rOFDM0_AGCParameter1, 0x30, 0x1);
PHY_SetBBReg(Adapter, 0xe74, 0x0c000000, 0x2);
PHY_SetBBReg(Adapter, 0xe78, 0x0c000000, 0x2);
PHY_SetBBReg(Adapter, 0xe7c, 0x0c000000, 0x2);
PHY_SetBBReg(Adapter, 0xe80, 0x0c000000, 0x2);
PHY_SetBBReg(Adapter, 0xe88, 0x0c000000, 0x2);
}
static int
phy_BB8723a_Config_ParaFile(struct rtw_adapter *Adapter)
{
struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(Adapter);
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
int rtStatus = _SUCCESS;
u8 sz8723BBRegFile[] = RTL8723_PHY_REG;
u8 sz8723AGCTableFile[] = RTL8723_AGC_TAB;
u8 sz8723BBRegPgFile[] = RTL8723_PHY_REG_PG;
u8 sz8723BBRegMpFile[] = RTL8723_PHY_REG_MP;
u8 *pszBBRegFile = NULL, *pszAGCTableFile = NULL;
u8 *pszBBRegPgFile = NULL, *pszBBRegMpFile = NULL;
/* RT_TRACE(COMP_INIT, DBG_TRACE, ("==>phy_BB8192S_Config_ParaFile\n")); */
pszBBRegFile = sz8723BBRegFile ;
pszAGCTableFile = sz8723AGCTableFile;
pszBBRegPgFile = sz8723BBRegPgFile;
pszBBRegMpFile = sz8723BBRegMpFile;
/* */
/* 1. Read PHY_REG.TXT BB INIT!! */
/* We will seperate as 88C / 92C according to chip version */
/* */
if (HAL_STATUS_FAILURE == ODM_ConfigBBWithHeaderFile23a(&pHalData->odmpriv,
CONFIG_BB_PHY_REG))
rtStatus = _FAIL;
if (rtStatus != _SUCCESS)
goto phy_BB8190_Config_ParaFile_Fail;
/* */
/* 20100318 Joseph: Config 2T2R to 1T2R if necessary. */
/* */
if (pHalData->rf_type == RF_1T2R) {
phy_BB8192C_Config_1T(Adapter);
DBG_8723A("phy_BB8723a_Config_ParaFile():Config to 1T!!\n");
}
/* */
/* 2. If EEPROM or EFUSE autoload OK, We must config by
PHY_REG_PG.txt */
/* */
if (pEEPROM->bautoload_fail_flag == false) {
pHalData->pwrGroupCnt = 0;
rtStatus = phy_ConfigBBWithPgHeaderFile(Adapter,
BaseBand_Config_PHY_REG);
}
if (rtStatus != _SUCCESS)
goto phy_BB8190_Config_ParaFile_Fail;
/* */
/* 3. BB AGC table Initialization */
/* */
if (HAL_STATUS_FAILURE == ODM_ConfigBBWithHeaderFile23a(&pHalData->odmpriv,
CONFIG_BB_AGC_TAB))
rtStatus = _FAIL;
phy_BB8190_Config_ParaFile_Fail:
return rtStatus;
}
int
PHY_BBConfig8723A(struct rtw_adapter *Adapter)
{
int rtStatus = _SUCCESS;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
u8 TmpU1B = 0;
u8 CrystalCap;
phy_InitBBRFRegisterDefinition(Adapter);
/* Suggested by Scott. tynli_test. 2010.12.30. */
/* 1. 0x28[1] = 1 */
TmpU1B = rtw_read8(Adapter, REG_AFE_PLL_CTRL);
udelay(2);
rtw_write8(Adapter, REG_AFE_PLL_CTRL, (TmpU1B|BIT1));
udelay(2);
/* 2. 0x29[7:0] = 0xFF */
rtw_write8(Adapter, REG_AFE_PLL_CTRL+1, 0xff);
udelay(2);
/* 3. 0x02[1:0] = 2b'11 */
TmpU1B = rtw_read8(Adapter, REG_SYS_FUNC_EN);
rtw_write8(Adapter, REG_SYS_FUNC_EN,
(TmpU1B | FEN_BB_GLB_RSTn | FEN_BBRSTB));
/* 4. 0x25[6] = 0 */
TmpU1B = rtw_read8(Adapter, REG_AFE_XTAL_CTRL + 1);
rtw_write8(Adapter, REG_AFE_XTAL_CTRL+1, (TmpU1B & (~BIT6)));
/* 5. 0x24[20] = 0 Advised by SD3 Alex Wang. 2011.02.09. */
TmpU1B = rtw_read8(Adapter, REG_AFE_XTAL_CTRL+2);
rtw_write8(Adapter, REG_AFE_XTAL_CTRL+2, (TmpU1B & (~BIT4)));
/* 6. 0x1f[7:0] = 0x07 */
rtw_write8(Adapter, REG_RF_CTRL, 0x07);
/* */
/* Config BB and AGC */
/* */
rtStatus = phy_BB8723a_Config_ParaFile(Adapter);
/* only for B-cut */
if (pHalData->EEPROMVersion >= 0x01) {
CrystalCap = pHalData->CrystalCap & 0x3F;
PHY_SetBBReg(Adapter, REG_MAC_PHY_CTRL, 0xFFF000,
(CrystalCap | (CrystalCap << 6)));
}
PHY_SetBBReg(Adapter, REG_LDOA15_CTRL, bMaskDWord, 0x01572505);
return rtStatus;
}
int
PHY_RFConfig8723A(struct rtw_adapter *Adapter)
{
int rtStatus = _SUCCESS;
/* */
/* RF config */
/* */
rtStatus = PHY_RF6052_Config8723A(Adapter);
return rtStatus;
}
static void getTxPowerIndex(struct rtw_adapter *Adapter,
u8 channel, u8 *cckPowerLevel, u8 *ofdmPowerLevel)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
u8 index = (channel - 1);
/* 1. CCK */
cckPowerLevel[RF_PATH_A] = pHalData->TxPwrLevelCck[RF_PATH_A][index];
cckPowerLevel[RF_PATH_B] = pHalData->TxPwrLevelCck[RF_PATH_B][index];
/* 2. OFDM for 1S or 2S */
if (GET_RF_TYPE(Adapter) == RF_1T2R || GET_RF_TYPE(Adapter) == RF_1T1R) {
/* Read HT 40 OFDM TX power */
ofdmPowerLevel[RF_PATH_A] =
pHalData->TxPwrLevelHT40_1S[RF_PATH_A][index];
ofdmPowerLevel[RF_PATH_B] =
pHalData->TxPwrLevelHT40_1S[RF_PATH_B][index];
} else if (GET_RF_TYPE(Adapter) == RF_2T2R) {
/* Read HT 40 OFDM TX power */
ofdmPowerLevel[RF_PATH_A] =
pHalData->TxPwrLevelHT40_2S[RF_PATH_A][index];
ofdmPowerLevel[RF_PATH_B] =
pHalData->TxPwrLevelHT40_2S[RF_PATH_B][index];
}
}
static void ccxPowerIndexCheck(struct rtw_adapter *Adapter, u8 channel,
u8 *cckPowerLevel, u8 *ofdmPowerLevel)
{
}
/*-----------------------------------------------------------------------------
* Function: SetTxPowerLevel8723A()
*
* Overview: This function is export to "HalCommon" moudule
* We must consider RF path later!!!!!!!
*
* Input: struct rtw_adapter * Adapter
* u8 channel
*
* Output: NONE
*
* Return: NONE
*
*---------------------------------------------------------------------------*/
void PHY_SetTxPowerLevel8723A(struct rtw_adapter *Adapter, u8 channel)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
u8 cckPowerLevel[2], ofdmPowerLevel[2]; /* [0]:RF-A, [1]:RF-B */
if (pHalData->bTXPowerDataReadFromEEPORM == false)
return;
getTxPowerIndex(Adapter, channel, &cckPowerLevel[0],
&ofdmPowerLevel[0]);
ccxPowerIndexCheck(Adapter, channel, &cckPowerLevel[0],
&ofdmPowerLevel[0]);
rtl823a_phy_rf6052setccktxpower(Adapter, &cckPowerLevel[0]);
rtl8723a_PHY_RF6052SetOFDMTxPower(Adapter, &ofdmPowerLevel[0], channel);
}
/*-----------------------------------------------------------------------------
* Function: PHY_SetBWMode23aCallback8192C()
*
* Overview: Timer callback function for SetSetBWMode23a
*
* Input: PRT_TIMER pTimer
*
* Output: NONE
*
* Return: NONE
*
* Note:
* (1) We do not take j mode into consideration now
* (2) Will two workitem of "switch channel" and
* "switch channel bandwidth" run concurrently?
*---------------------------------------------------------------------------*/
static void
_PHY_SetBWMode23a92C(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
u8 regBwOpMode;
u8 regRRSR_RSC;
if (pHalData->rf_chip == RF_PSEUDO_11N)
return;
/* There is no 40MHz mode in RF_8225. */
if (pHalData->rf_chip == RF_8225)
return;
if (Adapter->bDriverStopped)
return;
/* 3 */
/* 3<1>Set MAC register */
/* 3 */
regBwOpMode = rtw_read8(Adapter, REG_BWOPMODE);
regRRSR_RSC = rtw_read8(Adapter, REG_RRSR+2);
switch (pHalData->CurrentChannelBW) {
case HT_CHANNEL_WIDTH_20:
regBwOpMode |= BW_OPMODE_20MHZ;
rtw_write8(Adapter, REG_BWOPMODE, regBwOpMode);
break;
case HT_CHANNEL_WIDTH_40:
regBwOpMode &= ~BW_OPMODE_20MHZ;
rtw_write8(Adapter, REG_BWOPMODE, regBwOpMode);
regRRSR_RSC = (regRRSR_RSC & 0x90) |
(pHalData->nCur40MhzPrimeSC << 5);
rtw_write8(Adapter, REG_RRSR+2, regRRSR_RSC);
break;
default:
break;
}
/* 3 */
/* 3<2>Set PHY related register */
/* 3 */
switch (pHalData->CurrentChannelBW) {
/* 20 MHz channel*/
case HT_CHANNEL_WIDTH_20:
PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x0);
PHY_SetBBReg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x0);
PHY_SetBBReg(Adapter, rFPGA0_AnalogParameter2, BIT10, 1);
break;
/* 40 MHz channel*/
case HT_CHANNEL_WIDTH_40:
PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x1);
PHY_SetBBReg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x1);
/* Set Control channel to upper or lower. These settings
are required only for 40MHz */
PHY_SetBBReg(Adapter, rCCK0_System, bCCKSideBand,
(pHalData->nCur40MhzPrimeSC >> 1));
PHY_SetBBReg(Adapter, rOFDM1_LSTF, 0xC00,
pHalData->nCur40MhzPrimeSC);
PHY_SetBBReg(Adapter, rFPGA0_AnalogParameter2, BIT10, 0);
PHY_SetBBReg(Adapter, 0x818, (BIT26 | BIT27),
(pHalData->nCur40MhzPrimeSC ==
HAL_PRIME_CHNL_OFFSET_LOWER) ? 2:1);
break;
default:
/*RT_TRACE(COMP_DBG, DBG_LOUD,
("PHY_SetBWMode23aCallback8192C(): unknown Bandwidth: %#X\n" \
, pHalData->CurrentChannelBW));*/
break;
}
/* Skip over setting of J-mode in BB register here. Default value
is "None J mode". Emily 20070315 */
/* Added it for 20/40 mhz switch time evaluation by guangan 070531 */
/* NowL = PlatformEFIORead4Byte(Adapter, TSFR); */
/* NowH = PlatformEFIORead4Byte(Adapter, TSFR+4); */
/* EndTime = ((u64)NowH << 32) + NowL; */
/* RT_TRACE(COMP_SCAN, DBG_LOUD, ("SetBWMode23aCallback8190Pci: time
of SetBWMode23a = %I64d us!\n", (EndTime - BeginTime))); */
/* 3<3>Set RF related register */
switch (pHalData->rf_chip) {
case RF_8225:
/* PHY_SetRF8225Bandwidth(Adapter,
pHalData->CurrentChannelBW); */
break;
case RF_8256:
/* Please implement this function in Hal8190PciPhy8256.c */
/* PHY_SetRF8256Bandwidth(Adapter,
pHalData->CurrentChannelBW); */
break;
case RF_8258:
/* Please implement this function in Hal8190PciPhy8258.c */
/* PHY_SetRF8258Bandwidth(); */
break;
case RF_PSEUDO_11N:
/* Do Nothing */
break;
case RF_6052:
rtl8723a_phy_rf6052set_bw(Adapter, pHalData->CurrentChannelBW);
break;
default:
/* RT_ASSERT(false, ("Unknown RFChipID: %d\n",
pHalData->RFChipID)); */
break;
}
/* pHalData->SetBWMode23aInProgress = false; */
/* RT_TRACE(COMP_SCAN, DBG_LOUD,
("<== PHY_SetBWMode23aCallback8192C() \n")); */
}
/*-----------------------------------------------------------------------------
* Function: SetBWMode23a8190Pci()
*
* Overview: This function is export to "HalCommon" moudule
*
* Input: struct rtw_adapter * Adapter
* enum ht_channel_width Bandwidth 20M or 40M
*
* Output: NONE
*
* Return: NONE
*
* Note: We do not take j mode into consideration now
*---------------------------------------------------------------------------*/
void
PHY_SetBWMode23a8723A(struct rtw_adapter *Adapter,
enum ht_channel_width Bandwidth, unsigned char Offset)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
enum ht_channel_width tmpBW = pHalData->CurrentChannelBW;
pHalData->CurrentChannelBW = Bandwidth;
pHalData->nCur40MhzPrimeSC = Offset;
if ((!Adapter->bDriverStopped) && (!Adapter->bSurpriseRemoved))
_PHY_SetBWMode23a92C(Adapter);
else
pHalData->CurrentChannelBW = tmpBW;
}
static void _PHY_SwChnl8723A(struct rtw_adapter *Adapter, u8 channel)
{
u8 eRFPath;
u32 param1, param2;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
if (Adapter->bNotifyChannelChange)
DBG_8723A("[%s] ch = %d\n", __FUNCTION__, channel);
/* s1. pre common command - CmdID_SetTxPowerLevel */
PHY_SetTxPowerLevel8723A(Adapter, channel);
/* s2. RF dependent command - CmdID_RF_WriteReg,
param1 = RF_CHNLBW, param2 = channel */
param1 = RF_CHNLBW;
param2 = channel;
for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) {
pHalData->RfRegChnlVal[eRFPath] =
(pHalData->RfRegChnlVal[eRFPath] & 0xfffffc00) | param2;
PHY_SetRFReg(Adapter, (enum RF_RADIO_PATH)eRFPath, param1,
bRFRegOffsetMask, pHalData->RfRegChnlVal[eRFPath]);
}
/* s3. post common command - CmdID_End, None */
}
void PHY_SwChnl8723A(struct rtw_adapter *Adapter, u8 channel)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
u8 tmpchannel = pHalData->CurrentChannel;
bool result = true;
if (pHalData->rf_chip == RF_PSEUDO_11N) {
/* return immediately if it is peudo-phy */
return;
}
if (channel == 0)
channel = 1;
pHalData->CurrentChannel = channel;
if ((!Adapter->bDriverStopped) && (!Adapter->bSurpriseRemoved)) {
_PHY_SwChnl8723A(Adapter, channel);
if (!result)
pHalData->CurrentChannel = tmpchannel;
} else {
pHalData->CurrentChannel = tmpchannel;
}
}
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
/******************************************************************************
*
*
* Module: rtl8192c_rf6052.c (Source C File)
*
* Note: Provide RF 6052 series relative API.
*
* Function:
*
* Export:
*
* Abbrev:
*
* History:
* Data Who Remark
*
* 09/25/2008 MHC Create initial version.
* 11/05/2008 MHC Add API for tw power setting.
*
*
******************************************************************************/
#define _RTL8723A_RF6052_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <rtl8723a_hal.h>
/*---------------------------Define Local Constant---------------------------*/
/* Define local structure for debug!!!!! */
struct rf_shadow_compare_map {
/* Shadow register value */
u32 Value;
/* Compare or not flag */
u8 Compare;
/* Record If it had ever modified unpredicted */
u8 ErrorOrNot;
/* Recorver Flag */
u8 Recorver;
/* */
u8 Driver_Write;
};
/*-----------------------------------------------------------------------------
* Function: PHY_RF6052SetBandwidth()
*
* Overview: This function is called by SetBWMode23aCallback8190Pci() only
*
* Input: struct rtw_adapter * Adapter
* WIRELESS_BANDWIDTH_E Bandwidth 20M or 40M
*
* Output: NONE
*
* Return: NONE
*
* Note: For RF type 0222D
*---------------------------------------------------------------------------*/
void rtl8723a_phy_rf6052set_bw(
struct rtw_adapter *Adapter,
enum ht_channel_width Bandwidth) /* 20M or 40M */
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
switch (Bandwidth) {
case HT_CHANNEL_WIDTH_20:
pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff) | 0x0400);
PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
break;
case HT_CHANNEL_WIDTH_40:
pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff));
PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
break;
default:
break;
}
}
/*-----------------------------------------------------------------------------
* Function: PHY_RF6052SetCckTxPower
*
* Overview:
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 11/05/2008 MHC Simulate 8192series..
*
*---------------------------------------------------------------------------*/
void rtl823a_phy_rf6052setccktxpower(struct rtw_adapter *Adapter, u8 *pPowerlevel)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
u32 TxAGC[2] = {0, 0}, tmpval = 0;
bool TurboScanOff = false;
u8 idx1, idx2;
u8 *ptr;
/* According to SD3 eechou's suggestion, we need to disable turbo scan for RU. */
/* Otherwise, external PA will be broken if power index > 0x20. */
if (pHalData->EEPROMRegulatory != 0 || pHalData->ExternalPA)
TurboScanOff = true;
if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
TxAGC[RF_PATH_A] = 0x3f3f3f3f;
TxAGC[RF_PATH_B] = 0x3f3f3f3f;
TurboScanOff = true;/* disable turbo scan */
if (TurboScanOff) {
for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
TxAGC[idx1] =
pPowerlevel[idx1] | (pPowerlevel[idx1]<<8) |
(pPowerlevel[idx1]<<16) | (pPowerlevel[idx1]<<24);
/* 2010/10/18 MH For external PA module. We need to limit power index to be less than 0x20. */
if (TxAGC[idx1] > 0x20 && pHalData->ExternalPA)
TxAGC[idx1] = 0x20;
}
}
} else {
/* 20100427 Joseph: Driver dynamic Tx power shall not affect Tx power. It shall be determined by power training mechanism. */
/* Currently, we cannot fully disable driver dynamic tx power mechanism because it is referenced by BT coexist mechanism. */
/* In the future, two mechanism shall be separated from each other and maintained independantly. Thanks for Lanhsin's reminder. */
if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) {
TxAGC[RF_PATH_A] = 0x10101010;
TxAGC[RF_PATH_B] = 0x10101010;
} else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2) {
TxAGC[RF_PATH_A] = 0x00000000;
TxAGC[RF_PATH_B] = 0x00000000;
} else {
for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
TxAGC[idx1] =
pPowerlevel[idx1] | (pPowerlevel[idx1]<<8) |
(pPowerlevel[idx1]<<16) | (pPowerlevel[idx1]<<24);
}
if (pHalData->EEPROMRegulatory == 0) {
tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][6]) +
(pHalData->MCSTxPowerLevelOriginalOffset[0][7]<<8);
TxAGC[RF_PATH_A] += tmpval;
tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][14]) +
(pHalData->MCSTxPowerLevelOriginalOffset[0][15]<<24);
TxAGC[RF_PATH_B] += tmpval;
}
}
}
for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
ptr = (u8 *)(&TxAGC[idx1]);
for (idx2 = 0; idx2 < 4; idx2++) {
if (*ptr > RF6052_MAX_TX_PWR)
*ptr = RF6052_MAX_TX_PWR;
ptr++;
}
}
/* rf-A cck tx power */
tmpval = TxAGC[RF_PATH_A]&0xff;
PHY_SetBBReg(Adapter, rTxAGC_A_CCK1_Mcs32, bMaskByte1, tmpval);
tmpval = TxAGC[RF_PATH_A]>>8;
PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
/* rf-B cck tx power */
tmpval = TxAGC[RF_PATH_B]>>24;
PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, tmpval);
tmpval = TxAGC[RF_PATH_B]&0x00ffffff;
PHY_SetBBReg(Adapter, rTxAGC_B_CCK1_55_Mcs32, 0xffffff00, tmpval);
} /* PHY_RF6052SetCckTxPower */
/* powerbase0 for OFDM rates */
/* powerbase1 for HT MCS rates */
static void getPowerBase(
struct rtw_adapter *Adapter,
u8 *pPowerLevel,
u8 Channel,
u32 *OfdmBase,
u32 *MCSBase
)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
u32 powerBase0, powerBase1;
u8 Legacy_pwrdiff = 0;
s8 HT20_pwrdiff = 0;
u8 i, powerlevel[2];
for (i = 0; i < 2; i++) {
powerlevel[i] = pPowerLevel[i];
Legacy_pwrdiff = pHalData->TxPwrLegacyHtDiff[i][Channel-1];
powerBase0 = powerlevel[i] + Legacy_pwrdiff;
powerBase0 = (powerBase0<<24) | (powerBase0<<16) | (powerBase0<<8) | powerBase0;
*(OfdmBase+i) = powerBase0;
}
for (i = 0; i < 2; i++) {
/* Check HT20 to HT40 diff */
if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20) {
HT20_pwrdiff = pHalData->TxPwrHt20Diff[i][Channel-1];
powerlevel[i] += HT20_pwrdiff;
}
powerBase1 = powerlevel[i];
powerBase1 = (powerBase1<<24) | (powerBase1<<16) | (powerBase1<<8) | powerBase1;
*(MCSBase+i) = powerBase1;
}
}
static void getTxPowerWriteValByRegulatory(
struct rtw_adapter *Adapter,
u8 Channel,
u8 index,
u32 *powerBase0,
u32 *powerBase1,
u32 *pOutWriteVal
)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
u8 i, chnlGroup = 0, pwr_diff_limit[4];
u32 writeVal, customer_limit, rf;
/* Index 0 & 1 = legacy OFDM, 2-5 = HT_MCS rate */
for (rf = 0; rf < 2; rf++) {
switch (pHalData->EEPROMRegulatory) {
case 0: /* Realtek better performance */
/* increase power diff defined by Realtek for large power */
chnlGroup = 0;
writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf?8:0)] +
((index < 2) ? powerBase0[rf] : powerBase1[rf]);
break;
case 1: /* Realtek regulatory */
/* increase power diff defined by Realtek for regulatory */
if (pHalData->pwrGroupCnt == 1)
chnlGroup = 0;
if (pHalData->pwrGroupCnt >= 3) {
if (Channel <= 3)
chnlGroup = 0;
else if (Channel >= 4 && Channel <= 9)
chnlGroup = 1;
else if (Channel > 9)
chnlGroup = 2;
if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
chnlGroup++;
else
chnlGroup += 4;
}
writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf?8:0)] +
((index < 2) ? powerBase0[rf] : powerBase1[rf]);
break;
case 2: /* Better regulatory */
/* don't increase any power diff */
writeVal = ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
break;
case 3: /* Customer defined power diff. */
chnlGroup = 0;
for (i = 0; i < 4; i++) {
pwr_diff_limit[i] = (u8)((pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index +
(rf ? 8 : 0)]&(0x7f << (i*8))) >> (i*8));
if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_40) {
if (pwr_diff_limit[i] > pHalData->PwrGroupHT40[rf][Channel-1])
pwr_diff_limit[i] = pHalData->PwrGroupHT40[rf][Channel-1];
} else {
if (pwr_diff_limit[i] > pHalData->PwrGroupHT20[rf][Channel-1])
pwr_diff_limit[i] = pHalData->PwrGroupHT20[rf][Channel-1];
}
}
customer_limit = (pwr_diff_limit[3]<<24) | (pwr_diff_limit[2]<<16) |
(pwr_diff_limit[1]<<8) | (pwr_diff_limit[0]);
writeVal = customer_limit + ((index<2)?powerBase0[rf]:powerBase1[rf]);
break;
default:
chnlGroup = 0;
writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf?8:0)] +
((index < 2) ? powerBase0[rf] : powerBase1[rf]);
break;
}
/* 20100427 Joseph: Driver dynamic Tx power shall not affect Tx power. It shall be determined by power training mechanism. */
/* Currently, we cannot fully disable driver dynamic tx power mechanism because it is referenced by BT coexist mechanism. */
/* In the future, two mechanism shall be separated from each other and maintained independantly. Thanks for Lanhsin's reminder. */
if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1)
writeVal = 0x14141414;
else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2)
writeVal = 0x00000000;
/* 20100628 Joseph: High power mode for BT-Coexist mechanism. */
/* This mechanism is only applied when Driver-Highpower-Mechanism is OFF. */
if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_BT1)
writeVal = writeVal - 0x06060606;
else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_BT2)
writeVal = writeVal;
*(pOutWriteVal+rf) = writeVal;
}
}
static void writeOFDMPowerReg(struct rtw_adapter *Adapter, u8 index, u32 *pValue)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
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];
PHY_SetBBReg(Adapter, RegOffset, bMaskDWord, writeVal);
/* 201005115 Joseph: Set Tx Power diff for Tx power training mechanism. */
if (((pHalData->rf_type == RF_2T2R) &&
(RegOffset == rTxAGC_A_Mcs15_Mcs12 ||
RegOffset == rTxAGC_B_Mcs15_Mcs12)) ||
((pHalData->rf_type != RF_2T2R) &&
(RegOffset == rTxAGC_A_Mcs07_Mcs04 ||
RegOffset == rTxAGC_B_Mcs07_Mcs04))) {
writeVal = pwr_val[3];
if (RegOffset == rTxAGC_A_Mcs15_Mcs12 || RegOffset == rTxAGC_A_Mcs07_Mcs04)
RegOffset = 0xc90;
if (RegOffset == rTxAGC_B_Mcs15_Mcs12 || RegOffset == rTxAGC_B_Mcs07_Mcs04)
RegOffset = 0xc98;
for (i = 0; i < 3; i++) {
if (i != 2)
writeVal = (writeVal > 8) ? (writeVal-8) : 0;
else
writeVal = (writeVal > 6) ? (writeVal-6) : 0;
rtw_write8(Adapter, (u32)(RegOffset+i), (u8)writeVal);
}
}
}
}
/*-----------------------------------------------------------------------------
* Function: PHY_RF6052SetOFDMTxPower
*
* Overview: For legacy and HY OFDM, we must read EEPROM TX power index for
* different channel and read original value in TX power register area from
* 0xe00. We increase offset and original value to be correct tx pwr.
*
* Input: NONE
*
* Output: NONE
*
* Return: NONE
*
* Revised History:
* When Who Remark
* 11/05/2008 MHC Simulate 8192 series method.
* 01/06/2009 MHC 1. Prevent Path B tx power overflow or underflow dure to
* A/B pwr difference or legacy/HT pwr diff.
* 2. We concern with path B legacy/HT OFDM difference.
* 01/22/2009 MHC Support new EPRO format from SD3.
*
*---------------------------------------------------------------------------*/
void rtl8723a_PHY_RF6052SetOFDMTxPower(struct rtw_adapter *Adapter, u8 *pPowerLevel, u8 Channel)
{
u32 writeVal[2], powerBase0[2], powerBase1[2];
u8 index = 0;
getPowerBase(Adapter, pPowerLevel, Channel, &powerBase0[0], &powerBase1[0]);
for (index = 0; index < 6; index++) {
getTxPowerWriteValByRegulatory(Adapter, Channel, index,
&powerBase0[0], &powerBase1[0], &writeVal[0]);
writeOFDMPowerReg(Adapter, index, &writeVal[0]);
}
}
static int phy_RF6052_Config_ParaFile(struct rtw_adapter *Adapter)
{
u32 u4RegValue = 0;
u8 eRFPath;
struct bb_reg_define *pPhyReg;
int rtStatus = _SUCCESS;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
static char sz8723RadioAFile[] = RTL8723_PHY_RADIO_A;
static char sz8723RadioBFile[] = RTL8723_PHY_RADIO_B;
char *pszRadioAFile, *pszRadioBFile;
pszRadioAFile = sz8723RadioAFile;
pszRadioBFile = sz8723RadioBFile;
/* 3----------------------------------------------------------------- */
/* 3 <2> Initialize RF */
/* 3----------------------------------------------------------------- */
for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) {
pPhyReg = &pHalData->PHYRegDef[eRFPath];
/*----Store original RFENV control type----*/
switch (eRFPath) {
case RF_PATH_A:
case RF_PATH_C:
u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV);
break;
case RF_PATH_B:
case RF_PATH_D:
u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV<<16);
break;
}
/*----Set RF_ENV enable----*/
PHY_SetBBReg(Adapter, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1);
udelay(1);/* PlatformStallExecution(1); */
/*----Set RF_ENV output high----*/
PHY_SetBBReg(Adapter, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
udelay(1);/* PlatformStallExecution(1); */
/* Set bit number of Address and Data for RF register */
PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); /* Set 1 to 4 bits for 8255 */
udelay(1);/* PlatformStallExecution(1); */
PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); /* Set 0 to 12 bits for 8255 */
udelay(1);/* PlatformStallExecution(1); */
/*----Initialize RF fom connfiguration file----*/
switch (eRFPath) {
case RF_PATH_A:
if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile23a(&pHalData->odmpriv, (enum RF_RADIO_PATH)eRFPath, (enum RF_RADIO_PATH)eRFPath))
rtStatus = _FAIL;
break;
case RF_PATH_B:
if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile23a(&pHalData->odmpriv, (enum RF_RADIO_PATH)eRFPath, (enum RF_RADIO_PATH)eRFPath))
rtStatus = _FAIL;
break;
case RF_PATH_C:
break;
case RF_PATH_D:
break;
}
/*----Restore RFENV control type----*/;
switch (eRFPath) {
case RF_PATH_A:
case RF_PATH_C:
PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue);
break;
case RF_PATH_B:
case RF_PATH_D:
PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV<<16, u4RegValue);
break;
}
if (rtStatus != _SUCCESS) {
/* RT_TRACE(COMP_FPGA, DBG_LOUD, ("phy_RF6052_Config_ParaFile():Radio[%d] Fail!!", eRFPath)); */
goto phy_RF6052_Config_ParaFile_Fail;
}
}
phy_RF6052_Config_ParaFile_Fail:
return rtStatus;
}
int PHY_RF6052_Config8723A(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
int rtStatus = _SUCCESS;
/* Initialize general global value */
/* TODO: Extend RF_PATH_C and RF_PATH_D in the future */
if (pHalData->rf_type == RF_1T1R)
pHalData->NumTotalRFPath = 1;
else
pHalData->NumTotalRFPath = 2;
/* Config BB and RF */
rtStatus = phy_RF6052_Config_ParaFile(Adapter);
return rtStatus;
}
/* End of HalRf6052.c */
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#define _RTL8723A_REDESC_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <rtl8723a_hal.h>
static void process_rssi(struct rtw_adapter *padapter,
struct recv_frame *prframe)
{
struct rx_pkt_attrib *pattrib = &prframe->attrib;
struct signal_stat *signal_stat = &padapter->recvpriv.signal_strength_data;
if (signal_stat->update_req) {
signal_stat->total_num = 0;
signal_stat->total_val = 0;
signal_stat->update_req = 0;
}
signal_stat->total_num++;
signal_stat->total_val += pattrib->phy_info.SignalStrength;
signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;
}
static void process_link_qual(struct rtw_adapter *padapter,
struct recv_frame *prframe)
{
struct rx_pkt_attrib *pattrib;
struct signal_stat *signal_stat;
if (prframe == NULL || padapter == NULL)
return;
pattrib = &prframe->attrib;
signal_stat = &padapter->recvpriv.signal_qual_data;
if (signal_stat->update_req) {
signal_stat->total_num = 0;
signal_stat->total_val = 0;
signal_stat->update_req = 0;
}
signal_stat->total_num++;
signal_stat->total_val += pattrib->phy_info.SignalQuality;
signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;
}
/* void rtl8723a_process_phy_info(struct rtw_adapter *padapter, union recv_frame *prframe) */
void rtl8723a_process_phy_info(struct rtw_adapter *padapter, void *prframe)
{
struct recv_frame *precvframe = prframe;
/* Check RSSI */
process_rssi(padapter, precvframe);
/* Check EVM */
process_link_qual(padapter, precvframe);
}
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#define _RTL8723A_SRESET_C_
#include <rtl8723a_sreset.h>
#include <rtl8723a_hal.h>
void rtl8723a_sreset_xmit_status_check(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct sreset_priv *psrtpriv = &pHalData->srestpriv;
unsigned long current_time;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
unsigned int diff_time;
u32 txdma_status;
txdma_status = rtw_read32(padapter, REG_TXDMA_STATUS);
if (txdma_status != 0) {
DBG_8723A("%s REG_TXDMA_STATUS:0x%08x\n", __func__, txdma_status);
rtw_hal_sreset_reset23a(padapter);
}
current_time = jiffies;
if (0 == pxmitpriv->free_xmitbuf_cnt || 0 == pxmitpriv->free_xmit_extbuf_cnt) {
diff_time = jiffies_to_msecs(jiffies - psrtpriv->last_tx_time);
if (diff_time > 2000) {
if (psrtpriv->last_tx_complete_time == 0) {
psrtpriv->last_tx_complete_time = current_time;
} else {
diff_time = jiffies_to_msecs(jiffies - psrtpriv->last_tx_complete_time);
if (diff_time > 4000) {
/* padapter->Wifi_Error_Status = WIFI_TX_HANG; */
DBG_8723A("%s tx hang\n", __func__);
rtw_hal_sreset_reset23a(padapter);
}
}
}
}
if (psrtpriv->dbg_trigger_point == SRESET_TGP_XMIT_STATUS) {
psrtpriv->dbg_trigger_point = SRESET_TGP_NULL;
rtw_hal_sreset_reset23a(padapter);
return;
}
}
void rtl8723a_sreset_linked_status_check(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct sreset_priv *psrtpriv = &pHalData->srestpriv;
if (psrtpriv->dbg_trigger_point == SRESET_TGP_LINK_STATUS) {
psrtpriv->dbg_trigger_point = SRESET_TGP_NULL;
rtw_hal_sreset_reset23a(padapter);
return;
}
}
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#define _RTL8723A_XMIT_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <rtl8723a_hal.h>
void dump_txrpt_ccx_8723a(void *buf)
{
struct txrpt_ccx_8723a *txrpt_ccx = buf;
DBG_8723A("%s:\n"
"tag1:%u, rsvd:%u, int_bt:%u, int_tri:%u, int_ccx:%u\n"
"mac_id:%u, pkt_drop:%u, pkt_ok:%u, bmc:%u\n"
"retry_cnt:%u, lifetime_over:%u, retry_over:%u\n"
"ccx_qtime:%u\n"
"final_data_rate:0x%02x\n"
"qsel:%u, sw:0x%03x\n"
, __func__
, txrpt_ccx->tag1, txrpt_ccx->rsvd, txrpt_ccx->int_bt, txrpt_ccx->int_tri, txrpt_ccx->int_ccx
, txrpt_ccx->mac_id, txrpt_ccx->pkt_drop, txrpt_ccx->pkt_ok, txrpt_ccx->bmc
, txrpt_ccx->retry_cnt, txrpt_ccx->lifetime_over, txrpt_ccx->retry_over
, txrpt_ccx_qtime_8723a(txrpt_ccx)
, txrpt_ccx->final_data_rate
, txrpt_ccx->qsel, txrpt_ccx_sw_8723a(txrpt_ccx)
);
}
void handle_txrpt_ccx_8723a(struct rtw_adapter *adapter, void *buf)
{
struct txrpt_ccx_8723a *txrpt_ccx = buf;
if (txrpt_ccx->int_ccx) {
if (txrpt_ccx->pkt_ok)
rtw_ack_tx_done23a(&adapter->xmitpriv, RTW_SCTX_DONE_SUCCESS);
else
rtw_ack_tx_done23a(&adapter->xmitpriv, RTW_SCTX_DONE_CCX_PKT_FAIL);
}
}
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#include "drv_types.h"
#include "rtl8723a_hal.h"
#include "rtl8723a_led.h"
/* */
/* LED object. */
/* */
/* */
/* Prototype of protected function. */
/* */
/* */
/* LED_819xUsb routines. */
/* */
/* Description: */
/* Turn on LED according to LedPin specified. */
void SwLedOn23a(struct rtw_adapter *padapter, struct led_8723a *pLed)
{
u8 LedCfg = 0;
if ((padapter->bSurpriseRemoved == true) || (padapter->bDriverStopped == true))
return;
switch (pLed->LedPin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
rtw_write8(padapter, REG_LEDCFG0, (LedCfg&0xf0)|BIT5|BIT6); /* SW control led0 on. */
break;
case LED_PIN_LED1:
rtw_write8(padapter, REG_LEDCFG1, (LedCfg&0x00)|BIT6); /* SW control led1 on. */
break;
case LED_PIN_LED2:
LedCfg = rtw_read8(padapter, REG_LEDCFG2);
rtw_write8(padapter, REG_LEDCFG2, (LedCfg&0x80)|BIT5); /* SW control led1 on. */
break;
default:
break;
}
pLed->bLedOn = true;
}
/* Description: */
/* Turn off LED according to LedPin specified. */
void SwLedOff23a(struct rtw_adapter *padapter, struct led_8723a *pLed)
{
u8 LedCfg = 0;
/* struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); */
if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped))
goto exit;
switch (pLed->LedPin) {
case LED_PIN_GPIO0:
break;
case LED_PIN_LED0:
rtw_write8(padapter, REG_LEDCFG0, (LedCfg&0xf0)|BIT5|BIT6); /* SW control led0 on. */
break;
case LED_PIN_LED1:
rtw_write8(padapter, REG_LEDCFG1, (LedCfg&0x00)|BIT5|BIT6); /* SW control led1 on. */
break;
case LED_PIN_LED2:
LedCfg = rtw_read8(padapter, REG_LEDCFG2);
rtw_write8(padapter, REG_LEDCFG2, (LedCfg&0x80)|BIT3|BIT5); /* SW control led1 on. */
break;
default:
break;
}
exit:
pLed->bLedOn = false;
}
/* Interface to manipulate LED objects. */
/* Description: */
/* Initialize all LED_871x objects. */
void
rtl8723au_InitSwLeds(struct rtw_adapter *padapter)
{
struct led_priv *pledpriv = &padapter->ledpriv;
pledpriv->LedControlHandler = LedControl871x23a;
/* 8723as-vau wifi used led2 */
InitLed871x23a(padapter, &pledpriv->SwLed0, LED_PIN_LED2);
/* InitLed871x23a(padapter,&pledpriv->SwLed1, LED_PIN_LED2); */
}
/* Description: */
/* DeInitialize all LED_819xUsb objects. */
void
rtl8723au_DeInitSwLeds(struct rtw_adapter *padapter)
{
struct led_priv *ledpriv = &padapter->ledpriv;
DeInitLed871x23a(&ledpriv->SwLed0);
}
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#define _RTL8192CU_RECV_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <recv_osdep.h>
#include <mlme_osdep.h>
#include <linux/ip.h>
#include <linux/if_ether.h>
#include <ethernet.h>
#include <usb_ops.h>
#include <wifi.h>
#include <rtl8723a_hal.h>
void rtl8723au_init_recvbuf(struct rtw_adapter *padapter,
struct recv_buf *precvbuf)
{
}
int rtl8723au_init_recv_priv(struct rtw_adapter *padapter)
{
struct recv_priv *precvpriv = &padapter->recvpriv;
int i, size, res = _SUCCESS;
struct recv_buf *precvbuf;
unsigned long tmpaddr;
unsigned long alignment;
struct sk_buff *pskb;
tasklet_init(&precvpriv->recv_tasklet,
(void(*)(unsigned long))rtl8723au_recv_tasklet,
(unsigned long)padapter);
precvpriv->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!precvpriv->int_in_urb)
DBG_8723A("alloc_urb for interrupt in endpoint fail !!!!\n");
precvpriv->int_in_buf = kzalloc(USB_INTR_CONTENT_LENGTH, GFP_KERNEL);
if (!precvpriv->int_in_buf)
DBG_8723A("alloc_mem for interrupt in endpoint fail !!!!\n");
/* init recv_buf */
_rtw_init_queue23a(&precvpriv->free_recv_buf_queue);
size = NR_RECVBUFF * sizeof(struct recv_buf);
precvpriv->precv_buf = kzalloc(size, GFP_KERNEL);
if (!precvpriv->precv_buf) {
res = _FAIL;
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
("alloc recv_buf fail!\n"));
goto exit;
}
precvbuf = (struct recv_buf *)precvpriv->precv_buf;
for (i = 0; i < NR_RECVBUFF; i++) {
INIT_LIST_HEAD(&precvbuf->list);
res = rtw_os_recvbuf_resource_alloc23a(padapter, precvbuf);
if (res == _FAIL)
break;
precvbuf->adapter = padapter;
precvbuf++;
}
precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF;
skb_queue_head_init(&precvpriv->rx_skb_queue);
skb_queue_head_init(&precvpriv->free_recv_skb_queue);
for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) {
size = MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ;
pskb = __netdev_alloc_skb(padapter->pnetdev, size, GFP_KERNEL);
if (pskb) {
pskb->dev = padapter->pnetdev;
tmpaddr = (unsigned long)pskb->data;
alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));
skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
}
pskb = NULL;
}
exit:
return res;
}
void rtl8723au_free_recv_priv(struct rtw_adapter *padapter)
{
int i;
struct recv_buf *precvbuf;
struct recv_priv *precvpriv = &padapter->recvpriv;
precvbuf = (struct recv_buf *)precvpriv->precv_buf;
for (i = 0; i < NR_RECVBUFF; i++) {
rtw_os_recvbuf_resource_free23a(padapter, precvbuf);
precvbuf++;
}
kfree(precvpriv->precv_buf);
usb_free_urb(precvpriv->int_in_urb);
kfree(precvpriv->int_in_buf);
if (skb_queue_len(&precvpriv->rx_skb_queue))
DBG_8723A(KERN_WARNING "rx_skb_queue not empty\n");
skb_queue_purge(&precvpriv->rx_skb_queue);
if (skb_queue_len(&precvpriv->free_recv_skb_queue)) {
DBG_8723A(KERN_WARNING "free_recv_skb_queue not empty, %d\n",
skb_queue_len(&precvpriv->free_recv_skb_queue));
}
skb_queue_purge(&precvpriv->free_recv_skb_queue);
}
void update_recvframe_attrib(struct recv_frame *precvframe,
struct recv_stat *prxstat)
{
struct rx_pkt_attrib *pattrib;
struct recv_stat report;
struct rxreport_8723a *prxreport;
report.rxdw0 = le32_to_cpu(prxstat->rxdw0);
report.rxdw1 = le32_to_cpu(prxstat->rxdw1);
report.rxdw2 = le32_to_cpu(prxstat->rxdw2);
report.rxdw3 = le32_to_cpu(prxstat->rxdw3);
report.rxdw4 = le32_to_cpu(prxstat->rxdw4);
report.rxdw5 = le32_to_cpu(prxstat->rxdw5);
prxreport = (struct rxreport_8723a *)&report;
pattrib = &precvframe->attrib;
memset(pattrib, 0, sizeof(struct rx_pkt_attrib));
/* update rx report to recv_frame attribute */
pattrib->pkt_len = (u16)prxreport->pktlen;
pattrib->drvinfo_sz = (u8)(prxreport->drvinfosize << 3);
pattrib->physt = (u8)prxreport->physt;
pattrib->crc_err = (u8)prxreport->crc32;
pattrib->icv_err = (u8)prxreport->icverr;
pattrib->bdecrypted = (u8)(prxreport->swdec ? 0 : 1);
pattrib->encrypt = (u8)prxreport->security;
pattrib->qos = (u8)prxreport->qos;
pattrib->priority = (u8)prxreport->tid;
pattrib->amsdu = (u8)prxreport->amsdu;
pattrib->seq_num = (u16)prxreport->seq;
pattrib->frag_num = (u8)prxreport->frag;
pattrib->mfrag = (u8)prxreport->mf;
pattrib->mdata = (u8)prxreport->md;
pattrib->mcs_rate = (u8)prxreport->rxmcs;
pattrib->rxht = (u8)prxreport->rxht;
}
void update_recvframe_phyinfo(struct recv_frame *precvframe,
struct phy_stat *pphy_status)
{
struct rtw_adapter *padapter = precvframe->adapter;
struct rx_pkt_attrib *pattrib = &precvframe->attrib;
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct odm_phy_info *pPHYInfo = (struct odm_phy_info *)(&pattrib->phy_info);
struct odm_packet_info pkt_info;
u8 *sa = NULL, *da;
struct sta_priv *pstapriv;
struct sta_info *psta;
struct sk_buff *skb = precvframe->pkt;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
u8 *wlanhdr = skb->data;
pkt_info.bPacketMatchBSSID = false;
pkt_info.bPacketToSelf = false;
pkt_info.bPacketBeacon = false;
pkt_info.bPacketMatchBSSID =
(!ieee80211_is_ctl(hdr->frame_control) &&
!pattrib->icv_err &&
!pattrib->crc_err &&
!memcmp(get_hdr_bssid(wlanhdr),
get_bssid(&padapter->mlmepriv), ETH_ALEN));
da = ieee80211_get_DA(hdr);
pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID &&
(!memcmp(da, myid(&padapter->eeprompriv), ETH_ALEN));
pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID &&
ieee80211_is_beacon(hdr->frame_control);
pkt_info.StationID = 0xFF;
if (pkt_info.bPacketBeacon) {
if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == true)
sa = padapter->mlmepriv.cur_network.network.MacAddress;
/* to do Ad-hoc */
} else {
sa = ieee80211_get_SA(hdr);
}
pstapriv = &padapter->stapriv;
psta = rtw_get_stainfo23a(pstapriv, sa);
if (psta) {
pkt_info.StationID = psta->mac_id;
/* printk("%s ==> StationID(%d)\n", __FUNCTION__, pkt_info.StationID); */
}
pkt_info.Rate = pattrib->mcs_rate;
ODM_PhyStatusQuery23a(&pHalData->odmpriv, pPHYInfo,
(u8 *)pphy_status, &pkt_info);
precvframe->psta = NULL;
if (pkt_info.bPacketMatchBSSID &&
(check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)) {
if (psta) {
precvframe->psta = psta;
rtl8723a_process_phy_info(padapter, precvframe);
}
} else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon) {
if (check_fwstate(&padapter->mlmepriv,
WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) ==
true) {
if (psta)
precvframe->psta = psta;
}
rtl8723a_process_phy_info(padapter, precvframe);
}
}
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#define _RTL8192C_XMIT_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <wifi.h>
#include <osdep_intf.h>
#include <usb_ops.h>
/* include <rtl8192c_hal.h> */
#include <rtl8723a_hal.h>
s32 rtl8723au_init_xmit_priv(struct rtw_adapter *padapter)
{
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
tasklet_init(&pxmitpriv->xmit_tasklet,
(void(*)(unsigned long))rtl8723au_xmit_tasklet,
(unsigned long)padapter);
return _SUCCESS;
}
void rtl8723au_free_xmit_priv(struct rtw_adapter *padapter)
{
}
static void do_queue_select(struct rtw_adapter *padapter, struct pkt_attrib *pattrib)
{
u8 qsel;
qsel = pattrib->priority;
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
("### do_queue_select priority =%d , qsel = %d\n",
pattrib->priority, qsel));
pattrib->qsel = qsel;
}
static int urb_zero_packet_chk(struct rtw_adapter *padapter, int sz)
{
int blnSetTxDescOffset;
struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
if (pdvobj->ishighspeed) {
if (((sz + TXDESC_SIZE) % 512) == 0)
blnSetTxDescOffset = 1;
else
blnSetTxDescOffset = 0;
} else {
if (((sz + TXDESC_SIZE) % 64) == 0)
blnSetTxDescOffset = 1;
else
blnSetTxDescOffset = 0;
}
return blnSetTxDescOffset;
}
static void rtl8192cu_cal_txdesc_chksum(struct tx_desc *ptxdesc)
{
u16 *usPtr = (u16 *)ptxdesc;
u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */
u32 index;
u16 checksum = 0;
/* Clear first */
ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
for (index = 0 ; index < count ; index++)
checksum = checksum ^ le16_to_cpu(*(usPtr + index));
ptxdesc->txdw7 |= cpu_to_le32(0x0000ffff&checksum);
}
static void fill_txdesc_sectype(struct pkt_attrib *pattrib, struct tx_desc *ptxdesc)
{
if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
switch (pattrib->encrypt) {
/* SEC_TYPE */
case _WEP40_:
case _WEP104_:
ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000);
break;
case _TKIP_:
case _TKIP_WTMIC_:
/* ptxdesc->txdw1 |= cpu_to_le32((0x02<<22)&0x00c00000); */
ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000);
break;
case _AES_:
ptxdesc->txdw1 |= cpu_to_le32((0x03<<22)&0x00c00000);
break;
case _NO_PRIVACY_:
default:
break;
}
}
}
static void fill_txdesc_vcs(struct pkt_attrib *pattrib, u32 *pdw)
{
/* DBG_8723A("cvs_mode =%d\n", pattrib->vcs_mode); */
switch (pattrib->vcs_mode) {
case RTS_CTS:
*pdw |= cpu_to_le32(BIT(12));
break;
case CTS_TO_SELF:
*pdw |= cpu_to_le32(BIT(11));
break;
case NONE_VCS:
default:
break;
}
if (pattrib->vcs_mode) {
*pdw |= cpu_to_le32(BIT(13));
/* Set RTS BW */
if (pattrib->ht_en) {
*pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(27)) : 0;
if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
*pdw |= cpu_to_le32((0x01<<28)&0x30000000);
else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
*pdw |= cpu_to_le32((0x02<<28)&0x30000000);
else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
*pdw |= 0;
else
*pdw |= cpu_to_le32((0x03<<28)&0x30000000);
}
}
}
static void fill_txdesc_phy(struct pkt_attrib *pattrib, u32 *pdw)
{
if (pattrib->ht_en) {
*pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(25)) : 0;
if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
*pdw |= cpu_to_le32((0x01<<20)&0x003f0000);
else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
*pdw |= cpu_to_le32((0x02<<20)&0x003f0000);
else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
*pdw |= 0;
else
*pdw |= cpu_to_le32((0x03<<20)&0x003f0000);
}
}
static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bagg_pkt)
{
int pull = 0;
uint qsel;
struct rtw_adapter *padapter = pxmitframe->padapter;
struct pkt_attrib *pattrib = &pxmitframe->attrib;
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
struct tx_desc *ptxdesc = (struct tx_desc *)pmem;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
int bmcst = is_multicast_ether_addr(pattrib->ra);
if ((!bagg_pkt) && (urb_zero_packet_chk(padapter, sz) == 0)) {
ptxdesc = (struct tx_desc *)(pmem+PACKET_OFFSET_SZ);
pull = 1;
pxmitframe->pkt_offset--;
}
memset(ptxdesc, 0, sizeof(struct tx_desc));
if ((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG) {
/* offset 4 */
ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f);
qsel = (uint)(pattrib->qsel & 0x0000001f);
ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<<16) & 0x000f0000);
fill_txdesc_sectype(pattrib, ptxdesc);
if (pattrib->ampdu_en)
ptxdesc->txdw1 |= cpu_to_le32(BIT(5));/* AGG EN */
else
ptxdesc->txdw1 |= cpu_to_le32(BIT(6));/* AGG BK */
/* offset 8 */
/* offset 12 */
ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000);
/* offset 16 , offset 20 */
if (pattrib->qos_en)
ptxdesc->txdw4 |= cpu_to_le32(BIT(6));/* QoS */
if ((pattrib->ether_type != 0x888e) &&
(pattrib->ether_type != 0x0806) &&
(pattrib->dhcp_pkt != 1)) {
/* Non EAP & ARP & DHCP type data packet */
fill_txdesc_vcs(pattrib, &ptxdesc->txdw4);
fill_txdesc_phy(pattrib, &ptxdesc->txdw4);
ptxdesc->txdw4 |= cpu_to_le32(0x00000008);/* RTS Rate = 24M */
ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);/* */
/* use REG_INIDATA_RATE_SEL value */
ptxdesc->txdw5 |= cpu_to_le32(pdmpriv->INIDATA_RATE[pattrib->mac_id]);
} else {
/* EAP data packet and ARP packet. */
/* Use the 1M data rate to send the EAP/ARP packet. */
/* This will maybe make the handshake smooth. */
ptxdesc->txdw1 |= cpu_to_le32(BIT(6));/* AGG BK */
ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
ptxdesc->txdw4 |= cpu_to_le32(BIT(24));/* DATA_SHORT */
ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate));
}
} else if ((pxmitframe->frame_tag&0x0f) == MGNT_FRAMETAG) {
/* offset 4 */
ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f);
qsel = (uint)(pattrib->qsel&0x0000001f);
ptxdesc->txdw1 |= cpu_to_le32((qsel<<QSEL_SHT)&0x00001f00);
ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<<16) & 0x000f0000);
/* offset 8 */
/* CCX-TXRPT ack for xmit mgmt frames. */
if (pxmitframe->ack_report)
ptxdesc->txdw2 |= cpu_to_le32(BIT(19));
/* offset 12 */
ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000);
/* offset 16 */
ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
/* offset 20 */
ptxdesc->txdw5 |= cpu_to_le32(BIT(17));/* retry limit enable */
ptxdesc->txdw5 |= cpu_to_le32(0x00180000);/* retry limit = 6 */
ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate));
} else if ((pxmitframe->frame_tag&0x0f) == TXAGG_FRAMETAG) {
DBG_8723A("pxmitframe->frame_tag == TXAGG_FRAMETAG\n");
} else {
DBG_8723A("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag);
/* offset 4 */
ptxdesc->txdw1 |= cpu_to_le32((4)&0x1f);/* CAM_ID(MAC_ID) */
ptxdesc->txdw1 |= cpu_to_le32((6<<16) & 0x000f0000);/* raid */
/* offset 8 */
/* offset 12 */
ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000);
/* offset 16 */
ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
/* offset 20 */
ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate));
}
/* (1) The sequence number of each non-Qos frame / broadcast / multicast / */
/* mgnt frame should be controled by Hw because Fw will also send null data */
/* which we cannot control when Fw LPS enable. */
/* --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */
/* (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */
/* (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. */
if (!pattrib->qos_en) {
/* Hw set sequence number */
ptxdesc->txdw4 |= cpu_to_le32(BIT(7));
/* set bit3 to 1. */
ptxdesc->txdw3 |= cpu_to_le32((8 << 28));
}
/* offset 0 */
ptxdesc->txdw0 |= cpu_to_le32(sz&0x0000ffff);
ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000);/* 32 bytes for TX Desc */
if (bmcst)
ptxdesc->txdw0 |= cpu_to_le32(BIT(24));
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("offset0-txdesc = 0x%x\n", ptxdesc->txdw0));
/* offset 4 */
/* pkt_offset, unit:8 bytes padding */
if (pxmitframe->pkt_offset > 0)
ptxdesc->txdw1 |= cpu_to_le32((pxmitframe->pkt_offset << 26) & 0x7c000000);
rtl8192cu_cal_txdesc_chksum(ptxdesc);
return pull;
}
static s32 rtw_dump_xframe(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
{
s32 ret = _SUCCESS;
s32 inner_ret = _SUCCESS;
int t, sz, w_sz, pull = 0;
u8 *mem_addr;
u32 ff_hwaddr;
struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf;
struct pkt_attrib *pattrib = &pxmitframe->attrib;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
if ((pxmitframe->frame_tag == DATA_FRAMETAG) &&
(pxmitframe->attrib.ether_type != 0x0806) &&
(pxmitframe->attrib.ether_type != 0x888e) &&
(pxmitframe->attrib.dhcp_pkt != 1))
rtw_issue_addbareq_cmd23a(padapter, pxmitframe);
mem_addr = pxmitframe->buf_addr;
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_dump_xframe()\n"));
for (t = 0; t < pattrib->nr_frags; t++) {
if (inner_ret != _SUCCESS && ret == _SUCCESS)
ret = _FAIL;
if (t != (pattrib->nr_frags - 1)) {
RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
("pattrib->nr_frags =%d\n", pattrib->nr_frags));
sz = pxmitpriv->frag_len;
sz = sz - 4 - pattrib->icv_len;
} else {
/* no frag */
sz = pattrib->last_txcmdsz;
}
pull = update_txdesc(pxmitframe, mem_addr, sz, false);
if (pull) {
mem_addr += PACKET_OFFSET_SZ; /* pull txdesc head */
pxmitframe->buf_addr = mem_addr;
w_sz = sz + TXDESC_SIZE;
} else {
w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ;
}
ff_hwaddr = rtw_get_ff_hwaddr23a(pxmitframe);
inner_ret = rtw_write_port(padapter, ff_hwaddr, w_sz, pxmitbuf);
rtw_count_tx_stats23a(padapter, pxmitframe, sz);
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
("rtw_write_port, w_sz =%d\n", w_sz));
mem_addr += w_sz;
mem_addr = (u8 *)RND4(((unsigned long)(mem_addr)));
}
rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
if (ret != _SUCCESS)
rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN);
return ret;
}
s32 rtl8723au_xmitframe_complete(struct rtw_adapter *padapter,
struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
{
struct hw_xmit *phwxmits;
struct xmit_frame *pxmitframe;
int hwentry;
int res = _SUCCESS, xcnt = 0;
phwxmits = pxmitpriv->hwxmits;
hwentry = pxmitpriv->hwxmit_entry;
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("xmitframe_complete()\n"));
if (pxmitbuf == NULL) {
pxmitbuf = rtw_alloc_xmitbuf23a(pxmitpriv);
if (!pxmitbuf)
return false;
}
pxmitframe = rtw_dequeue_xframe23a(pxmitpriv, phwxmits, hwentry);
if (pxmitframe) {
pxmitframe->pxmitbuf = pxmitbuf;
pxmitframe->buf_addr = pxmitbuf->pbuf;
pxmitbuf->priv_data = pxmitframe;
if ((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG) {
if (pxmitframe->attrib.priority <= 15)/* TID0~15 */
res = rtw_xmitframe_coalesce23a(padapter, pxmitframe->pkt, pxmitframe);
rtw_os_xmit_complete23a(padapter, pxmitframe);/* always return ndis_packet after rtw_xmitframe_coalesce23a */
}
RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("xmitframe_complete(): rtw_dump_xframe\n"));
if (res == _SUCCESS) {
rtw_dump_xframe(padapter, pxmitframe);
} else {
rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
}
xcnt++;
} else {
rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
return false;
}
return true;
}
static s32 xmitframe_direct(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
{
s32 res = _SUCCESS;
res = rtw_xmitframe_coalesce23a(padapter, pxmitframe->pkt, pxmitframe);
if (res == _SUCCESS)
rtw_dump_xframe(padapter, pxmitframe);
return res;
}
/*
* Return
* true dump packet directly
* false enqueue packet
*/
static s32 pre_xmitframe(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
{
s32 res;
struct xmit_buf *pxmitbuf = NULL;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct pkt_attrib *pattrib = &pxmitframe->attrib;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
do_queue_select(padapter, pattrib);
spin_lock_bh(&pxmitpriv->lock);
#ifdef CONFIG_8723AU_AP_MODE
if (xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe)) {
struct sta_info *psta;
struct sta_priv *pstapriv = &padapter->stapriv;
spin_unlock_bh(&pxmitpriv->lock);
if (pattrib->psta)
psta = pattrib->psta;
else
psta = rtw_get_stainfo23a(pstapriv, pattrib->ra);
if (psta) {
if (psta->sleepq_len > (NR_XMITFRAME>>3))
wakeup_sta_to_xmit23a(padapter, psta);
}
return false;
}
#endif
if (rtw_txframes_sta_ac_pending23a(padapter, pattrib) > 0)
goto enqueue;
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true)
goto enqueue;
pxmitbuf = rtw_alloc_xmitbuf23a(pxmitpriv);
if (pxmitbuf == NULL)
goto enqueue;
spin_unlock_bh(&pxmitpriv->lock);
pxmitframe->pxmitbuf = pxmitbuf;
pxmitframe->buf_addr = pxmitbuf->pbuf;
pxmitbuf->priv_data = pxmitframe;
if (xmitframe_direct(padapter, pxmitframe) != _SUCCESS) {
rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
}
return true;
enqueue:
res = rtw_xmitframe_enqueue23a(padapter, pxmitframe);
spin_unlock_bh(&pxmitpriv->lock);
if (res != _SUCCESS) {
RT_TRACE(_module_xmit_osdep_c_, _drv_err_,
("pre_xmitframe: enqueue xmitframe fail\n"));
rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
/* Trick, make the statistics correct */
pxmitpriv->tx_pkts--;
pxmitpriv->tx_drop++;
return true;
}
return false;
}
s32 rtl8723au_mgnt_xmit(struct rtw_adapter *padapter, struct xmit_frame *pmgntframe)
{
return rtw_dump_xframe(padapter, pmgntframe);
}
/*
* Return
* true dump packet directly ok
* false temporary can't transmit packets to hardware
*/
s32 rtl8723au_hal_xmit(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
{
return pre_xmitframe(padapter, pxmitframe);
}
s32 rtl8723au_hal_xmitframe_enqueue(struct rtw_adapter *padapter,
struct xmit_frame *pxmitframe)
{
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
s32 err;
err = rtw_xmitframe_enqueue23a(padapter, pxmitframe);
if (err != _SUCCESS) {
rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
/* Trick, make the statistics correct */
pxmitpriv->tx_pkts--;
pxmitpriv->tx_drop++;
} else {
tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
}
return err;
}
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#define _HCI_HAL_INIT_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <rtw_efuse.h>
#include <HalPwrSeqCmd.h>
#include <Hal8723PwrSeq.h>
#include <rtl8723a_hal.h>
#include <rtl8723a_led.h>
#include <linux/ieee80211.h>
#include <usb_ops.h>
#include <usb_hal.h>
#include <usb_osintf.h>
static void
_ConfigChipOutEP(struct rtw_adapter *pAdapter, u8 NumOutPipe)
{
u8 value8;
struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
pHalData->OutEpQueueSel = 0;
pHalData->OutEpNumber = 0;
/* Normal and High queue */
value8 = rtw_read8(pAdapter, (REG_NORMAL_SIE_EP + 1));
if (value8 & USB_NORMAL_SIE_EP_MASK) {
pHalData->OutEpQueueSel |= TX_SELE_HQ;
pHalData->OutEpNumber++;
}
if ((value8 >> USB_NORMAL_SIE_EP_SHIFT) & USB_NORMAL_SIE_EP_MASK) {
pHalData->OutEpQueueSel |= TX_SELE_NQ;
pHalData->OutEpNumber++;
}
/* Low queue */
value8 = rtw_read8(pAdapter, (REG_NORMAL_SIE_EP + 2));
if (value8 & USB_NORMAL_SIE_EP_MASK) {
pHalData->OutEpQueueSel |= TX_SELE_LQ;
pHalData->OutEpNumber++;
}
/* TODO: Error recovery for this case */
/* RT_ASSERT((NumOutPipe == pHalData->OutEpNumber),
("Out EP number isn't match! %d(Descriptor) != %d (SIE reg)\n",
(u32)NumOutPipe, (u32)pHalData->OutEpNumber)); */
}
static bool rtl8723au_set_queue_pipe_mapping(struct rtw_adapter *pAdapter,
u8 NumInPipe, u8 NumOutPipe)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
bool result = false;
_ConfigChipOutEP(pAdapter, NumOutPipe);
/* Normal chip with one IN and one OUT doesn't have interrupt IN EP. */
if (pHalData->OutEpNumber == 1) {
if (NumInPipe != 1)
return result;
}
result = Hal_MappingOutPipe23a(pAdapter, NumOutPipe);
return result;
}
static void rtl8723au_interface_configure(struct rtw_adapter *padapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
if (pdvobjpriv->ishighspeed == true) {
/* 512 bytes */
pHalData->UsbBulkOutSize = USB_HIGH_SPEED_BULK_SIZE;
} else {
/* 64 bytes */
pHalData->UsbBulkOutSize = USB_FULL_SPEED_BULK_SIZE;
}
pHalData->interfaceIndex = pdvobjpriv->InterfaceNumber;
rtl8723au_set_queue_pipe_mapping(padapter,
pdvobjpriv->RtNumInPipes,
pdvobjpriv->RtNumOutPipes);
}
static u8 _InitPowerOn(struct rtw_adapter *padapter)
{
u8 status = _SUCCESS;
u16 value16 = 0;
u8 value8 = 0;
/* RSV_CTRL 0x1C[7:0] = 0x00
unlock ISO/CLK/Power control register */
rtw_write8(padapter, REG_RSV_CTRL, 0x0);
/* HW Power on sequence */
if (!HalPwrSeqCmdParsing23a(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
PWR_INTF_USB_MSK, rtl8723AU_card_enable_flow))
return _FAIL;
/* 0x04[19] = 1, suggest by Jackie 2011.05.09, reset 8051 */
value8 = rtw_read8(padapter, REG_APS_FSMCO+2);
rtw_write8(padapter, REG_APS_FSMCO + 2, (value8 | BIT3));
/* Enable MAC DMA/WMAC/SCHEDULE/SEC block */
/* Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy.
Added by tynli. 2011.08.31. */
value16 = rtw_read16(padapter, REG_CR);
value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN |
PROTOCOL_EN | SCHEDULE_EN | MACTXEN | MACRXEN |
ENSEC | CALTMR_EN);
rtw_write16(padapter, REG_CR, value16);
/* for Efuse PG, suggest by Jackie 2011.11.23 */
PHY_SetBBReg(padapter, REG_EFUSE_CTRL, BIT28|BIT29|BIT30, 0x06);
return status;
}
/* Shall USB interface init this? */
static void _InitInterrupt(struct rtw_adapter *Adapter)
{
u32 value32;
/* HISR - turn all on */
value32 = 0xFFFFFFFF;
rtw_write32(Adapter, REG_HISR, value32);
/* HIMR - turn all on */
rtw_write32(Adapter, REG_HIMR, value32);
}
static void _InitQueueReservedPage(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct registry_priv *pregistrypriv = &Adapter->registrypriv;
u32 numHQ = 0;
u32 numLQ = 0;
u32 numNQ = 0;
u32 numPubQ;
u32 value32;
u8 value8;
bool bWiFiConfig = pregistrypriv->wifi_spec;
/* u32 txQPageNum, txQPageUnit, txQRemainPage; */
{ /* for WMM */
/* RT_ASSERT((outEPNum>= 2), ("for WMM , number of out-ep "
"must more than or equal to 2!\n")); */
numPubQ = bWiFiConfig ?
WMM_NORMAL_PAGE_NUM_PUBQ : NORMAL_PAGE_NUM_PUBQ;
if (pHalData->OutEpQueueSel & TX_SELE_HQ) {
numHQ = bWiFiConfig ?
WMM_NORMAL_PAGE_NUM_HPQ : NORMAL_PAGE_NUM_HPQ;
}
if (pHalData->OutEpQueueSel & TX_SELE_LQ) {
numLQ = bWiFiConfig ?
WMM_NORMAL_PAGE_NUM_LPQ : NORMAL_PAGE_NUM_LPQ;
}
/* NOTE: This step shall be proceed before
writting REG_RQPN. */
if (pHalData->OutEpQueueSel & TX_SELE_NQ) {
numNQ = bWiFiConfig ?
WMM_NORMAL_PAGE_NUM_NPQ : NORMAL_PAGE_NUM_NPQ;
}
value8 = (u8)_NPQ(numNQ);
rtw_write8(Adapter, REG_RQPN_NPQ, value8);
}
/* TX DMA */
value32 = _HPQ(numHQ) | _LPQ(numLQ) | _PUBQ(numPubQ) | LD_RQPN;
rtw_write32(Adapter, REG_RQPN, value32);
}
static void _InitTxBufferBoundary(struct rtw_adapter *Adapter)
{
struct registry_priv *pregistrypriv = &Adapter->registrypriv;
u8 txpktbuf_bndy;
if (!pregistrypriv->wifi_spec)
txpktbuf_bndy = TX_PAGE_BOUNDARY;
else /* for WMM */
txpktbuf_bndy = WMM_NORMAL_TX_PAGE_BOUNDARY;
rtw_write8(Adapter, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy);
rtw_write8(Adapter, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy);
rtw_write8(Adapter, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy);
rtw_write8(Adapter, REG_TRXFF_BNDY, txpktbuf_bndy);
rtw_write8(Adapter, REG_TDECTRL+1, txpktbuf_bndy);
}
static void _InitPageBoundary(struct rtw_adapter *Adapter)
{
/* RX Page Boundary */
/* srand(static_cast<unsigned int>(time(NULL))); */
u16 rxff_bndy = 0x27FF;/* rand() % 1) ? 0x27FF : 0x23FF; */
rtw_write16(Adapter, (REG_TRXFF_BNDY + 2), rxff_bndy);
/* TODO: ?? shall we set tx boundary? */
}
static void
_InitNormalChipRegPriority(struct rtw_adapter *Adapter, u16 beQ, u16 bkQ,
u16 viQ, u16 voQ, u16 mgtQ, u16 hiQ)
{
u16 value16 = rtw_read16(Adapter, REG_TRXDMA_CTRL) & 0x7;
value16 |= _TXDMA_BEQ_MAP(beQ) | _TXDMA_BKQ_MAP(bkQ) |
_TXDMA_VIQ_MAP(viQ) | _TXDMA_VOQ_MAP(voQ) |
_TXDMA_MGQ_MAP(mgtQ) | _TXDMA_HIQ_MAP(hiQ);
rtw_write16(Adapter, REG_TRXDMA_CTRL, value16);
}
static void _InitNormalChipOneOutEpPriority(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
u16 value = 0;
switch (pHalData->OutEpQueueSel) {
case TX_SELE_HQ:
value = QUEUE_HIGH;
break;
case TX_SELE_LQ:
value = QUEUE_LOW;
break;
case TX_SELE_NQ:
value = QUEUE_NORMAL;
break;
default:
/* RT_ASSERT(false, ("Shall not reach here!\n")); */
break;
}
_InitNormalChipRegPriority(Adapter, value, value, value,
value, value, value);
}
static void _InitNormalChipTwoOutEpPriority(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct registry_priv *pregistrypriv = &Adapter->registrypriv;
u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ;
u16 valueHi = 0;
u16 valueLow = 0;
switch (pHalData->OutEpQueueSel) {
case (TX_SELE_HQ | TX_SELE_LQ):
valueHi = QUEUE_HIGH;
valueLow = QUEUE_LOW;
break;
case (TX_SELE_NQ | TX_SELE_LQ):
valueHi = QUEUE_NORMAL;
valueLow = QUEUE_LOW;
break;
case (TX_SELE_HQ | TX_SELE_NQ):
valueHi = QUEUE_HIGH;
valueLow = QUEUE_NORMAL;
break;
default:
/* RT_ASSERT(false, ("Shall not reach here!\n")); */
break;
}
if (!pregistrypriv->wifi_spec) {
beQ = valueLow;
bkQ = valueLow;
viQ = valueHi;
voQ = valueHi;
mgtQ = valueHi;
hiQ = valueHi;
} else {/* for WMM , CONFIG_OUT_EP_WIFI_MODE */
beQ = valueLow;
bkQ = valueHi;
viQ = valueHi;
voQ = valueLow;
mgtQ = valueHi;
hiQ = valueHi;
}
_InitNormalChipRegPriority(Adapter, beQ, bkQ, viQ, voQ, mgtQ, hiQ);
}
static void _InitNormalChipThreeOutEpPriority(struct rtw_adapter *Adapter)
{
struct registry_priv *pregistrypriv = &Adapter->registrypriv;
u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ;
if (!pregistrypriv->wifi_spec) {/* typical setting */
beQ = QUEUE_LOW;
bkQ = QUEUE_LOW;
viQ = QUEUE_NORMAL;
voQ = QUEUE_HIGH;
mgtQ = QUEUE_HIGH;
hiQ = QUEUE_HIGH;
} else {/* for WMM */
beQ = QUEUE_LOW;
bkQ = QUEUE_NORMAL;
viQ = QUEUE_NORMAL;
voQ = QUEUE_HIGH;
mgtQ = QUEUE_HIGH;
hiQ = QUEUE_HIGH;
}
_InitNormalChipRegPriority(Adapter, beQ, bkQ, viQ, voQ, mgtQ, hiQ);
}
static void _InitNormalChipQueuePriority(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
switch (pHalData->OutEpNumber) {
case 1:
_InitNormalChipOneOutEpPriority(Adapter);
break;
case 2:
_InitNormalChipTwoOutEpPriority(Adapter);
break;
case 3:
_InitNormalChipThreeOutEpPriority(Adapter);
break;
default:
/* RT_ASSERT(false, ("Shall not reach here!\n")); */
break;
}
}
static void _InitQueuePriority(struct rtw_adapter *Adapter)
{
_InitNormalChipQueuePriority(Adapter);
}
static void _InitNetworkType(struct rtw_adapter *Adapter)
{
u32 value32;
value32 = rtw_read32(Adapter, REG_CR);
/* TODO: use the other function to set network type */
value32 = (value32 & ~MASK_NETTYPE) | _NETTYPE(NT_LINK_AP);
rtw_write32(Adapter, REG_CR, value32);
}
static void _InitTransferPageSize(struct rtw_adapter *Adapter)
{
/* Tx page size is always 128. */
u8 value8;
value8 = _PSRX(PBP_128) | _PSTX(PBP_128);
rtw_write8(Adapter, REG_PBP, value8);
}
static void _InitDriverInfoSize(struct rtw_adapter *Adapter, u8 drvInfoSize)
{
rtw_write8(Adapter, REG_RX_DRVINFO_SZ, drvInfoSize);
}
static void _InitWMACSetting(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
/* don't turn on AAP, it will allow all packets to driver */
pHalData->ReceiveConfig = RCR_APM | RCR_AM | RCR_AB | RCR_CBSSID_DATA |
RCR_CBSSID_BCN | RCR_APP_ICV | RCR_AMF |
RCR_HTC_LOC_CTRL | RCR_APP_MIC |
RCR_APP_PHYSTS;
/* some REG_RCR will be modified later by
phy_ConfigMACWithHeaderFile() */
rtw_write32(Adapter, REG_RCR, pHalData->ReceiveConfig);
/* Accept all multicast address */
rtw_write32(Adapter, REG_MAR, 0xFFFFFFFF);
rtw_write32(Adapter, REG_MAR + 4, 0xFFFFFFFF);
/* Accept all data frames */
/* value16 = 0xFFFF; */
/* rtw_write16(Adapter, REG_RXFLTMAP2, value16); */
/* 2010.09.08 hpfan */
/* Since ADF is removed from RCR, ps-poll will not be indicate
to driver, */
/* RxFilterMap should mask ps-poll to gurantee AP mode can
rx ps-poll. */
/* value16 = 0x400; */
/* rtw_write16(Adapter, REG_RXFLTMAP1, value16); */
/* Accept all management frames */
/* value16 = 0xFFFF; */
/* rtw_write16(Adapter, REG_RXFLTMAP0, value16); */
/* enable RX_SHIFT bits */
/* rtw_write8(Adapter, REG_TRXDMA_CTRL, rtw_read8(Adapter,
REG_TRXDMA_CTRL)|BIT(1)); */
}
static void _InitAdaptiveCtrl(struct rtw_adapter *Adapter)
{
u16 value16;
u32 value32;
/* Response Rate Set */
value32 = rtw_read32(Adapter, REG_RRSR);
value32 &= ~RATE_BITMAP_ALL;
value32 |= RATE_RRSR_CCK_ONLY_1M;
rtw_write32(Adapter, REG_RRSR, value32);
/* CF-END Threshold */
/* m_spIoBase->rtw_write8(REG_CFEND_TH, 0x1); */
/* SIFS (used in NAV) */
value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10);
rtw_write16(Adapter, REG_SPEC_SIFS, value16);
/* Retry Limit */
value16 = _LRL(0x30) | _SRL(0x30);
rtw_write16(Adapter, REG_RL, value16);
}
static void _InitRateFallback(struct rtw_adapter *Adapter)
{
/* Set Data Auto Rate Fallback Retry Count register. */
rtw_write32(Adapter, REG_DARFRC, 0x00000000);
rtw_write32(Adapter, REG_DARFRC+4, 0x10080404);
rtw_write32(Adapter, REG_RARFRC, 0x04030201);
rtw_write32(Adapter, REG_RARFRC+4, 0x08070605);
}
static void _InitEDCA(struct rtw_adapter *Adapter)
{
/* Set Spec SIFS (used in NAV) */
rtw_write16(Adapter, REG_SPEC_SIFS, 0x100a);
rtw_write16(Adapter, REG_MAC_SPEC_SIFS, 0x100a);
/* Set SIFS for CCK */
rtw_write16(Adapter, REG_SIFS_CTX, 0x100a);
/* Set SIFS for OFDM */
rtw_write16(Adapter, REG_SIFS_TRX, 0x100a);
/* TXOP */
rtw_write32(Adapter, REG_EDCA_BE_PARAM, 0x005EA42B);
rtw_write32(Adapter, REG_EDCA_BK_PARAM, 0x0000A44F);
rtw_write32(Adapter, REG_EDCA_VI_PARAM, 0x005EA324);
rtw_write32(Adapter, REG_EDCA_VO_PARAM, 0x002FA226);
}
static void _InitHWLed(struct rtw_adapter *Adapter)
{
struct led_priv *pledpriv = &Adapter->ledpriv;
if (pledpriv->LedStrategy != HW_LED)
return;
/* HW led control */
/* to do .... */
/* must consider cases of antenna diversity/ commbo card/solo card/mini card */
}
static void _InitRDGSetting(struct rtw_adapter *Adapter)
{
rtw_write8(Adapter, REG_RD_CTRL, 0xFF);
rtw_write16(Adapter, REG_RD_NAV_NXT, 0x200);
rtw_write8(Adapter, REG_RD_RESP_PKT_TH, 0x05);
}
static void _InitRetryFunction(struct rtw_adapter *Adapter)
{
u8 value8;
value8 = rtw_read8(Adapter, REG_FWHW_TXQ_CTRL);
value8 |= EN_AMPDU_RTY_NEW;
rtw_write8(Adapter, REG_FWHW_TXQ_CTRL, value8);
/* Set ACK timeout */
rtw_write8(Adapter, REG_ACKTO, 0x40);
}
/*-----------------------------------------------------------------------------
* Function: usb_AggSettingTxUpdate()
*
* Overview: Seperate TX/RX parameters update independent for TP
* detection and dynamic TX/RX aggreagtion parameters update.
*
* Input: struct rtw_adapter *
*
* Output/Return: NONE
*
* Revised History:
* When Who Remark
* 12/10/2010 MHC Seperate to smaller function.
*
*---------------------------------------------------------------------------*/
static void usb_AggSettingTxUpdate(struct rtw_adapter *Adapter)
{
} /* usb_AggSettingTxUpdate */
/*-----------------------------------------------------------------------------
* Function: usb_AggSettingRxUpdate()
*
* Overview: Seperate TX/RX parameters update independent for TP
* detection and dynamic TX/RX aggreagtion parameters update.
*
* Input: struct rtw_adapter *
*
* Output/Return: NONE
*
* Revised History:
* When Who Remark
* 12/10/2010 MHC Seperate to smaller function.
*
*---------------------------------------------------------------------------*/
static void usb_AggSettingRxUpdate(struct rtw_adapter *Adapter)
{
} /* usb_AggSettingRxUpdate */
static void InitUsbAggregationSetting(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
/* Tx aggregation setting */
usb_AggSettingTxUpdate(Adapter);
/* Rx aggregation setting */
usb_AggSettingRxUpdate(Adapter);
/* 201/12/10 MH Add for USB agg mode dynamic switch. */
pHalData->UsbRxHighSpeedMode = false;
}
static void _InitOperationMode(struct rtw_adapter *Adapter)
{
}
static void _InitRFType(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
bool is92CU = IS_92C_SERIAL(pHalData->VersionID);
pHalData->rf_chip = RF_6052;
if (is92CU == false) {
pHalData->rf_type = RF_1T1R;
DBG_8723A("Set RF Chip ID to RF_6052 and RF type to 1T1R.\n");
return;
}
/* TODO: Consider that EEPROM set 92CU to 1T1R later. */
/* Force to overwrite setting according to chip version. Ignore
EEPROM setting. */
/* pHalData->RF_Type = is92CU ? RF_2T2R : RF_1T1R; */
MSG_8723A("Set RF Chip ID to RF_6052 and RF type to %d.\n",
pHalData->rf_type);
}
/* Set CCK and OFDM Block "ON" */
static void _BBTurnOnBlock(struct rtw_adapter *Adapter)
{
PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bCCKEn, 0x1);
PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bOFDMEn, 0x1);
}
#define MgntActSet_RF_State(...)
static void _RfPowerSave(struct rtw_adapter *padapter)
{
}
enum {
Antenna_Lfet = 1,
Antenna_Right = 2,
};
enum rt_rf_power_state RfOnOffDetect23a(struct rtw_adapter *pAdapter)
{
/* struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); */
u8 val8;
enum rt_rf_power_state rfpowerstate = rf_off;
if (pAdapter->pwrctrlpriv.bHWPowerdown) {
val8 = rtw_read8(pAdapter, REG_HSISR);
DBG_8723A("pwrdown, 0x5c(BIT7) =%02x\n", val8);
rfpowerstate = (val8 & BIT7) ? rf_off : rf_on;
} else { /* rf on/off */
rtw_write8(pAdapter, REG_MAC_PINMUX_CFG,
rtw_read8(pAdapter, REG_MAC_PINMUX_CFG) & ~BIT3);
val8 = rtw_read8(pAdapter, REG_GPIO_IO_SEL);
DBG_8723A("GPIO_IN =%02x\n", val8);
rfpowerstate = (val8 & BIT3) ? rf_on : rf_off;
}
return rfpowerstate;
} /* HalDetectPwrDownMode */
void _ps_open_RF23a(struct rtw_adapter *padapter);
static u32 rtl8723au_hal_init(struct rtw_adapter *Adapter)
{
u8 val8 = 0;
u32 boundary, status = _SUCCESS;
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv;
struct registry_priv *pregistrypriv = &Adapter->registrypriv;
u32 NavUpper = WiFiNavUpperUs;
unsigned long init_start_time = jiffies;
#define HAL_INIT_PROFILE_TAG(stage) do {} while (0)
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_BEGIN);
if (Adapter->pwrctrlpriv.bkeepfwalive) {
_ps_open_RF23a(Adapter);
if (pHalData->bIQKInitialized) {
rtl8723a_phy_iq_calibrate(Adapter, true);
} else {
rtl8723a_phy_iq_calibrate(Adapter, false);
pHalData->bIQKInitialized = true;
}
rtl8723a_odm_check_tx_power_tracking(Adapter);
rtl8723a_phy_lc_calibrate(Adapter);
goto exit;
}
/* Check if MAC has already power on. by tynli. 2011.05.27. */
val8 = rtw_read8(Adapter, REG_CR);
RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
("%s: REG_CR 0x100 = 0x%02x\n", __func__, val8));
/* Fix 92DU-VC S3 hang with the reason is that secondary mac is not
initialized. */
/* 0x100 value of first mac is 0xEA while 0x100 value of secondary
is 0x00 */
if (val8 == 0xEA) {
pHalData->bMACFuncEnable = false;
} else {
pHalData->bMACFuncEnable = true;
RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
("%s: MAC has already power on\n", __func__));
}
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_PW_ON);
status = _InitPowerOn(Adapter);
if (status == _FAIL) {
RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
("Failed to init power on!\n"));
goto exit;
}
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_LLTT);
if (!pregistrypriv->wifi_spec) {
boundary = TX_PAGE_BOUNDARY;
} else {
/* for WMM */
boundary = WMM_NORMAL_TX_PAGE_BOUNDARY;
}
if (!pHalData->bMACFuncEnable) {
status = InitLLTTable23a(Adapter, boundary);
if (status == _FAIL) {
RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
("Failed to init LLT table\n"));
goto exit;
}
}
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC01);
if (pHalData->bRDGEnable)
_InitRDGSetting(Adapter);
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_DOWNLOAD_FW);
status = rtl8723a_FirmwareDownload(Adapter);
if (status != _SUCCESS) {
Adapter->bFWReady = false;
pHalData->fw_ractrl = false;
DBG_8723A("fw download fail!\n");
goto exit;
} else {
Adapter->bFWReady = true;
pHalData->fw_ractrl = true;
DBG_8723A("fw download ok!\n");
}
rtl8723a_InitializeFirmwareVars(Adapter);
if (pwrctrlpriv->reg_rfoff == true) {
pwrctrlpriv->rf_pwrstate = rf_off;
}
/* 2010/08/09 MH We need to check if we need to turnon or off RF after detecting */
/* HW GPIO pin. Before PHY_RFConfig8192C. */
/* HalDetectPwrDownMode(Adapter); */
/* 2010/08/26 MH If Efuse does not support sective suspend then disable the function. */
/* HalDetectSelectiveSuspendMode(Adapter); */
/* Set RF type for BB/RF configuration */
_InitRFType(Adapter);/* _ReadRFType() */
/* Save target channel */
/* <Roger_Notes> Current Channel will be updated again later. */
pHalData->CurrentChannel = 6;/* default set to 6 */
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MAC);
status = PHY_MACConfig8723A(Adapter);
if (status == _FAIL) {
DBG_8723A("PHY_MACConfig8723A fault !!\n");
goto exit;
}
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_BB);
/* */
/* d. Initialize BB related configurations. */
/* */
status = PHY_BBConfig8723A(Adapter);
if (status == _FAIL) {
DBG_8723A("PHY_BBConfig8723A fault !!\n");
goto exit;
}
/* Add for tx power by rate fine tune. We need to call the function after BB config. */
/* Because the tx power by rate table is inited in BB config. */
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_RF);
status = PHY_RFConfig8723A(Adapter);
if (status == _FAIL) {
DBG_8723A("PHY_RFConfig8723A fault !!\n");
goto exit;
}
/* reducing 80M spur */
PHY_SetBBReg(Adapter, RF_T_METER, bMaskDWord, 0x0381808d);
PHY_SetBBReg(Adapter, RF_SYN_G4, bMaskDWord, 0xf2ffff83);
PHY_SetBBReg(Adapter, RF_SYN_G4, bMaskDWord, 0xf2ffff82);
PHY_SetBBReg(Adapter, RF_SYN_G4, bMaskDWord, 0xf2ffff83);
/* RFSW Control */
PHY_SetBBReg(Adapter, rFPGA0_TxInfo, bMaskDWord, 0x00000003); /* 0x804[14]= 0 */
PHY_SetBBReg(Adapter, rFPGA0_XAB_RFInterfaceSW, bMaskDWord, 0x07000760); /* 0x870[6:5]= b'11 */
PHY_SetBBReg(Adapter, rFPGA0_XA_RFInterfaceOE, bMaskDWord, 0x66F60210); /* 0x860[6:5]= b'00 */
RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("%s: 0x870 = value 0x%x\n", __func__, PHY_QueryBBReg(Adapter, 0x870, bMaskDWord)));
/* */
/* Joseph Note: Keep RfRegChnlVal for later use. */
/* */
pHalData->RfRegChnlVal[0] = PHY_QueryRFReg(Adapter, (enum RF_RADIO_PATH)0, RF_CHNLBW, bRFRegOffsetMask);
pHalData->RfRegChnlVal[1] = PHY_QueryRFReg(Adapter, (enum RF_RADIO_PATH)1, RF_CHNLBW, bRFRegOffsetMask);
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC02);
if (!pHalData->bMACFuncEnable) {
_InitQueueReservedPage(Adapter);
_InitTxBufferBoundary(Adapter);
}
_InitQueuePriority(Adapter);
_InitPageBoundary(Adapter);
_InitTransferPageSize(Adapter);
/* Get Rx PHY status in order to report RSSI and others. */
_InitDriverInfoSize(Adapter, DRVINFO_SZ);
_InitInterrupt(Adapter);
hal_init_macaddr23a(Adapter);/* set mac_address */
_InitNetworkType(Adapter);/* set msr */
_InitWMACSetting(Adapter);
_InitAdaptiveCtrl(Adapter);
_InitEDCA(Adapter);
_InitRateFallback(Adapter);
_InitRetryFunction(Adapter);
InitUsbAggregationSetting(Adapter);
_InitOperationMode(Adapter);/* todo */
rtl8723a_InitBeaconParameters(Adapter);
_InitHWLed(Adapter);
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_TURN_ON_BLOCK);
_BBTurnOnBlock(Adapter);
/* NicIFSetMacAddress(padapter, padapter->PermanentAddress); */
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_SECURITY);
invalidate_cam_all23a(Adapter);
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC11);
/* 2010/12/17 MH We need to set TX power according to EFUSE content at first. */
PHY_SetTxPowerLevel8723A(Adapter, pHalData->CurrentChannel);
rtl8723a_InitAntenna_Selection(Adapter);
/* HW SEQ CTRL */
/* set 0x0 to 0xFF by tynli. Default enable HW SEQ NUM. */
rtw_write8(Adapter, REG_HWSEQ_CTRL, 0xFF);
/* */
/* Disable BAR, suggested by Scott */
/* 2010.04.09 add by hpfan */
/* */
rtw_write32(Adapter, REG_BAR_MODE_CTRL, 0x0201ffff);
if (pregistrypriv->wifi_spec)
rtw_write16(Adapter, REG_FAST_EDCA_CTRL, 0);
/* Move by Neo for USB SS from above setp */
_RfPowerSave(Adapter);
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_IQK);
/* 2010/08/26 MH Merge from 8192CE. */
/* sherry masked that it has been done in _RfPowerSave */
/* 20110927 */
/* recovery for 8192cu and 9723Au 20111017 */
if (pwrctrlpriv->rf_pwrstate == rf_on) {
if (pHalData->bIQKInitialized) {
rtl8723a_phy_iq_calibrate(Adapter, true);
} else {
rtl8723a_phy_iq_calibrate(Adapter, false);
pHalData->bIQKInitialized = true;
}
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_PW_TRACK);
rtl8723a_odm_check_tx_power_tracking(Adapter);
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_LCK);
rtl8723a_phy_lc_calibrate(Adapter);
#ifdef CONFIG_8723AU_BT_COEXIST
rtl8723a_SingleDualAntennaDetection(Adapter);
#endif
}
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC21);
/* fixed USB interface interference issue */
rtw_write8(Adapter, 0xfe40, 0xe0);
rtw_write8(Adapter, 0xfe41, 0x8d);
rtw_write8(Adapter, 0xfe42, 0x80);
rtw_write32(Adapter, 0x20c, 0xfd0320);
/* Solve too many protocol error on USB bus */
if (!IS_81xxC_VENDOR_UMC_A_CUT(pHalData->VersionID)) {
/* 0xE6 = 0x94 */
rtw_write8(Adapter, 0xFE40, 0xE6);
rtw_write8(Adapter, 0xFE41, 0x94);
rtw_write8(Adapter, 0xFE42, 0x80);
/* 0xE0 = 0x19 */
rtw_write8(Adapter, 0xFE40, 0xE0);
rtw_write8(Adapter, 0xFE41, 0x19);
rtw_write8(Adapter, 0xFE42, 0x80);
/* 0xE5 = 0x91 */
rtw_write8(Adapter, 0xFE40, 0xE5);
rtw_write8(Adapter, 0xFE41, 0x91);
rtw_write8(Adapter, 0xFE42, 0x80);
/* 0xE2 = 0x81 */
rtw_write8(Adapter, 0xFE40, 0xE2);
rtw_write8(Adapter, 0xFE41, 0x81);
rtw_write8(Adapter, 0xFE42, 0x80);
}
/* HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_PABIAS); */
/* _InitPABias(Adapter); */
#ifdef CONFIG_8723AU_BT_COEXIST
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_BT_COEXIST);
/* Init BT hw config. */
BT_InitHwConfig(Adapter);
#endif
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_HAL_DM);
rtl8723a_InitHalDm(Adapter);
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC31);
rtw_hal_set_hwreg23a(Adapter, HW_VAR_NAV_UPPER, (u8 *)&NavUpper);
/* 2011/03/09 MH debug only, UMC-B cut pass 2500 S5 test, but we need to fin root cause. */
if (((rtw_read32(Adapter, rFPGA0_RFMOD) & 0xFF000000) != 0x83000000)) {
PHY_SetBBReg(Adapter, rFPGA0_RFMOD, BIT(24), 1);
RT_TRACE(_module_hci_hal_init_c_, _drv_err_, ("%s: IQK fail recorver\n", __func__));
}
/* ack for xmit mgmt frames. */
rtw_write32(Adapter, REG_FWHW_TXQ_CTRL, rtw_read32(Adapter, REG_FWHW_TXQ_CTRL)|BIT(12));
exit:
HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_END);
DBG_8723A("%s in %dms\n", __func__,
jiffies_to_msecs(jiffies - init_start_time));
return status;
}
static void phy_SsPwrSwitch92CU(struct rtw_adapter *Adapter,
enum rt_rf_power_state eRFPowerState,
int bRegSSPwrLvl)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
u8 value8;
u8 bytetmp;
switch (eRFPowerState) {
case rf_on:
if (bRegSSPwrLvl == 1) {
/* 1. Enable MAC Clock. Can not be enabled now. */
/* WriteXBYTE(REG_SYS_CLKR+1,
ReadXBYTE(REG_SYS_CLKR+1) | BIT(3)); */
/* 2. Force PWM, Enable SPS18_LDO_Marco_Block */
rtw_write8(Adapter, REG_SPS0_CTRL,
rtw_read8(Adapter, REG_SPS0_CTRL) |
(BIT0|BIT3));
/* 3. restore BB, AFE control register. */
/* RF */
if (pHalData->rf_type == RF_2T2R)
PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter,
0x380038, 1);
else
PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter,
0x38, 1);
PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0xf0, 1);
PHY_SetBBReg(Adapter, rFPGA0_RFMOD, BIT1, 0);
/* AFE */
if (pHalData->rf_type == RF_2T2R)
PHY_SetBBReg(Adapter, rRx_Wait_CCA, bMaskDWord,
0x63DB25A0);
else if (pHalData->rf_type == RF_1T1R)
PHY_SetBBReg(Adapter, rRx_Wait_CCA, bMaskDWord,
0x631B25A0);
/* 4. issue 3-wire command that RF set to Rx idle
mode. This is used to re-write the RX idle mode. */
/* We can only prvide a usual value instead and then
HW will modify the value by itself. */
PHY_SetRFReg(Adapter, RF_PATH_A, 0,
bRFRegOffsetMask, 0x32D95);
if (pHalData->rf_type == RF_2T2R) {
PHY_SetRFReg(Adapter, RF_PATH_B, 0,
bRFRegOffsetMask, 0x32D95);
}
} else { /* Level 2 or others. */
/* h. AFE_PLL_CTRL 0x28[7:0] = 0x80
disable AFE PLL */
rtw_write8(Adapter, REG_AFE_PLL_CTRL, 0x81);
/* i. AFE_XTAL_CTRL 0x24[15:0] = 0x880F
gated AFE DIG_CLOCK */
rtw_write16(Adapter, REG_AFE_XTAL_CTRL, 0x800F);
mdelay(1);
/* 2. Force PWM, Enable SPS18_LDO_Marco_Block */
rtw_write8(Adapter, REG_SPS0_CTRL,
rtw_read8(Adapter, REG_SPS0_CTRL) |
(BIT0|BIT3));
/* 3. restore BB, AFE control register. */
/* RF */
if (pHalData->rf_type == RF_2T2R)
PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter,
0x380038, 1);
else
PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter,
0x38, 1);
PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0xf0, 1);
PHY_SetBBReg(Adapter, rFPGA0_RFMOD, BIT1, 0);
/* AFE */
if (pHalData->rf_type == RF_2T2R)
PHY_SetBBReg(Adapter, rRx_Wait_CCA,
bMaskDWord, 0x63DB25A0);
else if (pHalData->rf_type == RF_1T1R)
PHY_SetBBReg(Adapter, rRx_Wait_CCA,
bMaskDWord, 0x631B25A0);
/* 4. issue 3-wire command that RF set to Rx idle
mode. This is used to re-write the RX idle mode. */
/* We can only prvide a usual value instead and
then HW will modify the value by itself. */
PHY_SetRFReg(Adapter, RF_PATH_A, 0,
bRFRegOffsetMask, 0x32D95);
if (pHalData->rf_type == RF_2T2R) {
PHY_SetRFReg(Adapter, RF_PATH_B, 0,
bRFRegOffsetMask, 0x32D95);
}
/* 5. gated MAC Clock */
bytetmp = rtw_read8(Adapter, REG_APSD_CTRL);
rtw_write8(Adapter, REG_APSD_CTRL, bytetmp & ~BIT6);
mdelay(10);
/* Set BB reset at first */
rtw_write8(Adapter, REG_SYS_FUNC_EN, 0x17); /* 0x16 */
/* Enable TX */
rtw_write8(Adapter, REG_TXPAUSE, 0x0);
}
break;
case rf_sleep:
case rf_off:
value8 = rtw_read8(Adapter, REG_SPS0_CTRL) ;
if (IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID))
value8 &= ~(BIT0);
else
value8 &= ~(BIT0|BIT3);
if (bRegSSPwrLvl == 1) {
RT_TRACE(_module_hal_init_c_, _drv_err_, ("SS LVL1\n"));
/* Disable RF and BB only for SelectSuspend. */
/* 1. Set BB/RF to shutdown. */
/* (1) Reg878[5:3]= 0 RF rx_code for
preamble power saving */
/* (2)Reg878[21:19]= 0 Turn off RF-B */
/* (3) RegC04[7:4]= 0 Turn off all paths
for packet detection */
/* (4) Reg800[1] = 1 enable preamble power
saving */
Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF0] =
PHY_QueryBBReg(Adapter, rFPGA0_XAB_RFParameter,
bMaskDWord);
Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF1] =
PHY_QueryBBReg(Adapter, rOFDM0_TRxPathEnable,
bMaskDWord);
Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF2] =
PHY_QueryBBReg(Adapter, rFPGA0_RFMOD,
bMaskDWord);
if (pHalData->rf_type == RF_2T2R) {
PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter,
0x380038, 0);
} else if (pHalData->rf_type == RF_1T1R) {
PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter,
0x38, 0);
}
PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0xf0, 0);
PHY_SetBBReg(Adapter, rFPGA0_RFMOD, BIT1, 1);
/* 2 .AFE control register to power down. bit[30:22] */
Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_AFE0] =
PHY_QueryBBReg(Adapter, rRx_Wait_CCA,
bMaskDWord);
if (pHalData->rf_type == RF_2T2R)
PHY_SetBBReg(Adapter, rRx_Wait_CCA, bMaskDWord,
0x00DB25A0);
else if (pHalData->rf_type == RF_1T1R)
PHY_SetBBReg(Adapter, rRx_Wait_CCA, bMaskDWord,
0x001B25A0);
/* 3. issue 3-wire command that RF set to power down.*/
PHY_SetRFReg(Adapter, RF_PATH_A, 0, bRFRegOffsetMask, 0);
if (pHalData->rf_type == RF_2T2R)
PHY_SetRFReg(Adapter, RF_PATH_B, 0,
bRFRegOffsetMask, 0);
/* 4. Force PFM , disable SPS18_LDO_Marco_Block */
rtw_write8(Adapter, REG_SPS0_CTRL, value8);
} else { /* Level 2 or others. */
RT_TRACE(_module_hal_init_c_, _drv_err_, ("SS LVL2\n"));
{
u8 eRFPath = RF_PATH_A, value8 = 0;
rtw_write8(Adapter, REG_TXPAUSE, 0xFF);
PHY_SetRFReg(Adapter,
(enum RF_RADIO_PATH)eRFPath,
0x0, bMaskByte0, 0x0);
value8 |= APSDOFF;
/* 0x40 */
rtw_write8(Adapter, REG_APSD_CTRL, value8);
/* After switch APSD, we need to delay
for stability */
mdelay(10);
/* Set BB reset at first */
value8 = 0 ;
value8 |= (FEN_USBD | FEN_USBA |
FEN_BB_GLB_RSTn);
/* 0x16 */
rtw_write8(Adapter, REG_SYS_FUNC_EN, value8);
}
/* Disable RF and BB only for SelectSuspend. */
/* 1. Set BB/RF to shutdown. */
/* (1) Reg878[5:3]= 0 RF rx_code for
preamble power saving */
/* (2)Reg878[21:19]= 0 Turn off RF-B */
/* (3) RegC04[7:4]= 0 Turn off all paths for
packet detection */
/* (4) Reg800[1] = 1 enable preamble power
saving */
Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF0] =
PHY_QueryBBReg(Adapter, rFPGA0_XAB_RFParameter,
bMaskDWord);
Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF1] =
PHY_QueryBBReg(Adapter, rOFDM0_TRxPathEnable,
bMaskDWord);
Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF2] =
PHY_QueryBBReg(Adapter, rFPGA0_RFMOD,
bMaskDWord);
if (pHalData->rf_type == RF_2T2R)
PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter,
0x380038, 0);
else if (pHalData->rf_type == RF_1T1R)
PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter,
0x38, 0);
PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0xf0, 0);
PHY_SetBBReg(Adapter, rFPGA0_RFMOD, BIT1, 1);
/* 2 .AFE control register to power down. bit[30:22] */
Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_AFE0] =
PHY_QueryBBReg(Adapter, rRx_Wait_CCA,
bMaskDWord);
if (pHalData->rf_type == RF_2T2R)
PHY_SetBBReg(Adapter, rRx_Wait_CCA, bMaskDWord,
0x00DB25A0);
else if (pHalData->rf_type == RF_1T1R)
PHY_SetBBReg(Adapter, rRx_Wait_CCA, bMaskDWord,
0x001B25A0);
/* 3. issue 3-wire command that RF set to power down. */
PHY_SetRFReg(Adapter, RF_PATH_A, 0, bRFRegOffsetMask, 0);
if (pHalData->rf_type == RF_2T2R)
PHY_SetRFReg(Adapter, RF_PATH_B, 0,
bRFRegOffsetMask, 0);
/* 4. Force PFM , disable SPS18_LDO_Marco_Block */
rtw_write8(Adapter, REG_SPS0_CTRL, value8);
/* 2010/10/13 MH/Isaachsu exchange sequence. */
/* h. AFE_PLL_CTRL 0x28[7:0] = 0x80
disable AFE PLL */
rtw_write8(Adapter, REG_AFE_PLL_CTRL, 0x80);
mdelay(1);
/* i. AFE_XTAL_CTRL 0x24[15:0] = 0x880F
gated AFE DIG_CLOCK */
rtw_write16(Adapter, REG_AFE_XTAL_CTRL, 0xA80F);
}
break;
default:
break;
}
} /* phy_PowerSwitch92CU */
void _ps_open_RF23a(struct rtw_adapter *padapter)
{
/* here call with bRegSSPwrLvl 1, bRegSSPwrLvl 2 needs to be verified */
phy_SsPwrSwitch92CU(padapter, rf_on, 1);
}
static void CardDisableRTL8723U(struct rtw_adapter *Adapter)
{
u8 u1bTmp;
DBG_8723A("CardDisableRTL8723U\n");
/* USB-MF Card Disable Flow */
/* 1. Run LPS WL RFOFF flow */
HalPwrSeqCmdParsing23a(Adapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
PWR_INTF_USB_MSK, rtl8723AU_enter_lps_flow);
/* 2. 0x1F[7:0] = 0 turn off RF */
rtw_write8(Adapter, REG_RF_CTRL, 0x00);
/* ==== Reset digital sequence ====== */
if ((rtw_read8(Adapter, REG_MCUFWDL)&BIT7) &&
Adapter->bFWReady) /* 8051 RAM code */
rtl8723a_FirmwareSelfReset(Adapter);
/* Reset MCU. Suggested by Filen. 2011.01.26. by tynli. */
u1bTmp = rtw_read8(Adapter, REG_SYS_FUNC_EN+1);
rtw_write8(Adapter, REG_SYS_FUNC_EN+1, (u1bTmp & (~BIT2)));
/* g. MCUFWDL 0x80[1:0]= 0 reset MCU ready status */
rtw_write8(Adapter, REG_MCUFWDL, 0x00);
/* ==== Reset digital sequence end ====== */
/* Card disable power action flow */
HalPwrSeqCmdParsing23a(Adapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
PWR_INTF_USB_MSK,
rtl8723AU_card_disable_flow);
/* Reset MCU IO Wrapper, added by Roger, 2011.08.30. */
u1bTmp = rtw_read8(Adapter, REG_RSV_CTRL + 1);
rtw_write8(Adapter, REG_RSV_CTRL+1, (u1bTmp & (~BIT0)));
u1bTmp = rtw_read8(Adapter, REG_RSV_CTRL + 1);
rtw_write8(Adapter, REG_RSV_CTRL+1, u1bTmp | BIT0);
/* 7. RSV_CTRL 0x1C[7:0] = 0x0E lock ISO/CLK/Power control register */
rtw_write8(Adapter, REG_RSV_CTRL, 0x0e);
}
static u32 rtl8723au_hal_deinit(struct rtw_adapter *padapter)
{
DBG_8723A("==> %s\n", __func__);
#ifdef CONFIG_8723AU_BT_COEXIST
BT_HaltProcess(padapter);
#endif
/* 2011/02/18 To Fix RU LNA power leakage problem. We need to
execute below below in Adapter init and halt sequence.
According to EEchou's opinion, we can enable the ability for all */
/* IC. Accord to johnny's opinion, only RU need the support. */
CardDisableRTL8723U(padapter);
return _SUCCESS;
}
static unsigned int rtl8723au_inirp_init(struct rtw_adapter *Adapter)
{
u8 i;
struct recv_buf *precvbuf;
uint status;
struct intf_hdl *pintfhdl = &Adapter->iopriv.intf;
struct recv_priv *precvpriv = &Adapter->recvpriv;
u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
struct recv_buf *rbuf);
u32 (*_read_interrupt)(struct intf_hdl *pintfhdl, u32 addr);
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
_read_port = pintfhdl->io_ops._read_port;
status = _SUCCESS;
RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("===> usb_inirp_init\n"));
precvpriv->ff_hwaddr = RECV_BULK_IN_ADDR;
/* issue Rx irp to receive data */
precvbuf = (struct recv_buf *)precvpriv->precv_buf;
for (i = 0; i < NR_RECVBUFF; i++) {
if (_read_port(pintfhdl, precvpriv->ff_hwaddr, 0, precvbuf) ==
false) {
RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
("usb_rx_init: usb_read_port error\n"));
status = _FAIL;
goto exit;
}
precvbuf++;
precvpriv->free_recv_buf_queue_cnt--;
}
_read_interrupt = pintfhdl->io_ops._read_interrupt;
if (_read_interrupt(pintfhdl, RECV_INT_IN_ADDR) == false) {
RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
("usb_rx_init: usb_read_interrupt error\n"));
status = _FAIL;
}
pHalData->IntrMask[0] = rtw_read32(Adapter, REG_USB_HIMR);
MSG_8723A("pHalData->IntrMask = 0x%04x\n", pHalData->IntrMask[0]);
pHalData->IntrMask[0] |= UHIMR_C2HCMD|UHIMR_CPWM;
rtw_write32(Adapter, REG_USB_HIMR, pHalData->IntrMask[0]);
exit:
RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
("<=== usb_inirp_init\n"));
return status;
}
static unsigned int rtl8723au_inirp_deinit(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
("\n ===> usb_rx_deinit\n"));
rtw_read_port_cancel(Adapter);
pHalData->IntrMask[0] = rtw_read32(Adapter, REG_USB_HIMR);
MSG_8723A("%s pHalData->IntrMask = 0x%04x\n", __func__,
pHalData->IntrMask[0]);
pHalData->IntrMask[0] = 0x0;
rtw_write32(Adapter, REG_USB_HIMR, pHalData->IntrMask[0]);
RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
("\n <=== usb_rx_deinit\n"));
return _SUCCESS;
}
static void _ReadBoardType(struct rtw_adapter *Adapter, u8 *PROMContent,
bool AutoloadFail)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
u8 boardType = BOARD_USB_DONGLE;
if (AutoloadFail) {
if (IS_8723_SERIES(pHalData->VersionID))
pHalData->rf_type = RF_1T1R;
else
pHalData->rf_type = RF_2T2R;
pHalData->BoardType = boardType;
return;
}
boardType = PROMContent[EEPROM_NORMAL_BoardType];
boardType &= BOARD_TYPE_NORMAL_MASK;/* bit[7:5] */
boardType >>= 5;
pHalData->BoardType = boardType;
MSG_8723A("_ReadBoardType(%x)\n", pHalData->BoardType);
if (boardType == BOARD_USB_High_PA)
pHalData->ExternalPA = 1;
}
static void _ReadLEDSetting(struct rtw_adapter *Adapter, u8 *PROMContent,
bool AutoloadFail)
{
struct led_priv *pledpriv = &Adapter->ledpriv;
pledpriv->LedStrategy = HW_LED;
}
static void Hal_EfuseParsePIDVID_8723AU(struct rtw_adapter *pAdapter,
u8 *hwinfo, bool AutoLoadFail)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
if (AutoLoadFail) {
pHalData->EEPROMVID = 0;
pHalData->EEPROMPID = 0;
} else {
/* VID, PID */
pHalData->EEPROMVID =
le16_to_cpu(*(u16 *)&hwinfo[EEPROM_VID_8723AU]);
pHalData->EEPROMPID =
le16_to_cpu(*(u16 *)&hwinfo[EEPROM_PID_8723AU]);
}
MSG_8723A("EEPROM VID = 0x%4x\n", pHalData->EEPROMVID);
MSG_8723A("EEPROM PID = 0x%4x\n", pHalData->EEPROMPID);
}
static void Hal_EfuseParseMACAddr_8723AU(struct rtw_adapter *padapter,
u8 *hwinfo, bool AutoLoadFail)
{
u16 i;
u8 sMacAddr[ETH_ALEN] = {0x00, 0xE0, 0x4C, 0x87, 0x23, 0x00};
struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
if (AutoLoadFail) {
for (i = 0; i < 6; i++)
pEEPROM->mac_addr[i] = sMacAddr[i];
} else {
/* Read Permanent MAC address */
memcpy(pEEPROM->mac_addr, &hwinfo[EEPROM_MAC_ADDR_8723AU],
ETH_ALEN);
}
RT_TRACE(_module_hci_hal_init_c_, _drv_notice_,
("Hal_EfuseParseMACAddr_8723AU: Permanent Address =%02x:%02x:"
"%02x:%02x:%02x:%02x\n",
pEEPROM->mac_addr[0], pEEPROM->mac_addr[1],
pEEPROM->mac_addr[2], pEEPROM->mac_addr[3],
pEEPROM->mac_addr[4], pEEPROM->mac_addr[5]));
}
static void readAdapterInfo(struct rtw_adapter *padapter)
{
struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
/* struct hal_data_8723a * pHalData = GET_HAL_DATA(padapter); */
u8 hwinfo[HWSET_MAX_SIZE];
Hal_InitPGData(padapter, hwinfo);
Hal_EfuseParseIDCode(padapter, hwinfo);
Hal_EfuseParsePIDVID_8723AU(padapter, hwinfo,
pEEPROM->bautoload_fail_flag);
Hal_EfuseParseEEPROMVer(padapter, hwinfo,
pEEPROM->bautoload_fail_flag);
Hal_EfuseParseMACAddr_8723AU(padapter, hwinfo,
pEEPROM->bautoload_fail_flag);
Hal_EfuseParsetxpowerinfo_8723A(padapter, hwinfo,
pEEPROM->bautoload_fail_flag);
_ReadBoardType(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
Hal_EfuseParseBTCoexistInfo_8723A(padapter, hwinfo,
pEEPROM->bautoload_fail_flag);
rtl8723a_EfuseParseChnlPlan(padapter, hwinfo,
pEEPROM->bautoload_fail_flag);
Hal_EfuseParseThermalMeter_8723A(padapter, hwinfo,
pEEPROM->bautoload_fail_flag);
_ReadLEDSetting(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
/* _ReadRFSetting(Adapter, PROMContent, pEEPROM->bautoload_fail_flag); */
/* _ReadPSSetting(Adapter, PROMContent, pEEPROM->bautoload_fail_flag); */
Hal_EfuseParseAntennaDiversity(padapter, hwinfo,
pEEPROM->bautoload_fail_flag);
Hal_EfuseParseEEPROMVer(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
Hal_EfuseParseCustomerID(padapter, hwinfo,
pEEPROM->bautoload_fail_flag);
Hal_EfuseParseRateIndicationOption(padapter, hwinfo,
pEEPROM->bautoload_fail_flag);
Hal_EfuseParseXtal_8723A(padapter, hwinfo,
pEEPROM->bautoload_fail_flag);
/* */
/* The following part initialize some vars by PG info. */
/* */
Hal_InitChannelPlan23a(padapter);
/* hal_CustomizedBehavior_8723U(Adapter); */
/* Adapter->bDongle = (PROMContent[EEPROM_EASY_REPLACEMENT] == 1)? 0: 1; */
DBG_8723A("%s(): REPLACEMENT = %x\n", __func__, padapter->bDongle);
}
static void _ReadPROMContent(struct rtw_adapter *Adapter)
{
struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(Adapter);
u8 eeValue;
eeValue = rtw_read8(Adapter, REG_9346CR);
/* To check system boot selection. */
pEEPROM->EepromOrEfuse = (eeValue & BOOT_FROM_EEPROM) ? true : false;
pEEPROM->bautoload_fail_flag = (eeValue & EEPROM_EN) ? false : true;
DBG_8723A("Boot from %s, Autoload %s !\n",
(pEEPROM->EepromOrEfuse ? "EEPROM" : "EFUSE"),
(pEEPROM->bautoload_fail_flag ? "Fail" : "OK"));
readAdapterInfo(Adapter);
}
static void _ReadRFType(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
pHalData->rf_chip = RF_6052;
}
static void _ReadSilmComboMode(struct rtw_adapter *Adapter)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
pHalData->SlimComboDbg = false; /* Default is not debug mode. */
}
/* */
/* Description: */
/* We should set Efuse cell selection to WiFi cell in default. */
/* */
/* Assumption: */
/* PASSIVE_LEVEL */
/* */
/* Added by Roger, 2010.11.23. */
/* */
static void hal_EfuseCellSel(struct rtw_adapter *Adapter)
{
u32 value32;
value32 = rtw_read32(Adapter, EFUSE_TEST);
value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0);
rtw_write32(Adapter, EFUSE_TEST, value32);
}
static int _ReadAdapterInfo8723AU(struct rtw_adapter *Adapter)
{
/* struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); */
unsigned long start = jiffies;
MSG_8723A("====> _ReadAdapterInfo8723AU\n");
hal_EfuseCellSel(Adapter);
_ReadRFType(Adapter);/* rf_chip -> _InitRFType() */
_ReadPROMContent(Adapter);
/* 2010/10/25 MH THe function must be called after
borad_type & IC-Version recognize. */
_ReadSilmComboMode(Adapter);
/* MSG_8723A("%s()(done), rf_chip = 0x%x, rf_type = 0x%x\n",
__func__, pHalData->rf_chip, pHalData->rf_type); */
MSG_8723A("<==== _ReadAdapterInfo8723AU in %d ms\n",
jiffies_to_msecs(jiffies - start));
return _SUCCESS;
}
static void ReadAdapterInfo8723AU(struct rtw_adapter *Adapter)
{
/* Read EEPROM size before call any EEPROM function */
Adapter->EepromAddressSize = GetEEPROMSize8723A(Adapter);
_ReadAdapterInfo8723AU(Adapter);
}
#define GPIO_DEBUG_PORT_NUM 0
static void rtl8723au_trigger_gpio_0(struct rtw_adapter *padapter)
{
u32 gpioctrl;
DBG_8723A("==> trigger_gpio_0...\n");
rtw_write16_async(padapter, REG_GPIO_PIN_CTRL, 0);
rtw_write8_async(padapter, REG_GPIO_PIN_CTRL+2, 0xFF);
gpioctrl = (BIT(GPIO_DEBUG_PORT_NUM) << 24)|
(BIT(GPIO_DEBUG_PORT_NUM) << 16);
rtw_write32_async(padapter, REG_GPIO_PIN_CTRL, gpioctrl);
gpioctrl |= (BIT(GPIO_DEBUG_PORT_NUM)<<8);
rtw_write32_async(padapter, REG_GPIO_PIN_CTRL, gpioctrl);
DBG_8723A("<=== trigger_gpio_0...\n");
}
/*
* If variable not handled here,
* some variables will be processed in SetHwReg8723A()
*/
static void SetHwReg8723AU(struct rtw_adapter *Adapter, u8 variable, u8 *val)
{
switch (variable) {
case HW_VAR_RXDMA_AGG_PG_TH:
break;
case HW_VAR_SET_RPWM:
rtl8723a_set_rpwm(Adapter, *val);
break;
case HW_VAR_TRIGGER_GPIO_0:
rtl8723au_trigger_gpio_0(Adapter);
break;
default:
SetHwReg8723A(Adapter, variable, val);
break;
}
}
/*
* If variable not handled here,
* some variables will be processed in GetHwReg8723A()
*/
static void GetHwReg8723AU(struct rtw_adapter *Adapter, u8 variable, u8 *val)
{
GetHwReg8723A(Adapter, variable, val);
}
/* */
/* Description: */
/* Query setting of specified variable. */
/* */
static u8 GetHalDefVar8192CUsb(struct rtw_adapter *Adapter,
enum hal_def_variable eVariable, void *pValue)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
u8 bResult = _SUCCESS;
switch (eVariable) {
case HAL_DEF_UNDERCORATEDSMOOTHEDPWDB:
*((int *)pValue) = pHalData->dmpriv.UndecoratedSmoothedPWDB;
break;
case HAL_DEF_IS_SUPPORT_ANT_DIV:
break;
case HAL_DEF_CURRENT_ANTENNA:
break;
case HAL_DEF_DRVINFO_SZ:
*((u32 *)pValue) = DRVINFO_SZ;
break;
case HAL_DEF_MAX_RECVBUF_SZ:
*((u32 *)pValue) = MAX_RECVBUF_SZ;
break;
case HAL_DEF_RX_PACKET_OFFSET:
*((u32 *)pValue) = RXDESC_SIZE + DRVINFO_SZ;
break;
case HAL_DEF_DBG_DUMP_RXPKT:
*((u8 *)pValue) = pHalData->bDumpRxPkt;
break;
case HAL_DEF_DBG_DM_FUNC:
*((u32 *)pValue) = pHalData->odmpriv.SupportAbility;
break;
case HW_VAR_MAX_RX_AMPDU_FACTOR:
*((u32 *)pValue) = IEEE80211_HT_MAX_AMPDU_64K;
break;
case HW_DEF_ODM_DBG_FLAG:
{
struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
printk("pDM_Odm->DebugComponents = 0x%llx\n",
pDM_Odm->DebugComponents);
}
break;
default:
/* RT_TRACE(COMP_INIT, DBG_WARNING, ("GetHalDefVar8192CUsb(): "
"Unkown variable: %d!\n", eVariable)); */
bResult = _FAIL;
break;
}
return bResult;
}
/* Change default setting of specified variable. */
static u8 SetHalDefVar8192CUsb(struct rtw_adapter *Adapter,
enum hal_def_variable eVariable, void *pValue)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
u8 bResult = _SUCCESS;
switch (eVariable) {
case HAL_DEF_DBG_DUMP_RXPKT:
pHalData->bDumpRxPkt = *((u8 *)pValue);
break;
case HAL_DEF_DBG_DM_FUNC:
{
u8 dm_func = *((u8 *)pValue);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
struct dm_odm_t *podmpriv = &pHalData->odmpriv;
if (dm_func == 0) { /* disable all dynamic func */
podmpriv->SupportAbility = DYNAMIC_FUNC_DISABLE;
DBG_8723A("==> Disable all dynamic function...\n");
} else if (dm_func == 1) {/* disable DIG */
podmpriv->SupportAbility &= (~DYNAMIC_BB_DIG);
DBG_8723A("==> Disable DIG...\n");
} else if (dm_func == 2) {/* disable High power */
podmpriv->SupportAbility &= (~DYNAMIC_BB_DYNAMIC_TXPWR);
} else if (dm_func == 3) {/* disable tx power tracking */
podmpriv->SupportAbility &= (~DYNAMIC_RF_CALIBRATION);
DBG_8723A("==> Disable tx power tracking...\n");
} else if (dm_func == 4) {/* disable BT coexistence */
pdmpriv->DMFlag &= (~DYNAMIC_FUNC_BT);
} else if (dm_func == 5) {/* disable antenna diversity */
podmpriv->SupportAbility &= (~DYNAMIC_BB_ANT_DIV);
} else if (dm_func == 6) {/* turn on all dynamic func */
if (!(podmpriv->SupportAbility & DYNAMIC_BB_DIG)) {
struct dig_t *pDigTable =
&podmpriv->DM_DigTable;
pDigTable->CurIGValue = rtw_read8(Adapter, 0xc50);
}
pdmpriv->DMFlag |= DYNAMIC_FUNC_BT;
podmpriv->SupportAbility = DYNAMIC_ALL_FUNC_ENABLE;
DBG_8723A("==> Turn on all dynamic function...\n");
}
}
break;
case HW_DEF_FA_CNT_DUMP:
{
u8 bRSSIDump = *((u8 *)pValue);
struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
if (bRSSIDump)
pDM_Odm->DebugComponents = ODM_COMP_DIG|ODM_COMP_FA_CNT;
else
pDM_Odm->DebugComponents = 0;
}
break;
case HW_DEF_ODM_DBG_FLAG:
{
u64 DebugComponents = *((u64 *)pValue);
struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
pDM_Odm->DebugComponents = DebugComponents;
}
break;
default:
/* RT_TRACE(COMP_INIT, DBG_TRACE, ("SetHalDefVar819xUsb(): "
"Unkown variable: %d!\n", eVariable)); */
bResult = _FAIL;
break;
}
return bResult;
}
static void UpdateHalRAMask8192CUsb(struct rtw_adapter *padapter,
u32 mac_id, u8 rssi_level)
{
u8 init_rate = 0;
u8 networkType, raid;
u32 mask, rate_bitmap;
u8 shortGIrate = false;
int supportRateNum = 0;
struct sta_info *psta;
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
struct dm_priv *pdmpriv = &pHalData->dmpriv;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
if (mac_id >= NUM_STA) /* CAM_SIZE */
return;
psta = pmlmeinfo->FW_sta_info[mac_id].psta;
if (psta == NULL)
return;
switch (mac_id) {
case 0:/* for infra mode */
supportRateNum =
rtw_get_rateset_len23a(cur_network->SupportedRates);
networkType = judge_network_type23a(padapter,
cur_network->SupportedRates,
supportRateNum) & 0xf;
/* pmlmeext->cur_wireless_mode = networkType; */
raid = networktype_to_raid23a(networkType);
mask = update_supported_rate23a(cur_network->SupportedRates,
supportRateNum);
mask |= (pmlmeinfo->HT_enable) ?
update_MSC_rate23a(&pmlmeinfo->HT_caps) : 0;
if (support_short_GI23a(padapter, &pmlmeinfo->HT_caps))
shortGIrate = true;
break;
case 1:/* for broadcast/multicast */
supportRateNum = rtw_get_rateset_len23a(
pmlmeinfo->FW_sta_info[mac_id].SupportedRates);
if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
networkType = WIRELESS_11B;
else
networkType = WIRELESS_11G;
raid = networktype_to_raid23a(networkType);
mask = update_basic_rate23a(cur_network->SupportedRates,
supportRateNum);
break;
default: /* for each sta in IBSS */
supportRateNum = rtw_get_rateset_len23a(
pmlmeinfo->FW_sta_info[mac_id].SupportedRates);
networkType = judge_network_type23a(padapter,
pmlmeinfo->FW_sta_info[mac_id].SupportedRates,
supportRateNum) & 0xf;
/* pmlmeext->cur_wireless_mode = networkType; */
raid = networktype_to_raid23a(networkType);
mask = update_supported_rate23a(cur_network->SupportedRates,
supportRateNum);
/* todo: support HT in IBSS */
break;
}
/* mask &= 0x0fffffff; */
rate_bitmap = 0x0fffffff;
rate_bitmap = ODM_Get_Rate_Bitmap23a(&pHalData->odmpriv,
mac_id, mask, rssi_level);
printk(KERN_DEBUG "%s => mac_id:%d, networkType:0x%02x, "
"mask:0x%08x\n\t ==> rssi_level:%d, rate_bitmap:0x%08x\n",
__func__,
mac_id, networkType, mask, rssi_level, rate_bitmap);
mask &= rate_bitmap;
mask |= ((raid<<28)&0xf0000000);
init_rate = get_highest_rate_idx23a(mask)&0x3f;
if (pHalData->fw_ractrl == true) {
u8 arg = 0;
/* arg = (cam_idx-4)&0x1f;MACID */
arg = mac_id&0x1f;/* MACID */
arg |= BIT(7);
if (shortGIrate == true)
arg |= BIT(5);
DBG_8723A("update raid entry, mask = 0x%x, arg = 0x%x\n",
mask, arg);
rtl8723a_set_raid_cmd(padapter, mask, arg);
} else {
if (shortGIrate == true)
init_rate |= BIT(6);
rtw_write8(padapter, (REG_INIDATA_RATE_SEL+mac_id), init_rate);
}
/* set ra_id */
psta->raid = raid;
psta->init_rate = init_rate;
/* set correct initial date rate for each mac_id */
pdmpriv->INIDATA_RATE[mac_id] = init_rate;
}
static void rtl8723au_init_default_value(struct rtw_adapter *padapter)
{
rtl8723a_init_default_value(padapter);
}
static u8 rtl8192cu_ps_func(struct rtw_adapter *Adapter,
enum hal_intf_ps_func efunc_id, u8 *val)
{
return true;
}
int rtl8723au_set_hal_ops(struct rtw_adapter *padapter)
{
struct hal_ops *pHalFunc = &padapter->HalFunc;
padapter->HalData = kzalloc(sizeof(struct hal_data_8723a), GFP_KERNEL);
if (!padapter->HalData) {
DBG_8723A("cannot alloc memory for HAL DATA\n");
return -ENOMEM;
}
padapter->hal_data_sz = sizeof(struct hal_data_8723a);
pHalFunc->hal_init = &rtl8723au_hal_init;
pHalFunc->hal_deinit = &rtl8723au_hal_deinit;
pHalFunc->inirp_init = &rtl8723au_inirp_init;
pHalFunc->inirp_deinit = &rtl8723au_inirp_deinit;
pHalFunc->init_xmit_priv = &rtl8723au_init_xmit_priv;
pHalFunc->free_xmit_priv = &rtl8723au_free_xmit_priv;
pHalFunc->init_recv_priv = &rtl8723au_init_recv_priv;
pHalFunc->free_recv_priv = &rtl8723au_free_recv_priv;
pHalFunc->InitSwLeds = NULL;
pHalFunc->DeInitSwLeds = NULL;
pHalFunc->init_default_value = &rtl8723au_init_default_value;
pHalFunc->intf_chip_configure = &rtl8723au_interface_configure;
pHalFunc->read_adapter_info = &ReadAdapterInfo8723AU;
pHalFunc->SetHwRegHandler = &SetHwReg8723AU;
pHalFunc->GetHwRegHandler = &GetHwReg8723AU;
pHalFunc->GetHalDefVarHandler = &GetHalDefVar8192CUsb;
pHalFunc->SetHalDefVarHandler = &SetHalDefVar8192CUsb;
pHalFunc->UpdateRAMaskHandler = &UpdateHalRAMask8192CUsb;
pHalFunc->hal_xmit = &rtl8723au_hal_xmit;
pHalFunc->mgnt_xmit = &rtl8723au_mgnt_xmit;
pHalFunc->hal_xmitframe_enqueue = &rtl8723au_hal_xmitframe_enqueue;
pHalFunc->interface_ps_func = &rtl8192cu_ps_func;
rtl8723a_set_hal_ops(pHalFunc);
return 0;
}
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
******************************************************************************/
#define _HCI_OPS_OS_C_
#include <osdep_service.h>
#include <drv_types.h>
#include <osdep_intf.h>
#include <usb_ops.h>
#include <recv_osdep.h>
#include <rtl8723a_hal.h>
#include <rtl8723a_recv.h>
static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u8 request, u16 value, u16 index, void *pdata, u16 len, u8 requesttype)
{
struct rtw_adapter *padapter = pintfhdl->padapter ;
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
struct usb_device *udev = pdvobjpriv->pusbdev;
unsigned int pipe;
int status = 0;
u8 reqtype;
u8 *pIo_buf;
int vendorreq_times = 0;
if ((padapter->bSurpriseRemoved) || (padapter->pwrctrlpriv.pnp_bstop_trx)) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usbctrl_vendorreq:(padapter->bSurpriseRemoved||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
status = -EPERM;
goto exit;
}
if (len > MAX_VENDOR_REQ_CMD_SIZE) {
DBG_8723A("[%s] Buffer len error , vendor request failed\n", __FUNCTION__);
status = -EINVAL;
goto exit;
}
mutex_lock(&pdvobjpriv->usb_vendor_req_mutex);
/* Acquire IO memory for vendorreq */
pIo_buf = pdvobjpriv->usb_vendor_req_buf;
if (pIo_buf == NULL) {
DBG_8723A("[%s] pIo_buf == NULL \n", __FUNCTION__);
status = -ENOMEM;
goto release_mutex;
}
while (++vendorreq_times <= MAX_USBCTRL_VENDORREQ_TIMES) {
memset(pIo_buf, 0, len);
if (requesttype == 0x01) {
pipe = usb_rcvctrlpipe(udev, 0);/* read_in */
reqtype = REALTEK_USB_VENQT_READ;
} else {
pipe = usb_sndctrlpipe(udev, 0);/* write_out */
reqtype = REALTEK_USB_VENQT_WRITE;
memcpy(pIo_buf, pdata, len);
}
status = rtw_usb_control_msg(udev, pipe, request, reqtype,
value, index, pIo_buf, len,
RTW_USB_CONTROL_MSG_TIMEOUT);
if (status == len) { /* Success this control transfer. */
rtw_reset_continual_urb_error(pdvobjpriv);
if (requesttype == 0x01) {
/* For Control read transfer, we have to copy
* the read data from pIo_buf to pdata.
*/
memcpy(pdata, pIo_buf, len);
}
} else { /* error cases */
DBG_8723A("reg 0x%x, usb %s %u fail, status:%d value ="
" 0x%x, vendorreq_times:%d\n",
value, (requesttype == 0x01) ? "read" : "write",
len, status, *(u32 *)pdata, vendorreq_times);
if (status < 0) {
if (status == (-ESHUTDOWN) || status == -ENODEV) {
padapter->bSurpriseRemoved = true;
} else {
struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
pHalData->srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL;
}
} else { /* status != len && status >= 0 */
if (status > 0) {
if (requesttype == 0x01) {
/* For Control read transfer, we have to copy
* the read data from pIo_buf to pdata.
*/
memcpy(pdata, pIo_buf, len);
}
}
}
if (rtw_inc_and_chk_continual_urb_error(pdvobjpriv)) {
padapter->bSurpriseRemoved = true;
break;
}
}
/* firmware download is checksumed, don't retry */
if ((value >= FW_8723A_START_ADDRESS && value <= FW_8723A_END_ADDRESS) || status == len)
break;
}
release_mutex:
mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex);
exit:
return status;
}
static u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr)
{
u8 request;
u8 requesttype;
u16 wvalue;
u16 index;
u16 len;
u8 data = 0;
request = 0x05;
requesttype = 0x01;/* read_in */
index = 0;/* n/a */
wvalue = (u16)(addr&0x0000ffff);
len = 1;
usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
return data;
}
static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
{
u8 request;
u8 requesttype;
u16 wvalue;
u16 index;
u16 len;
u16 data = 0;
request = 0x05;
requesttype = 0x01;/* read_in */
index = 0;/* n/a */
wvalue = (u16)(addr&0x0000ffff);
len = 2;
usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
return data;
}
static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
{
u8 request;
u8 requesttype;
u16 wvalue;
u16 index;
u16 len;
u32 data = 0;
request = 0x05;
requesttype = 0x01;/* read_in */
index = 0;/* n/a */
wvalue = (u16)(addr&0x0000ffff);
len = 4;
usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
return data;
}
static int usb_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
{
u8 request;
u8 requesttype;
u16 wvalue;
u16 index;
u16 len;
u8 data;
int ret;
request = 0x05;
requesttype = 0x00;/* write_out */
index = 0;/* n/a */
wvalue = (u16)(addr&0x0000ffff);
len = 1;
data = val;
ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
return ret;
}
static int usb_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
{
u8 request;
u8 requesttype;
u16 wvalue;
u16 index;
u16 len;
u16 data;
int ret;
request = 0x05;
requesttype = 0x00;/* write_out */
index = 0;/* n/a */
wvalue = (u16)(addr&0x0000ffff);
len = 2;
data = val;
ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
return ret;
}
static int usb_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
{
u8 request;
u8 requesttype;
u16 wvalue;
u16 index;
u16 len;
u32 data;
int ret;
request = 0x05;
requesttype = 0x00;/* write_out */
index = 0;/* n/a */
wvalue = (u16)(addr&0x0000ffff);
len = 4;
data = val;
ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
return ret;
}
static int usb_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata)
{
u8 request;
u8 requesttype;
u16 wvalue;
u16 index;
u16 len;
u8 buf[VENDOR_CMD_MAX_DATA_LEN] = {0};
int ret;
request = 0x05;
requesttype = 0x00;/* write_out */
index = 0;/* n/a */
wvalue = (u16)(addr&0x0000ffff);
len = length;
memcpy(buf, pdata, len);
ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, buf, len, requesttype);
return ret;
}
/*
* Description:
* Recognize the interrupt content by reading the interrupt
* register or content and masking interrupt mask (IMR)
* if it is our NIC's interrupt. After recognizing, we may clear
* the all interrupts (ISR).
* Arguments:
* [in] Adapter -
* The adapter context.
* [in] pContent -
* Under PCI interface, this field is ignord.
* Under USB interface, the content is the interrupt
* content pointer.
* Under SDIO interface, this is the interrupt type which
* is Local interrupt or system interrupt.
* [in] ContentLen -
* The length in byte of pContent.
* Return:
* If any interrupt matches the mask (IMR), return true, and
* return false otherwise.
*/
static bool
InterruptRecognized8723AU(struct rtw_adapter *Adapter, void *pContent,
u32 ContentLen)
{
struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
u8 *buffer = (u8 *)pContent;
struct reportpwrstate_parm report;
memcpy(&pHalData->IntArray[0], &buffer[USB_INTR_CONTENT_HISR_OFFSET],
4);
pHalData->IntArray[0] &= pHalData->IntrMask[0];
/* For HISR extension. Added by tynli. 2009.10.07. */
memcpy(&pHalData->IntArray[1],
&buffer[USB_INTR_CONTENT_HISRE_OFFSET], 4);
pHalData->IntArray[1] &= pHalData->IntrMask[1];
/* We sholud remove this function later because DDK suggest
* not to executing too many operations in MPISR */
memcpy(&report.state, &buffer[USB_INTR_CPWM_OFFSET], 1);
return ((pHalData->IntArray[0])&pHalData->IntrMask[0]) != 0 ||
((pHalData->IntArray[1])&pHalData->IntrMask[1]) != 0;
}
static void usb_read_interrupt_complete(struct urb *purb, struct pt_regs *regs)
{
int err;
struct rtw_adapter *padapter = (struct rtw_adapter *)purb->context;
if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
padapter->bReadPortCancel) {
DBG_8723A("%s() RX Warning! bDriverStopped(%d) OR "
"bSurpriseRemoved(%d) bReadPortCancel(%d)\n",
__FUNCTION__, padapter->bDriverStopped,
padapter->bSurpriseRemoved,
padapter->bReadPortCancel);
return;
}
if (purb->status == 0) {
struct c2h_evt_hdr *c2h_evt;
c2h_evt = (struct c2h_evt_hdr *)purb->transfer_buffer;
if (purb->actual_length > USB_INTR_CONTENT_LENGTH) {
DBG_8723A("usb_read_interrupt_complete: purb->actual_"
"length > USB_INTR_CONTENT_LENGTH\n");
goto urb_submit;
}
InterruptRecognized8723AU(padapter, purb->transfer_buffer,
purb->actual_length);
if (c2h_evt_exist(c2h_evt)) {
if (c2h_id_filter_ccx_8723a(c2h_evt->id)) {
/* Handle CCX report here */
handle_txrpt_ccx_8723a(padapter, (void *)(c2h_evt->payload));
/* Replace with special pointer to
trigger c2h_evt_clear23a */
if (rtw_cbuf_push23a(padapter->evtpriv.c2h_queue,
(void *)&padapter->evtpriv) !=
_SUCCESS)
DBG_8723A("%s rtw_cbuf_push23a fail\n",
__func__);
schedule_work(&padapter->evtpriv.c2h_wk);
} else if ((c2h_evt = (struct c2h_evt_hdr *)
kmalloc(16, GFP_ATOMIC))) {
memcpy(c2h_evt, purb->transfer_buffer, 16);
if (rtw_cbuf_push23a(padapter->evtpriv.c2h_queue,
(void *)c2h_evt) != _SUCCESS)
DBG_8723A("%s rtw_cbuf_push23a fail\n",
__func__);
schedule_work(&padapter->evtpriv.c2h_wk);
} else {
/* Error handling for malloc fail */
if (rtw_cbuf_push23a(padapter->evtpriv.c2h_queue,
(void *)NULL) != _SUCCESS)
DBG_8723A("%s rtw_cbuf_push23a fail\n",
__func__);
schedule_work(&padapter->evtpriv.c2h_wk);
}
}
urb_submit:
err = usb_submit_urb(purb, GFP_ATOMIC);
if (err && (err != -EPERM)) {
DBG_8723A("cannot submit interrupt in-token(err = "
"0x%08x), urb_status = %d\n",
err, purb->status);
}
} else {
DBG_8723A("###=> usb_read_interrupt_complete => urb "
"status(%d)\n", purb->status);
switch (purb->status) {
case -EINVAL:
case -EPIPE:
case -ENODEV:
case -ESHUTDOWN:
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port_complete:bSurpriseRemoved ="
"true\n"));
/* Fall Through here */
case -ENOENT:
padapter->bDriverStopped = true;
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port_complete:bDriverStopped ="
"true\n"));
break;
case -EPROTO:
break;
case -EINPROGRESS:
DBG_8723A("ERROR: URB IS IN PROGRESS!/n");
break;
default:
break;
}
}
}
static u32 usb_read_interrupt(struct intf_hdl *pintfhdl, u32 addr)
{
int err;
unsigned int pipe;
u32 ret = _SUCCESS;
struct rtw_adapter *adapter = pintfhdl->padapter;
struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter);
struct recv_priv *precvpriv = &adapter->recvpriv;
struct usb_device *pusbd = pdvobj->pusbdev;
/* translate DMA FIFO addr to pipehandle */
pipe = ffaddr2pipehdl23a(pdvobj, addr);
usb_fill_int_urb(precvpriv->int_in_urb, pusbd, pipe,
precvpriv->int_in_buf, USB_INTR_CONTENT_LENGTH,
usb_read_interrupt_complete, adapter, 1);
err = usb_submit_urb(precvpriv->int_in_urb, GFP_ATOMIC);
if (err && (err != -EPERM)) {
DBG_8723A("cannot submit interrupt in-token(err = 0x%08x),"
"urb_status = %d\n", err,
precvpriv->int_in_urb->status);
ret = _FAIL;
}
return ret;
}
static int recvbuf2recvframe(struct rtw_adapter *padapter, struct sk_buff *pskb)
{
u8 *pbuf;
u8 shift_sz = 0;
u16 pkt_cnt;
u32 pkt_offset, skb_len, alloc_sz;
s32 transfer_len;
struct recv_stat *prxstat;
struct phy_stat *pphy_info = NULL;
struct sk_buff *pkt_copy = NULL;
struct recv_frame *precvframe = NULL;
struct rx_pkt_attrib *pattrib = NULL;
struct recv_priv *precvpriv = &padapter->recvpriv;
struct rtw_queue *pfree_recv_queue = &precvpriv->free_recv_queue;
transfer_len = (s32)pskb->len;
pbuf = pskb->data;
prxstat = (struct recv_stat *)pbuf;
pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
do {
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
("recvbuf2recvframe: rxdesc = offsset 0:0x%08x, "
"4:0x%08x, 8:0x%08x, C:0x%08x\n", prxstat->rxdw0,
prxstat->rxdw1, prxstat->rxdw2, prxstat->rxdw4));
prxstat = (struct recv_stat *)pbuf;
precvframe = rtw_alloc_recvframe23a(pfree_recv_queue);
if (!precvframe) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
("recvbuf2recvframe: precvframe == NULL\n"));
DBG_8723A("%s()-%d: rtw_alloc_recvframe23a() failed! RX "
"Drop!\n", __FUNCTION__, __LINE__);
goto _exit_recvbuf2recvframe;
}
INIT_LIST_HEAD(&precvframe->list);
update_recvframe_attrib(precvframe, prxstat);
pattrib = &precvframe->attrib;
if (pattrib->crc_err) {
DBG_8723A("%s()-%d: RX Warning! rx CRC ERROR !!\n",
__FUNCTION__, __LINE__);
rtw_free_recvframe23a(precvframe, pfree_recv_queue);
goto _exit_recvbuf2recvframe;
}
pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz +
pattrib->shift_sz + pattrib->pkt_len;
if ((pattrib->pkt_len <= 0) || (pkt_offset > transfer_len)) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
("recvbuf2recvframe: pkt_len<= 0\n"));
DBG_8723A("%s()-%d: RX Warning!\n",
__FUNCTION__, __LINE__);
rtw_free_recvframe23a(precvframe, pfree_recv_queue);
goto _exit_recvbuf2recvframe;
}
/* Modified by Albert 20101213 */
/* For 8 bytes IP header alignment. */
/* Qos data, wireless lan header length is 26 */
if (pattrib->qos) {
shift_sz = 6;
} else {
shift_sz = 0;
}
skb_len = pattrib->pkt_len;
/* for first fragment packet, driver need allocate
* 1536+drvinfo_sz+RXDESC_SIZE to defrag packet.
* modify alloc_sz for recvive crc error packet
* by thomas 2011-06-02 */
if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
/* alloc_sz = 1664; 1664 is 128 alignment. */
if (skb_len <= 1650)
alloc_sz = 1664;
else
alloc_sz = skb_len + 14;
} else {
alloc_sz = skb_len;
/* 6 is for IP header 8 bytes alignment in QoS packet case. */
/* 8 is for skb->data 4 bytes alignment. */
alloc_sz += 14;
}
pkt_copy = netdev_alloc_skb(padapter->pnetdev, alloc_sz);
if (pkt_copy) {
pkt_copy->dev = padapter->pnetdev;
precvframe->pkt = pkt_copy;
skb_reserve(pkt_copy, 8 - ((unsigned long)(pkt_copy->data) & 7));/* force pkt_copy->data at 8-byte alignment address */
/*force ip_hdr at 8-byte alignment address according to shift_sz. */
skb_reserve(pkt_copy, shift_sz);
memcpy(pkt_copy->data, (pbuf + pattrib->shift_sz + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len);
skb_put(pkt_copy, skb_len);
} else {
if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
DBG_8723A("recvbuf2recvframe: alloc_skb fail, "
"drop frag frame \n");
rtw_free_recvframe23a(precvframe,
pfree_recv_queue);
goto _exit_recvbuf2recvframe;
}
precvframe->pkt = skb_clone(pskb, GFP_ATOMIC);
if (!precvframe->pkt) {
DBG_8723A("recvbuf2recvframe: skb_clone "
"fail\n");
rtw_free_recvframe23a(precvframe,
pfree_recv_queue);
goto _exit_recvbuf2recvframe;
}
}
if (pattrib->physt) {
pphy_info = (struct phy_stat *)(pbuf + RXDESC_OFFSET);
update_recvframe_phyinfo(precvframe, pphy_info);
}
if (rtw_recv_entry23a(precvframe) != _SUCCESS)
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
("recvbuf2recvframe: rtw_recv_entry23a"
"(precvframe) != _SUCCESS\n"));
pkt_cnt--;
transfer_len -= pkt_offset;
pbuf += pkt_offset;
precvframe = NULL;
pkt_copy = NULL;
if (transfer_len > 0 && pkt_cnt == 0)
pkt_cnt = (le32_to_cpu(prxstat->rxdw2)>>16) & 0xff;
} while ((transfer_len > 0) && (pkt_cnt > 0));
_exit_recvbuf2recvframe:
return _SUCCESS;
}
void rtl8723au_recv_tasklet(void *priv)
{
struct sk_buff *pskb;
struct rtw_adapter *padapter = (struct rtw_adapter *)priv;
struct recv_priv *precvpriv = &padapter->recvpriv;
while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) {
if ((padapter->bDriverStopped) ||
(padapter->bSurpriseRemoved)) {
DBG_8723A("recv_tasklet => bDriverStopped or "
"bSurpriseRemoved \n");
dev_kfree_skb_any(pskb);
break;
}
recvbuf2recvframe(padapter, pskb);
skb_reset_tail_pointer(pskb);
pskb->len = 0;
skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
}
}
static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs)
{
struct recv_buf *precvbuf = (struct recv_buf *)purb->context;
struct rtw_adapter *padapter = (struct rtw_adapter *)precvbuf->adapter;
struct recv_priv *precvpriv = &padapter->recvpriv;
struct hal_data_8723a *pHalData;
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port_complete!!!\n"));
precvpriv->rx_pending_cnt--;
if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
padapter->bReadPortCancel) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port_complete:bDriverStopped(%d) OR "
"bSurpriseRemoved(%d)\n", padapter->bDriverStopped,
padapter->bSurpriseRemoved));
DBG_8723A("%s()-%d: RX Warning! bDriverStopped(%d) OR "
"bSurpriseRemoved(%d) bReadPortCancel(%d)\n",
__FUNCTION__, __LINE__, padapter->bDriverStopped,
padapter->bSurpriseRemoved, padapter->bReadPortCancel);
return;
}
if (purb->status == 0) {
if ((purb->actual_length > MAX_RECVBUF_SZ) ||
(purb->actual_length < RXDESC_SIZE)) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port_complete: (purb->actual_"
"length > MAX_RECVBUF_SZ) || (purb->actual_"
"length < RXDESC_SIZE)\n"));
rtw_read_port(padapter, precvpriv->ff_hwaddr, 0,
precvbuf);
DBG_8723A("%s()-%d: RX Warning!\n",
__FUNCTION__, __LINE__);
} else {
rtw_reset_continual_urb_error(
adapter_to_dvobj(padapter));
skb_put(precvbuf->pskb, purb->actual_length);
skb_queue_tail(&precvpriv->rx_skb_queue,
precvbuf->pskb);
if (skb_queue_len(&precvpriv->rx_skb_queue) <= 1)
tasklet_schedule(&precvpriv->recv_tasklet);
precvbuf->pskb = NULL;
rtw_read_port(padapter, precvpriv->ff_hwaddr, 0,
precvbuf);
}
} else {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port_complete : purb->status(%d) != 0 \n",
purb->status));
skb_put(precvbuf->pskb, purb->actual_length);
precvbuf->pskb = NULL;
DBG_8723A("###=> usb_read_port_complete => urb status(%d)\n",
purb->status);
if (rtw_inc_and_chk_continual_urb_error(
adapter_to_dvobj(padapter))) {
padapter->bSurpriseRemoved = true;
}
switch (purb->status) {
case -EINVAL:
case -EPIPE:
case -ENODEV:
case -ESHUTDOWN:
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port_complete:bSurprise"
"Removed = true\n"));
/* Intentional fall through here */
case -ENOENT:
padapter->bDriverStopped = true;
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port_complete:"
"bDriverStopped = true\n"));
break;
case -EPROTO:
case -EOVERFLOW:
pHalData = GET_HAL_DATA(padapter);
pHalData->srestpriv.Wifi_Error_Status =
USB_READ_PORT_FAIL;
rtw_read_port(padapter, precvpriv->ff_hwaddr,
0, precvbuf);
break;
case -EINPROGRESS:
DBG_8723A("ERROR: URB IS IN PROGRESS!/n");
break;
default:
break;
}
}
}
static u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
struct recv_buf *precvbuf)
{
int err;
unsigned int pipe;
unsigned long tmpaddr = 0;
unsigned long alignment = 0;
u32 ret = _SUCCESS;
struct urb *purb = NULL;
struct rtw_adapter *adapter = pintfhdl->padapter;
struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter);
struct recv_priv *precvpriv = &adapter->recvpriv;
struct usb_device *pusbd = pdvobj->pusbdev;
if (adapter->bDriverStopped || adapter->bSurpriseRemoved ||
adapter->pwrctrlpriv.pnp_bstop_trx) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port:(padapter->bDriverStopped ||"
"padapter->bSurpriseRemoved ||adapter->"
"pwrctrlpriv.pnp_bstop_trx)!!!\n"));
return _FAIL;
}
if (!precvbuf) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("usb_read_port:precvbuf == NULL\n"));
return _FAIL;
}
if (!precvbuf->pskb)
precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
rtl8723au_init_recvbuf(adapter, precvbuf);
/* re-assign for linux based on skb */
if (!precvbuf->pskb) {
precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
if (precvbuf->pskb == NULL) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("init_recvbuf(): alloc_skb fail!\n"));
return _FAIL;
}
tmpaddr = (unsigned long)precvbuf->pskb->data;
alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
}
precvpriv->rx_pending_cnt++;
purb = precvbuf->purb;
/* translate DMA FIFO addr to pipehandle */
pipe = ffaddr2pipehdl23a(pdvobj, addr);
usb_fill_bulk_urb(purb, pusbd, pipe, precvbuf->pskb->data,
MAX_RECVBUF_SZ, usb_read_port_complete,
precvbuf);/* context is precvbuf */
err = usb_submit_urb(purb, GFP_ATOMIC);
if ((err) && (err != -EPERM)) {
RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
("cannot submit rx in-token(err = 0x%.8x), URB_STATUS "
"= 0x%.8x", err, purb->status));
DBG_8723A("cannot submit rx in-token(err = 0x%08x), urb_status "
"= %d\n", err, purb->status);
ret = _FAIL;
}
return ret;
}
void rtl8723au_xmit_tasklet(void *priv)
{
int ret = false;
struct rtw_adapter *padapter = (struct rtw_adapter *)priv;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
if (check_fwstate(&padapter->mlmepriv, _FW_UNDER_SURVEY))
return;
while (1) {
if ((padapter->bDriverStopped) ||
(padapter->bSurpriseRemoved) ||
(padapter->bWritePortCancel)) {
DBG_8723A("xmit_tasklet => bDriverStopped or "
"bSurpriseRemoved or bWritePortCancel\n");
break;
}
ret = rtl8723au_xmitframe_complete(padapter, pxmitpriv, NULL);
if (!ret)
break;
}
}
void rtl8723au_set_intf_ops(struct _io_ops *pops)
{
memset((u8 *)pops, 0, sizeof(struct _io_ops));
pops->_read8 = &usb_read8;
pops->_read16 = &usb_read16;
pops->_read32 = &usb_read32;
pops->_read_mem = &usb_read_mem23a;
pops->_read_port = &usb_read_port;
pops->_write8 = &usb_write8;
pops->_write16 = &usb_write16;
pops->_write32 = &usb_write32;
pops->_writeN = &usb_writeN;
pops->_write_mem = &usb_write_mem23a;
pops->_write_port = &usb_write_port23a;
pops->_read_port_cancel = &usb_read_port_cancel23a;
pops->_write_port_cancel = &usb_write_port23a_cancel;
pops->_read_interrupt = &usb_read_interrupt;
}
void rtl8723au_set_hw_type(struct rtw_adapter *padapter)
{
padapter->chip_type = RTL8723A;
padapter->HardwareType = HARDWARE_TYPE_RTL8723AU;
DBG_8723A("CHIP TYPE: RTL8723A\n");
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment