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 bdaddr_t bdaddr; 32 struct rpmsg_endpoint *acl_channel; 33 struct rpmsg_endpoint *cmd_channel; 34 }; 35 36 static int btqcomsmd_recv(struct hci_dev *hdev, unsigned int type, 37 const void *data, size_t count) 38 { 39 struct sk_buff *skb; 40 41 /* Use GFP_ATOMIC as we're in IRQ context */ 42 skb = bt_skb_alloc(count, GFP_ATOMIC); 43 if (!skb) { 44 hdev->stat.err_rx++; 45 return -ENOMEM; 46 } 47 48 hci_skb_pkt_type(skb) = type; 49 skb_put_data(skb, data, count); 50 51 return hci_recv_frame(hdev, skb); 52 } 53 54 static int btqcomsmd_acl_callback(struct rpmsg_device *rpdev, void *data, 55 int count, void *priv, u32 addr) 56 { 57 struct btqcomsmd *btq = priv; 58 59 btq->hdev->stat.byte_rx += count; 60 return btqcomsmd_recv(btq->hdev, HCI_ACLDATA_PKT, data, count); 61 } 62 63 static int btqcomsmd_cmd_callback(struct rpmsg_device *rpdev, void *data, 64 int count, void *priv, u32 addr) 65 { 66 struct btqcomsmd *btq = priv; 67 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 hdev->stat.acl_tx++; 80 hdev->stat.byte_tx += skb->len; 81 break; 82 case HCI_COMMAND_PKT: 83 ret = rpmsg_send(btq->cmd_channel, skb->data, skb->len); 84 hdev->stat.cmd_tx++; 85 break; 86 default: 87 ret = -EILSEQ; 88 break; 89 } 90 91 if (!ret) 92 kfree_skb(skb); 93 94 return ret; 95 } 96 97 static int btqcomsmd_open(struct hci_dev *hdev) 98 { 99 return 0; 100 } 101 102 static int btqcomsmd_close(struct hci_dev *hdev) 103 { 104 return 0; 105 } 106 107 static int btqcomsmd_setup(struct hci_dev *hdev) 108 { 109 struct btqcomsmd *btq = hci_get_drvdata(hdev); 110 struct sk_buff *skb; 111 int err; 112 113 skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); 114 if (IS_ERR(skb)) 115 return PTR_ERR(skb); 116 kfree_skb(skb); 117 118 /* Devices do not have persistent storage for BD address. If no 119 * BD address has been retrieved during probe, mark the device 120 * as having an invalid BD address. 121 */ 122 if (!bacmp(&btq->bdaddr, BDADDR_ANY)) { 123 set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); 124 return 0; 125 } 126 127 /* When setting a configured BD address fails, mark the device 128 * as having an invalid BD address. 129 */ 130 err = qca_set_bdaddr_rome(hdev, &btq->bdaddr); 131 if (err) { 132 set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); 133 return 0; 134 } 135 136 return 0; 137 } 138 139 static int btqcomsmd_probe(struct platform_device *pdev) 140 { 141 struct btqcomsmd *btq; 142 struct hci_dev *hdev; 143 void *wcnss; 144 int ret; 145 146 btq = devm_kzalloc(&pdev->dev, sizeof(*btq), GFP_KERNEL); 147 if (!btq) 148 return -ENOMEM; 149 150 wcnss = dev_get_drvdata(pdev->dev.parent); 151 152 btq->acl_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_ACL", 153 btqcomsmd_acl_callback, btq); 154 if (IS_ERR(btq->acl_channel)) 155 return PTR_ERR(btq->acl_channel); 156 157 btq->cmd_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_CMD", 158 btqcomsmd_cmd_callback, btq); 159 if (IS_ERR(btq->cmd_channel)) 160 return PTR_ERR(btq->cmd_channel); 161 162 /* The local-bd-address property is usually injected by the 163 * bootloader which has access to the allocated BD address. 164 */ 165 if (!of_property_read_u8_array(pdev->dev.of_node, "local-bd-address", 166 (u8 *)&btq->bdaddr, sizeof(bdaddr_t))) { 167 dev_info(&pdev->dev, "BD address %pMR retrieved from device-tree", 168 &btq->bdaddr); 169 } 170 171 hdev = hci_alloc_dev(); 172 if (!hdev) 173 return -ENOMEM; 174 175 hci_set_drvdata(hdev, btq); 176 btq->hdev = hdev; 177 SET_HCIDEV_DEV(hdev, &pdev->dev); 178 179 hdev->bus = HCI_SMD; 180 hdev->open = btqcomsmd_open; 181 hdev->close = btqcomsmd_close; 182 hdev->send = btqcomsmd_send; 183 hdev->setup = btqcomsmd_setup; 184 hdev->set_bdaddr = qca_set_bdaddr_rome; 185 186 ret = hci_register_dev(hdev); 187 if (ret < 0) { 188 hci_free_dev(hdev); 189 return ret; 190 } 191 192 platform_set_drvdata(pdev, btq); 193 194 return 0; 195 } 196 197 static int btqcomsmd_remove(struct platform_device *pdev) 198 { 199 struct btqcomsmd *btq = platform_get_drvdata(pdev); 200 201 hci_unregister_dev(btq->hdev); 202 hci_free_dev(btq->hdev); 203 204 rpmsg_destroy_ept(btq->cmd_channel); 205 rpmsg_destroy_ept(btq->acl_channel); 206 207 return 0; 208 } 209 210 static const struct of_device_id btqcomsmd_of_match[] = { 211 { .compatible = "qcom,wcnss-bt", }, 212 { }, 213 }; 214 MODULE_DEVICE_TABLE(of, btqcomsmd_of_match); 215 216 static struct platform_driver btqcomsmd_driver = { 217 .probe = btqcomsmd_probe, 218 .remove = btqcomsmd_remove, 219 .driver = { 220 .name = "btqcomsmd", 221 .of_match_table = btqcomsmd_of_match, 222 }, 223 }; 224 225 module_platform_driver(btqcomsmd_driver); 226 227 MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>"); 228 MODULE_DESCRIPTION("Qualcomm SMD HCI driver"); 229 MODULE_LICENSE("GPL v2"); 230