]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
Bluetooth: btusb: Configure Marvell to use one of the pins for oob wakeup
authorRajat Jain <rajatja@google.com>
Wed, 1 Feb 2017 22:24:10 +0000 (14:24 -0800)
committerMarcel Holtmann <marcel@holtmann.org>
Thu, 16 Feb 2017 16:21:59 +0000 (17:21 +0100)
The Marvell devices may have many gpio pins, and hence for wakeup
on these out-of-band pins, the chip needs to be told which pin is
to be used for wakeup, using an hci command.

Thus, we read the pin number etc from the device tree node and send
a command to the chip.

Signed-off-by: Rajat Jain <rajatja@google.com>
Reviewed-by: Brian Norris <briannorris@chromium.org>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Documentation/devicetree/bindings/net/btusb.txt
Documentation/devicetree/bindings/net/marvell-bt-8xxx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/marvell-bt-sd8xxx.txt [deleted file]
drivers/bluetooth/btusb.c

index 2c0355c859723418ecd57f291dfd672804e1cdc4..01fa2d4188d4a90048258229a9433792f1078b28 100644 (file)
@@ -10,6 +10,9 @@ Required properties:
 
                  "usb1286,204e" (Marvell 8997)
 
+Also, vendors that use btusb may have device additional properties, e.g:
+Documentation/devicetree/bindings/net/marvell-bt-8xxx.txt
+
 Optional properties:
 
   - interrupt-parent: phandle of the parent interrupt controller
diff --git a/Documentation/devicetree/bindings/net/marvell-bt-8xxx.txt b/Documentation/devicetree/bindings/net/marvell-bt-8xxx.txt
new file mode 100644 (file)
index 0000000..9be1059
--- /dev/null
@@ -0,0 +1,86 @@
+Marvell 8897/8997 (sd8897/sd8997) bluetooth devices (SDIO or USB based)
+------
+The 8997 devices supports multiple interfaces. When used on SDIO interfaces,
+the btmrvl driver is used and when used on USB interface, the btusb driver is
+used.
+
+Required properties:
+
+  - compatible : should be one of the following:
+       * "marvell,sd8897-bt" (for SDIO)
+       * "marvell,sd8997-bt" (for SDIO)
+       * "usb1286,204e"      (for USB)
+
+Optional properties:
+
+  - marvell,cal-data: Calibration data downloaded to the device during
+                     initialization. This is an array of 28 values(u8).
+                     This is only applicable to SDIO devices.
+
+  - marvell,wakeup-pin: It represents wakeup pin number of the bluetooth chip.
+                       firmware will use the pin to wakeup host system (u16).
+  - marvell,wakeup-gap-ms: wakeup gap represents wakeup latency of the host
+                     platform. The value will be configured to firmware. This
+                     is needed to work chip's sleep feature as expected (u16).
+  - interrupt-parent: phandle of the parent interrupt controller
+  - interrupt-names: Used only for USB based devices (See below)
+  - interrupts : specifies the interrupt pin number to the cpu. For SDIO, the
+                driver will use the first interrupt specified in the interrupt
+                array. For USB based devices, the driver will use the interrupt
+                named "wakeup" from the interrupt-names and interrupt arrays.
+                The driver will request an irq based on this interrupt number.
+                During system suspend, the irq will be enabled so that the
+                bluetooth chip can wakeup host platform under certain
+                conditions. During system resume, the irq will be disabled
+                to make sure unnecessary interrupt is not received.
+
+Example:
+
+IRQ pin 119 is used as system wakeup source interrupt.
+wakeup pin 13 and gap 100ms are configured so that firmware can wakeup host
+using this device side pin and wakeup latency.
+
+Example for SDIO device follows (calibration data is also available in
+below example).
+
+&mmc3 {
+       status = "okay";
+       vmmc-supply = <&wlan_en_reg>;
+       bus-width = <4>;
+       cap-power-off-card;
+       keep-power-in-suspend;
+
+       #address-cells = <1>;
+       #size-cells = <0>;
+       btmrvl: bluetooth@2 {
+               compatible = "marvell,sd8897-bt";
+               reg = <2>;
+               interrupt-parent = <&pio>;
+               interrupts = <119 IRQ_TYPE_LEVEL_LOW>;
+
+               marvell,cal-data = /bits/ 8 <
+                       0x37 0x01 0x1c 0x00 0xff 0xff 0xff 0xff 0x01 0x7f 0x04 0x02
+                       0x00 0x00 0xba 0xce 0xc0 0xc6 0x2d 0x00 0x00 0x00 0x00 0x00
+                       0x00 0x00 0xf0 0x00>;
+               marvell,wakeup-pin = /bits/ 16 <0x0d>;
+               marvell,wakeup-gap-ms = /bits/ 16 <0x64>;
+       };
+};
+
+Example for USB device:
+
+&usb_host1_ohci {
+    status = "okay";
+    #address-cells = <1>;
+    #size-cells = <0>;
+
+    mvl_bt1: bt@1 {
+       compatible = "usb1286,204e";
+       reg = <1>;
+       interrupt-parent = <&gpio0>;
+       interrupt-names = "wakeup";
+       interrupts = <119 IRQ_TYPE_LEVEL_LOW>;
+       marvell,wakeup-pin = /bits/ 16 <0x0d>;
+       marvell,wakeup-gap-ms = /bits/ 16 <0x64>;
+    };
+};
diff --git a/Documentation/devicetree/bindings/net/marvell-bt-sd8xxx.txt b/Documentation/devicetree/bindings/net/marvell-bt-sd8xxx.txt
deleted file mode 100644 (file)
index 6a9a63c..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-Marvell 8897/8997 (sd8897/sd8997) bluetooth SDIO devices
-------
-
-Required properties:
-
-  - compatible : should be one of the following:
-       * "marvell,sd8897-bt"
-       * "marvell,sd8997-bt"
-
-Optional properties:
-
-  - marvell,cal-data: Calibration data downloaded to the device during
-                     initialization. This is an array of 28 values(u8).
-
-  - marvell,wakeup-pin: It represents wakeup pin number of the bluetooth chip.
-                       firmware will use the pin to wakeup host system (u16).
-  - marvell,wakeup-gap-ms: wakeup gap represents wakeup latency of the host
-                     platform. The value will be configured to firmware. This
-                     is needed to work chip's sleep feature as expected (u16).
-  - interrupt-parent: phandle of the parent interrupt controller
-  - interrupts : interrupt pin number to the cpu. Driver will request an irq based
-                on this interrupt number. During system suspend, the irq will be
-                enabled so that the bluetooth chip can wakeup host platform under
-                certain condition. During system resume, the irq will be disabled
-                to make sure unnecessary interrupt is not received.
-
-Example:
-
-IRQ pin 119 is used as system wakeup source interrupt.
-wakeup pin 13 and gap 100ms are configured so that firmware can wakeup host
-using this device side pin and wakeup latency.
-calibration data is also available in below example.
-
-&mmc3 {
-       status = "okay";
-       vmmc-supply = <&wlan_en_reg>;
-       bus-width = <4>;
-       cap-power-off-card;
-       keep-power-in-suspend;
-
-       #address-cells = <1>;
-       #size-cells = <0>;
-       btmrvl: bluetooth@2 {
-               compatible = "marvell,sd8897-bt";
-               reg = <2>;
-               interrupt-parent = <&pio>;
-               interrupts = <119 IRQ_TYPE_LEVEL_LOW>;
-
-               marvell,cal-data = /bits/ 8 <
-                       0x37 0x01 0x1c 0x00 0xff 0xff 0xff 0xff 0x01 0x7f 0x04 0x02
-                       0x00 0x00 0xba 0xce 0xc0 0xc6 0x2d 0x00 0x00 0x00 0x00 0x00
-                       0x00 0x00 0xf0 0x00>;
-               marvell,wakeup-pin = /bits/ 16 <0x0d>;
-               marvell,wakeup-gap-ms = /bits/ 16 <0x64>;
-       };
-};
index f6bf990ccaeb1377603ab029c6eb5fcdfe0b8f1d..362361f08fbd0cc7e685bec3931701d72a7dd1b2 100644 (file)
@@ -2347,6 +2347,50 @@ static int btusb_shutdown_intel(struct hci_dev *hdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+/* Configure an out-of-band gpio as wake-up pin, if specified in device tree */
+static int marvell_config_oob_wake(struct hci_dev *hdev)
+{
+       struct sk_buff *skb;
+       struct btusb_data *data = hci_get_drvdata(hdev);
+       struct device *dev = &data->udev->dev;
+       u16 pin, gap, opcode;
+       int ret;
+       u8 cmd[5];
+
+       /* Move on if no wakeup pin specified */
+       if (of_property_read_u16(dev->of_node, "marvell,wakeup-pin", &pin) ||
+           of_property_read_u16(dev->of_node, "marvell,wakeup-gap-ms", &gap))
+               return 0;
+
+       /* Vendor specific command to configure a GPIO as wake-up pin */
+       opcode = hci_opcode_pack(0x3F, 0x59);
+       cmd[0] = opcode & 0xFF;
+       cmd[1] = opcode >> 8;
+       cmd[2] = 2; /* length of parameters that follow */
+       cmd[3] = pin;
+       cmd[4] = gap; /* time in ms, for which wakeup pin should be asserted */
+
+       skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
+       if (!skb) {
+               bt_dev_err(hdev, "%s: No memory\n", __func__);
+               return -ENOMEM;
+       }
+
+       memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd));
+       hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
+
+       ret = btusb_send_frame(hdev, skb);
+       if (ret) {
+               bt_dev_err(hdev, "%s: configuration failed\n", __func__);
+               kfree_skb(skb);
+               return ret;
+       }
+
+       return 0;
+}
+#endif
+
 static int btusb_set_bdaddr_marvell(struct hci_dev *hdev,
                                    const bdaddr_t *bdaddr)
 {
@@ -2922,6 +2966,13 @@ static int btusb_probe(struct usb_interface *intf,
        err = btusb_config_oob_wake(hdev);
        if (err)
                goto out_free_dev;
+
+       /* Marvell devices may need a specific chip configuration */
+       if (id->driver_info & BTUSB_MARVELL && data->oob_wake_irq) {
+               err = marvell_config_oob_wake(hdev);
+               if (err)
+                       goto out_free_dev;
+       }
 #endif
        if (id->driver_info & BTUSB_CW6622)
                set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);