btqcomsmd.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2016, Linaro Ltd.
  4. * Copyright (c) 2015, Sony Mobile Communications Inc.
  5. */
  6. #include <linux/module.h>
  7. #include <linux/slab.h>
  8. #include <linux/rpmsg.h>
  9. #include <linux/of.h>
  10. #include <linux/soc/qcom/wcnss_ctrl.h>
  11. #include <linux/platform_device.h>
  12. #include <net/bluetooth/bluetooth.h>
  13. #include <net/bluetooth/hci_core.h>
  14. #include "btqca.h"
  15. struct btqcomsmd {
  16. struct hci_dev *hdev;
  17. struct rpmsg_endpoint *acl_channel;
  18. struct rpmsg_endpoint *cmd_channel;
  19. };
  20. static int btqcomsmd_recv(struct hci_dev *hdev, unsigned int type,
  21. const void *data, size_t count)
  22. {
  23. struct sk_buff *skb;
  24. /* Use GFP_ATOMIC as we're in IRQ context */
  25. skb = bt_skb_alloc(count, GFP_ATOMIC);
  26. if (!skb) {
  27. hdev->stat.err_rx++;
  28. return -ENOMEM;
  29. }
  30. hci_skb_pkt_type(skb) = type;
  31. skb_put_data(skb, data, count);
  32. return hci_recv_frame(hdev, skb);
  33. }
  34. static int btqcomsmd_acl_callback(struct rpmsg_device *rpdev, void *data,
  35. int count, void *priv, u32 addr)
  36. {
  37. struct btqcomsmd *btq = priv;
  38. btq->hdev->stat.byte_rx += count;
  39. return btqcomsmd_recv(btq->hdev, HCI_ACLDATA_PKT, data, count);
  40. }
  41. static int btqcomsmd_cmd_callback(struct rpmsg_device *rpdev, void *data,
  42. int count, void *priv, u32 addr)
  43. {
  44. struct btqcomsmd *btq = priv;
  45. btq->hdev->stat.byte_rx += count;
  46. return btqcomsmd_recv(btq->hdev, HCI_EVENT_PKT, data, count);
  47. }
  48. static int btqcomsmd_send(struct hci_dev *hdev, struct sk_buff *skb)
  49. {
  50. struct btqcomsmd *btq = hci_get_drvdata(hdev);
  51. int ret;
  52. switch (hci_skb_pkt_type(skb)) {
  53. case HCI_ACLDATA_PKT:
  54. ret = rpmsg_send(btq->acl_channel, skb->data, skb->len);
  55. if (ret) {
  56. hdev->stat.err_tx++;
  57. break;
  58. }
  59. hdev->stat.acl_tx++;
  60. hdev->stat.byte_tx += skb->len;
  61. break;
  62. case HCI_COMMAND_PKT:
  63. ret = rpmsg_send(btq->cmd_channel, skb->data, skb->len);
  64. if (ret) {
  65. hdev->stat.err_tx++;
  66. break;
  67. }
  68. hdev->stat.cmd_tx++;
  69. hdev->stat.byte_tx += skb->len;
  70. break;
  71. default:
  72. ret = -EILSEQ;
  73. break;
  74. }
  75. if (!ret)
  76. kfree_skb(skb);
  77. return ret;
  78. }
  79. static int btqcomsmd_open(struct hci_dev *hdev)
  80. {
  81. return 0;
  82. }
  83. static int btqcomsmd_close(struct hci_dev *hdev)
  84. {
  85. return 0;
  86. }
  87. static int btqcomsmd_setup(struct hci_dev *hdev)
  88. {
  89. struct sk_buff *skb;
  90. skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
  91. if (IS_ERR(skb))
  92. return PTR_ERR(skb);
  93. kfree_skb(skb);
  94. /* Devices do not have persistent storage for BD address. Retrieve
  95. * it from the firmware node property.
  96. */
  97. set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
  98. return 0;
  99. }
  100. static int btqcomsmd_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
  101. {
  102. int ret;
  103. ret = qca_set_bdaddr_rome(hdev, bdaddr);
  104. if (ret)
  105. return ret;
  106. /* The firmware stops responding for a while after setting the bdaddr,
  107. * causing timeouts for subsequent commands. Sleep a bit to avoid this.
  108. */
  109. usleep_range(1000, 10000);
  110. return 0;
  111. }
  112. static int btqcomsmd_probe(struct platform_device *pdev)
  113. {
  114. struct btqcomsmd *btq;
  115. struct hci_dev *hdev;
  116. void *wcnss;
  117. int ret;
  118. btq = devm_kzalloc(&pdev->dev, sizeof(*btq), GFP_KERNEL);
  119. if (!btq)
  120. return -ENOMEM;
  121. wcnss = dev_get_drvdata(pdev->dev.parent);
  122. btq->acl_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_ACL",
  123. btqcomsmd_acl_callback, btq);
  124. if (IS_ERR(btq->acl_channel))
  125. return PTR_ERR(btq->acl_channel);
  126. btq->cmd_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_CMD",
  127. btqcomsmd_cmd_callback, btq);
  128. if (IS_ERR(btq->cmd_channel)) {
  129. ret = PTR_ERR(btq->cmd_channel);
  130. goto destroy_acl_channel;
  131. }
  132. hdev = hci_alloc_dev();
  133. if (!hdev) {
  134. ret = -ENOMEM;
  135. goto destroy_cmd_channel;
  136. }
  137. hci_set_drvdata(hdev, btq);
  138. btq->hdev = hdev;
  139. SET_HCIDEV_DEV(hdev, &pdev->dev);
  140. hdev->bus = HCI_SMD;
  141. hdev->open = btqcomsmd_open;
  142. hdev->close = btqcomsmd_close;
  143. hdev->send = btqcomsmd_send;
  144. hdev->setup = btqcomsmd_setup;
  145. hdev->set_bdaddr = btqcomsmd_set_bdaddr;
  146. ret = hci_register_dev(hdev);
  147. if (ret < 0)
  148. goto hci_free_dev;
  149. platform_set_drvdata(pdev, btq);
  150. return 0;
  151. hci_free_dev:
  152. hci_free_dev(hdev);
  153. destroy_cmd_channel:
  154. rpmsg_destroy_ept(btq->cmd_channel);
  155. destroy_acl_channel:
  156. rpmsg_destroy_ept(btq->acl_channel);
  157. return ret;
  158. }
  159. static void btqcomsmd_remove(struct platform_device *pdev)
  160. {
  161. struct btqcomsmd *btq = platform_get_drvdata(pdev);
  162. hci_unregister_dev(btq->hdev);
  163. hci_free_dev(btq->hdev);
  164. rpmsg_destroy_ept(btq->cmd_channel);
  165. rpmsg_destroy_ept(btq->acl_channel);
  166. }
  167. static const struct of_device_id btqcomsmd_of_match[] = {
  168. { .compatible = "qcom,wcnss-bt", },
  169. { },
  170. };
  171. MODULE_DEVICE_TABLE(of, btqcomsmd_of_match);
  172. static struct platform_driver btqcomsmd_driver = {
  173. .probe = btqcomsmd_probe,
  174. .remove_new = btqcomsmd_remove,
  175. .driver = {
  176. .name = "btqcomsmd",
  177. .of_match_table = btqcomsmd_of_match,
  178. },
  179. };
  180. module_platform_driver(btqcomsmd_driver);
  181. MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
  182. MODULE_DESCRIPTION("Qualcomm SMD HCI driver");
  183. MODULE_LICENSE("GPL v2");