Wifi:BT: add power toggle control.
authorgwl <gwl@rock-chips.com>
Thu, 10 Apr 2014 01:52:49 +0000 (09:52 +0800)
committergwl <gwl@rock-chips.com>
Thu, 10 Apr 2014 01:52:57 +0000 (09:52 +0800)
arch/arm/boot/dts/rk3288-tb.dts
include/linux/rfkill-bt.h
include/linux/rfkill-wlan.h
net/rfkill/rfkill-bt.c
net/rfkill/rfkill-wlan.c

index 2f92b7ec099bd973bd90bc9c316a9f7011d0c839..b885f6049a28c8bc65669dd4d482cff675bc7328 100755 (executable)
@@ -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>;
index de81161ff3a14aa2f332276cd9619ee2b10e7cf7..4a014b64a92c9a3a2bdbd4a320d2967eeb721c1a 100755 (executable)
@@ -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 */
 
index 8711e8afc050d86df29ea4f2ab11c8ec930dbebb..00be802805ca46a2e13f26a58db9cfa0cd031497 100755 (executable)
@@ -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);
index 90f7918d4480682fa6668006892aeb4ea7b869c0..3728bec3944346f8292d0f60c51cfb1f9da3dad0 100755 (executable)
@@ -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;
index a4b2c02f0856fd18bdfe2f719ef459896465c32d..acc25127d6f711ee30d60094ff729490e5c0985b 100755 (executable)
@@ -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");
                }
     }