Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: ISC
  2/* Copyright (C) 2021 MediaTek Inc.
  3 *
  4 */
  5#include <linux/module.h>
  6#include <linux/firmware.h>
  7
  8#include <net/bluetooth/bluetooth.h>
  9#include <net/bluetooth/hci_core.h>
 10
 11#include "btmtk.h"
 12
 13#define VERSION "0.1"
 14
 15/* It is for mt79xx download rom patch*/
 16#define MTK_FW_ROM_PATCH_HEADER_SIZE	32
 17#define MTK_FW_ROM_PATCH_GD_SIZE	64
 18#define MTK_FW_ROM_PATCH_SEC_MAP_SIZE	64
 19#define MTK_SEC_MAP_COMMON_SIZE	12
 20#define MTK_SEC_MAP_NEED_SEND_SIZE	52
 21
 22struct btmtk_patch_header {
 23	u8 datetime[16];
 24	u8 platform[4];
 25	__le16 hwver;
 26	__le16 swver;
 27	__le32 magicnum;
 28} __packed;
 29
 30struct btmtk_global_desc {
 31	__le32 patch_ver;
 32	__le32 sub_sys;
 33	__le32 feature_opt;
 34	__le32 section_num;
 35} __packed;
 36
 37struct btmtk_section_map {
 38	__le32 sectype;
 39	__le32 secoffset;
 40	__le32 secsize;
 41	union {
 42		__le32 u4SecSpec[13];
 43		struct {
 44			__le32 dlAddr;
 45			__le32 dlsize;
 46			__le32 seckeyidx;
 47			__le32 alignlen;
 48			__le32 sectype;
 49			__le32 dlmodecrctype;
 50			__le32 crc;
 51			__le32 reserved[6];
 52		} bin_info_spec;
 53	};
 54} __packed;
 55
 56static void btmtk_coredump(struct hci_dev *hdev)
 57{
 58	int err;
 59
 60	err = __hci_cmd_send(hdev, 0xfd5b, 0, NULL);
 61	if (err < 0)
 62		bt_dev_err(hdev, "Coredump failed (%d)", err);
 63}
 64
 65static void btmtk_coredump_hdr(struct hci_dev *hdev, struct sk_buff *skb)
 66{
 67	struct btmediatek_data *data = hci_get_priv(hdev);
 68	char buf[80];
 69
 70	snprintf(buf, sizeof(buf), "Controller Name: 0x%X\n",
 71		 data->dev_id);
 72	skb_put_data(skb, buf, strlen(buf));
 73
 74	snprintf(buf, sizeof(buf), "Firmware Version: 0x%X\n",
 75		 data->cd_info.fw_version);
 76	skb_put_data(skb, buf, strlen(buf));
 77
 78	snprintf(buf, sizeof(buf), "Driver: %s\n",
 79		 data->cd_info.driver_name);
 80	skb_put_data(skb, buf, strlen(buf));
 81
 82	snprintf(buf, sizeof(buf), "Vendor: MediaTek\n");
 83	skb_put_data(skb, buf, strlen(buf));
 84}
 85
 86static void btmtk_coredump_notify(struct hci_dev *hdev, int state)
 87{
 88	struct btmediatek_data *data = hci_get_priv(hdev);
 89
 90	switch (state) {
 91	case HCI_DEVCOREDUMP_IDLE:
 92		data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
 93		break;
 94	case HCI_DEVCOREDUMP_ACTIVE:
 95		data->cd_info.state = HCI_DEVCOREDUMP_ACTIVE;
 96		break;
 97	case HCI_DEVCOREDUMP_TIMEOUT:
 98	case HCI_DEVCOREDUMP_ABORT:
 99	case HCI_DEVCOREDUMP_DONE:
100		data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
101		btmtk_reset_sync(hdev);
102		break;
103	}
104}
105
106int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
107			      wmt_cmd_sync_func_t wmt_cmd_sync)
108{
109	struct btmtk_hci_wmt_params wmt_params;
110	struct btmtk_patch_header *hdr;
111	struct btmtk_global_desc *globaldesc = NULL;
112	struct btmtk_section_map *sectionmap;
113	const struct firmware *fw;
114	const u8 *fw_ptr;
115	const u8 *fw_bin_ptr;
116	int err, dlen, i, status;
117	u8 flag, first_block, retry;
118	u32 section_num, dl_size, section_offset;
119	u8 cmd[64];
120
121	err = request_firmware(&fw, fwname, &hdev->dev);
122	if (err < 0) {
123		bt_dev_err(hdev, "Failed to load firmware file (%d)", err);
124		return err;
125	}
126
127	fw_ptr = fw->data;
128	fw_bin_ptr = fw_ptr;
129	hdr = (struct btmtk_patch_header *)fw_ptr;
130	globaldesc = (struct btmtk_global_desc *)(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE);
131	section_num = le32_to_cpu(globaldesc->section_num);
132
133	bt_dev_info(hdev, "HW/SW Version: 0x%04x%04x, Build Time: %s",
134		    le16_to_cpu(hdr->hwver), le16_to_cpu(hdr->swver), hdr->datetime);
135
136	for (i = 0; i < section_num; i++) {
137		first_block = 1;
138		fw_ptr = fw_bin_ptr;
139		sectionmap = (struct btmtk_section_map *)(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE +
140			      MTK_FW_ROM_PATCH_GD_SIZE + MTK_FW_ROM_PATCH_SEC_MAP_SIZE * i);
141
142		section_offset = le32_to_cpu(sectionmap->secoffset);
143		dl_size = le32_to_cpu(sectionmap->bin_info_spec.dlsize);
144
145		if (dl_size > 0) {
146			retry = 20;
147			while (retry > 0) {
148				cmd[0] = 0; /* 0 means legacy dl mode. */
149				memcpy(cmd + 1,
150				       fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE +
151				       MTK_FW_ROM_PATCH_GD_SIZE +
152				       MTK_FW_ROM_PATCH_SEC_MAP_SIZE * i +
153				       MTK_SEC_MAP_COMMON_SIZE,
154				       MTK_SEC_MAP_NEED_SEND_SIZE + 1);
155
156				wmt_params.op = BTMTK_WMT_PATCH_DWNLD;
157				wmt_params.status = &status;
158				wmt_params.flag = 0;
159				wmt_params.dlen = MTK_SEC_MAP_NEED_SEND_SIZE + 1;
160				wmt_params.data = &cmd;
161
162				err = wmt_cmd_sync(hdev, &wmt_params);
163				if (err < 0) {
164					bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)",
165						   err);
166					goto err_release_fw;
167				}
168
169				if (status == BTMTK_WMT_PATCH_UNDONE) {
170					break;
171				} else if (status == BTMTK_WMT_PATCH_PROGRESS) {
172					msleep(100);
173					retry--;
174				} else if (status == BTMTK_WMT_PATCH_DONE) {
175					goto next_section;
176				} else {
177					bt_dev_err(hdev, "Failed wmt patch dwnld status (%d)",
178						   status);
179					err = -EIO;
180					goto err_release_fw;
181				}
182			}
183
184			fw_ptr += section_offset;
185			wmt_params.op = BTMTK_WMT_PATCH_DWNLD;
186			wmt_params.status = NULL;
187
188			while (dl_size > 0) {
189				dlen = min_t(int, 250, dl_size);
190				if (first_block == 1) {
191					flag = 1;
192					first_block = 0;
193				} else if (dl_size - dlen <= 0) {
194					flag = 3;
195				} else {
196					flag = 2;
197				}
198
199				wmt_params.flag = flag;
200				wmt_params.dlen = dlen;
201				wmt_params.data = fw_ptr;
202
203				err = wmt_cmd_sync(hdev, &wmt_params);
204				if (err < 0) {
205					bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)",
206						   err);
207					goto err_release_fw;
208				}
209
210				dl_size -= dlen;
211				fw_ptr += dlen;
212			}
213		}
214next_section:
215		continue;
216	}
217	/* Wait a few moments for firmware activation done */
218	usleep_range(100000, 120000);
219
220err_release_fw:
221	release_firmware(fw);
222
223	return err;
224}
225EXPORT_SYMBOL_GPL(btmtk_setup_firmware_79xx);
226
227int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
228			 wmt_cmd_sync_func_t wmt_cmd_sync)
229{
230	struct btmtk_hci_wmt_params wmt_params;
231	const struct firmware *fw;
232	const u8 *fw_ptr;
233	size_t fw_size;
234	int err, dlen;
235	u8 flag, param;
236
237	err = request_firmware(&fw, fwname, &hdev->dev);
238	if (err < 0) {
239		bt_dev_err(hdev, "Failed to load firmware file (%d)", err);
240		return err;
241	}
242
243	/* Power on data RAM the firmware relies on. */
244	param = 1;
245	wmt_params.op = BTMTK_WMT_FUNC_CTRL;
246	wmt_params.flag = 3;
247	wmt_params.dlen = sizeof(param);
248	wmt_params.data = &param;
249	wmt_params.status = NULL;
250
251	err = wmt_cmd_sync(hdev, &wmt_params);
252	if (err < 0) {
253		bt_dev_err(hdev, "Failed to power on data RAM (%d)", err);
254		goto err_release_fw;
255	}
256
257	fw_ptr = fw->data;
258	fw_size = fw->size;
259
260	/* The size of patch header is 30 bytes, should be skip */
261	if (fw_size < 30) {
262		err = -EINVAL;
263		goto err_release_fw;
264	}
265
266	fw_size -= 30;
267	fw_ptr += 30;
268	flag = 1;
269
270	wmt_params.op = BTMTK_WMT_PATCH_DWNLD;
271	wmt_params.status = NULL;
272
273	while (fw_size > 0) {
274		dlen = min_t(int, 250, fw_size);
275
276		/* Tell device the position in sequence */
277		if (fw_size - dlen <= 0)
278			flag = 3;
279		else if (fw_size < fw->size - 30)
280			flag = 2;
281
282		wmt_params.flag = flag;
283		wmt_params.dlen = dlen;
284		wmt_params.data = fw_ptr;
285
286		err = wmt_cmd_sync(hdev, &wmt_params);
287		if (err < 0) {
288			bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)",
289				   err);
290			goto err_release_fw;
291		}
292
293		fw_size -= dlen;
294		fw_ptr += dlen;
295	}
296
297	wmt_params.op = BTMTK_WMT_RST;
298	wmt_params.flag = 4;
299	wmt_params.dlen = 0;
300	wmt_params.data = NULL;
301	wmt_params.status = NULL;
302
303	/* Activate funciton the firmware providing to */
304	err = wmt_cmd_sync(hdev, &wmt_params);
305	if (err < 0) {
306		bt_dev_err(hdev, "Failed to send wmt rst (%d)", err);
307		goto err_release_fw;
308	}
309
310	/* Wait a few moments for firmware activation done */
311	usleep_range(10000, 12000);
312
313err_release_fw:
314	release_firmware(fw);
315
316	return err;
317}
318EXPORT_SYMBOL_GPL(btmtk_setup_firmware);
319
320int btmtk_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
321{
322	struct sk_buff *skb;
323	long ret;
324
325	skb = __hci_cmd_sync(hdev, 0xfc1a, 6, bdaddr, HCI_INIT_TIMEOUT);
326	if (IS_ERR(skb)) {
327		ret = PTR_ERR(skb);
328		bt_dev_err(hdev, "changing Mediatek device address failed (%ld)",
329			   ret);
330		return ret;
331	}
332	kfree_skb(skb);
333
334	return 0;
335}
336EXPORT_SYMBOL_GPL(btmtk_set_bdaddr);
337
338void btmtk_reset_sync(struct hci_dev *hdev)
339{
340	struct btmediatek_data *reset_work = hci_get_priv(hdev);
341	int err;
342
343	hci_dev_lock(hdev);
344
345	err = hci_cmd_sync_queue(hdev, reset_work->reset_sync, NULL, NULL);
346	if (err)
347		bt_dev_err(hdev, "failed to reset (%d)", err);
348
349	hci_dev_unlock(hdev);
350}
351EXPORT_SYMBOL_GPL(btmtk_reset_sync);
352
353int btmtk_register_coredump(struct hci_dev *hdev, const char *name,
354			    u32 fw_version)
355{
356	struct btmediatek_data *data = hci_get_priv(hdev);
357
358	if (!IS_ENABLED(CONFIG_DEV_COREDUMP))
359		return -EOPNOTSUPP;
360
361	data->cd_info.fw_version = fw_version;
362	data->cd_info.state = HCI_DEVCOREDUMP_IDLE;
363	data->cd_info.driver_name = name;
364
365	return hci_devcd_register(hdev, btmtk_coredump, btmtk_coredump_hdr,
366				  btmtk_coredump_notify);
367}
368EXPORT_SYMBOL_GPL(btmtk_register_coredump);
369
370int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
371{
372	struct btmediatek_data *data = hci_get_priv(hdev);
373	int err;
374
375	if (!IS_ENABLED(CONFIG_DEV_COREDUMP))
376		return 0;
377
378	switch (data->cd_info.state) {
379	case HCI_DEVCOREDUMP_IDLE:
380		err = hci_devcd_init(hdev, MTK_COREDUMP_SIZE);
381		if (err < 0)
382			break;
383		data->cd_info.cnt = 0;
384
385		/* It is supposed coredump can be done within 5 seconds */
386		schedule_delayed_work(&hdev->dump.dump_timeout,
387				      msecs_to_jiffies(5000));
388		fallthrough;
389	case HCI_DEVCOREDUMP_ACTIVE:
390	default:
391		err = hci_devcd_append(hdev, skb);
392		if (err < 0)
393			break;
394		data->cd_info.cnt++;
395
396		/* Mediatek coredump data would be more than MTK_COREDUMP_NUM */
397		if (data->cd_info.cnt > MTK_COREDUMP_NUM &&
398		    skb->len > MTK_COREDUMP_END_LEN)
399			if (!memcmp((char *)&skb->data[skb->len - MTK_COREDUMP_END_LEN],
400				    MTK_COREDUMP_END, MTK_COREDUMP_END_LEN - 1)) {
401				bt_dev_info(hdev, "Mediatek coredump end");
402				hci_devcd_complete(hdev);
403			}
404
405		break;
406	}
407
408	if (err < 0)
409		kfree_skb(skb);
410
411	return err;
412}
413EXPORT_SYMBOL_GPL(btmtk_process_coredump);
414
415MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
416MODULE_AUTHOR("Mark Chen <mark-yw.chen@mediatek.com>");
417MODULE_DESCRIPTION("Bluetooth support for MediaTek devices ver " VERSION);
418MODULE_VERSION(VERSION);
419MODULE_LICENSE("GPL");
420MODULE_FIRMWARE(FIRMWARE_MT7622);
421MODULE_FIRMWARE(FIRMWARE_MT7663);
422MODULE_FIRMWARE(FIRMWARE_MT7668);
423MODULE_FIRMWARE(FIRMWARE_MT7961);
424MODULE_FIRMWARE(FIRMWARE_MT7925);