| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Bluetooth HCI Three-wire UART driver |
|---|
| 4 | 5 | * |
|---|
| 5 | 6 | * Copyright (C) 2012 Intel Corporation |
|---|
| 6 | | - * |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 10 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 11 | | - * (at your option) any later version. |
|---|
| 12 | | - * |
|---|
| 13 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 14 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 15 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 16 | | - * GNU General Public License for more details. |
|---|
| 17 | | - * |
|---|
| 18 | | - * You should have received a copy of the GNU General Public License |
|---|
| 19 | | - * along with this program; if not, write to the Free Software |
|---|
| 20 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 21 | | - * |
|---|
| 22 | 7 | */ |
|---|
| 23 | 8 | |
|---|
| 24 | 9 | #include <linux/acpi.h> |
|---|
| .. | .. |
|---|
| 26 | 11 | #include <linux/gpio/consumer.h> |
|---|
| 27 | 12 | #include <linux/kernel.h> |
|---|
| 28 | 13 | #include <linux/mod_devicetable.h> |
|---|
| 14 | +#include <linux/of_device.h> |
|---|
| 29 | 15 | #include <linux/serdev.h> |
|---|
| 30 | 16 | #include <linux/skbuff.h> |
|---|
| 31 | 17 | |
|---|
| .. | .. |
|---|
| 115 | 101 | int (*setup)(struct h5 *h5); |
|---|
| 116 | 102 | void (*open)(struct h5 *h5); |
|---|
| 117 | 103 | void (*close)(struct h5 *h5); |
|---|
| 104 | + int (*suspend)(struct h5 *h5); |
|---|
| 105 | + int (*resume)(struct h5 *h5); |
|---|
| 118 | 106 | const struct acpi_gpio_mapping *acpi_gpio_map; |
|---|
| 119 | 107 | }; |
|---|
| 120 | 108 | |
|---|
| .. | .. |
|---|
| 190 | 178 | { |
|---|
| 191 | 179 | struct h5 *h5 = hu->priv; |
|---|
| 192 | 180 | |
|---|
| 193 | | - BT_ERR("Peer device has reset"); |
|---|
| 181 | + bt_dev_err(hu->hdev, "Peer device has reset"); |
|---|
| 194 | 182 | |
|---|
| 195 | 183 | h5->state = H5_UNINITIALIZED; |
|---|
| 196 | 184 | |
|---|
| .. | .. |
|---|
| 311 | 299 | break; |
|---|
| 312 | 300 | |
|---|
| 313 | 301 | __skb_unlink(skb, &h5->unack); |
|---|
| 314 | | - kfree_skb(skb); |
|---|
| 302 | + dev_kfree_skb_irq(skb); |
|---|
| 315 | 303 | } |
|---|
| 316 | 304 | |
|---|
| 317 | 305 | if (skb_queue_empty(&h5->unack)) |
|---|
| .. | .. |
|---|
| 401 | 389 | case HCI_EVENT_PKT: |
|---|
| 402 | 390 | case HCI_ACLDATA_PKT: |
|---|
| 403 | 391 | case HCI_SCODATA_PKT: |
|---|
| 392 | + case HCI_ISODATA_PKT: |
|---|
| 404 | 393 | hci_skb_pkt_type(h5->rx_skb) = H5_HDR_PKT_TYPE(hdr); |
|---|
| 405 | 394 | |
|---|
| 406 | 395 | /* Remove Three-wire header */ |
|---|
| .. | .. |
|---|
| 452 | 441 | H5_HDR_LEN(hdr)); |
|---|
| 453 | 442 | |
|---|
| 454 | 443 | if (((hdr[0] + hdr[1] + hdr[2] + hdr[3]) & 0xff) != 0xff) { |
|---|
| 455 | | - BT_ERR("Invalid header checksum"); |
|---|
| 444 | + bt_dev_err(hu->hdev, "Invalid header checksum"); |
|---|
| 456 | 445 | h5_reset_rx(h5); |
|---|
| 457 | 446 | return 0; |
|---|
| 458 | 447 | } |
|---|
| 459 | 448 | |
|---|
| 460 | 449 | if (H5_HDR_RELIABLE(hdr) && H5_HDR_SEQ(hdr) != h5->tx_ack) { |
|---|
| 461 | | - BT_ERR("Out-of-order packet arrived (%u != %u)", |
|---|
| 462 | | - H5_HDR_SEQ(hdr), h5->tx_ack); |
|---|
| 450 | + bt_dev_err(hu->hdev, "Out-of-order packet arrived (%u != %u)", |
|---|
| 451 | + H5_HDR_SEQ(hdr), h5->tx_ack); |
|---|
| 463 | 452 | h5_reset_rx(h5); |
|---|
| 464 | 453 | return 0; |
|---|
| 465 | 454 | } |
|---|
| 466 | 455 | |
|---|
| 467 | 456 | if (h5->state != H5_ACTIVE && |
|---|
| 468 | 457 | H5_HDR_PKT_TYPE(hdr) != HCI_3WIRE_LINK_PKT) { |
|---|
| 469 | | - BT_ERR("Non-link packet received in non-active state"); |
|---|
| 458 | + bt_dev_err(hu->hdev, "Non-link packet received in non-active state"); |
|---|
| 470 | 459 | h5_reset_rx(h5); |
|---|
| 471 | 460 | return 0; |
|---|
| 472 | 461 | } |
|---|
| .. | .. |
|---|
| 489 | 478 | |
|---|
| 490 | 479 | h5->rx_skb = bt_skb_alloc(H5_MAX_LEN, GFP_ATOMIC); |
|---|
| 491 | 480 | if (!h5->rx_skb) { |
|---|
| 492 | | - BT_ERR("Can't allocate mem for new packet"); |
|---|
| 481 | + bt_dev_err(hu->hdev, "Can't allocate mem for new packet"); |
|---|
| 493 | 482 | h5_reset_rx(h5); |
|---|
| 494 | 483 | return -ENOMEM; |
|---|
| 495 | 484 | } |
|---|
| .. | .. |
|---|
| 537 | 526 | skb_put_data(h5->rx_skb, byte, 1); |
|---|
| 538 | 527 | h5->rx_pending--; |
|---|
| 539 | 528 | |
|---|
| 540 | | - BT_DBG("unsliped 0x%02hhx, rx_pending %zu", *byte, h5->rx_pending); |
|---|
| 529 | + BT_DBG("unslipped 0x%02hhx, rx_pending %zu", *byte, h5->rx_pending); |
|---|
| 541 | 530 | } |
|---|
| 542 | 531 | |
|---|
| 543 | 532 | static void h5_reset_rx(struct h5 *h5) |
|---|
| .. | .. |
|---|
| 565 | 554 | |
|---|
| 566 | 555 | if (h5->rx_pending > 0) { |
|---|
| 567 | 556 | if (*ptr == SLIP_DELIMITER) { |
|---|
| 568 | | - BT_ERR("Too short H5 packet"); |
|---|
| 557 | + bt_dev_err(hu->hdev, "Too short H5 packet"); |
|---|
| 569 | 558 | h5_reset_rx(h5); |
|---|
| 570 | 559 | continue; |
|---|
| 571 | 560 | } |
|---|
| .. | .. |
|---|
| 592 | 581 | struct h5 *h5 = hu->priv; |
|---|
| 593 | 582 | |
|---|
| 594 | 583 | if (skb->len > 0xfff) { |
|---|
| 595 | | - BT_ERR("Packet too long (%u bytes)", skb->len); |
|---|
| 584 | + bt_dev_err(hu->hdev, "Packet too long (%u bytes)", skb->len); |
|---|
| 596 | 585 | kfree_skb(skb); |
|---|
| 597 | 586 | return 0; |
|---|
| 598 | 587 | } |
|---|
| 599 | 588 | |
|---|
| 600 | 589 | if (h5->state != H5_ACTIVE) { |
|---|
| 601 | | - BT_ERR("Ignoring HCI data in non-active state"); |
|---|
| 590 | + bt_dev_err(hu->hdev, "Ignoring HCI data in non-active state"); |
|---|
| 602 | 591 | kfree_skb(skb); |
|---|
| 603 | 592 | return 0; |
|---|
| 604 | 593 | } |
|---|
| .. | .. |
|---|
| 610 | 599 | break; |
|---|
| 611 | 600 | |
|---|
| 612 | 601 | case HCI_SCODATA_PKT: |
|---|
| 602 | + case HCI_ISODATA_PKT: |
|---|
| 613 | 603 | skb_queue_tail(&h5->unrel, skb); |
|---|
| 614 | 604 | break; |
|---|
| 615 | 605 | |
|---|
| 616 | 606 | default: |
|---|
| 617 | | - BT_ERR("Unknown packet type %u", hci_skb_pkt_type(skb)); |
|---|
| 607 | + bt_dev_err(hu->hdev, "Unknown packet type %u", hci_skb_pkt_type(skb)); |
|---|
| 618 | 608 | kfree_skb(skb); |
|---|
| 619 | 609 | break; |
|---|
| 620 | 610 | } |
|---|
| .. | .. |
|---|
| 652 | 642 | case HCI_ACLDATA_PKT: |
|---|
| 653 | 643 | case HCI_COMMAND_PKT: |
|---|
| 654 | 644 | case HCI_SCODATA_PKT: |
|---|
| 645 | + case HCI_ISODATA_PKT: |
|---|
| 655 | 646 | case HCI_3WIRE_LINK_PKT: |
|---|
| 656 | 647 | case HCI_3WIRE_ACK_PKT: |
|---|
| 657 | 648 | return true; |
|---|
| .. | .. |
|---|
| 669 | 660 | int i; |
|---|
| 670 | 661 | |
|---|
| 671 | 662 | if (!valid_packet_type(pkt_type)) { |
|---|
| 672 | | - BT_ERR("Unknown packet type %u", pkt_type); |
|---|
| 663 | + bt_dev_err(hu->hdev, "Unknown packet type %u", pkt_type); |
|---|
| 673 | 664 | return NULL; |
|---|
| 674 | 665 | } |
|---|
| 675 | 666 | |
|---|
| .. | .. |
|---|
| 746 | 737 | } |
|---|
| 747 | 738 | |
|---|
| 748 | 739 | skb_queue_head(&h5->unrel, skb); |
|---|
| 749 | | - BT_ERR("Could not dequeue pkt because alloc_skb failed"); |
|---|
| 740 | + bt_dev_err(hu->hdev, "Could not dequeue pkt because alloc_skb failed"); |
|---|
| 750 | 741 | } |
|---|
| 751 | 742 | |
|---|
| 752 | 743 | spin_lock_irqsave_nested(&h5->unack.lock, flags, SINGLE_DEPTH_NESTING); |
|---|
| .. | .. |
|---|
| 766 | 757 | } |
|---|
| 767 | 758 | |
|---|
| 768 | 759 | skb_queue_head(&h5->rel, skb); |
|---|
| 769 | | - BT_ERR("Could not dequeue pkt because alloc_skb failed"); |
|---|
| 760 | + bt_dev_err(hu->hdev, "Could not dequeue pkt because alloc_skb failed"); |
|---|
| 770 | 761 | } |
|---|
| 771 | 762 | |
|---|
| 772 | 763 | unlock: |
|---|
| .. | .. |
|---|
| 798 | 789 | |
|---|
| 799 | 790 | static int h5_serdev_probe(struct serdev_device *serdev) |
|---|
| 800 | 791 | { |
|---|
| 801 | | - const struct acpi_device_id *match; |
|---|
| 802 | 792 | struct device *dev = &serdev->dev; |
|---|
| 803 | 793 | struct h5 *h5; |
|---|
| 804 | 794 | |
|---|
| .. | .. |
|---|
| 806 | 796 | if (!h5) |
|---|
| 807 | 797 | return -ENOMEM; |
|---|
| 808 | 798 | |
|---|
| 809 | | - set_bit(HCI_UART_RESET_ON_INIT, &h5->serdev_hu.hdev_flags); |
|---|
| 810 | | - |
|---|
| 811 | 799 | h5->hu = &h5->serdev_hu; |
|---|
| 812 | 800 | h5->serdev_hu.serdev = serdev; |
|---|
| 813 | 801 | serdev_device_set_drvdata(serdev, h5); |
|---|
| 814 | 802 | |
|---|
| 815 | 803 | if (has_acpi_companion(dev)) { |
|---|
| 804 | + const struct acpi_device_id *match; |
|---|
| 805 | + |
|---|
| 816 | 806 | match = acpi_match_device(dev->driver->acpi_match_table, dev); |
|---|
| 817 | 807 | if (!match) |
|---|
| 818 | 808 | return -ENODEV; |
|---|
| .. | .. |
|---|
| 823 | 813 | if (h5->vnd->acpi_gpio_map) |
|---|
| 824 | 814 | devm_acpi_dev_add_driver_gpios(dev, |
|---|
| 825 | 815 | h5->vnd->acpi_gpio_map); |
|---|
| 816 | + } else { |
|---|
| 817 | + const void *data; |
|---|
| 818 | + |
|---|
| 819 | + data = of_device_get_match_data(dev); |
|---|
| 820 | + if (!data) |
|---|
| 821 | + return -ENODEV; |
|---|
| 822 | + |
|---|
| 823 | + h5->vnd = (const struct h5_vnd *)data; |
|---|
| 826 | 824 | } |
|---|
| 825 | + |
|---|
| 827 | 826 | |
|---|
| 828 | 827 | h5->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW); |
|---|
| 829 | 828 | if (IS_ERR(h5->enable_gpio)) |
|---|
| .. | .. |
|---|
| 842 | 841 | struct h5 *h5 = serdev_device_get_drvdata(serdev); |
|---|
| 843 | 842 | |
|---|
| 844 | 843 | hci_uart_unregister_device(&h5->serdev_hu); |
|---|
| 844 | +} |
|---|
| 845 | + |
|---|
| 846 | +static int __maybe_unused h5_serdev_suspend(struct device *dev) |
|---|
| 847 | +{ |
|---|
| 848 | + struct h5 *h5 = dev_get_drvdata(dev); |
|---|
| 849 | + int ret = 0; |
|---|
| 850 | + |
|---|
| 851 | + if (h5->vnd && h5->vnd->suspend) |
|---|
| 852 | + ret = h5->vnd->suspend(h5); |
|---|
| 853 | + |
|---|
| 854 | + return ret; |
|---|
| 855 | +} |
|---|
| 856 | + |
|---|
| 857 | +static int __maybe_unused h5_serdev_resume(struct device *dev) |
|---|
| 858 | +{ |
|---|
| 859 | + struct h5 *h5 = dev_get_drvdata(dev); |
|---|
| 860 | + int ret = 0; |
|---|
| 861 | + |
|---|
| 862 | + if (h5->vnd && h5->vnd->resume) |
|---|
| 863 | + ret = h5->vnd->resume(h5); |
|---|
| 864 | + |
|---|
| 865 | + return ret; |
|---|
| 845 | 866 | } |
|---|
| 846 | 867 | |
|---|
| 847 | 868 | #ifdef CONFIG_BT_HCIUART_RTL |
|---|
| .. | .. |
|---|
| 915 | 936 | gpiod_set_value_cansleep(h5->enable_gpio, 0); |
|---|
| 916 | 937 | } |
|---|
| 917 | 938 | |
|---|
| 939 | +/* Suspend/resume support. On many devices the RTL BT device loses power during |
|---|
| 940 | + * suspend/resume, causing it to lose its firmware and all state. So we simply |
|---|
| 941 | + * turn it off on suspend and reprobe on resume. This mirrors how RTL devices |
|---|
| 942 | + * are handled in the USB driver, where the USB_QUIRK_RESET_RESUME is used which |
|---|
| 943 | + * also causes a reprobe on resume. |
|---|
| 944 | + */ |
|---|
| 945 | +static int h5_btrtl_suspend(struct h5 *h5) |
|---|
| 946 | +{ |
|---|
| 947 | + serdev_device_set_flow_control(h5->hu->serdev, false); |
|---|
| 948 | + gpiod_set_value_cansleep(h5->device_wake_gpio, 0); |
|---|
| 949 | + gpiod_set_value_cansleep(h5->enable_gpio, 0); |
|---|
| 950 | + return 0; |
|---|
| 951 | +} |
|---|
| 952 | + |
|---|
| 953 | +struct h5_btrtl_reprobe { |
|---|
| 954 | + struct device *dev; |
|---|
| 955 | + struct work_struct work; |
|---|
| 956 | +}; |
|---|
| 957 | + |
|---|
| 958 | +static void h5_btrtl_reprobe_worker(struct work_struct *work) |
|---|
| 959 | +{ |
|---|
| 960 | + struct h5_btrtl_reprobe *reprobe = |
|---|
| 961 | + container_of(work, struct h5_btrtl_reprobe, work); |
|---|
| 962 | + int ret; |
|---|
| 963 | + |
|---|
| 964 | + ret = device_reprobe(reprobe->dev); |
|---|
| 965 | + if (ret && ret != -EPROBE_DEFER) |
|---|
| 966 | + dev_err(reprobe->dev, "Reprobe error %d\n", ret); |
|---|
| 967 | + |
|---|
| 968 | + put_device(reprobe->dev); |
|---|
| 969 | + kfree(reprobe); |
|---|
| 970 | + module_put(THIS_MODULE); |
|---|
| 971 | +} |
|---|
| 972 | + |
|---|
| 973 | +static int h5_btrtl_resume(struct h5 *h5) |
|---|
| 974 | +{ |
|---|
| 975 | + struct h5_btrtl_reprobe *reprobe; |
|---|
| 976 | + |
|---|
| 977 | + reprobe = kzalloc(sizeof(*reprobe), GFP_KERNEL); |
|---|
| 978 | + if (!reprobe) |
|---|
| 979 | + return -ENOMEM; |
|---|
| 980 | + |
|---|
| 981 | + __module_get(THIS_MODULE); |
|---|
| 982 | + |
|---|
| 983 | + INIT_WORK(&reprobe->work, h5_btrtl_reprobe_worker); |
|---|
| 984 | + reprobe->dev = get_device(&h5->hu->serdev->dev); |
|---|
| 985 | + queue_work(system_long_wq, &reprobe->work); |
|---|
| 986 | + return 0; |
|---|
| 987 | +} |
|---|
| 988 | + |
|---|
| 918 | 989 | static const struct acpi_gpio_params btrtl_device_wake_gpios = { 0, 0, false }; |
|---|
| 919 | 990 | static const struct acpi_gpio_params btrtl_enable_gpios = { 1, 0, false }; |
|---|
| 920 | 991 | static const struct acpi_gpio_params btrtl_host_wake_gpios = { 2, 0, false }; |
|---|
| .. | .. |
|---|
| 929 | 1000 | .setup = h5_btrtl_setup, |
|---|
| 930 | 1001 | .open = h5_btrtl_open, |
|---|
| 931 | 1002 | .close = h5_btrtl_close, |
|---|
| 1003 | + .suspend = h5_btrtl_suspend, |
|---|
| 1004 | + .resume = h5_btrtl_resume, |
|---|
| 932 | 1005 | .acpi_gpio_map = acpi_btrtl_gpios, |
|---|
| 933 | 1006 | }; |
|---|
| 934 | 1007 | #endif |
|---|
| .. | .. |
|---|
| 943 | 1016 | MODULE_DEVICE_TABLE(acpi, h5_acpi_match); |
|---|
| 944 | 1017 | #endif |
|---|
| 945 | 1018 | |
|---|
| 1019 | +static const struct dev_pm_ops h5_serdev_pm_ops = { |
|---|
| 1020 | + SET_SYSTEM_SLEEP_PM_OPS(h5_serdev_suspend, h5_serdev_resume) |
|---|
| 1021 | +}; |
|---|
| 1022 | + |
|---|
| 1023 | +static const struct of_device_id rtl_bluetooth_of_match[] = { |
|---|
| 1024 | +#ifdef CONFIG_BT_HCIUART_RTL |
|---|
| 1025 | + { .compatible = "realtek,rtl8822cs-bt", |
|---|
| 1026 | + .data = (const void *)&rtl_vnd }, |
|---|
| 1027 | + { .compatible = "realtek,rtl8723bs-bt", |
|---|
| 1028 | + .data = (const void *)&rtl_vnd }, |
|---|
| 1029 | +#endif |
|---|
| 1030 | + { }, |
|---|
| 1031 | +}; |
|---|
| 1032 | +MODULE_DEVICE_TABLE(of, rtl_bluetooth_of_match); |
|---|
| 1033 | + |
|---|
| 946 | 1034 | static struct serdev_device_driver h5_serdev_driver = { |
|---|
| 947 | 1035 | .probe = h5_serdev_probe, |
|---|
| 948 | 1036 | .remove = h5_serdev_remove, |
|---|
| 949 | 1037 | .driver = { |
|---|
| 950 | 1038 | .name = "hci_uart_h5", |
|---|
| 951 | 1039 | .acpi_match_table = ACPI_PTR(h5_acpi_match), |
|---|
| 1040 | + .pm = &h5_serdev_pm_ops, |
|---|
| 1041 | + .of_match_table = rtl_bluetooth_of_match, |
|---|
| 952 | 1042 | }, |
|---|
| 953 | 1043 | }; |
|---|
| 954 | 1044 | |
|---|