1 /* 2 * 3 * Bluetooth HCI UART driver for Broadcom devices 4 * 5 * Copyright (C) 2015 Intel Corporation 6 * 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 */ 23 24 #include <linux/kernel.h> 25 #include <linux/errno.h> 26 #include <linux/skbuff.h> 27 #include <linux/firmware.h> 28 29 #include <net/bluetooth/bluetooth.h> 30 #include <net/bluetooth/hci_core.h> 31 32 #include "btbcm.h" 33 #include "hci_uart.h" 34 35 struct bcm_data { 36 struct sk_buff *rx_skb; 37 struct sk_buff_head txq; 38 }; 39 40 static int bcm_set_baudrate(struct hci_uart *hu, unsigned int speed) 41 { 42 struct hci_dev *hdev = hu->hdev; 43 struct sk_buff *skb; 44 struct bcm_update_uart_baud_rate param; 45 46 if (speed > 3000000) { 47 struct bcm_write_uart_clock_setting clock; 48 49 clock.type = BCM_UART_CLOCK_48MHZ; 50 51 BT_DBG("%s: Set Controller clock (%d)", hdev->name, clock.type); 52 53 /* This Broadcom specific command changes the UART's controller 54 * clock for baud rate > 3000000. 55 */ 56 skb = __hci_cmd_sync(hdev, 0xfc45, 1, &clock, HCI_INIT_TIMEOUT); 57 if (IS_ERR(skb)) { 58 int err = PTR_ERR(skb); 59 BT_ERR("%s: BCM: failed to write clock command (%d)", 60 hdev->name, err); 61 return err; 62 } 63 64 kfree_skb(skb); 65 } 66 67 BT_DBG("%s: Set Controller UART speed to %d bit/s", hdev->name, speed); 68 69 param.zero = cpu_to_le16(0); 70 param.baud_rate = cpu_to_le32(speed); 71 72 /* This Broadcom specific command changes the UART's controller baud 73 * rate. 74 */ 75 skb = __hci_cmd_sync(hdev, 0xfc18, sizeof(param), ¶m, 76 HCI_INIT_TIMEOUT); 77 if (IS_ERR(skb)) { 78 int err = PTR_ERR(skb); 79 BT_ERR("%s: BCM: failed to write update baudrate command (%d)", 80 hdev->name, err); 81 return err; 82 } 83 84 kfree_skb(skb); 85 86 return 0; 87 } 88 89 static int bcm_open(struct hci_uart *hu) 90 { 91 struct bcm_data *bcm; 92 93 BT_DBG("hu %p", hu); 94 95 bcm = kzalloc(sizeof(*bcm), GFP_KERNEL); 96 if (!bcm) 97 return -ENOMEM; 98 99 skb_queue_head_init(&bcm->txq); 100 101 hu->priv = bcm; 102 return 0; 103 } 104 105 static int bcm_close(struct hci_uart *hu) 106 { 107 struct bcm_data *bcm = hu->priv; 108 109 BT_DBG("hu %p", hu); 110 111 skb_queue_purge(&bcm->txq); 112 kfree_skb(bcm->rx_skb); 113 kfree(bcm); 114 115 hu->priv = NULL; 116 return 0; 117 } 118 119 static int bcm_flush(struct hci_uart *hu) 120 { 121 struct bcm_data *bcm = hu->priv; 122 123 BT_DBG("hu %p", hu); 124 125 skb_queue_purge(&bcm->txq); 126 127 return 0; 128 } 129 130 static int bcm_setup(struct hci_uart *hu) 131 { 132 char fw_name[64]; 133 const struct firmware *fw; 134 unsigned int speed; 135 int err; 136 137 BT_DBG("hu %p", hu); 138 139 hu->hdev->set_bdaddr = btbcm_set_bdaddr; 140 141 err = btbcm_initialize(hu->hdev, fw_name, sizeof(fw_name)); 142 if (err) 143 return err; 144 145 err = request_firmware(&fw, fw_name, &hu->hdev->dev); 146 if (err < 0) { 147 BT_INFO("%s: BCM: Patch %s not found", hu->hdev->name, fw_name); 148 return 0; 149 } 150 151 err = btbcm_patchram(hu->hdev, fw); 152 if (err) { 153 BT_INFO("%s: BCM: Patch failed (%d)", hu->hdev->name, err); 154 goto finalize; 155 } 156 157 /* Init speed if any */ 158 if (hu->init_speed) 159 speed = hu->init_speed; 160 else if (hu->proto->init_speed) 161 speed = hu->proto->init_speed; 162 else 163 speed = 0; 164 165 if (speed) 166 hci_uart_set_baudrate(hu, speed); 167 168 /* Operational speed if any */ 169 if (hu->oper_speed) 170 speed = hu->oper_speed; 171 else if (hu->proto->oper_speed) 172 speed = hu->proto->oper_speed; 173 else 174 speed = 0; 175 176 if (speed) { 177 err = bcm_set_baudrate(hu, speed); 178 if (!err) 179 hci_uart_set_baudrate(hu, speed); 180 } 181 182 finalize: 183 release_firmware(fw); 184 185 err = btbcm_finalize(hu->hdev); 186 187 return err; 188 } 189 190 static const struct h4_recv_pkt bcm_recv_pkts[] = { 191 { H4_RECV_ACL, .recv = hci_recv_frame }, 192 { H4_RECV_SCO, .recv = hci_recv_frame }, 193 { H4_RECV_EVENT, .recv = hci_recv_frame }, 194 }; 195 196 static int bcm_recv(struct hci_uart *hu, const void *data, int count) 197 { 198 struct bcm_data *bcm = hu->priv; 199 200 if (!test_bit(HCI_UART_REGISTERED, &hu->flags)) 201 return -EUNATCH; 202 203 bcm->rx_skb = h4_recv_buf(hu->hdev, bcm->rx_skb, data, count, 204 bcm_recv_pkts, ARRAY_SIZE(bcm_recv_pkts)); 205 if (IS_ERR(bcm->rx_skb)) { 206 int err = PTR_ERR(bcm->rx_skb); 207 BT_ERR("%s: Frame reassembly failed (%d)", hu->hdev->name, err); 208 bcm->rx_skb = NULL; 209 return err; 210 } 211 212 return count; 213 } 214 215 static int bcm_enqueue(struct hci_uart *hu, struct sk_buff *skb) 216 { 217 struct bcm_data *bcm = hu->priv; 218 219 BT_DBG("hu %p skb %p", hu, skb); 220 221 /* Prepend skb with frame type */ 222 memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); 223 skb_queue_tail(&bcm->txq, skb); 224 225 return 0; 226 } 227 228 static struct sk_buff *bcm_dequeue(struct hci_uart *hu) 229 { 230 struct bcm_data *bcm = hu->priv; 231 232 return skb_dequeue(&bcm->txq); 233 } 234 235 static const struct hci_uart_proto bcm_proto = { 236 .id = HCI_UART_BCM, 237 .name = "BCM", 238 .init_speed = 115200, 239 .oper_speed = 4000000, 240 .open = bcm_open, 241 .close = bcm_close, 242 .flush = bcm_flush, 243 .setup = bcm_setup, 244 .set_baudrate = bcm_set_baudrate, 245 .recv = bcm_recv, 246 .enqueue = bcm_enqueue, 247 .dequeue = bcm_dequeue, 248 }; 249 250 int __init bcm_init(void) 251 { 252 return hci_uart_register_proto(&bcm_proto); 253 } 254 255 int __exit bcm_deinit(void) 256 { 257 return hci_uart_unregister_proto(&bcm_proto); 258 } 259