2 * Copyright (c) 2015, Sony Mobile Communications Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include <linux/module.h>
15 #include <linux/slab.h>
16 #include <linux/soc/qcom/smd.h>
17 #include <net/bluetooth/bluetooth.h>
18 #include <net/bluetooth/hci_core.h>
19 #include <net/bluetooth/hci.h>
21 #define EDL_NVM_ACCESS_SET_REQ_CMD 0x01
22 #define EDL_NVM_ACCESS_OPCODE 0xfc0b
25 struct qcom_smd_channel *acl_channel;
26 struct qcom_smd_channel *cmd_channel;
29 static int btqcomsmd_recv(struct hci_dev *hdev,
37 /* Use GFP_ATOMIC as we're in IRQ context */
38 skb = bt_skb_alloc(count, GFP_ATOMIC);
42 bt_cb(skb)->pkt_type = type;
44 /* Use io accessor as data might be ioremapped */
45 buf = skb_put(skb, count);
46 memcpy_fromio(buf, data, count);
48 return hci_recv_frame(hdev, skb);
51 static int btqcomsmd_acl_callback(struct qcom_smd_device *qsdev,
55 struct hci_dev *hdev = dev_get_drvdata(&qsdev->dev);
57 return btqcomsmd_recv(hdev, HCI_ACLDATA_PKT, data, count);
60 static int btqcomsmd_cmd_callback(struct qcom_smd_device *qsdev,
64 struct hci_dev *hdev = dev_get_drvdata(&qsdev->dev);
66 return btqcomsmd_recv(hdev, HCI_EVENT_PKT, data, count);
69 static int btqcomsmd_send(struct hci_dev *hdev, struct sk_buff *skb)
71 struct btqcomsmd *btq = hci_get_drvdata(hdev);
74 switch (bt_cb(skb)->pkt_type) {
77 ret = qcom_smd_send(btq->acl_channel, skb->data, skb->len);
80 ret = qcom_smd_send(btq->cmd_channel, skb->data, skb->len);
90 static int btqcomsmd_open(struct hci_dev *hdev)
92 set_bit(HCI_RUNNING, &hdev->flags);
96 static int btqcomsmd_close(struct hci_dev *hdev)
98 clear_bit(HCI_RUNNING, &hdev->flags);
102 static int btqcomsmd_set_bdaddr(struct hci_dev *hdev,
103 const bdaddr_t *bdaddr)
109 cmd[0] = EDL_NVM_ACCESS_SET_REQ_CMD;
110 cmd[1] = 0x02; /* TAG ID */
111 cmd[2] = sizeof(bdaddr_t); /* size */
112 memcpy(cmd + 3, bdaddr, sizeof(bdaddr_t));
113 skb = __hci_cmd_sync_ev(hdev,
114 EDL_NVM_ACCESS_OPCODE,
116 HCI_VENDOR_PKT, HCI_INIT_TIMEOUT);
119 BT_ERR("%s: Change address command failed (%d)",
129 static int btqcomsmd_probe(struct qcom_smd_device *sdev)
131 struct qcom_smd_channel *acl;
132 struct btqcomsmd *btq;
133 struct hci_dev *hdev;
136 acl = qcom_smd_open_channel(sdev,
138 btqcomsmd_acl_callback);
142 btq = devm_kzalloc(&sdev->dev, sizeof(*btq), GFP_KERNEL);
146 btq->acl_channel = acl;
147 btq->cmd_channel = sdev->channel;
149 hdev = hci_alloc_dev();
154 hdev->open = btqcomsmd_open;
155 hdev->close = btqcomsmd_close;
156 hdev->send = btqcomsmd_send;
157 hdev->set_bdaddr = btqcomsmd_set_bdaddr;
159 ret = hci_register_dev(hdev);
165 hci_set_drvdata(hdev, btq);
166 dev_set_drvdata(&sdev->dev, hdev);
171 static void btqcomsmd_remove(struct qcom_smd_device *sdev)
173 struct hci_dev *hdev = dev_get_drvdata(&sdev->dev);;
175 hci_unregister_dev(hdev);
179 static const struct qcom_smd_id btqcomsmd_match[] = {
180 { .name = "APPS_RIVA_BT_CMD" },
184 static struct qcom_smd_driver btqcomsmd_cmd_driver = {
185 .probe = btqcomsmd_probe,
186 .remove = btqcomsmd_remove,
187 .callback = btqcomsmd_cmd_callback,
188 .smd_match_table = btqcomsmd_match,
191 .owner = THIS_MODULE,
195 module_qcom_smd_driver(btqcomsmd_cmd_driver);
197 MODULE_DESCRIPTION("Qualcomm SMD HCI driver");
198 MODULE_LICENSE("GPL v2");