Wifi:BT: add power toggle control.

This commit is contained in:
gwl
2014-04-10 09:52:49 +08:00
parent c817f7be5e
commit ed7869a3f4
5 changed files with 81 additions and 4 deletions

View File

@@ -28,6 +28,8 @@
wireless-bluetooth {
compatible = "bluetooth-platdata";
//wifi-bt-power-toggle;
uart_rts_gpios = <&gpio4 GPIO_C3 GPIO_ACTIVE_LOW>;
pinctrl-names = "default","rts_gpio";
pinctrl-0 = <&uart0_rts>;

View File

@@ -56,6 +56,7 @@ struct rfkill_rk_irq {
struct rfkill_rk_platform_data {
char *name;
enum rfkill_type type;
bool power_toggle;
struct pinctrl *pinctrl;
struct rfkill_rk_gpio poweron_gpio;
struct rfkill_rk_gpio reset_gpio;
@@ -64,5 +65,7 @@ struct rfkill_rk_platform_data {
struct rfkill_rk_gpio rts_gpio;
};
int rfkill_get_bt_power_state(int *power, bool *toggle);
#endif /* __RFKILL_GPIO_H */

View File

@@ -38,6 +38,7 @@ struct rksdmmc_gpio_wifi_moudle {
struct rksdmmc_gpio GPS_LAN; //pin33--GPS_LAN
};
int rfkill_get_wifi_power_state(int *power);
void *rockchip_mem_prealloc(int section, unsigned long size);
int rockchip_wifi_power(int on);
int rockchip_wifi_set_carddetect(int val);

View File

@@ -24,6 +24,7 @@
#include <asm/gpio.h>
#include <linux/delay.h>
#include <linux/rfkill-bt.h>
#include <linux/rfkill-wlan.h>
#include <linux/wakelock.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
@@ -245,6 +246,22 @@ void rfkill_rk_sleep_bt(bool sleep)
}
EXPORT_SYMBOL(rfkill_rk_sleep_bt);
static int bt_power_state = 0;
int rfkill_get_bt_power_state(int *power, bool *toggle)
{
struct rfkill_rk_data *mrfkill = g_rfkill;
if (mrfkill == NULL) {
LOG("%s: rfkill-bt driver has not Successful initialized\n", __func__);
return -1;
}
*toggle = mrfkill->pdata->power_toggle;
*power = bt_power_state;
return 0;
}
static int rfkill_rk_set_power(void *data, bool blocked)
{
struct rfkill_rk_data *rfkill = data;
@@ -254,11 +271,20 @@ static int rfkill_rk_set_power(void *data, bool blocked)
struct rfkill_rk_gpio* rts = &rfkill->pdata->rts_gpio;
struct pinctrl *pinctrl = rfkill->pdata->pinctrl;
#endif
int power = 0; bool toggle = false;
DBG("Enter %s\n", __func__);
DBG("Set blocked:%d\n", blocked);
toggle = rfkill->pdata->power_toggle;
if (toggle) {
if(!rfkill_get_wifi_power_state(&power) && power == 1) {
LOG("%s: bt shouldn't control the power, it was enabled by wifi!\n", __func__);
return 0;
}
}
if (false == blocked) {
rfkill_rk_sleep_bt(BT_WAKEUP); // ensure bt is wakeup
@@ -287,6 +313,7 @@ static int rfkill_rk_set_power(void *data, bool blocked)
pinctrl_select_state(pinctrl, rts->default_state);
}
#endif
bt_power_state = 1;
LOG("bt turn on power\n");
} else {
if (gpio_is_valid(poweron->io))
@@ -295,6 +322,7 @@ static int rfkill_rk_set_power(void *data, bool blocked)
msleep(20);
}
bt_power_state = 0;
LOG("bt shut off power\n");
if (gpio_is_valid(reset->io))
{
@@ -436,6 +464,13 @@ static int bluetooth_platdata_parse_dt(struct device *dev,
memset(data, 0, sizeof(*data));
if (of_find_property(node, "wifi-bt-power-toggle", NULL)) {
data->power_toggle = true;
LOG("%s: get property wifi-bt-power-toggle.\n");
} else {
data->power_toggle = false;
}
gpio = of_get_named_gpio_flags(node, "uart_rts_gpios", 0, &flags);
if (gpio_is_valid(gpio)) {
data->rts_gpio.io = gpio;

View File

@@ -24,6 +24,7 @@
#include <linux/regulator/consumer.h>
#include <linux/delay.h>
#include <linux/rfkill-wlan.h>
#include <linux/rfkill-bt.h>
#include <linux/wakelock.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
@@ -178,6 +179,26 @@ void *rockchip_mem_prealloc(int section, unsigned long size) { return NULL;}
#endif
EXPORT_SYMBOL(rockchip_mem_prealloc);
/**************************************************************************
*
* get wifi power state Func
*
*************************************************************************/
static int wifi_power_state = 0;
int rfkill_get_wifi_power_state(int *power)
{
struct rfkill_wlan_data *mrfkill = g_rfkill;
if (mrfkill == NULL) {
LOG("%s: rfkill-wlan driver has not Successful initialized\n", __func__);
return -1;
}
*power = wifi_power_state;
return 0;
}
/**************************************************************************
*
* Wifi Power Control Func
@@ -190,6 +211,8 @@ int rockchip_wifi_power(int on)
struct rfkill_wlan_data *mrfkill = g_rfkill;
struct rksdmmc_gpio *poweron, *reset;
struct regulator *ldo = NULL;
int power = 0;
bool toggle = false;
LOG("%s: %d\n", __func__, on);
@@ -198,6 +221,13 @@ int rockchip_wifi_power(int on)
return -1;
}
if(!rfkill_get_bt_power_state(&power, &toggle)) {
if (toggle == true && power == 1) {
LOG("%s: wifi shouldn't control the power, it was enabled by BT!\n", __func__);
return 0;
}
}
if (mrfkill->pdata->mregulator.power_ctrl_by_pmu) {
char *ldostr;
int ret = -1;
@@ -218,15 +248,19 @@ int rockchip_wifi_power(int on)
ret = regulator_enable(ldo);
if(ret != 0){
LOG("%s: faild to enable %s\n", __func__, ldostr);
}
LOG("wifi turn on power.\n");
} else {
wifi_power_state = 1;
LOG("wifi turn on power.\n");
}
} else {
LOG("wifi shut off power.\n");
LOG("%s: %s disabled\n", __func__, ldostr);
ret = regulator_disable(ldo);
if(ret != 0){
LOG("%s: faild to disable %s\n", __func__, ldostr);
}
} else {
wifi_power_state = 0;
LOG("wifi shut off power.\n");
}
}
regulator_put(ldo);
msleep(100);
@@ -246,6 +280,7 @@ int rockchip_wifi_power(int on)
msleep(100);
}
wifi_power_state = 1;
LOG("wifi turn on power. %d\n", poweron->io);
}else{
if (gpio_is_valid(poweron->io)) {
@@ -257,6 +292,7 @@ int rockchip_wifi_power(int on)
gpio_set_value(reset->io, !(reset->enable));
}
wifi_power_state = 0;
LOG("wifi shut off power.\n");
}
}