diff options
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r-- | drivers/bluetooth/ath3k.c | 8 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_drv.h | 11 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_main.c | 35 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_sdio.c | 79 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_sdio.h | 6 | ||||
-rw-r--r-- | drivers/bluetooth/btusb.c | 12 | ||||
-rw-r--r-- | drivers/bluetooth/hci_bcm.c | 1 | ||||
-rw-r--r-- | drivers/bluetooth/hci_bcsp.c | 57 | ||||
-rw-r--r-- | drivers/bluetooth/hci_intel.c | 6 | ||||
-rw-r--r-- | drivers/bluetooth/hci_ldisc.c | 11 | ||||
-rw-r--r-- | drivers/bluetooth/hci_uart.h | 1 |
11 files changed, 171 insertions, 56 deletions
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index a520fe6f1..1fac1e8c7 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -122,6 +122,7 @@ static const struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x13d3, 0x3432) }, { USB_DEVICE(0x13d3, 0x3472) }, { USB_DEVICE(0x13d3, 0x3474) }, + { USB_DEVICE(0x13d3, 0x3487) }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xE02C) }, @@ -188,6 +189,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3487), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU22 with sflash firmware */ { USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 }, @@ -206,7 +208,8 @@ static int ath3k_load_firmware(struct usb_device *udev, const struct firmware *firmware) { u8 *send_buf; - int err, pipe, len, size, sent = 0; + int len = 0; + int err, pipe, size, sent = 0; int count = firmware->size; BT_DBG("udev %p", udev); @@ -302,7 +305,8 @@ static int ath3k_load_fwfile(struct usb_device *udev, const struct firmware *firmware) { u8 *send_buf; - int err, pipe, len, size, count, sent = 0; + int len = 0; + int err, pipe, size, count, sent = 0; int ret; count = firmware->size; diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index 05904732e..f742384b5 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h @@ -23,6 +23,17 @@ #include <linux/bitops.h> #include <linux/slab.h> #include <net/bluetooth/bluetooth.h> +#include <linux/err.h> +#include <linux/gpio.h> +#include <linux/gfp.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/of_gpio.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/slab.h> +#include <linux/of_irq.h> #define BTM_HEADER_LEN 4 #define BTM_UPLD_SIZE 2312 diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index f25a825a6..7ad8d61c0 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -510,34 +510,39 @@ static int btmrvl_download_cal_data(struct btmrvl_private *priv, static int btmrvl_check_device_tree(struct btmrvl_private *priv) { struct device_node *dt_node; + struct btmrvl_sdio_card *card = priv->btmrvl_dev.card; u8 cal_data[BT_CAL_HDR_LEN + BT_CAL_DATA_SIZE]; - int ret; - u32 val; + int ret = 0; + u16 gpio, gap; + + if (card->plt_of_node) { + dt_node = card->plt_of_node; + ret = of_property_read_u16(dt_node, "marvell,wakeup-pin", + &gpio); + if (ret) + gpio = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; + + ret = of_property_read_u16(dt_node, "marvell,wakeup-gap-ms", + &gap); + if (ret) + gap = (u8)(priv->btmrvl_dev.gpio_gap & 0x00ff); - for_each_compatible_node(dt_node, NULL, "btmrvl,cfgdata") { - ret = of_property_read_u32(dt_node, "btmrvl,gpio-gap", &val); - if (!ret) - priv->btmrvl_dev.gpio_gap = val; + priv->btmrvl_dev.gpio_gap = (gpio << 8) + gap; - ret = of_property_read_u8_array(dt_node, "btmrvl,cal-data", + ret = of_property_read_u8_array(dt_node, "marvell,cal-data", cal_data + BT_CAL_HDR_LEN, BT_CAL_DATA_SIZE); - if (ret) { - of_node_put(dt_node); + if (ret) return ret; - } BT_DBG("Use cal data from device tree"); ret = btmrvl_download_cal_data(priv, cal_data, BT_CAL_DATA_SIZE); - if (ret) { + if (ret) BT_ERR("Fail to download calibrate data"); - of_node_put(dt_node); - return ret; - } } - return 0; + return ret; } static int btmrvl_setup(struct hci_dev *hdev) diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index d6588947c..e569ff003 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -52,6 +52,68 @@ static struct memory_type_mapping mem_type_mapping_tbl[] = { {"EXTLAST", NULL, 0, 0xFE}, }; +static const struct of_device_id btmrvl_sdio_of_match_table[] = { + { .compatible = "marvell,sd8897-bt" }, + { .compatible = "marvell,sd8997-bt" }, + { } +}; + +static irqreturn_t btmrvl_wake_irq_bt(int irq, void *priv) +{ + struct btmrvl_plt_wake_cfg *cfg = priv; + + if (cfg->irq_bt >= 0) { + pr_info("%s: wake by bt", __func__); + cfg->wake_by_bt = true; + disable_irq_nosync(irq); + } + + return IRQ_HANDLED; +} + +/* This function parses device tree node using mmc subnode devicetree API. + * The device node is saved in card->plt_of_node. + * If the device tree node exists and includes interrupts attributes, this + * function will request platform specific wakeup interrupt. + */ +static int btmrvl_sdio_probe_of(struct device *dev, + struct btmrvl_sdio_card *card) +{ + struct btmrvl_plt_wake_cfg *cfg; + int ret; + + if (!dev->of_node || + !of_match_node(btmrvl_sdio_of_match_table, dev->of_node)) { + pr_err("sdio platform data not available"); + return -1; + } + + card->plt_of_node = dev->of_node; + + card->plt_wake_cfg = devm_kzalloc(dev, sizeof(*card->plt_wake_cfg), + GFP_KERNEL); + cfg = card->plt_wake_cfg; + if (cfg && card->plt_of_node) { + cfg->irq_bt = irq_of_parse_and_map(card->plt_of_node, 0); + if (!cfg->irq_bt) { + dev_err(dev, "fail to parse irq_bt from device tree"); + } else { + ret = devm_request_irq(dev, cfg->irq_bt, + btmrvl_wake_irq_bt, + IRQF_TRIGGER_LOW, + "bt_wake", cfg); + if (ret) { + dev_err(dev, + "Failed to request irq_bt %d (%d)\n", + cfg->irq_bt, ret); + } + disable_irq(cfg->irq_bt); + } + } + + return 0; +} + /* The btmrvl_sdio_remove() callback function is called * when user removes this module from kernel space or ejects * the card from the slot. The driver handles these 2 cases @@ -1464,6 +1526,9 @@ static int btmrvl_sdio_probe(struct sdio_func *func, btmrvl_sdio_enable_host_int(card); + /* Device tree node parsing and platform specific configuration*/ + btmrvl_sdio_probe_of(&func->dev, card); + priv = btmrvl_add_card(card); if (!priv) { BT_ERR("Initializing card failed!"); @@ -1544,6 +1609,13 @@ static int btmrvl_sdio_suspend(struct device *dev) return 0; } + /* Enable platform specific wakeup interrupt */ + if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0) { + card->plt_wake_cfg->wake_by_bt = false; + enable_irq(card->plt_wake_cfg->irq_bt); + enable_irq_wake(card->plt_wake_cfg->irq_bt); + } + priv = card->priv; priv->adapter->is_suspending = true; hcidev = priv->btmrvl_dev.hcidev; @@ -1606,6 +1678,13 @@ static int btmrvl_sdio_resume(struct device *dev) BT_DBG("%s: SDIO resume", hcidev->name); hci_resume_dev(hcidev); + /* Disable platform specific wakeup interrupt */ + if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0) { + disable_irq_wake(card->plt_wake_cfg->irq_bt); + if (!card->plt_wake_cfg->wake_by_bt) + disable_irq(card->plt_wake_cfg->irq_bt); + } + return 0; } diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h index 1a3bd064c..3a522d23e 100644 --- a/drivers/bluetooth/btmrvl_sdio.h +++ b/drivers/bluetooth/btmrvl_sdio.h @@ -62,6 +62,10 @@ #define FIRMWARE_READY 0xfedc +struct btmrvl_plt_wake_cfg { + int irq_bt; + bool wake_by_bt; +}; struct btmrvl_sdio_card_reg { u8 cfg; @@ -97,6 +101,8 @@ struct btmrvl_sdio_card { u16 sd_blksz_fw_dl; u8 rx_unit; struct btmrvl_private *priv; + struct device_node *plt_of_node; + struct btmrvl_plt_wake_cfg *plt_wake_cfg; }; struct btmrvl_sdio_device { diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 154b9ecc9..bc83c2bb5 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -236,6 +236,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3487), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, @@ -2001,12 +2002,13 @@ static int btusb_setup_intel_new(struct hci_dev *hdev) return -EINVAL; } - /* At the moment only the hardware variant iBT 3.0 (LnP/SfP) is - * supported by this firmware loading method. This check has been - * put in place to ensure correct forward compatibility options - * when newer hardware variants come along. + /* At the moment the iBT 3.0 hardware variants 0x0b (LnP/SfP) + * and 0x0c (WsP) are supported by this firmware loading method. + * + * This check has been put in place to ensure correct forward + * compatibility options when newer hardware variants come along. */ - if (ver.hw_variant != 0x0b) { + if (ver.hw_variant != 0x0b && ver.hw_variant != 0x0c) { BT_ERR("%s: Unsupported Intel hardware variant (%u)", hdev->name, ver.hw_variant); return -EINVAL; diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 923ec3375..f639417ca 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -825,6 +825,7 @@ static const struct acpi_device_id bcm_acpi_match[] = { { "BCM2E64", 0 }, { "BCM2E65", 0 }, { "BCM2E67", 0 }, + { "BCM2E71", 0 }, { "BCM2E7B", 0 }, { "BCM2E7C", 0 }, { }, diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index 064f2fefa..d7d23ceba 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c @@ -102,13 +102,12 @@ static const u16 crc_table[] = { /* Initialise the crc calculator */ #define BCSP_CRC_INIT(x) x = 0xffff -/* - Update crc with next data byte - - Implementation note - The data byte is treated as two nibbles. The crc is generated - in reverse, i.e., bits are fed into the register from the top. -*/ +/* Update crc with next data byte + * + * Implementation note + * The data byte is treated as two nibbles. The crc is generated + * in reverse, i.e., bits are fed into the register from the top. + */ static void bcsp_crc_update(u16 *crc, u8 d) { u16 reg = *crc; @@ -223,9 +222,10 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data, } /* Max len of packet: (original len +4(bcsp hdr) +2(crc))*2 - (because bytes 0xc0 and 0xdb are escaped, worst case is - when the packet is all made of 0xc0 and 0xdb :) ) - + 2 (0xc0 delimiters at start and end). */ + * (because bytes 0xc0 and 0xdb are escaped, worst case is + * when the packet is all made of 0xc0 and 0xdb :) ) + * + 2 (0xc0 delimiters at start and end). + */ nskb = alloc_skb((len + 6) * 2 + 2, GFP_ATOMIC); if (!nskb) @@ -285,7 +285,7 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu) struct bcsp_struct *bcsp = hu->priv; unsigned long flags; struct sk_buff *skb; - + /* First of all, check for unreliable messages in the queue, since they have priority */ @@ -305,8 +305,9 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu) } /* Now, try to send a reliable pkt. We can only send a - reliable packet if the number of packets sent but not yet ack'ed - is < than the winsize */ + * reliable packet if the number of packets sent but not yet ack'ed + * is < than the winsize + */ spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING); @@ -332,12 +333,14 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu) spin_unlock_irqrestore(&bcsp->unack.lock, flags); /* We could not send a reliable packet, either because there are - none or because there are too many unack'ed pkts. Did we receive - any packets we have not acknowledged yet ? */ + * none or because there are too many unack'ed pkts. Did we receive + * any packets we have not acknowledged yet ? + */ if (bcsp->txack_req) { /* if so, craft an empty ACK pkt and send it on BCSP unreliable - channel 0 */ + * channel 0 + */ struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, NULL, 0, BCSP_ACK_PKT); return nskb; } @@ -399,8 +402,9 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp) } /* Handle BCSP link-establishment packets. When we - detect a "sync" packet, symptom that the BT module has reset, - we do nothing :) (yet) */ + * detect a "sync" packet, symptom that the BT module has reset, + * we do nothing :) (yet) + */ static void bcsp_handle_le_pkt(struct hci_uart *hu) { struct bcsp_struct *bcsp = hu->priv; @@ -462,7 +466,7 @@ static inline void bcsp_unslip_one_byte(struct bcsp_struct *bcsp, unsigned char case 0xdd: memcpy(skb_put(bcsp->rx_skb, 1), &db, 1); if ((bcsp->rx_skb->data[0] & 0x40) != 0 && - bcsp->rx_state != BCSP_W4_CRC) + bcsp->rx_state != BCSP_W4_CRC) bcsp_crc_update(&bcsp->message_crc, 0xdb); bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC; bcsp->rx_count--; @@ -534,7 +538,7 @@ static void bcsp_complete_rx_pkt(struct hci_uart *hu) } else { BT_ERR("Packet for unknown channel (%u %s)", bcsp->rx_skb->data[1] & 0x0f, - bcsp->rx_skb->data[0] & 0x80 ? + bcsp->rx_skb->data[0] & 0x80 ? "reliable" : "unreliable"); kfree_skb(bcsp->rx_skb); } @@ -562,7 +566,7 @@ static int bcsp_recv(struct hci_uart *hu, const void *data, int count) struct bcsp_struct *bcsp = hu->priv; const unsigned char *ptr; - BT_DBG("hu %p count %d rx_state %d rx_count %ld", + BT_DBG("hu %p count %d rx_state %d rx_count %ld", hu, count, bcsp->rx_state, bcsp->rx_count); ptr = data; @@ -591,7 +595,7 @@ static int bcsp_recv(struct hci_uart *hu, const void *data, int count) continue; } if (bcsp->rx_skb->data[0] & 0x80 /* reliable pkt */ - && (bcsp->rx_skb->data[0] & 0x07) != bcsp->rxseq_txack) { + && (bcsp->rx_skb->data[0] & 0x07) != bcsp->rxseq_txack) { BT_ERR("Out-of-order packet arrived, got %u expected %u", bcsp->rx_skb->data[0] & 0x07, bcsp->rxseq_txack); @@ -601,7 +605,7 @@ static int bcsp_recv(struct hci_uart *hu, const void *data, int count) continue; } bcsp->rx_state = BCSP_W4_DATA; - bcsp->rx_count = (bcsp->rx_skb->data[1] >> 4) + + bcsp->rx_count = (bcsp->rx_skb->data[1] >> 4) + (bcsp->rx_skb->data[2] << 4); /* May be 0 */ continue; @@ -615,7 +619,7 @@ static int bcsp_recv(struct hci_uart *hu, const void *data, int count) case BCSP_W4_CRC: if (bitrev16(bcsp->message_crc) != bscp_get_crc(bcsp)) { - BT_ERR ("Checksum failed: computed %04x received %04x", + BT_ERR("Checksum failed: computed %04x received %04x", bitrev16(bcsp->message_crc), bscp_get_crc(bcsp)); @@ -653,8 +657,9 @@ static int bcsp_recv(struct hci_uart *hu, const void *data, int count) BCSP_CRC_INIT(bcsp->message_crc); /* Do not increment ptr or decrement count - * Allocate packet. Max len of a BCSP pkt= - * 0xFFF (payload) +4 (header) +2 (crc) */ + * Allocate packet. Max len of a BCSP pkt= + * 0xFFF (payload) +4 (header) +2 (crc) + */ bcsp->rx_skb = bt_skb_alloc(0x1005, GFP_ATOMIC); if (!bcsp->rx_skb) { diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c index fefff3498..4124269aa 100644 --- a/drivers/bluetooth/hci_intel.c +++ b/drivers/bluetooth/hci_intel.c @@ -1210,8 +1210,7 @@ static int intel_probe(struct platform_device *pdev) idev->pdev = pdev; - idev->reset = devm_gpiod_get_optional(&pdev->dev, "reset", - GPIOD_OUT_LOW); + idev->reset = devm_gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(idev->reset)) { dev_err(&pdev->dev, "Unable to retrieve gpio\n"); return PTR_ERR(idev->reset); @@ -1223,8 +1222,7 @@ static int intel_probe(struct platform_device *pdev) dev_err(&pdev->dev, "No IRQ, falling back to gpio-irq\n"); - host_wake = devm_gpiod_get_optional(&pdev->dev, "host-wake", - GPIOD_IN); + host_wake = devm_gpiod_get(&pdev->dev, "host-wake", GPIOD_IN); if (IS_ERR(host_wake)) { dev_err(&pdev->dev, "Unable to retrieve IRQ\n"); goto no_irq; diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index c00168a5b..49b3e1e2d 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -227,7 +227,7 @@ static int hci_uart_flush(struct hci_dev *hdev) tty_ldisc_flush(tty); tty_driver_flush_buffer(tty); - if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) + if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) hu->proto->flush(hu); return 0; @@ -492,7 +492,7 @@ static void hci_uart_tty_close(struct tty_struct *tty) cancel_work_sync(&hu->write_work); - if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) { + if (test_and_clear_bit(HCI_UART_PROTO_READY, &hu->flags)) { if (hdev) { if (test_bit(HCI_UART_REGISTERED, &hu->flags)) hci_unregister_dev(hdev); @@ -500,6 +500,7 @@ static void hci_uart_tty_close(struct tty_struct *tty) } hu->proto->close(hu); } + clear_bit(HCI_UART_PROTO_SET, &hu->flags); kfree(hu); } @@ -526,7 +527,7 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty) if (tty != hu->tty) return; - if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) + if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) hci_uart_tx_wakeup(hu); } @@ -550,7 +551,7 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, if (!hu || tty != hu->tty) return; - if (!test_bit(HCI_UART_PROTO_SET, &hu->flags)) + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) return; /* It does not need a lock here as it is already protected by a mutex in @@ -638,9 +639,11 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id) return err; hu->proto = p; + set_bit(HCI_UART_PROTO_READY, &hu->flags); err = hci_uart_register_dev(hu); if (err) { + clear_bit(HCI_UART_PROTO_READY, &hu->flags); p->close(hu); return err; } diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h index 4814ff08f..839bad1d8 100644 --- a/drivers/bluetooth/hci_uart.h +++ b/drivers/bluetooth/hci_uart.h @@ -95,6 +95,7 @@ struct hci_uart { /* HCI_UART proto flag bits */ #define HCI_UART_PROTO_SET 0 #define HCI_UART_REGISTERED 1 +#define HCI_UART_PROTO_READY 2 /* TX states */ #define HCI_UART_SENDING 1 |