btqcomsmd.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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. btq->hdev->stat.byte_rx += count;
  55. return btqcomsmd_recv(btq->hdev, HCI_EVENT_PKT, data, count);
  56. }
  57. static int btqcomsmd_send(struct hci_dev *hdev, struct sk_buff *skb)
  58. {
  59. struct btqcomsmd *btq = hci_get_drvdata(hdev);
  60. int ret;
  61. switch (hci_skb_pkt_type(skb)) {
  62. case HCI_ACLDATA_PKT:
  63. ret = rpmsg_send(btq->acl_channel, skb->data, skb->len);
  64. if (ret) {
  65. hdev->stat.err_tx++;
  66. break;
  67. }
  68. hdev->stat.acl_tx++;
  69. hdev->stat.byte_tx += skb->len;
  70. break;
  71. case HCI_COMMAND_PKT:
  72. ret = rpmsg_send(btq->cmd_channel, skb->data, skb->len);
  73. if (ret) {
  74. hdev->stat.err_tx++;
  75. break;
  76. }
  77. hdev->stat.cmd_tx++;
  78. hdev->stat.byte_tx += skb->len;
  79. break;
  80. default:
  81. ret = -EILSEQ;
  82. break;
  83. }
  84. if (!ret)
  85. kfree_skb(skb);
  86. return ret;
  87. }
  88. static int btqcomsmd_open(struct hci_dev *hdev)
  89. {
  90. return 0;
  91. }
  92. static int btqcomsmd_close(struct hci_dev *hdev)
  93. {
  94. return 0;
  95. }
  96. static int btqcomsmd_setup(struct hci_dev *hdev)
  97. {
  98. struct btqcomsmd *btq = hci_get_drvdata(hdev);
  99. struct sk_buff *skb;
  100. int err;
  101. skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
  102. if (IS_ERR(skb))
  103. return PTR_ERR(skb);
  104. kfree_skb(skb);
  105. /* Devices do not have persistent storage for BD address. If no
  106. * BD address has been retrieved during probe, mark the device
  107. * as having an invalid BD address.
  108. */
  109. if (!bacmp(&btq->bdaddr, BDADDR_ANY)) {
  110. set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
  111. return 0;
  112. }
  113. /* When setting a configured BD address fails, mark the device
  114. * as having an invalid BD address.
  115. */
  116. err = qca_set_bdaddr_rome(hdev, &btq->bdaddr);
  117. if (err) {
  118. set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
  119. return 0;
  120. }
  121. return 0;
  122. }
  123. static int btqcomsmd_probe(struct platform_device *pdev)
  124. {
  125. struct btqcomsmd *btq;
  126. struct hci_dev *hdev;
  127. void *wcnss;
  128. int ret;
  129. btq = devm_kzalloc(&pdev->dev, sizeof(*btq), GFP_KERNEL);
  130. if (!btq)
  131. return -ENOMEM;
  132. wcnss = dev_get_drvdata(pdev->dev.parent);
  133. btq->acl_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_ACL",
  134. btqcomsmd_acl_callback, btq);
  135. if (IS_ERR(btq->acl_channel))
  136. return PTR_ERR(btq->acl_channel);
  137. btq->cmd_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_CMD",
  138. btqcomsmd_cmd_callback, btq);
  139. if (IS_ERR(btq->cmd_channel))
  140. return PTR_ERR(btq->cmd_channel);
  141. /* The local-bd-address property is usually injected by the
  142. * bootloader which has access to the allocated BD address.
  143. */
  144. if (!of_property_read_u8_array(pdev->dev.of_node, "local-bd-address",
  145. (u8 *)&btq->bdaddr, sizeof(bdaddr_t))) {
  146. dev_info(&pdev->dev, "BD address %pMR retrieved from device-tree",
  147. &btq->bdaddr);
  148. }
  149. hdev = hci_alloc_dev();
  150. if (!hdev)
  151. return -ENOMEM;
  152. hci_set_drvdata(hdev, btq);
  153. btq->hdev = hdev;
  154. SET_HCIDEV_DEV(hdev, &pdev->dev);
  155. hdev->bus = HCI_SMD;
  156. hdev->open = btqcomsmd_open;
  157. hdev->close = btqcomsmd_close;
  158. hdev->send = btqcomsmd_send;
  159. hdev->setup = btqcomsmd_setup;
  160. hdev->set_bdaddr = qca_set_bdaddr_rome;
  161. ret = hci_register_dev(hdev);
  162. if (ret < 0) {
  163. hci_free_dev(hdev);
  164. return ret;
  165. }
  166. platform_set_drvdata(pdev, btq);
  167. return 0;
  168. }
  169. static int btqcomsmd_remove(struct platform_device *pdev)
  170. {
  171. struct btqcomsmd *btq = platform_get_drvdata(pdev);
  172. hci_unregister_dev(btq->hdev);
  173. hci_free_dev(btq->hdev);
  174. rpmsg_destroy_ept(btq->cmd_channel);
  175. rpmsg_destroy_ept(btq->acl_channel);
  176. return 0;
  177. }
  178. static const struct of_device_id btqcomsmd_of_match[] = {
  179. { .compatible = "qcom,wcnss-bt", },
  180. { },
  181. };
  182. MODULE_DEVICE_TABLE(of, btqcomsmd_of_match);
  183. static struct platform_driver btqcomsmd_driver = {
  184. .probe = btqcomsmd_probe,
  185. .remove = btqcomsmd_remove,
  186. .driver = {
  187. .name = "btqcomsmd",
  188. .of_match_table = btqcomsmd_of_match,
  189. },
  190. };
  191. module_platform_driver(btqcomsmd_driver);
  192. MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
  193. MODULE_DESCRIPTION("Qualcomm SMD HCI driver");
  194. MODULE_LICENSE("GPL v2");