btqcomsmd.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * Copyright (c) 2016, Linaro Ltd.
  3. * Copyright (c) 2015, Sony Mobile Communications Inc.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 and
  7. * only version 2 as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include <linux/module.h>
  15. #include <linux/slab.h>
  16. #include <linux/rpmsg.h>
  17. #include <linux/of.h>
  18. #include <linux/soc/qcom/wcnss_ctrl.h>
  19. #include <linux/platform_device.h>
  20. #include <net/bluetooth/bluetooth.h>
  21. #include <net/bluetooth/hci_core.h>
  22. #include "btqca.h"
  23. struct btqcomsmd {
  24. struct hci_dev *hdev;
  25. bdaddr_t bdaddr;
  26. struct rpmsg_endpoint *acl_channel;
  27. struct rpmsg_endpoint *cmd_channel;
  28. };
  29. static int btqcomsmd_recv(struct hci_dev *hdev, unsigned int type,
  30. const void *data, size_t count)
  31. {
  32. struct sk_buff *skb;
  33. /* Use GFP_ATOMIC as we're in IRQ context */
  34. skb = bt_skb_alloc(count, GFP_ATOMIC);
  35. if (!skb) {
  36. hdev->stat.err_rx++;
  37. return -ENOMEM;
  38. }
  39. hci_skb_pkt_type(skb) = type;
  40. skb_put_data(skb, data, count);
  41. return hci_recv_frame(hdev, skb);
  42. }
  43. static int btqcomsmd_acl_callback(struct rpmsg_device *rpdev, void *data,
  44. int count, void *priv, u32 addr)
  45. {
  46. struct btqcomsmd *btq = priv;
  47. btq->hdev->stat.byte_rx += count;
  48. return btqcomsmd_recv(btq->hdev, HCI_ACLDATA_PKT, data, count);
  49. }
  50. static int btqcomsmd_cmd_callback(struct rpmsg_device *rpdev, void *data,
  51. int count, void *priv, u32 addr)
  52. {
  53. struct btqcomsmd *btq = priv;
  54. return btqcomsmd_recv(btq->hdev, HCI_EVENT_PKT, data, count);
  55. }
  56. static int btqcomsmd_send(struct hci_dev *hdev, struct sk_buff *skb)
  57. {
  58. struct btqcomsmd *btq = hci_get_drvdata(hdev);
  59. int ret;
  60. switch (hci_skb_pkt_type(skb)) {
  61. case HCI_ACLDATA_PKT:
  62. ret = rpmsg_send(btq->acl_channel, skb->data, skb->len);
  63. hdev->stat.acl_tx++;
  64. hdev->stat.byte_tx += skb->len;
  65. break;
  66. case HCI_COMMAND_PKT:
  67. ret = rpmsg_send(btq->cmd_channel, skb->data, skb->len);
  68. hdev->stat.cmd_tx++;
  69. break;
  70. default:
  71. ret = -EILSEQ;
  72. break;
  73. }
  74. if (!ret)
  75. kfree_skb(skb);
  76. return ret;
  77. }
  78. static int btqcomsmd_open(struct hci_dev *hdev)
  79. {
  80. return 0;
  81. }
  82. static int btqcomsmd_close(struct hci_dev *hdev)
  83. {
  84. return 0;
  85. }
  86. static int btqcomsmd_setup(struct hci_dev *hdev)
  87. {
  88. struct btqcomsmd *btq = hci_get_drvdata(hdev);
  89. struct sk_buff *skb;
  90. int err;
  91. skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
  92. if (IS_ERR(skb))
  93. return PTR_ERR(skb);
  94. kfree_skb(skb);
  95. /* Devices do not have persistent storage for BD address. If no
  96. * BD address has been retrieved during probe, mark the device
  97. * as having an invalid BD address.
  98. */
  99. if (!bacmp(&btq->bdaddr, BDADDR_ANY)) {
  100. set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
  101. return 0;
  102. }
  103. /* When setting a configured BD address fails, mark the device
  104. * as having an invalid BD address.
  105. */
  106. err = qca_set_bdaddr_rome(hdev, &btq->bdaddr);
  107. if (err) {
  108. set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
  109. return 0;
  110. }
  111. return 0;
  112. }
  113. static int btqcomsmd_probe(struct platform_device *pdev)
  114. {
  115. struct btqcomsmd *btq;
  116. struct hci_dev *hdev;
  117. void *wcnss;
  118. int ret;
  119. btq = devm_kzalloc(&pdev->dev, sizeof(*btq), GFP_KERNEL);
  120. if (!btq)
  121. return -ENOMEM;
  122. wcnss = dev_get_drvdata(pdev->dev.parent);
  123. btq->acl_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_ACL",
  124. btqcomsmd_acl_callback, btq);
  125. if (IS_ERR(btq->acl_channel))
  126. return PTR_ERR(btq->acl_channel);
  127. btq->cmd_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_CMD",
  128. btqcomsmd_cmd_callback, btq);
  129. if (IS_ERR(btq->cmd_channel))
  130. return PTR_ERR(btq->cmd_channel);
  131. /* The local-bd-address property is usually injected by the
  132. * bootloader which has access to the allocated BD address.
  133. */
  134. if (!of_property_read_u8_array(pdev->dev.of_node, "local-bd-address",
  135. (u8 *)&btq->bdaddr, sizeof(bdaddr_t))) {
  136. dev_info(&pdev->dev, "BD address %pMR retrieved from device-tree",
  137. &btq->bdaddr);
  138. }
  139. hdev = hci_alloc_dev();
  140. if (!hdev)
  141. return -ENOMEM;
  142. hci_set_drvdata(hdev, btq);
  143. btq->hdev = hdev;
  144. SET_HCIDEV_DEV(hdev, &pdev->dev);
  145. hdev->bus = HCI_SMD;
  146. hdev->open = btqcomsmd_open;
  147. hdev->close = btqcomsmd_close;
  148. hdev->send = btqcomsmd_send;
  149. hdev->setup = btqcomsmd_setup;
  150. hdev->set_bdaddr = qca_set_bdaddr_rome;
  151. ret = hci_register_dev(hdev);
  152. if (ret < 0) {
  153. hci_free_dev(hdev);
  154. return ret;
  155. }
  156. platform_set_drvdata(pdev, btq);
  157. return 0;
  158. }
  159. static int 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. return 0;
  167. }
  168. static const struct of_device_id btqcomsmd_of_match[] = {
  169. { .compatible = "qcom,wcnss-bt", },
  170. { },
  171. };
  172. MODULE_DEVICE_TABLE(of, btqcomsmd_of_match);
  173. static struct platform_driver btqcomsmd_driver = {
  174. .probe = btqcomsmd_probe,
  175. .remove = btqcomsmd_remove,
  176. .driver = {
  177. .name = "btqcomsmd",
  178. .of_match_table = btqcomsmd_of_match,
  179. },
  180. };
  181. module_platform_driver(btqcomsmd_driver);
  182. MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
  183. MODULE_DESCRIPTION("Qualcomm SMD HCI driver");
  184. MODULE_LICENSE("GPL v2");