1
/******************************************************************************
2
* Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of version 2 of the GNU General Public License as
6
* published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful, but WITHOUT
9
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13
* You should have received a copy of the GNU General Public License along with
14
* this program; if not, write to the Free Software Foundation, Inc.,
15
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17
* The full GNU General Public License is included in this distribution in the
18
* file called LICENSE.
20
* Contact Information:
21
* wlanfae <wlanfae@realtek.com>
22
******************************************************************************/
25
#include "rtl_rfkill.h"
27
#ifdef CONFIG_RTL_RFKILL
28
static void rtl8192_before_radio_check(struct net_device *dev,
30
bool *turnonbypowerdomain)
32
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
33
PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
35
*rf_state = (priv->rtllib->eRFPowerState != eRfOn);
36
#ifdef CONFIG_ASPM_OR_D3
37
if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM))
40
RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM);
42
else if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3))
45
RT_LEAVE_D3(dev, false);
46
RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3);
50
if (RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC)) {
51
Power_DomainInit92SE(dev);
52
*turnonbypowerdomain = true;
57
static bool rtl8192_radio_on_off_checking(struct net_device *dev)
59
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
64
u1Tmp = read_nic_byte(dev, 0x06);
67
#ifdef CONFIG_BT_COEXIST
68
if (pHalData->bt_coexist.BluetoothCoexist) {
69
if (pHalData->bt_coexist.BT_CoexistType == BT_2Wire) {
70
PlatformEFIOWrite1Byte(pAdapter, MAC_PINMUX_CFG, 0xa);
71
u1Tmp = PlatformEFIORead1Byte(pAdapter, GPIO_IO_SEL);
73
u1Tmp = PlatformEFIORead1Byte(pAdapter, GPIO_IN);
74
RTPRINT(FPWR, PWRHW, ("GPIO_IN=%02x\n", u1Tmp));
75
retval = (u1Tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? eRfOn : eRfOff;
76
} else if ((pHalData->bt_coexist.BT_CoexistType == BT_ISSC_3Wire) ||
77
(pHalData->bt_coexist.BT_CoexistType == BT_Accel) ||
78
(pHalData->bt_coexist.BT_CoexistType == BT_CSR)) {
79
u4tmp = PHY_QueryBBReg(pAdapter, 0x87c, bMaskDWord);
80
if ((u4tmp & BIT17) != 0) {
81
PHY_SetBBReg(pAdapter, 0x87c, bMaskDWord, u4tmp & ~BIT17);
83
RTPRINT(FBT, BT_RFPoll, ("BT write 0x87c (~BIT17) = 0x%x\n", u4tmp &~BIT17));
85
u4tmp = PHY_QueryBBReg(pAdapter, 0x8e0, bMaskDWord);
86
RTPRINT(FBT, BT_RFPoll, ("BT read 0x8e0 (BIT24)= 0x%x\n", u4tmp));
87
retval = (u4tmp & BIT24) ? eRfOn : eRfOff;
88
RTPRINT(FBT, BT_RFPoll, ("BT check RF state to %s\n", (retval==eRfOn)? "ON":"OFF"));
93
write_nic_byte(dev, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO));
94
u1Tmp = read_nic_byte(dev, GPIO_IO_SEL);
96
u1Tmp &= HAL_8192S_HW_GPIO_OFF_MASK;
97
write_nic_byte(dev, GPIO_IO_SEL, u1Tmp);
101
u1Tmp = read_nic_byte(dev, GPIO_IN);
102
gpio = u1Tmp & HAL_8192S_HW_GPIO_OFF_BIT;
107
printk("%s: gpio = %x\n", __FUNCTION__, gpio);
108
if(gpio_test % 5 == 0) {
113
printk("%s: gpio_test = %d, gpio = %x\n", __FUNCTION__, gpio_test++ % 20, gpio);
120
static void rtl8192_after_radio_check(struct net_device *dev, bool rf_state, bool turnonbypowerdomain)
122
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
123
PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl));
125
if (turnonbypowerdomain) {
126
PHY_SetRtl8192seRfHalt(dev);
127
RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
129
#ifdef CONFIG_ASPM_OR_D3
131
if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM) {
133
RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM);
136
else if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3) {
137
RT_ENTER_D3(dev, false);
138
RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3);
146
static bool rtl8192_is_radio_enabled(struct net_device *dev, bool *radio_enabled)
148
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
149
bool rf_state = false;
150
bool turnonbypowerdomain = false;
153
rtl8192_before_radio_check(dev, &rf_state, &turnonbypowerdomain);
154
*radio_enabled = rtl8192_radio_on_off_checking(dev);
155
rtl8192_after_radio_check(dev, rf_state, turnonbypowerdomain);
156
if (priv->bResetInProgress) {
157
priv->RFChangeInProgress = false;
166
bool rtl8192_rfkill_init(struct net_device *dev)
168
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
169
struct wireless_dev *wdev = &priv->rtllib->wdev;
171
bool valid = rtl8192_is_radio_enabled(dev, &radio_enabled);
174
priv->rfkill_off = radio_enabled;
175
printk(KERN_INFO "rtl8192: wireless switch is %s\n",
176
priv->rfkill_off ? "on" : "off");
177
wiphy_rfkill_set_hw_state(wdev->wiphy, !priv->rfkill_off);
178
wiphy_rfkill_start_polling(wdev->wiphy);
185
void rtl8192_rfkill_poll(struct net_device *dev)
187
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
188
struct wireless_dev *wdev = &priv->rtllib->wdev;
192
if (priv->being_init_adapter) {
196
if (priv->ResetProgress == RESET_TYPE_SILENT) {
197
RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF),
198
"%s(): silent Reseting, ignore rf polling!\n", __FUNCTION__);
202
valid = rtl8192_is_radio_enabled(dev, &radio_enabled);
204
if (unlikely(radio_enabled != priv->rfkill_off)) {
205
priv->rfkill_off = radio_enabled;
206
printk(KERN_INFO "rtl8192: wireless radio switch turned %s\n",
207
radio_enabled ? "on" : "off");
208
wiphy_rfkill_set_hw_state(wdev->wiphy, !radio_enabled);
213
void rtl8192_rfkill_exit(struct net_device *dev)
215
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
216
struct wireless_dev *wdev = &priv->rtllib->wdev;
218
wiphy_rfkill_stop_polling(wdev->wiphy);