]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Bluetooth: hci_ll: Add support for the external clock
authorUlf Hansson <ulf.hansson@linaro.org>
Wed, 7 Jun 2017 09:08:21 +0000 (11:08 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Fri, 9 Jun 2017 05:35:32 +0000 (07:35 +0200)
Add support to manage the external clock provided to the WiLink combo chip
as it's needed for any of the transport interfaces.

To avoid breaking platforms not yet specifying the external clock, we make
it optional. In case the clock is successfully fetched during ->probe(),
let's manage it via the ->open|close() callbacks, to make sure the device
get properly powered on/off.

Fixes: ea452678734e ("arm64: dts: hikey: Fix WiFi support")
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Tested-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
drivers/bluetooth/hci_ll.c

index 1b0487310117fab219c5e27d63eadd6f3723570f..2b16d48d82ee94ed7cf43610b2f3024d43888fa0 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/serdev.h>
 #include <linux/skbuff.h>
 #include <linux/ti_wilink_st.h>
+#include <linux/clk.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
@@ -84,6 +85,7 @@ struct ll_device {
        struct hci_uart hu;
        struct serdev_device *serdev;
        struct gpio_desc *enable_gpio;
+       struct clk *ext_clk;
 };
 
 struct ll_struct {
@@ -146,8 +148,12 @@ static int ll_open(struct hci_uart *hu)
 
        hu->priv = ll;
 
-       if (hu->serdev)
+       if (hu->serdev) {
+               struct ll_device *lldev = serdev_device_get_drvdata(hu->serdev);
                serdev_device_open(hu->serdev);
+               if (!IS_ERR(lldev->ext_clk))
+                       clk_prepare_enable(lldev->ext_clk);
+       }
 
        return 0;
 }
@@ -181,6 +187,8 @@ static int ll_close(struct hci_uart *hu)
                struct ll_device *lldev = serdev_device_get_drvdata(hu->serdev);
                gpiod_set_value_cansleep(lldev->enable_gpio, 0);
 
+               clk_disable_unprepare(lldev->ext_clk);
+
                serdev_device_close(hu->serdev);
        }
 
@@ -721,6 +729,10 @@ static int hci_ti_probe(struct serdev_device *serdev)
        if (IS_ERR(lldev->enable_gpio))
                return PTR_ERR(lldev->enable_gpio);
 
+       lldev->ext_clk = devm_clk_get(&serdev->dev, "ext_clock");
+       if (IS_ERR(lldev->ext_clk) && PTR_ERR(lldev->ext_clk) != -ENOENT)
+               return PTR_ERR(lldev->ext_clk);
+
        of_property_read_u32(serdev->dev.of_node, "max-speed", &max_speed);
        hci_uart_set_speeds(hu, 115200, max_speed);