ARM64: DTS: Add rk3399-firefly uart4 device, node as /dev/ttyS1
[firefly-linux-kernel-4.4.55.git] / net / rfkill / rfkill-bt.c
old mode 100755 (executable)
new mode 100644 (file)
index 06c666a..332eb47
@@ -21,9 +21,9 @@
 #include <linux/rfkill.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#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>
@@ -31,6 +31,7 @@
 #include <linux/proc_fs.h>
 #include <linux/uaccess.h>
 #include <linux/gpio.h>
+#include <linux/fs.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <uapi/linux/rfkill.h>
 #ifdef CONFIG_OF
@@ -244,21 +245,49 @@ 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;
     struct rfkill_rk_gpio *poweron = &rfkill->pdata->poweron_gpio;
     struct rfkill_rk_gpio *reset = &rfkill->pdata->reset_gpio;
-#if defined(CONFIG_AP6210) || defined(CONFIG_AP6335)
     struct rfkill_rk_gpio* rts = &rfkill->pdata->rts_gpio;
     struct pinctrl *pinctrl = rfkill->pdata->pinctrl;
-#endif
+    int power = 0, vref_ctrl_enable = 0;
+    bool toggle = false;
 
     DBG("Enter %s\n", __func__);
 
     DBG("Set blocked:%d\n", blocked);
 
+    toggle = rfkill->pdata->power_toggle;
+    if (!rfkill_get_wifi_power_state(&power, &vref_ctrl_enable)) {
+        if (true == toggle && 1 == power) {
+            LOG("%s: bt shouldn't control the power, it was enabled by wifi!\n", __func__);
+            return 0;
+        }
+    } else {
+        LOG("%s: cannot get wifi power state!\n", __func__);
+        return -1;
+    }
+
        if (false == blocked) { 
+
         rfkill_rk_sleep_bt(BT_WAKEUP); // ensure bt is wakeup
 
                if (gpio_is_valid(poweron->io))
@@ -274,7 +303,7 @@ static int rfkill_rk_set_power(void *data, bool blocked)
             msleep(20);
                        gpio_direction_output(reset->io, reset->enable);
         }
-#if defined(CONFIG_AP6210) || defined(CONFIG_AP6335)
+
         if (pinctrl != NULL && gpio_is_valid(rts->io))
         {
             pinctrl_select_state(pinctrl, rts->gpio_state);
@@ -285,7 +314,8 @@ static int rfkill_rk_set_power(void *data, bool blocked)
             gpio_direction_output(rts->io, !rts->enable);
             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))
@@ -294,12 +324,14 @@ 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))
         {      
                        gpio_direction_output(reset->io, !reset->enable);/* bt reset active*/
             msleep(20);
         }
+
        }
 
        return 0;
@@ -384,28 +416,29 @@ static const struct rfkill_ops rfkill_rk_ops = {
 
 static struct proc_dir_entry *bluetooth_dir, *sleep_dir;
 
-static int bluesleep_read_proc_lpm(char *page, char **start, off_t offset,
-                                       int count, int *eof, void *data)
+static ssize_t bluesleep_read_proc_lpm(struct file *file, char __user *buffer,
+                                      size_t count, loff_t *data)
 {
-    *eof = 1;
-    return sprintf(page, "unsupported to read\n");
+    return sprintf(buffer, "unsupported to read\n");
 }
 
-static int bluesleep_write_proc_lpm(struct file *file, const char *buffer,
-                                       unsigned long count, void *data)
+static ssize_t bluesleep_write_proc_lpm(struct file *file,
+                                       const char __user *buffer,
+                                       size_t count, loff_t *data)
 {
     return count;
 }
 
-static int bluesleep_read_proc_btwrite(char *page, char **start, off_t offset,
-                                       int count, int *eof, void *data)
+static ssize_t bluesleep_read_proc_btwrite(struct file *file,
+                                          char __user *buffer,
+                                          size_t count, loff_t *data)
 {
-    *eof = 1;
-    return sprintf(page, "unsupported to read\n");
+    return sprintf(buffer, "unsupported to read\n");
 }
 
-static int bluesleep_write_proc_btwrite(struct file *file, const char *buffer,
-                                       unsigned long count, void *data)
+static ssize_t bluesleep_write_proc_btwrite(struct file *file,
+                                           const char __user *buffer,
+                                           size_t count, loff_t *data)
 {
     char b;
 
@@ -437,6 +470,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", __func__);
+    } 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;
@@ -462,27 +502,33 @@ static int bluetooth_platdata_parse_dt(struct device *dev,
         data->poweron_gpio.io = gpio;
         data->poweron_gpio.enable = (flags == GPIO_ACTIVE_HIGH)? 1:0;
         LOG("%s: get property: BT,power_gpio = %d.\n", __func__, gpio);
-    }
+    } else data->poweron_gpio.io = -1;
     gpio = of_get_named_gpio_flags(node, "BT,reset_gpio", 0, &flags);
     if (gpio_is_valid(gpio)){
         data->reset_gpio.io = gpio;
         data->reset_gpio.enable = (flags == GPIO_ACTIVE_HIGH)? 1:0;
         LOG("%s: get property: BT,reset_gpio = %d.\n", __func__, gpio);
-    }
+    } else data->reset_gpio.io = -1;
     gpio = of_get_named_gpio_flags(node, "BT,wake_gpio", 0, &flags);
     if (gpio_is_valid(gpio)){
         data->wake_gpio.io = gpio;
         data->wake_gpio.enable = (flags == GPIO_ACTIVE_HIGH)? 1:0;
         LOG("%s: get property: BT,wake_gpio = %d.\n", __func__, gpio);
-    }
+    } else data->wake_gpio.io = -1;
     gpio = of_get_named_gpio_flags(node, "BT,wake_host_irq", 0, &flags);
     if (gpio_is_valid(gpio)) {
         data->wake_host_irq.gpio.io = gpio;
         data->wake_host_irq.gpio.enable = flags;
         LOG("%s: get property: BT,wake_host_irq = %d.\n", __func__, gpio);
-    }
+    } else data->wake_host_irq.gpio.io = -1;
 
-    return 0;
+       data->ext_clk = devm_clk_get(dev, "ext_clock");
+       if (IS_ERR(data->ext_clk)) {
+               LOG("%s: clk_get failed!!!.\n", __func__);
+       } else {
+               clk_prepare_enable(data->ext_clk);
+       }
+       return 0;
 }
 #endif //CONFIG_OF
 
@@ -527,10 +573,8 @@ static int rfkill_rk_probe(struct platform_device *pdev)
     pdata->type = RFKILL_TYPE_BLUETOOTH;
 
        rfkill = devm_kzalloc(&pdev->dev, sizeof(*rfkill), GFP_KERNEL);
-       if (!rfkill) {
-        kfree(pdata);
+       if (!rfkill)
                return -ENOMEM;
-    }
 
        rfkill->pdata = pdata;
     rfkill->pdev = pdev;
@@ -575,10 +619,12 @@ static int rfkill_rk_probe(struct platform_device *pdev)
     ret = rfkill_rk_setup_gpio(pdev, &pdata->wake_gpio, pdata->name, "wake");
     if (ret) goto fail_gpio;
 
-    ret = rfkill_rk_setup_wake_irq(rfkill);
+    ret = rfkill_rk_setup_gpio(pdev, &pdata->rts_gpio, rfkill->pdata->name, "rts"); 
     if (ret) goto fail_gpio;
 
-    ret = rfkill_rk_setup_gpio(pdev, &pdata->rts_gpio, rfkill->pdata->name, "rts"); 
+    wake_lock_init(&(rfkill->bt_irq_wl), WAKE_LOCK_SUSPEND, "rfkill_rk_irq_wl");
+
+    ret = rfkill_rk_setup_wake_irq(rfkill);
     if (ret) goto fail_gpio;
 
     DBG("setup rfkill\n");
@@ -592,7 +638,6 @@ static int rfkill_rk_probe(struct platform_device *pdev)
        if (ret < 0)
                goto fail_rfkill;
 
-    wake_lock_init(&(rfkill->bt_irq_wl), WAKE_LOCK_SUSPEND, "rfkill_rk_irq_wl");
     INIT_DELAYED_WORK(&rfkill->bt_sleep_delay_work, rfkill_rk_delay_sleep_bt);
 
     //rfkill_rk_set_power(rfkill, BT_BLOCKED);
@@ -615,12 +660,12 @@ static int rfkill_rk_probe(struct platform_device *pdev)
 fail_rfkill:
        rfkill_destroy(rfkill->rfkill_dev);
 fail_alloc:
-    g_rfkill = NULL;
 
        remove_proc_entry("btwrite", sleep_dir);
        remove_proc_entry("lpm", sleep_dir);
 fail_gpio:
 
+        g_rfkill = NULL;
        return ret;
 }
 
@@ -657,8 +702,7 @@ static int rfkill_rk_remove(struct platform_device *pdev)
     
     if (gpio_is_valid(rfkill->pdata->poweron_gpio.io))
         gpio_free(rfkill->pdata->poweron_gpio.io);
-
-    kfree(rfkill);
+       clk_disable_unprepare(rfkill->pdata->ext_clk);
     g_rfkill = NULL;
 
        return 0;