Commit | Line | Data |
---|---|---|
83e81961 BYTK |
1 | /* |
2 | * Bluetooth supports for Qualcomm Atheros chips | |
3 | * | |
4 | * Copyright (c) 2015 The Linux Foundation. All rights reserved. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 | |
8 | * as published by the Free Software Foundation | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program; if not, write to the Free Software | |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | * | |
19 | */ | |
20 | #include <linux/module.h> | |
21 | #include <linux/firmware.h> | |
22 | ||
23 | #include <net/bluetooth/bluetooth.h> | |
24 | #include <net/bluetooth/hci_core.h> | |
25 | ||
26 | #include "btqca.h" | |
27 | ||
28 | #define VERSION "0.1" | |
29 | ||
30 | static int rome_patch_ver_req(struct hci_dev *hdev, u32 *rome_version) | |
31 | { | |
32 | struct sk_buff *skb; | |
33 | struct edl_event_hdr *edl; | |
34 | struct rome_version *ver; | |
35 | char cmd; | |
36 | int err = 0; | |
37 | ||
38 | BT_DBG("%s: ROME Patch Version Request", hdev->name); | |
39 | ||
40 | cmd = EDL_PATCH_VER_REQ_CMD; | |
41 | skb = __hci_cmd_sync_ev(hdev, EDL_PATCH_CMD_OPCODE, EDL_PATCH_CMD_LEN, | |
42 | &cmd, HCI_VENDOR_PKT, HCI_INIT_TIMEOUT); | |
43 | if (IS_ERR(skb)) { | |
44 | err = PTR_ERR(skb); | |
45 | BT_ERR("%s: Failed to read version of ROME (%d)", hdev->name, | |
46 | err); | |
47 | return err; | |
48 | } | |
49 | ||
50 | if (skb->len != sizeof(*edl) + sizeof(*ver)) { | |
51 | BT_ERR("%s: Version size mismatch len %d", hdev->name, | |
52 | skb->len); | |
53 | err = -EILSEQ; | |
54 | goto out; | |
55 | } | |
56 | ||
57 | edl = (struct edl_event_hdr *)(skb->data); | |
58 | if (!edl || !edl->data) { | |
59 | BT_ERR("%s: TLV with no header or no data", hdev->name); | |
60 | err = -EILSEQ; | |
61 | goto out; | |
62 | } | |
63 | ||
64 | if (edl->cresp != EDL_CMD_REQ_RES_EVT || | |
65 | edl->rtype != EDL_APP_VER_RES_EVT) { | |
66 | BT_ERR("%s: Wrong packet received %d %d", hdev->name, | |
67 | edl->cresp, edl->rtype); | |
68 | err = -EIO; | |
69 | goto out; | |
70 | } | |
71 | ||
72 | ver = (struct rome_version *)(edl->data); | |
73 | ||
74 | BT_DBG("%s: Product:0x%08x", hdev->name, le32_to_cpu(ver->product_id)); | |
75 | BT_DBG("%s: Patch :0x%08x", hdev->name, le16_to_cpu(ver->patch_ver)); | |
76 | BT_DBG("%s: ROM :0x%08x", hdev->name, le16_to_cpu(ver->rome_ver)); | |
77 | BT_DBG("%s: SOC :0x%08x", hdev->name, le32_to_cpu(ver->soc_id)); | |
78 | ||
79 | /* ROME chipset version can be decided by patch and SoC | |
80 | * version, combination with upper 2 bytes from SoC | |
81 | * and lower 2 bytes from patch will be used. | |
82 | */ | |
83 | *rome_version = (le32_to_cpu(ver->soc_id) << 16) | | |
84 | (le16_to_cpu(ver->rome_ver) & 0x0000ffff); | |
85 | ||
86 | out: | |
87 | kfree_skb(skb); | |
88 | ||
89 | return err; | |
90 | } | |
91 | ||
92 | static int rome_reset(struct hci_dev *hdev) | |
93 | { | |
94 | struct sk_buff *skb; | |
95 | int err; | |
96 | ||
97 | BT_DBG("%s: ROME HCI_RESET", hdev->name); | |
98 | ||
99 | skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); | |
100 | if (IS_ERR(skb)) { | |
101 | err = PTR_ERR(skb); | |
102 | BT_ERR("%s: Reset failed (%d)", hdev->name, err); | |
103 | return err; | |
104 | } | |
105 | ||
106 | kfree_skb(skb); | |
107 | ||
108 | return 0; | |
109 | } | |
110 | ||
111 | static void rome_tlv_check_data(struct rome_config *config, | |
112 | const struct firmware *fw) | |
113 | { | |
114 | const u8 *data; | |
115 | u32 type_len; | |
116 | u16 tag_id, tag_len; | |
117 | int idx, length; | |
118 | struct tlv_type_hdr *tlv; | |
119 | struct tlv_type_patch *tlv_patch; | |
120 | struct tlv_type_nvm *tlv_nvm; | |
121 | ||
122 | tlv = (struct tlv_type_hdr *)fw->data; | |
123 | ||
124 | type_len = le32_to_cpu(tlv->type_len); | |
125 | length = (type_len >> 8) & 0x00ffffff; | |
126 | ||
127 | BT_DBG("TLV Type\t\t : 0x%x", type_len & 0x000000ff); | |
128 | BT_DBG("Length\t\t : %d bytes", length); | |
129 | ||
130 | switch (config->type) { | |
131 | case TLV_TYPE_PATCH: | |
132 | tlv_patch = (struct tlv_type_patch *)tlv->data; | |
133 | BT_DBG("Total Length\t\t : %d bytes", | |
134 | le32_to_cpu(tlv_patch->total_size)); | |
135 | BT_DBG("Patch Data Length\t : %d bytes", | |
136 | le32_to_cpu(tlv_patch->data_length)); | |
137 | BT_DBG("Signing Format Version : 0x%x", | |
138 | tlv_patch->format_version); | |
139 | BT_DBG("Signature Algorithm\t : 0x%x", | |
140 | tlv_patch->signature); | |
141 | BT_DBG("Reserved\t\t : 0x%x", | |
142 | le16_to_cpu(tlv_patch->reserved1)); | |
143 | BT_DBG("Product ID\t\t : 0x%04x", | |
144 | le16_to_cpu(tlv_patch->product_id)); | |
145 | BT_DBG("Rom Build Version\t : 0x%04x", | |
146 | le16_to_cpu(tlv_patch->rom_build)); | |
147 | BT_DBG("Patch Version\t\t : 0x%04x", | |
148 | le16_to_cpu(tlv_patch->patch_version)); | |
149 | BT_DBG("Reserved\t\t : 0x%x", | |
150 | le16_to_cpu(tlv_patch->reserved2)); | |
151 | BT_DBG("Patch Entry Address\t : 0x%x", | |
152 | le32_to_cpu(tlv_patch->entry)); | |
153 | break; | |
154 | ||
155 | case TLV_TYPE_NVM: | |
156 | idx = 0; | |
157 | data = tlv->data; | |
158 | while (idx < length) { | |
159 | tlv_nvm = (struct tlv_type_nvm *)(data + idx); | |
160 | ||
161 | tag_id = le16_to_cpu(tlv_nvm->tag_id); | |
162 | tag_len = le16_to_cpu(tlv_nvm->tag_len); | |
163 | ||
164 | /* Update NVM tags as needed */ | |
165 | switch (tag_id) { | |
166 | case EDL_TAG_ID_HCI: | |
167 | /* HCI transport layer parameters | |
168 | * enabling software inband sleep | |
169 | * onto controller side. | |
170 | */ | |
171 | tlv_nvm->data[0] |= 0x80; | |
172 | ||
173 | /* UART Baud Rate */ | |
174 | tlv_nvm->data[2] = config->user_baud_rate; | |
175 | ||
176 | break; | |
177 | ||
178 | case EDL_TAG_ID_DEEP_SLEEP: | |
179 | /* Sleep enable mask | |
180 | * enabling deep sleep feature on controller. | |
181 | */ | |
182 | tlv_nvm->data[0] |= 0x01; | |
183 | ||
184 | break; | |
185 | } | |
186 | ||
187 | idx += (sizeof(u16) + sizeof(u16) + 8 + tag_len); | |
188 | } | |
189 | break; | |
190 | ||
191 | default: | |
192 | BT_ERR("Unknown TLV type %d", config->type); | |
193 | break; | |
194 | } | |
195 | } | |
196 | ||
197 | static int rome_tlv_send_segment(struct hci_dev *hdev, int idx, int seg_size, | |
198 | const u8 *data) | |
199 | { | |
200 | struct sk_buff *skb; | |
201 | struct edl_event_hdr *edl; | |
202 | struct tlv_seg_resp *tlv_resp; | |
203 | u8 cmd[MAX_SIZE_PER_TLV_SEGMENT + 2]; | |
204 | int err = 0; | |
205 | ||
206 | BT_DBG("%s: Download segment #%d size %d", hdev->name, idx, seg_size); | |
207 | ||
208 | cmd[0] = EDL_PATCH_TLV_REQ_CMD; | |
209 | cmd[1] = seg_size; | |
210 | memcpy(cmd + 2, data, seg_size); | |
211 | ||
212 | skb = __hci_cmd_sync_ev(hdev, EDL_PATCH_CMD_OPCODE, seg_size + 2, cmd, | |
213 | HCI_VENDOR_PKT, HCI_INIT_TIMEOUT); | |
214 | if (IS_ERR(skb)) { | |
215 | err = PTR_ERR(skb); | |
216 | BT_ERR("%s: Failed to send TLV segment (%d)", hdev->name, err); | |
217 | return err; | |
218 | } | |
219 | ||
220 | if (skb->len != sizeof(*edl) + sizeof(*tlv_resp)) { | |
221 | BT_ERR("%s: TLV response size mismatch", hdev->name); | |
222 | err = -EILSEQ; | |
223 | goto out; | |
224 | } | |
225 | ||
226 | edl = (struct edl_event_hdr *)(skb->data); | |
227 | if (!edl || !edl->data) { | |
228 | BT_ERR("%s: TLV with no header or no data", hdev->name); | |
229 | err = -EILSEQ; | |
230 | goto out; | |
231 | } | |
232 | ||
233 | tlv_resp = (struct tlv_seg_resp *)(edl->data); | |
234 | ||
235 | if (edl->cresp != EDL_CMD_REQ_RES_EVT || | |
236 | edl->rtype != EDL_TVL_DNLD_RES_EVT || tlv_resp->result != 0x00) { | |
237 | BT_ERR("%s: TLV with error stat 0x%x rtype 0x%x (0x%x)", | |
238 | hdev->name, edl->cresp, edl->rtype, tlv_resp->result); | |
239 | err = -EIO; | |
240 | } | |
241 | ||
242 | out: | |
243 | kfree_skb(skb); | |
244 | ||
245 | return err; | |
246 | } | |
247 | ||
248 | static int rome_tlv_download_request(struct hci_dev *hdev, | |
249 | const struct firmware *fw) | |
250 | { | |
251 | const u8 *buffer, *data; | |
252 | int total_segment, remain_size; | |
253 | int ret, i; | |
254 | ||
255 | if (!fw || !fw->data) | |
256 | return -EINVAL; | |
257 | ||
258 | total_segment = fw->size / MAX_SIZE_PER_TLV_SEGMENT; | |
259 | remain_size = fw->size % MAX_SIZE_PER_TLV_SEGMENT; | |
260 | ||
261 | BT_DBG("%s: Total segment num %d remain size %d total size %zu", | |
262 | hdev->name, total_segment, remain_size, fw->size); | |
263 | ||
264 | data = fw->data; | |
265 | for (i = 0; i < total_segment; i++) { | |
266 | buffer = data + i * MAX_SIZE_PER_TLV_SEGMENT; | |
267 | ret = rome_tlv_send_segment(hdev, i, MAX_SIZE_PER_TLV_SEGMENT, | |
268 | buffer); | |
269 | if (ret < 0) | |
270 | return -EIO; | |
271 | } | |
272 | ||
273 | if (remain_size) { | |
274 | buffer = data + total_segment * MAX_SIZE_PER_TLV_SEGMENT; | |
275 | ret = rome_tlv_send_segment(hdev, total_segment, remain_size, | |
276 | buffer); | |
277 | if (ret < 0) | |
278 | return -EIO; | |
279 | } | |
280 | ||
281 | return 0; | |
282 | } | |
283 | ||
284 | static int rome_download_firmware(struct hci_dev *hdev, | |
285 | struct rome_config *config) | |
286 | { | |
287 | const struct firmware *fw; | |
288 | int ret; | |
289 | ||
290 | BT_INFO("%s: ROME Downloading %s", hdev->name, config->fwname); | |
291 | ||
292 | ret = request_firmware(&fw, config->fwname, &hdev->dev); | |
293 | if (ret) { | |
294 | BT_ERR("%s: Failed to request file: %s (%d)", hdev->name, | |
295 | config->fwname, ret); | |
296 | return ret; | |
297 | } | |
298 | ||
299 | rome_tlv_check_data(config, fw); | |
300 | ||
301 | ret = rome_tlv_download_request(hdev, fw); | |
302 | if (ret) { | |
303 | BT_ERR("%s: Failed to download file: %s (%d)", hdev->name, | |
304 | config->fwname, ret); | |
305 | } | |
306 | ||
307 | release_firmware(fw); | |
308 | ||
309 | return ret; | |
310 | } | |
311 | ||
312 | int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr) | |
313 | { | |
314 | struct sk_buff *skb; | |
315 | u8 cmd[9]; | |
316 | int err; | |
317 | ||
318 | cmd[0] = EDL_NVM_ACCESS_SET_REQ_CMD; | |
319 | cmd[1] = 0x02; /* TAG ID */ | |
320 | cmd[2] = sizeof(bdaddr_t); /* size */ | |
321 | memcpy(cmd + 3, bdaddr, sizeof(bdaddr_t)); | |
322 | skb = __hci_cmd_sync_ev(hdev, EDL_NVM_ACCESS_OPCODE, sizeof(cmd), cmd, | |
323 | HCI_VENDOR_PKT, HCI_INIT_TIMEOUT); | |
324 | if (IS_ERR(skb)) { | |
325 | err = PTR_ERR(skb); | |
326 | BT_ERR("%s: Change address command failed (%d)", | |
327 | hdev->name, err); | |
328 | return err; | |
329 | } | |
330 | ||
331 | kfree_skb(skb); | |
332 | ||
333 | return 0; | |
334 | } | |
335 | EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome); | |
336 | ||
337 | int qca_uart_setup_rome(struct hci_dev *hdev, uint8_t baudrate) | |
338 | { | |
339 | u32 rome_ver = 0; | |
340 | struct rome_config config; | |
341 | int err; | |
342 | ||
343 | BT_DBG("%s: ROME setup on UART", hdev->name); | |
344 | ||
345 | config.user_baud_rate = baudrate; | |
346 | ||
347 | /* Get ROME version information */ | |
348 | err = rome_patch_ver_req(hdev, &rome_ver); | |
349 | if (err < 0 || rome_ver == 0) { | |
350 | BT_ERR("%s: Failed to get version 0x%x", hdev->name, err); | |
351 | return err; | |
352 | } | |
353 | ||
354 | BT_INFO("%s: ROME controller version 0x%08x", hdev->name, rome_ver); | |
355 | ||
356 | /* Download rampatch file */ | |
357 | config.type = TLV_TYPE_PATCH; | |
358 | snprintf(config.fwname, sizeof(config.fwname), "qca/rampatch_%08x.bin", | |
359 | rome_ver); | |
360 | err = rome_download_firmware(hdev, &config); | |
361 | if (err < 0) { | |
362 | BT_ERR("%s: Failed to download patch (%d)", hdev->name, err); | |
363 | return err; | |
364 | } | |
365 | ||
366 | /* Download NVM configuration */ | |
367 | config.type = TLV_TYPE_NVM; | |
368 | snprintf(config.fwname, sizeof(config.fwname), "qca/nvm_%08x.bin", | |
369 | rome_ver); | |
370 | err = rome_download_firmware(hdev, &config); | |
371 | if (err < 0) { | |
372 | BT_ERR("%s: Failed to download NVM (%d)", hdev->name, err); | |
373 | return err; | |
374 | } | |
375 | ||
376 | /* Perform HCI reset */ | |
377 | err = rome_reset(hdev); | |
378 | if (err < 0) { | |
379 | BT_ERR("%s: Failed to run HCI_RESET (%d)", hdev->name, err); | |
380 | return err; | |
381 | } | |
382 | ||
383 | BT_INFO("%s: ROME setup on UART is completed", hdev->name); | |
384 | ||
385 | return 0; | |
386 | } | |
387 | EXPORT_SYMBOL_GPL(qca_uart_setup_rome); | |
388 | ||
389 | MODULE_AUTHOR("Ben Young Tae Kim <ytkim@qca.qualcomm.com>"); | |
390 | MODULE_DESCRIPTION("Bluetooth support for Qualcomm Atheros family ver " VERSION); | |
391 | MODULE_VERSION(VERSION); | |
392 | MODULE_LICENSE("GPL"); |