xref: /linux/drivers/bluetooth/btmtk.c (revision 41fb0cf1bced59c1fe178cf6cc9f716b5da9e40e)
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 
22 struct btmtk_patch_header {
23 	u8 datetime[16];
24 	u8 platform[4];
25 	__le16 hwver;
26 	__le16 swver;
27 	__le32 magicnum;
28 } __packed;
29 
30 struct btmtk_global_desc {
31 	__le32 patch_ver;
32 	__le32 sub_sys;
33 	__le32 feature_opt;
34 	__le32 section_num;
35 } __packed;
36 
37 struct 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 
56 int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
57 			      wmt_cmd_sync_func_t wmt_cmd_sync)
58 {
59 	struct btmtk_hci_wmt_params wmt_params;
60 	struct btmtk_global_desc *globaldesc = NULL;
61 	struct btmtk_section_map *sectionmap;
62 	const struct firmware *fw;
63 	const u8 *fw_ptr;
64 	const u8 *fw_bin_ptr;
65 	int err, dlen, i, status;
66 	u8 flag, first_block, retry;
67 	u32 section_num, dl_size, section_offset;
68 	u8 cmd[64];
69 
70 	err = request_firmware(&fw, fwname, &hdev->dev);
71 	if (err < 0) {
72 		bt_dev_err(hdev, "Failed to load firmware file (%d)", err);
73 		return err;
74 	}
75 
76 	fw_ptr = fw->data;
77 	fw_bin_ptr = fw_ptr;
78 	globaldesc = (struct btmtk_global_desc *)(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE);
79 	section_num = le32_to_cpu(globaldesc->section_num);
80 
81 	for (i = 0; i < section_num; i++) {
82 		first_block = 1;
83 		fw_ptr = fw_bin_ptr;
84 		sectionmap = (struct btmtk_section_map *)(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE +
85 			      MTK_FW_ROM_PATCH_GD_SIZE + MTK_FW_ROM_PATCH_SEC_MAP_SIZE * i);
86 
87 		section_offset = le32_to_cpu(sectionmap->secoffset);
88 		dl_size = le32_to_cpu(sectionmap->bin_info_spec.dlsize);
89 
90 		if (dl_size > 0) {
91 			retry = 20;
92 			while (retry > 0) {
93 				cmd[0] = 0; /* 0 means legacy dl mode. */
94 				memcpy(cmd + 1,
95 				       fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE +
96 				       MTK_FW_ROM_PATCH_GD_SIZE +
97 				       MTK_FW_ROM_PATCH_SEC_MAP_SIZE * i +
98 				       MTK_SEC_MAP_COMMON_SIZE,
99 				       MTK_SEC_MAP_NEED_SEND_SIZE + 1);
100 
101 				wmt_params.op = BTMTK_WMT_PATCH_DWNLD;
102 				wmt_params.status = &status;
103 				wmt_params.flag = 0;
104 				wmt_params.dlen = MTK_SEC_MAP_NEED_SEND_SIZE + 1;
105 				wmt_params.data = &cmd;
106 
107 				err = wmt_cmd_sync(hdev, &wmt_params);
108 				if (err < 0) {
109 					bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)",
110 						   err);
111 					goto err_release_fw;
112 				}
113 
114 				if (status == BTMTK_WMT_PATCH_UNDONE) {
115 					break;
116 				} else if (status == BTMTK_WMT_PATCH_PROGRESS) {
117 					msleep(100);
118 					retry--;
119 				} else if (status == BTMTK_WMT_PATCH_DONE) {
120 					goto next_section;
121 				} else {
122 					bt_dev_err(hdev, "Failed wmt patch dwnld status (%d)",
123 						   status);
124 					goto err_release_fw;
125 				}
126 			}
127 
128 			fw_ptr += section_offset;
129 			wmt_params.op = BTMTK_WMT_PATCH_DWNLD;
130 			wmt_params.status = NULL;
131 
132 			while (dl_size > 0) {
133 				dlen = min_t(int, 250, dl_size);
134 				if (first_block == 1) {
135 					flag = 1;
136 					first_block = 0;
137 				} else if (dl_size - dlen <= 0) {
138 					flag = 3;
139 				} else {
140 					flag = 2;
141 				}
142 
143 				wmt_params.flag = flag;
144 				wmt_params.dlen = dlen;
145 				wmt_params.data = fw_ptr;
146 
147 				err = wmt_cmd_sync(hdev, &wmt_params);
148 				if (err < 0) {
149 					bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)",
150 						   err);
151 					goto err_release_fw;
152 				}
153 
154 				dl_size -= dlen;
155 				fw_ptr += dlen;
156 			}
157 		}
158 next_section:
159 		continue;
160 	}
161 	/* Wait a few moments for firmware activation done */
162 	usleep_range(100000, 120000);
163 
164 err_release_fw:
165 	release_firmware(fw);
166 
167 	return err;
168 }
169 EXPORT_SYMBOL_GPL(btmtk_setup_firmware_79xx);
170 
171 int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
172 			 wmt_cmd_sync_func_t wmt_cmd_sync)
173 {
174 	struct btmtk_hci_wmt_params wmt_params;
175 	const struct firmware *fw;
176 	const u8 *fw_ptr;
177 	size_t fw_size;
178 	int err, dlen;
179 	u8 flag, param;
180 
181 	err = request_firmware(&fw, fwname, &hdev->dev);
182 	if (err < 0) {
183 		bt_dev_err(hdev, "Failed to load firmware file (%d)", err);
184 		return err;
185 	}
186 
187 	/* Power on data RAM the firmware relies on. */
188 	param = 1;
189 	wmt_params.op = BTMTK_WMT_FUNC_CTRL;
190 	wmt_params.flag = 3;
191 	wmt_params.dlen = sizeof(param);
192 	wmt_params.data = &param;
193 	wmt_params.status = NULL;
194 
195 	err = wmt_cmd_sync(hdev, &wmt_params);
196 	if (err < 0) {
197 		bt_dev_err(hdev, "Failed to power on data RAM (%d)", err);
198 		goto err_release_fw;
199 	}
200 
201 	fw_ptr = fw->data;
202 	fw_size = fw->size;
203 
204 	/* The size of patch header is 30 bytes, should be skip */
205 	if (fw_size < 30) {
206 		err = -EINVAL;
207 		goto err_release_fw;
208 	}
209 
210 	fw_size -= 30;
211 	fw_ptr += 30;
212 	flag = 1;
213 
214 	wmt_params.op = BTMTK_WMT_PATCH_DWNLD;
215 	wmt_params.status = NULL;
216 
217 	while (fw_size > 0) {
218 		dlen = min_t(int, 250, fw_size);
219 
220 		/* Tell device the position in sequence */
221 		if (fw_size - dlen <= 0)
222 			flag = 3;
223 		else if (fw_size < fw->size - 30)
224 			flag = 2;
225 
226 		wmt_params.flag = flag;
227 		wmt_params.dlen = dlen;
228 		wmt_params.data = fw_ptr;
229 
230 		err = wmt_cmd_sync(hdev, &wmt_params);
231 		if (err < 0) {
232 			bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)",
233 				   err);
234 			goto err_release_fw;
235 		}
236 
237 		fw_size -= dlen;
238 		fw_ptr += dlen;
239 	}
240 
241 	wmt_params.op = BTMTK_WMT_RST;
242 	wmt_params.flag = 4;
243 	wmt_params.dlen = 0;
244 	wmt_params.data = NULL;
245 	wmt_params.status = NULL;
246 
247 	/* Activate funciton the firmware providing to */
248 	err = wmt_cmd_sync(hdev, &wmt_params);
249 	if (err < 0) {
250 		bt_dev_err(hdev, "Failed to send wmt rst (%d)", err);
251 		goto err_release_fw;
252 	}
253 
254 	/* Wait a few moments for firmware activation done */
255 	usleep_range(10000, 12000);
256 
257 err_release_fw:
258 	release_firmware(fw);
259 
260 	return err;
261 }
262 EXPORT_SYMBOL_GPL(btmtk_setup_firmware);
263 
264 int btmtk_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
265 {
266 	struct sk_buff *skb;
267 	long ret;
268 
269 	skb = __hci_cmd_sync(hdev, 0xfc1a, 6, bdaddr, HCI_INIT_TIMEOUT);
270 	if (IS_ERR(skb)) {
271 		ret = PTR_ERR(skb);
272 		bt_dev_err(hdev, "changing Mediatek device address failed (%ld)",
273 			   ret);
274 		return ret;
275 	}
276 	kfree_skb(skb);
277 
278 	return 0;
279 }
280 EXPORT_SYMBOL_GPL(btmtk_set_bdaddr);
281 
282 MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
283 MODULE_AUTHOR("Mark Chen <mark-yw.chen@mediatek.com>");
284 MODULE_DESCRIPTION("Bluetooth support for MediaTek devices ver " VERSION);
285 MODULE_VERSION(VERSION);
286 MODULE_LICENSE("GPL");
287 MODULE_FIRMWARE(FIRMWARE_MT7663);
288 MODULE_FIRMWARE(FIRMWARE_MT7668);
289 MODULE_FIRMWARE(FIRMWARE_MT7961);
290