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 15 #include <linux/module.h> 16 #include <linux/slab.h> 17 #include <linux/rpmsg.h> 18 #include <linux/of.h> 19 20 #include <linux/soc/qcom/wcnss_ctrl.h> 21 #include <linux/platform_device.h> 22 23 #include <net/bluetooth/bluetooth.h> 24 #include <net/bluetooth/hci_core.h> 25 26 #include "btqca.h" 27 28 struct btqcomsmd { 29 struct hci_dev *hdev; 30 31 struct rpmsg_endpoint *acl_channel; 32 struct rpmsg_endpoint *cmd_channel; 33 }; 34 35 static int btqcomsmd_recv(struct hci_dev *hdev, unsigned int type, 36 const void *data, size_t count) 37 { 38 struct sk_buff *skb; 39 40 /* Use GFP_ATOMIC as we're in IRQ context */ 41 skb = bt_skb_alloc(count, GFP_ATOMIC); 42 if (!skb) { 43 hdev->stat.err_rx++; 44 return -ENOMEM; 45 } 46 47 hci_skb_pkt_type(skb) = type; 48 skb_put_data(skb, data, count); 49 50 return hci_recv_frame(hdev, skb); 51 } 52 53 static int btqcomsmd_acl_callback(struct rpmsg_device *rpdev, void *data, 54 int count, void *priv, u32 addr) 55 { 56 struct btqcomsmd *btq = priv; 57 58 btq->hdev->stat.byte_rx += count; 59 return btqcomsmd_recv(btq->hdev, HCI_ACLDATA_PKT, data, count); 60 } 61 62 static int btqcomsmd_cmd_callback(struct rpmsg_device *rpdev, void *data, 63 int count, void *priv, u32 addr) 64 { 65 struct btqcomsmd *btq = priv; 66 67 btq->hdev->stat.byte_rx += count; 68 return btqcomsmd_recv(btq->hdev, HCI_EVENT_PKT, data, count); 69 } 70 71 static int btqcomsmd_send(struct hci_dev *hdev, struct sk_buff *skb) 72 { 73 struct btqcomsmd *btq = hci_get_drvdata(hdev); 74 int ret; 75 76 switch (hci_skb_pkt_type(skb)) { 77 case HCI_ACLDATA_PKT: 78 ret = rpmsg_send(btq->acl_channel, skb->data, skb->len); 79 if (ret) { 80 hdev->stat.err_tx++; 81 break; 82 } 83 hdev->stat.acl_tx++; 84 hdev->stat.byte_tx += skb->len; 85 break; 86 case HCI_COMMAND_PKT: 87 ret = rpmsg_send(btq->cmd_channel, skb->data, skb->len); 88 if (ret) { 89 hdev->stat.err_tx++; 90 break; 91 } 92 hdev->stat.cmd_tx++; 93 hdev->stat.byte_tx += skb->len; 94 break; 95 default: 96 ret = -EILSEQ; 97 break; 98 } 99 100 if (!ret) 101 kfree_skb(skb); 102 103 return ret; 104 } 105 106 static int btqcomsmd_open(struct hci_dev *hdev) 107 { 108 return 0; 109 } 110 111 static int btqcomsmd_close(struct hci_dev *hdev) 112 { 113 return 0; 114 } 115 116 static int btqcomsmd_setup(struct hci_dev *hdev) 117 { 118 struct sk_buff *skb; 119 120 skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); 121 if (IS_ERR(skb)) 122 return PTR_ERR(skb); 123 kfree_skb(skb); 124 125 /* Devices do not have persistent storage for BD address. Retrieve 126 * it from the firmware node property. 127 */ 128 set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); 129 130 return 0; 131 } 132 133 static int btqcomsmd_probe(struct platform_device *pdev) 134 { 135 struct btqcomsmd *btq; 136 struct hci_dev *hdev; 137 void *wcnss; 138 int ret; 139 140 btq = devm_kzalloc(&pdev->dev, sizeof(*btq), GFP_KERNEL); 141 if (!btq) 142 return -ENOMEM; 143 144 wcnss = dev_get_drvdata(pdev->dev.parent); 145 146 btq->acl_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_ACL", 147 btqcomsmd_acl_callback, btq); 148 if (IS_ERR(btq->acl_channel)) 149 return PTR_ERR(btq->acl_channel); 150 151 btq->cmd_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_CMD", 152 btqcomsmd_cmd_callback, btq); 153 if (IS_ERR(btq->cmd_channel)) 154 return PTR_ERR(btq->cmd_channel); 155 156 hdev = hci_alloc_dev(); 157 if (!hdev) 158 return -ENOMEM; 159 160 hci_set_drvdata(hdev, btq); 161 btq->hdev = hdev; 162 SET_HCIDEV_DEV(hdev, &pdev->dev); 163 164 hdev->bus = HCI_SMD; 165 hdev->open = btqcomsmd_open; 166 hdev->close = btqcomsmd_close; 167 hdev->send = btqcomsmd_send; 168 hdev->setup = btqcomsmd_setup; 169 hdev->set_bdaddr = qca_set_bdaddr_rome; 170 171 ret = hci_register_dev(hdev); 172 if (ret < 0) { 173 hci_free_dev(hdev); 174 return ret; 175 } 176 177 platform_set_drvdata(pdev, btq); 178 179 return 0; 180 } 181 182 static int btqcomsmd_remove(struct platform_device *pdev) 183 { 184 struct btqcomsmd *btq = platform_get_drvdata(pdev); 185 186 hci_unregister_dev(btq->hdev); 187 hci_free_dev(btq->hdev); 188 189 rpmsg_destroy_ept(btq->cmd_channel); 190 rpmsg_destroy_ept(btq->acl_channel); 191 192 return 0; 193 } 194 195 static const struct of_device_id btqcomsmd_of_match[] = { 196 { .compatible = "qcom,wcnss-bt", }, 197 { }, 198 }; 199 MODULE_DEVICE_TABLE(of, btqcomsmd_of_match); 200 201 static struct platform_driver btqcomsmd_driver = { 202 .probe = btqcomsmd_probe, 203 .remove = btqcomsmd_remove, 204 .driver = { 205 .name = "btqcomsmd", 206 .of_match_table = btqcomsmd_of_match, 207 }, 208 }; 209 210 module_platform_driver(btqcomsmd_driver); 211 212 MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>"); 213 MODULE_DESCRIPTION("Qualcomm SMD HCI driver"); 214 MODULE_LICENSE("GPL v2"); 215