diff --git a/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt b/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt new file mode 100644 index 0000000000000000000000000000000000000000..4194ff7e6ee678181f18b9cf1b9dc3e90bf93abb --- /dev/null +++ b/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt @@ -0,0 +1,35 @@ +Broadcom Bluetooth Chips +--------------------- + +This documents the binding structure and common properties for serial +attached Broadcom devices. + +Serial attached Broadcom devices shall be a child node of the host UART +device the slave device is attached to. + +Required properties: + + - compatible: should contain one of the following: + * "brcm,bcm43438-bt" + +Optional properties: + + - max-speed: see Documentation/devicetree/bindings/serial/slave-device.txt + - shutdown-gpios: GPIO specifier, used to enable the BT module + - device-wakeup-gpios: GPIO specifier, used to wakeup the controller + - host-wakeup-gpios: GPIO specifier, used to wakeup the host processor + - clocks: clock specifier if external clock provided to the controller + - clock-names: should be "extclk" + + +Example: + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = <921600>; + }; +}; diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 3a6ead603e492e4a150e8fa6b1add11526154fb1..fae5a74dc737cbd1841c10498708793d9562b93e 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -168,6 +168,7 @@ config BT_HCIUART_INTEL config BT_HCIUART_BCM bool "Broadcom protocol support" depends on BT_HCIUART + depends on BT_HCIUART_SERDEV select BT_HCIUART_H4 select BT_BCM help diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index d4b0b655dde6b8b7c2d064d2635884a47b97be41..b07ca9565291fb504ad8b9ea8955ac176cf2f913 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -93,6 +93,7 @@ static void bluecard_detach(struct pcmcia_device *p_dev); /* Hardware states */ #define CARD_READY 1 +#define CARD_ACTIVITY 2 #define CARD_HAS_PCCARD_ID 4 #define CARD_HAS_POWER_LED 5 #define CARD_HAS_ACTIVITY_LED 6 @@ -160,16 +161,14 @@ static void bluecard_activity_led_timeout(u_long arg) struct bluecard_info *info = (struct bluecard_info *)arg; unsigned int iobase = info->p_dev->resource[0]->start; - if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) - return; - - if (test_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state))) { - /* Disable activity LED */ - outb(0x08 | 0x20, iobase + 0x30); - } else { - /* Disable power LED */ - outb(0x00, iobase + 0x30); + if (test_bit(CARD_ACTIVITY, &(info->hw_state))) { + /* leave LED in inactive state for HZ/10 for blink effect */ + clear_bit(CARD_ACTIVITY, &(info->hw_state)); + mod_timer(&(info->timer), jiffies + HZ / 10); } + + /* Disable activity LED, enable power LED */ + outb(0x08 | 0x20, iobase + 0x30); } @@ -177,22 +176,22 @@ static void bluecard_enable_activity_led(struct bluecard_info *info) { unsigned int iobase = info->p_dev->resource[0]->start; - if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) + /* don't disturb running blink timer */ + if (timer_pending(&(info->timer))) return; - if (test_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state))) { - /* Enable activity LED */ - outb(0x10 | 0x40, iobase + 0x30); + set_bit(CARD_ACTIVITY, &(info->hw_state)); - /* Stop the LED after HZ/4 */ - mod_timer(&(info->timer), jiffies + HZ / 4); + if (test_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state))) { + /* Enable activity LED, keep power LED enabled */ + outb(0x18 | 0x60, iobase + 0x30); } else { - /* Enable power LED */ - outb(0x08 | 0x20, iobase + 0x30); - - /* Stop the LED after HZ/2 */ - mod_timer(&(info->timer), jiffies + HZ / 2); + /* Disable power LED */ + outb(0x00, iobase + 0x30); } + + /* Stop the LED after HZ/10 */ + mod_timer(&(info->timer), jiffies + HZ / 10); } @@ -625,16 +624,13 @@ static int bluecard_hci_flush(struct hci_dev *hdev) static int bluecard_hci_open(struct hci_dev *hdev) { struct bluecard_info *info = hci_get_drvdata(hdev); + unsigned int iobase = info->p_dev->resource[0]->start; if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE); - if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) { - unsigned int iobase = info->p_dev->resource[0]->start; - - /* Enable LED */ - outb(0x08 | 0x20, iobase + 0x30); - } + /* Enable power LED */ + outb(0x08 | 0x20, iobase + 0x30); return 0; } @@ -643,15 +639,15 @@ static int bluecard_hci_open(struct hci_dev *hdev) static int bluecard_hci_close(struct hci_dev *hdev) { struct bluecard_info *info = hci_get_drvdata(hdev); + unsigned int iobase = info->p_dev->resource[0]->start; bluecard_hci_flush(hdev); - if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) { - unsigned int iobase = info->p_dev->resource[0]->start; + /* Stop LED timer */ + del_timer_sync(&(info->timer)); - /* Disable LED */ - outb(0x00, iobase + 0x30); - } + /* Disable power LED */ + outb(0x00, iobase + 0x30); return 0; } diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c index 9ab6cfbb831d81b8f533b35bd4b27161a6f5ef76..cc4bdefa6648b8776b12c7e3f3587d5ecc46aad0 100644 --- a/drivers/bluetooth/btbcm.c +++ b/drivers/bluetooth/btbcm.c @@ -287,6 +287,37 @@ static struct sk_buff *btbcm_read_usb_product(struct hci_dev *hdev) return skb; } +static int btbcm_read_info(struct hci_dev *hdev) +{ + struct sk_buff *skb; + + /* Read Verbose Config Version Info */ + skb = btbcm_read_verbose_config(hdev); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]); + kfree_skb(skb); + + /* Read Controller Features */ + skb = btbcm_read_controller_features(hdev); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + BT_INFO("%s: BCM: features 0x%2.2x", hdev->name, skb->data[1]); + kfree_skb(skb); + + /* Read Local Name */ + skb = btbcm_read_local_name(hdev); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1)); + kfree_skb(skb); + + return 0; +} + static const struct { u16 subver; const char *name; @@ -322,13 +353,10 @@ int btbcm_initialize(struct hci_dev *hdev, char *fw_name, size_t len) subver = le16_to_cpu(ver->lmp_subver); kfree_skb(skb); - /* Read Verbose Config Version Info */ - skb = btbcm_read_verbose_config(hdev); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]); - kfree_skb(skb); + /* Read controller information */ + err = btbcm_read_info(hdev); + if (err) + return err; switch ((rev & 0xf000) >> 12) { case 0: @@ -431,29 +459,10 @@ int btbcm_setup_patchram(struct hci_dev *hdev) subver = le16_to_cpu(ver->lmp_subver); kfree_skb(skb); - /* Read Verbose Config Version Info */ - skb = btbcm_read_verbose_config(hdev); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - BT_INFO("%s: BCM: chip id %u", hdev->name, skb->data[1]); - kfree_skb(skb); - - /* Read Controller Features */ - skb = btbcm_read_controller_features(hdev); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - BT_INFO("%s: BCM: features 0x%2.2x", hdev->name, skb->data[1]); - kfree_skb(skb); - - /* Read Local Name */ - skb = btbcm_read_local_name(hdev); - if (IS_ERR(skb)) - return PTR_ERR(skb); - - BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1)); - kfree_skb(skb); + /* Read controller information */ + err = btbcm_read_info(hdev); + if (err) + return err; switch ((rev & 0xf000) >> 12) { case 0: diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 24cc8383fdd439d299d59b7848f279772a535446..7a5c06aaa18106e11f5963da2d8add0ff89c9669 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -66,6 +66,7 @@ static struct usb_driver btusb_driver; #define BTUSB_BCM2045 0x40000 #define BTUSB_IFNUM_2 0x80000 #define BTUSB_CW6622 0x100000 +#define BTUSB_BCM_NO_PRODID 0x200000 static const struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ @@ -170,6 +171,10 @@ static const struct usb_device_id btusb_table[] = { { USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01), .driver_info = BTUSB_BCM_PATCHRAM }, + /* Broadcom devices with missing product id */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0000, 0x0000, 0xff, 0x01, 0x01), + .driver_info = BTUSB_BCM_PATCHRAM | BTUSB_BCM_NO_PRODID }, + /* Intel Bluetooth USB Bootloader (RAM module) */ { USB_DEVICE(0x8087, 0x0a5a), .driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC }, @@ -359,6 +364,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x13d3, 0x3410), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3416), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK }, + { USB_DEVICE(0x13d3, 0x3494), .driver_info = BTUSB_REALTEK }, /* Additional Realtek 8821AE Bluetooth devices */ { USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK }, @@ -1082,6 +1088,10 @@ static int btusb_open(struct hci_dev *hdev) } data->intf->needs_remote_wakeup = 1; + /* device specific wakeup source enabled and required for USB + * remote wakeup while host is suspended + */ + device_wakeup_enable(&data->udev->dev); if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags)) goto done; @@ -1145,6 +1155,7 @@ static int btusb_close(struct hci_dev *hdev) goto failed; data->intf->needs_remote_wakeup = 0; + device_wakeup_disable(&data->udev->dev); usb_autopm_put_interface(data->intf); failed: @@ -2898,6 +2909,19 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info == BTUSB_IGNORE) return -ENODEV; + if (id->driver_info & BTUSB_BCM_NO_PRODID) { + struct usb_device *udev = interface_to_usbdev(intf); + + /* For the broken Broadcom devices that show 0000:0000 + * as USB vendor and product information, check that the + * manufacturer string identifies them as Broadcom based + * devices. + */ + if (!udev->manufacturer || + strcmp(udev->manufacturer, "Broadcom Corp")) + return -ENODEV; + } + if (id->driver_info & BTUSB_ATH3012) { struct usb_device *udev = interface_to_usbdev(intf); diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 6b42372c53efb52ca5a8cf37f4e8c5363145b332..e2540113d0dac122463a92053cd4564c3cb09ef5 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -34,6 +36,7 @@ #include #include #include +#include #include #include @@ -41,11 +44,15 @@ #include "btbcm.h" #include "hci_uart.h" +#define BCM_NULL_PKT 0x00 +#define BCM_NULL_SIZE 0 + #define BCM_LM_DIAG_PKT 0x07 #define BCM_LM_DIAG_SIZE 63 #define BCM_AUTOSUSPEND_DELAY 5000 /* default autosleep delay */ +/* platform device driver resources */ struct bcm_device { struct list_head list; @@ -59,6 +66,7 @@ struct bcm_device { bool clk_enabled; u32 init_speed; + u32 oper_speed; int irq; u8 irq_polarity; @@ -68,6 +76,12 @@ struct bcm_device { #endif }; +/* serdev driver resources */ +struct bcm_serdev { + struct hci_uart hu; +}; + +/* generic bcm uart resources */ struct bcm_data { struct sk_buff *rx_skb; struct sk_buff_head txq; @@ -79,6 +93,14 @@ struct bcm_data { static DEFINE_MUTEX(bcm_device_lock); static LIST_HEAD(bcm_device_list); +static inline void host_set_baudrate(struct hci_uart *hu, unsigned int speed) +{ + if (hu->serdev) + serdev_device_set_baudrate(hu->serdev, speed); + else + hci_uart_set_baudrate(hu, speed); +} + static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed) { struct hci_dev *hdev = hu->hdev; @@ -289,6 +311,14 @@ static int bcm_open(struct hci_uart *hu) hu->priv = bcm; + /* If this is a serdev defined device, then only use + * serdev open primitive and skip the rest. + */ + if (hu->serdev) { + serdev_device_open(hu->serdev); + goto out; + } + if (!hu->tty->dev) goto out; @@ -303,6 +333,7 @@ static int bcm_open(struct hci_uart *hu) if (hu->tty->dev->parent == dev->pdev->dev.parent) { bcm->dev = dev; hu->init_speed = dev->init_speed; + hu->oper_speed = dev->oper_speed; #ifdef CONFIG_PM dev->hu = hu; #endif @@ -323,6 +354,12 @@ static int bcm_close(struct hci_uart *hu) bt_dev_dbg(hu->hdev, "hu %p", hu); + /* If this is a serdev defined device, only use serdev + * close primitive and then continue as usual. + */ + if (hu->serdev) + serdev_device_close(hu->serdev); + /* Protect bcm->dev against removal of the device or driver */ mutex_lock(&bcm_device_lock); if (bcm_device_exists(bdev)) { @@ -398,7 +435,7 @@ static int bcm_setup(struct hci_uart *hu) speed = 0; if (speed) - hci_uart_set_baudrate(hu, speed); + host_set_baudrate(hu, speed); /* Operational speed if any */ if (hu->oper_speed) @@ -411,7 +448,7 @@ static int bcm_setup(struct hci_uart *hu) if (speed) { err = bcm_set_baudrate(hu, speed); if (!err) - hci_uart_set_baudrate(hu, speed); + host_set_baudrate(hu, speed); } finalize: @@ -434,11 +471,19 @@ static int bcm_setup(struct hci_uart *hu) .lsize = 0, \ .maxlen = BCM_LM_DIAG_SIZE +#define BCM_RECV_NULL \ + .type = BCM_NULL_PKT, \ + .hlen = BCM_NULL_SIZE, \ + .loff = 0, \ + .lsize = 0, \ + .maxlen = BCM_NULL_SIZE + static const struct h4_recv_pkt bcm_recv_pkts[] = { { H4_RECV_ACL, .recv = hci_recv_frame }, { H4_RECV_SCO, .recv = hci_recv_frame }, { H4_RECV_EVENT, .recv = hci_recv_frame }, { BCM_RECV_LM_DIAG, .recv = hci_recv_diag }, + { BCM_RECV_NULL, .recv = hci_recv_diag }, }; static int bcm_recv(struct hci_uart *hu, const void *data, int count) @@ -699,8 +744,10 @@ static int bcm_resource(struct acpi_resource *ares, void *data) case ACPI_RESOURCE_TYPE_SERIAL_BUS: sb = &ares->data.uart_serial_bus; - if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_UART) + if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_UART) { dev->init_speed = sb->default_baud_rate; + dev->oper_speed = 4000000; + } break; default: @@ -853,7 +900,6 @@ static const struct hci_uart_proto bcm_proto = { .name = "Broadcom", .manufacturer = 15, .init_speed = 115200, - .oper_speed = 4000000, .open = bcm_open, .close = bcm_close, .flush = bcm_flush, @@ -903,9 +949,57 @@ static struct platform_driver bcm_driver = { }, }; +static int bcm_serdev_probe(struct serdev_device *serdev) +{ + struct bcm_serdev *bcmdev; + u32 speed; + int err; + + bcmdev = devm_kzalloc(&serdev->dev, sizeof(*bcmdev), GFP_KERNEL); + if (!bcmdev) + return -ENOMEM; + + bcmdev->hu.serdev = serdev; + serdev_device_set_drvdata(serdev, bcmdev); + + err = device_property_read_u32(&serdev->dev, "max-speed", &speed); + if (!err) + bcmdev->hu.oper_speed = speed; + + return hci_uart_register_device(&bcmdev->hu, &bcm_proto); +} + +static void bcm_serdev_remove(struct serdev_device *serdev) +{ + struct bcm_serdev *bcmdev = serdev_device_get_drvdata(serdev); + + hci_uart_unregister_device(&bcmdev->hu); +} + +#ifdef CONFIG_OF +static const struct of_device_id bcm_bluetooth_of_match[] = { + { .compatible = "brcm,bcm43438-bt" }, + { }, +}; +MODULE_DEVICE_TABLE(of, bcm_bluetooth_of_match); +#endif + +static struct serdev_device_driver bcm_serdev_driver = { + .probe = bcm_serdev_probe, + .remove = bcm_serdev_remove, + .driver = { + .name = "hci_uart_bcm", + .of_match_table = of_match_ptr(bcm_bluetooth_of_match), + }, +}; + int __init bcm_init(void) { + /* For now, we need to keep both platform device + * driver (ACPI generated) and serdev driver (DT). + */ platform_driver_register(&bcm_driver); + serdev_device_driver_register(&bcm_serdev_driver); return hci_uart_register_proto(&bcm_proto); } @@ -913,6 +1007,7 @@ int __init bcm_init(void) int __exit bcm_deinit(void) { platform_driver_unregister(&bcm_driver); + serdev_device_driver_unregister(&bcm_serdev_driver); return hci_uart_unregister_proto(&bcm_proto); } diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index 68f951b3e85aa725485bef77de63f162f0241d97..db82a40875e8da3c9ad39881046d27bd8f0ee596 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig @@ -45,6 +45,11 @@ config BT_BREDR bool "Bluetooth Classic (BR/EDR) features" depends on BT default y + help + Bluetooth Classic includes support for Basic Rate (BR) + available with Bluetooth version 1.0b or later and support + for Enhanced Data Rate (EDR) available with Bluetooth + version 2.0 or later. source "net/bluetooth/rfcomm/Kconfig" @@ -58,11 +63,18 @@ config BT_HS bool "Bluetooth High Speed (HS) features" depends on BT_BREDR default y + help + Bluetooth High Speed includes support for off-loading + Bluetooth connections via 802.11 (wifi) physical layer + available with Bluetooth version 3.0 or later. config BT_LE bool "Bluetooth Low Energy (LE) features" depends on BT default y + help + Bluetooth Low Energy includes support low-energy physical + layer available with Bluetooth version 4.0 or later. config BT_6LOWPAN tristate "Bluetooth 6LoWPAN support" diff --git a/net/bluetooth/selftest.c b/net/bluetooth/selftest.c index ee92c925ecc5d3ac42bc041f60924da80672e1b8..34a1227f43910e9d728e6a312e5933a9231aed9f 100644 --- a/net/bluetooth/selftest.c +++ b/net/bluetooth/selftest.c @@ -164,7 +164,7 @@ static int __init test_ecdh_sample(const u8 priv_a[32], const u8 priv_b[32], ret = -EINVAL; out: - kfree(dhkey_a); + kfree(tmp); return ret; }