2 This is part of the rtl8192 driver
3 released under the GPL (See file COPYING for details).
5 This files contains programming code for the rtl8256
8 *Many* thanks to Realtek Corp. for their great support!
13 #include "r8192E_hw.h"
14 #include "r819xE_phyreg.h"
15 #include "r819xE_phy.h"
16 #include "r8190_rtl8256.h"
18 /*--------------------------------------------------------------------------
19 * Overview: set RF band width (20M or 40M)
20 * Input: struct net_device* dev
21 * WIRELESS_BANDWIDTH_E Bandwidth //20M or 40M
24 * Note: 8226 support both 20M and 40 MHz
25 *---------------------------------------------------------------------------*/
26 void PHY_SetRF8256Bandwidth(struct r8192_priv
*priv
, HT_CHANNEL_WIDTH Bandwidth
) //20M or 40M
30 //for(eRFPath = RF90_PATH_A; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
31 for(eRFPath
= 0; eRFPath
<priv
->NumTotalRFPath
; eRFPath
++)
33 if (!rtl8192_phy_CheckIsLegalRFPath(priv
, eRFPath
))
38 case HT_CHANNEL_WIDTH_20
:
39 if(priv
->card_8192_version
== VERSION_8190_BD
|| priv
->card_8192_version
== VERSION_8190_BE
)// 8256 D-cut, E-cut, xiong: consider it later!
41 rtl8192_phy_SetRFReg(priv
, (RF90_RADIO_PATH_E
)eRFPath
, 0x0b, bMask12Bits
, 0x100); //phy para:1ba
42 rtl8192_phy_SetRFReg(priv
, (RF90_RADIO_PATH_E
)eRFPath
, 0x2c, bMask12Bits
, 0x3d7);
43 rtl8192_phy_SetRFReg(priv
, (RF90_RADIO_PATH_E
)eRFPath
, 0x0e, bMask12Bits
, 0x021);
45 //cosa add for sd3's request 01/23/2008
46 //rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x14, bMask12Bits, 0x5ab);
50 RT_TRACE(COMP_ERR
, "PHY_SetRF8256Bandwidth(): unknown hardware version\n");
54 case HT_CHANNEL_WIDTH_20_40
:
55 if(priv
->card_8192_version
== VERSION_8190_BD
||priv
->card_8192_version
== VERSION_8190_BE
)// 8256 D-cut, E-cut, xiong: consider it later!
57 rtl8192_phy_SetRFReg(priv
, (RF90_RADIO_PATH_E
)eRFPath
, 0x0b, bMask12Bits
, 0x300); //phy para:3ba
58 rtl8192_phy_SetRFReg(priv
, (RF90_RADIO_PATH_E
)eRFPath
, 0x2c, bMask12Bits
, 0x3ff);
59 rtl8192_phy_SetRFReg(priv
, (RF90_RADIO_PATH_E
)eRFPath
, 0x0e, bMask12Bits
, 0x0e1);
64 RT_TRACE(COMP_ERR
, "PHY_SetRF8256Bandwidth(): unknown hardware version\n");
70 RT_TRACE(COMP_ERR
, "PHY_SetRF8256Bandwidth(): unknown Bandwidth: %#X\n",Bandwidth
);
76 /*--------------------------------------------------------------------------
77 * Overview: Interface to config 8256
78 * Input: struct net_device* dev
81 *---------------------------------------------------------------------------*/
82 RT_STATUS
PHY_RF8256_Config(struct r8192_priv
*priv
)
84 // Initialize general global value
86 RT_STATUS rtStatus
= RT_STATUS_SUCCESS
;
87 // TODO: Extend RF_PATH_C and RF_PATH_D in the future
88 priv
->NumTotalRFPath
= RTL819X_TOTAL_RF_PATH
;
90 rtStatus
= phy_RF8256_Config_ParaFile(priv
);
95 /*--------------------------------------------------------------------------
96 * Overview: Interface to config 8256
97 * Input: struct net_device* dev
100 *---------------------------------------------------------------------------*/
101 RT_STATUS
phy_RF8256_Config_ParaFile(struct r8192_priv
*priv
)
105 RT_STATUS rtStatus
= RT_STATUS_SUCCESS
;
106 BB_REGISTER_DEFINITION_T
*pPhyReg
;
107 u32 RegOffSetToBeCheck
= 0x3;
108 u32 RegValueToBeCheck
= 0x7f1;
109 u32 RF3_Final_Value
= 0;
110 u8 ConstRetryTimes
= 5, RetryTimes
= 5;
113 //3//-----------------------------------------------------------------
114 //3// <2> Initialize RF
115 //3//-----------------------------------------------------------------
116 for(eRFPath
= (RF90_RADIO_PATH_E
)RF90_PATH_A
; eRFPath
<priv
->NumTotalRFPath
; eRFPath
++)
118 if (!rtl8192_phy_CheckIsLegalRFPath(priv
, eRFPath
))
121 pPhyReg
= &priv
->PHYRegDef
[eRFPath
];
123 /*----Store original RFENV control type----*/
128 u4RegValue
= rtl8192_QueryBBReg(priv
, pPhyReg
->rfintfs
, bRFSI_RFENV
);
132 u4RegValue
= rtl8192_QueryBBReg(priv
, pPhyReg
->rfintfs
, bRFSI_RFENV
<<16);
136 /*----Set RF_ENV enable----*/
137 rtl8192_setBBreg(priv
, pPhyReg
->rfintfe
, bRFSI_RFENV
<<16, 0x1);
139 /*----Set RF_ENV output high----*/
140 rtl8192_setBBreg(priv
, pPhyReg
->rfintfo
, bRFSI_RFENV
, 0x1);
142 /* Set bit number of Address and Data for RF register */
143 rtl8192_setBBreg(priv
, pPhyReg
->rfHSSIPara2
, b3WireAddressLength
, 0x0); // Set 0 to 4 bits for Z-serial and set 1 to 6 bits for 8258
144 rtl8192_setBBreg(priv
, pPhyReg
->rfHSSIPara2
, b3WireDataLength
, 0x0); // Set 0 to 12 bits for Z-serial and 8258, and set 1 to 14 bits for ???
146 rtl8192_phy_SetRFReg(priv
, (RF90_RADIO_PATH_E
) eRFPath
, 0x0, bMask12Bits
, 0xbf);
148 /*----Check RF block (for FPGA platform only)----*/
149 // TODO: this function should be removed on ASIC , Emily 2007.2.2
150 rtStatus
= rtl8192_phy_checkBBAndRF(priv
, HW90_BLOCK_RF
, (RF90_RADIO_PATH_E
)eRFPath
);
151 if(rtStatus
!= RT_STATUS_SUCCESS
)
153 RT_TRACE(COMP_ERR
, "PHY_RF8256_Config():Check Radio[%d] Fail!!\n", eRFPath
);
154 goto phy_RF8256_Config_ParaFile_Fail
;
157 RetryTimes
= ConstRetryTimes
;
159 /*----Initialize RF fom connfiguration file----*/
163 while(RF3_Final_Value
!=RegValueToBeCheck
&& RetryTimes
!=0)
165 ret
= rtl8192_phy_ConfigRFWithHeaderFile(priv
,(RF90_RADIO_PATH_E
)eRFPath
);
166 RF3_Final_Value
= rtl8192_phy_QueryRFReg(priv
, (RF90_RADIO_PATH_E
)eRFPath
, RegOffSetToBeCheck
, bMask12Bits
);
167 RT_TRACE(COMP_RF
, "RF %d %d register final value: %x\n", eRFPath
, RegOffSetToBeCheck
, RF3_Final_Value
);
172 while(RF3_Final_Value
!=RegValueToBeCheck
&& RetryTimes
!=0)
174 ret
= rtl8192_phy_ConfigRFWithHeaderFile(priv
,(RF90_RADIO_PATH_E
)eRFPath
);
175 RF3_Final_Value
= rtl8192_phy_QueryRFReg(priv
, (RF90_RADIO_PATH_E
)eRFPath
, RegOffSetToBeCheck
, bMask12Bits
);
176 RT_TRACE(COMP_RF
, "RF %d %d register final value: %x\n", eRFPath
, RegOffSetToBeCheck
, RF3_Final_Value
);
181 while(RF3_Final_Value
!=RegValueToBeCheck
&& RetryTimes
!=0)
183 ret
= rtl8192_phy_ConfigRFWithHeaderFile(priv
,(RF90_RADIO_PATH_E
)eRFPath
);
184 RF3_Final_Value
= rtl8192_phy_QueryRFReg(priv
, (RF90_RADIO_PATH_E
)eRFPath
, RegOffSetToBeCheck
, bMask12Bits
);
185 RT_TRACE(COMP_RF
, "RF %d %d register final value: %x\n", eRFPath
, RegOffSetToBeCheck
, RF3_Final_Value
);
190 while(RF3_Final_Value
!=RegValueToBeCheck
&& RetryTimes
!=0)
192 ret
= rtl8192_phy_ConfigRFWithHeaderFile(priv
,(RF90_RADIO_PATH_E
)eRFPath
);
193 RF3_Final_Value
= rtl8192_phy_QueryRFReg(priv
, (RF90_RADIO_PATH_E
)eRFPath
, RegOffSetToBeCheck
, bMask12Bits
);
194 RT_TRACE(COMP_RF
, "RF %d %d register final value: %x\n", eRFPath
, RegOffSetToBeCheck
, RF3_Final_Value
);
200 /*----Restore RFENV control type----*/;
205 rtl8192_setBBreg(priv
, pPhyReg
->rfintfs
, bRFSI_RFENV
, u4RegValue
);
209 rtl8192_setBBreg(priv
, pPhyReg
->rfintfs
, bRFSI_RFENV
<<16, u4RegValue
);
214 RT_TRACE(COMP_ERR
, "phy_RF8256_Config_ParaFile():Radio[%d] Fail!!", eRFPath
);
215 goto phy_RF8256_Config_ParaFile_Fail
;
220 RT_TRACE(COMP_PHY
, "PHY Initialization Success\n") ;
221 return RT_STATUS_SUCCESS
;
223 phy_RF8256_Config_ParaFile_Fail
:
224 RT_TRACE(COMP_ERR
, "PHY Initialization failed\n") ;
225 return RT_STATUS_FAILURE
;
229 void PHY_SetRF8256CCKTxPower(struct r8192_priv
*priv
, u8 powerlevel
)
234 if(priv
->bDynamicTxLowPower
== true)//cosa 04282008 for cck long range
236 if(priv
->CustomerID
== RT_CID_819x_Netcore
)
239 TxAGC
+= priv
->CckPwEnl
;
243 rtl8192_setBBreg(priv
, rTxAGC_CCK_Mcs32
, bTxAGCRateCCK
, TxAGC
);
247 void PHY_SetRF8256OFDMTxPower(struct r8192_priv
*priv
, u8 powerlevel
)
250 u32 writeVal
, powerBase0
, powerBase1
, writeVal_tmp
;
252 u16 RegOffset
[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c};
253 u8 byte0
, byte1
, byte2
, byte3
;
255 powerBase0
= powerlevel
+ priv
->LegacyHTTxPowerDiff
; //OFDM rates
256 powerBase0
= (powerBase0
<<24) | (powerBase0
<<16) |(powerBase0
<<8) |powerBase0
;
257 powerBase1
= powerlevel
; //MCS rates
258 powerBase1
= (powerBase1
<<24) | (powerBase1
<<16) |(powerBase1
<<8) |powerBase1
;
260 for(index
=0; index
<6; index
++)
262 writeVal
= priv
->MCSTxPowerLevelOriginalOffset
[index
] + ((index
<2)?powerBase0
:powerBase1
);
263 byte0
= (u8
)(writeVal
& 0x7f);
264 byte1
= (u8
)((writeVal
& 0x7f00)>>8);
265 byte2
= (u8
)((writeVal
& 0x7f0000)>>16);
266 byte3
= (u8
)((writeVal
& 0x7f000000)>>24);
267 if(byte0
> 0x24) // Max power index = 0x24
278 writeVal_tmp
= (byte3
<<24) | (byte2
<<16) |(byte1
<<8) |byte0
;
279 priv
->Pwr_Track
= writeVal_tmp
;
282 if(priv
->bDynamicTxHighPower
== true) //Add by Jacken 2008/03/06 //when DM implement, add this
284 writeVal
= 0x03030303;
288 writeVal
= (byte3
<<24) | (byte2
<<16) |(byte1
<<8) |byte0
;
290 rtl8192_setBBreg(priv
, RegOffset
[index
], 0x7f7f7f7f, writeVal
);
294 #define MAX_DOZE_WAITING_TIMES_9x 64
295 static void r8192e_drain_tx_queues(struct r8192_priv
*priv
)
299 for (QueueID
= 0, i
= 0; QueueID
< MAX_TX_QUEUE
; )
301 struct rtl8192_tx_ring
*ring
= &priv
->tx_ring
[QueueID
];
303 if(skb_queue_len(&ring
->queue
) == 0)
312 if (i
>= MAX_DOZE_WAITING_TIMES_9x
)
314 RT_TRACE(COMP_POWER
, "r8192e_drain_tx_queues() timeout queue %d\n", QueueID
);
320 static bool SetRFPowerState8190(struct r8192_priv
*priv
,
321 RT_RF_POWER_STATE eRFPowerState
)
323 PRT_POWER_SAVE_CONTROL pPSC
= &priv
->PowerSaveControl
;
326 if (eRFPowerState
== priv
->eRFPowerState
&&
327 priv
->bHwRfOffAction
== 0) {
332 switch( eRFPowerState
)
337 if ((priv
->eRFPowerState
== eRfOff
) &&
338 RT_IN_PS_LEVEL(pPSC
, RT_RF_OFF_LEVL_HALT_NIC
))
341 * The current RF state is OFF and the RF OFF level
342 * is halting the NIC, re-initialize the NIC.
344 if (!NicIFEnableNIC(priv
)) {
345 RT_TRACE(COMP_ERR
, "%s(): NicIFEnableNIC failed\n",__FUNCTION__
);
350 RT_CLEAR_PS_LEVEL(pPSC
, RT_RF_OFF_LEVL_HALT_NIC
);
352 write_nic_byte(priv
, ANAPAR
, 0x37);//160MHz
354 //enable clock 80/88 MHz
355 rtl8192_setBBreg(priv
, rFPGA0_AnalogParameter1
, 0x4, 0x1); // 0x880[2]
356 priv
->bHwRfOffAction
= 0;
360 rtl8192_setBBreg(priv
, rFPGA0_XA_RFInterfaceOE
, BIT4
, 0x1); // 0x860[4]
361 //analog to digital on
362 rtl8192_setBBreg(priv
, rFPGA0_AnalogParameter4
, 0x300, 0x3);// 0x88c[9:8]
363 //digital to analog on
364 rtl8192_setBBreg(priv
, rFPGA0_AnalogParameter1
, 0x18, 0x3); // 0x880[4:3]
366 rtl8192_setBBreg(priv
, rOFDM0_TRxPathEnable
, 0x3, 0x3);// 0xc04[1:0]
368 rtl8192_setBBreg(priv
, rOFDM1_TRxPathEnable
, 0x3, 0x3);// 0xd04[1:0]
369 //analog to digital part2 on
370 rtl8192_setBBreg(priv
, rFPGA0_AnalogParameter1
, 0x60, 0x3); // 0x880[6:5]
377 // In current solution, RFSleep=RFOff in order to save power under 802.11 power save.
378 // By Bruce, 2008-01-16.
382 // HW setting had been configured with deeper mode.
383 if(priv
->eRFPowerState
== eRfOff
)
386 r8192e_drain_tx_queues(priv
);
388 PHY_SetRtl8192eRfOff(priv
);
395 // Disconnect with Any AP or STA.
397 r8192e_drain_tx_queues(priv
);
400 if (pPSC
->RegRfPsLevel
& RT_RF_OFF_LEVL_HALT_NIC
&& !RT_IN_PS_LEVEL(pPSC
, RT_RF_OFF_LEVL_HALT_NIC
))
402 /* Disable all components. */
403 NicIFDisableNIC(priv
);
404 RT_SET_PS_LEVEL(pPSC
, RT_RF_OFF_LEVL_HALT_NIC
);
406 else if (!(pPSC
->RegRfPsLevel
& RT_RF_OFF_LEVL_HALT_NIC
))
408 /* Normal case - IPS should go to this. */
409 PHY_SetRtl8192eRfOff(priv
);
415 RT_TRACE(COMP_ERR
, "SetRFPowerState8190(): unknow state to set: 0x%X!!!\n", eRFPowerState
);
421 // Update current RF state variable.
422 priv
->eRFPowerState
= eRFPowerState
;
433 static void MgntDisconnectIBSS(struct r8192_priv
*priv
)
436 bool bFilterOutNonAssociatedBSSID
= false;
438 priv
->ieee80211
->state
= IEEE80211_NOLINK
;
440 for(i
=0;i
<6;i
++) priv
->ieee80211
->current_network
.bssid
[i
]= 0x55;
441 priv
->OpMode
= RT_OP_MODE_NO_LINK
;
442 write_nic_word(priv
, BSSIDR
, ((u16
*)priv
->ieee80211
->current_network
.bssid
)[0]);
443 write_nic_dword(priv
, BSSIDR
+2, ((u32
*)(priv
->ieee80211
->current_network
.bssid
+2))[0]);
445 RT_OP_MODE OpMode
= priv
->OpMode
;
446 u8 btMsr
= read_nic_byte(priv
, MSR
);
452 case RT_OP_MODE_INFRASTRUCTURE
:
453 btMsr
|= MSR_LINK_MANAGED
;
456 case RT_OP_MODE_IBSS
:
457 btMsr
|= MSR_LINK_ADHOC
;
458 // led link set separate
462 btMsr
|= MSR_LINK_MASTER
;
466 btMsr
|= MSR_LINK_NONE
;
470 write_nic_byte(priv
, MSR
, btMsr
);
472 ieee80211_stop_send_beacons(priv
->ieee80211
);
474 // If disconnect, clear RCR CBSSID bit
475 bFilterOutNonAssociatedBSSID
= false;
478 Type
= bFilterOutNonAssociatedBSSID
;
479 RegRCR
= read_nic_dword(priv
, RCR
);
480 priv
->ReceiveConfig
= RegRCR
;
482 RegRCR
|= (RCR_CBSSID
);
483 else if (Type
== false)
484 RegRCR
&= (~RCR_CBSSID
);
487 write_nic_dword(priv
, RCR
, RegRCR
);
488 priv
->ReceiveConfig
= RegRCR
;
492 notify_wx_assoc_event(priv
->ieee80211
);
496 static void MlmeDisassociateRequest(struct r8192_priv
*priv
, u8
*asSta
,
501 RemovePeerTS(priv
->ieee80211
, asSta
);
503 SendDisassociation( priv
->ieee80211
, asSta
, asRsn
);
505 if(memcpy(priv
->ieee80211
->current_network
.bssid
,asSta
,6) == NULL
)
507 //ShuChen TODO: change media status.
508 //ShuChen TODO: What to do when disassociate.
509 priv
->ieee80211
->state
= IEEE80211_NOLINK
;
510 for(i
=0;i
<6;i
++) priv
->ieee80211
->current_network
.bssid
[i
] = 0x22;
511 priv
->OpMode
= RT_OP_MODE_NO_LINK
;
513 RT_OP_MODE OpMode
= priv
->OpMode
;
514 u8 btMsr
= read_nic_byte(priv
, MSR
);
520 case RT_OP_MODE_INFRASTRUCTURE
:
521 btMsr
|= MSR_LINK_MANAGED
;
524 case RT_OP_MODE_IBSS
:
525 btMsr
|= MSR_LINK_ADHOC
;
526 // led link set separate
530 btMsr
|= MSR_LINK_MASTER
;
534 btMsr
|= MSR_LINK_NONE
;
538 write_nic_byte(priv
, MSR
, btMsr
);
540 ieee80211_disassociate(priv
->ieee80211
);
542 write_nic_word(priv
, BSSIDR
, ((u16
*)priv
->ieee80211
->current_network
.bssid
)[0]);
543 write_nic_dword(priv
, BSSIDR
+2, ((u32
*)(priv
->ieee80211
->current_network
.bssid
+2))[0]);
550 static void MgntDisconnectAP(struct r8192_priv
*priv
, u8 asRsn
)
552 bool bFilterOutNonAssociatedBSSID
= false;
555 /* If disconnect, clear RCR CBSSID bit */
556 bFilterOutNonAssociatedBSSID
= false;
558 Type
= bFilterOutNonAssociatedBSSID
;
559 RegRCR
= read_nic_dword(priv
, RCR
);
560 priv
->ReceiveConfig
= RegRCR
;
563 RegRCR
|= (RCR_CBSSID
);
564 else if (Type
== false)
565 RegRCR
&= (~RCR_CBSSID
);
567 write_nic_dword(priv
, RCR
, RegRCR
);
568 priv
->ReceiveConfig
= RegRCR
;
570 MlmeDisassociateRequest(priv
, priv
->ieee80211
->current_network
.bssid
, asRsn
);
572 priv
->ieee80211
->state
= IEEE80211_NOLINK
;
576 static bool MgntDisconnect(struct r8192_priv
*priv
, u8 asRsn
)
578 // In adhoc mode, update beacon frame.
579 if( priv
->ieee80211
->state
== IEEE80211_LINKED
)
581 if( priv
->ieee80211
->iw_mode
== IW_MODE_ADHOC
)
583 MgntDisconnectIBSS(priv
);
585 if( priv
->ieee80211
->iw_mode
== IW_MODE_INFRA
)
587 // We clear key here instead of MgntDisconnectAP() because that
588 // MgntActSet_802_11_DISASSOCIATE() is an interface called by OS,
589 // e.g. OID_802_11_DISASSOCIATE in Windows while as MgntDisconnectAP() is
590 // used to handle disassociation related things to AP, e.g. send Disassoc
591 // frame to AP. 2005.01.27, by rcnjko.
592 MgntDisconnectAP(priv
, asRsn
);
601 // Chang RF Power State.
602 // Note that, only MgntActSet_RF_State() is allowed to set HW_VAR_RF_STATE.
607 bool MgntActSet_RF_State(struct r8192_priv
*priv
, RT_RF_POWER_STATE StateToSet
,
608 RT_RF_CHANGE_SOURCE ChangeSource
)
610 bool bActionAllowed
= false;
611 bool bConnectBySSID
= false;
612 RT_RF_POWER_STATE rtState
;
614 RT_TRACE(COMP_POWER
, "===>MgntActSet_RF_State(): StateToSet(%d)\n",StateToSet
);
616 spin_lock(&priv
->rf_ps_lock
);
618 rtState
= priv
->eRFPowerState
;
623 priv
->RfOffReason
&= (~ChangeSource
);
625 if (!priv
->RfOffReason
)
627 priv
->RfOffReason
= 0;
628 bActionAllowed
= true;
631 if(rtState
== eRfOff
&& ChangeSource
>=RF_CHANGE_BY_HW
)
633 bConnectBySSID
= true;
637 RT_TRACE(COMP_POWER
, "MgntActSet_RF_State - eRfon reject pMgntInfo->RfOffReason= 0x%x, ChangeSource=0x%X\n", priv
->RfOffReason
, ChangeSource
);
643 if (priv
->RfOffReason
> RF_CHANGE_BY_IPS
)
645 // Disconnect to current BSS when radio off. Asked by QuanTa.
646 MgntDisconnect(priv
, disas_lv_ss
);
649 priv
->RfOffReason
|= ChangeSource
;
650 bActionAllowed
= true;
654 priv
->RfOffReason
|= ChangeSource
;
655 bActionAllowed
= true;
661 RT_TRACE(COMP_POWER
, "MgntActSet_RF_State(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n", StateToSet
, priv
->RfOffReason
);
662 // Config HW to the specified mode.
663 SetRFPowerState8190(priv
, StateToSet
);
667 RT_TRACE(COMP_POWER
, "MgntActSet_RF_State(): Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n", StateToSet
, ChangeSource
, priv
->RfOffReason
);
670 // Release RF spinlock
671 spin_unlock(&priv
->rf_ps_lock
);
673 RT_TRACE(COMP_POWER
, "<===MgntActSet_RF_State()\n");
674 return bActionAllowed
;