0001
0002
0003
0004
0005
0006
0007 #include <linux/module.h>
0008 #include <linux/slab.h>
0009 #include <linux/rpmsg.h>
0010 #include <linux/of.h>
0011
0012 #include <linux/soc/qcom/wcnss_ctrl.h>
0013 #include <linux/platform_device.h>
0014
0015 #include <net/bluetooth/bluetooth.h>
0016 #include <net/bluetooth/hci_core.h>
0017
0018 #include "btqca.h"
0019
0020 struct btqcomsmd {
0021 struct hci_dev *hdev;
0022
0023 struct rpmsg_endpoint *acl_channel;
0024 struct rpmsg_endpoint *cmd_channel;
0025 };
0026
0027 static int btqcomsmd_recv(struct hci_dev *hdev, unsigned int type,
0028 const void *data, size_t count)
0029 {
0030 struct sk_buff *skb;
0031
0032
0033 skb = bt_skb_alloc(count, GFP_ATOMIC);
0034 if (!skb) {
0035 hdev->stat.err_rx++;
0036 return -ENOMEM;
0037 }
0038
0039 hci_skb_pkt_type(skb) = type;
0040 skb_put_data(skb, data, count);
0041
0042 return hci_recv_frame(hdev, skb);
0043 }
0044
0045 static int btqcomsmd_acl_callback(struct rpmsg_device *rpdev, void *data,
0046 int count, void *priv, u32 addr)
0047 {
0048 struct btqcomsmd *btq = priv;
0049
0050 btq->hdev->stat.byte_rx += count;
0051 return btqcomsmd_recv(btq->hdev, HCI_ACLDATA_PKT, data, count);
0052 }
0053
0054 static int btqcomsmd_cmd_callback(struct rpmsg_device *rpdev, void *data,
0055 int count, void *priv, u32 addr)
0056 {
0057 struct btqcomsmd *btq = priv;
0058
0059 btq->hdev->stat.byte_rx += count;
0060 return btqcomsmd_recv(btq->hdev, HCI_EVENT_PKT, data, count);
0061 }
0062
0063 static int btqcomsmd_send(struct hci_dev *hdev, struct sk_buff *skb)
0064 {
0065 struct btqcomsmd *btq = hci_get_drvdata(hdev);
0066 int ret;
0067
0068 switch (hci_skb_pkt_type(skb)) {
0069 case HCI_ACLDATA_PKT:
0070 ret = rpmsg_send(btq->acl_channel, skb->data, skb->len);
0071 if (ret) {
0072 hdev->stat.err_tx++;
0073 break;
0074 }
0075 hdev->stat.acl_tx++;
0076 hdev->stat.byte_tx += skb->len;
0077 break;
0078 case HCI_COMMAND_PKT:
0079 ret = rpmsg_send(btq->cmd_channel, skb->data, skb->len);
0080 if (ret) {
0081 hdev->stat.err_tx++;
0082 break;
0083 }
0084 hdev->stat.cmd_tx++;
0085 hdev->stat.byte_tx += skb->len;
0086 break;
0087 default:
0088 ret = -EILSEQ;
0089 break;
0090 }
0091
0092 if (!ret)
0093 kfree_skb(skb);
0094
0095 return ret;
0096 }
0097
0098 static int btqcomsmd_open(struct hci_dev *hdev)
0099 {
0100 return 0;
0101 }
0102
0103 static int btqcomsmd_close(struct hci_dev *hdev)
0104 {
0105 return 0;
0106 }
0107
0108 static int btqcomsmd_setup(struct hci_dev *hdev)
0109 {
0110 struct sk_buff *skb;
0111
0112 skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
0113 if (IS_ERR(skb))
0114 return PTR_ERR(skb);
0115 kfree_skb(skb);
0116
0117
0118
0119
0120 set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
0121
0122 return 0;
0123 }
0124
0125 static int btqcomsmd_probe(struct platform_device *pdev)
0126 {
0127 struct btqcomsmd *btq;
0128 struct hci_dev *hdev;
0129 void *wcnss;
0130 int ret;
0131
0132 btq = devm_kzalloc(&pdev->dev, sizeof(*btq), GFP_KERNEL);
0133 if (!btq)
0134 return -ENOMEM;
0135
0136 wcnss = dev_get_drvdata(pdev->dev.parent);
0137
0138 btq->acl_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_ACL",
0139 btqcomsmd_acl_callback, btq);
0140 if (IS_ERR(btq->acl_channel))
0141 return PTR_ERR(btq->acl_channel);
0142
0143 btq->cmd_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_CMD",
0144 btqcomsmd_cmd_callback, btq);
0145 if (IS_ERR(btq->cmd_channel)) {
0146 ret = PTR_ERR(btq->cmd_channel);
0147 goto destroy_acl_channel;
0148 }
0149
0150 hdev = hci_alloc_dev();
0151 if (!hdev) {
0152 ret = -ENOMEM;
0153 goto destroy_cmd_channel;
0154 }
0155
0156 hci_set_drvdata(hdev, btq);
0157 btq->hdev = hdev;
0158 SET_HCIDEV_DEV(hdev, &pdev->dev);
0159
0160 hdev->bus = HCI_SMD;
0161 hdev->open = btqcomsmd_open;
0162 hdev->close = btqcomsmd_close;
0163 hdev->send = btqcomsmd_send;
0164 hdev->setup = btqcomsmd_setup;
0165 hdev->set_bdaddr = qca_set_bdaddr_rome;
0166
0167 ret = hci_register_dev(hdev);
0168 if (ret < 0)
0169 goto hci_free_dev;
0170
0171 platform_set_drvdata(pdev, btq);
0172
0173 return 0;
0174
0175 hci_free_dev:
0176 hci_free_dev(hdev);
0177 destroy_cmd_channel:
0178 rpmsg_destroy_ept(btq->cmd_channel);
0179 destroy_acl_channel:
0180 rpmsg_destroy_ept(btq->acl_channel);
0181
0182 return ret;
0183 }
0184
0185 static int btqcomsmd_remove(struct platform_device *pdev)
0186 {
0187 struct btqcomsmd *btq = platform_get_drvdata(pdev);
0188
0189 hci_unregister_dev(btq->hdev);
0190 hci_free_dev(btq->hdev);
0191
0192 rpmsg_destroy_ept(btq->cmd_channel);
0193 rpmsg_destroy_ept(btq->acl_channel);
0194
0195 return 0;
0196 }
0197
0198 static const struct of_device_id btqcomsmd_of_match[] = {
0199 { .compatible = "qcom,wcnss-bt", },
0200 { },
0201 };
0202 MODULE_DEVICE_TABLE(of, btqcomsmd_of_match);
0203
0204 static struct platform_driver btqcomsmd_driver = {
0205 .probe = btqcomsmd_probe,
0206 .remove = btqcomsmd_remove,
0207 .driver = {
0208 .name = "btqcomsmd",
0209 .of_match_table = btqcomsmd_of_match,
0210 },
0211 };
0212
0213 module_platform_driver(btqcomsmd_driver);
0214
0215 MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
0216 MODULE_DESCRIPTION("Qualcomm SMD HCI driver");
0217 MODULE_LICENSE("GPL v2");