xref: /openbmc/linux/drivers/bluetooth/btmtk.c (revision 8e74a48d)
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 					err = -EIO;
125 					goto err_release_fw;
126 				}
127 			}
128 
129 			fw_ptr += section_offset;
130 			wmt_params.op = BTMTK_WMT_PATCH_DWNLD;
131 			wmt_params.status = NULL;
132 
133 			while (dl_size > 0) {
134 				dlen = min_t(int, 250, dl_size);
135 				if (first_block == 1) {
136 					flag = 1;
137 					first_block = 0;
138 				} else if (dl_size - dlen <= 0) {
139 					flag = 3;
140 				} else {
141 					flag = 2;
142 				}
143 
144 				wmt_params.flag = flag;
145 				wmt_params.dlen = dlen;
146 				wmt_params.data = fw_ptr;
147 
148 				err = wmt_cmd_sync(hdev, &wmt_params);
149 				if (err < 0) {
150 					bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)",
151 						   err);
152 					goto err_release_fw;
153 				}
154 
155 				dl_size -= dlen;
156 				fw_ptr += dlen;
157 			}
158 		}
159 next_section:
160 		continue;
161 	}
162 	/* Wait a few moments for firmware activation done */
163 	usleep_range(100000, 120000);
164 
165 err_release_fw:
166 	release_firmware(fw);
167 
168 	return err;
169 }
170 EXPORT_SYMBOL_GPL(btmtk_setup_firmware_79xx);
171 
172 int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
173 			 wmt_cmd_sync_func_t wmt_cmd_sync)
174 {
175 	struct btmtk_hci_wmt_params wmt_params;
176 	const struct firmware *fw;
177 	const u8 *fw_ptr;
178 	size_t fw_size;
179 	int err, dlen;
180 	u8 flag, param;
181 
182 	err = request_firmware(&fw, fwname, &hdev->dev);
183 	if (err < 0) {
184 		bt_dev_err(hdev, "Failed to load firmware file (%d)", err);
185 		return err;
186 	}
187 
188 	/* Power on data RAM the firmware relies on. */
189 	param = 1;
190 	wmt_params.op = BTMTK_WMT_FUNC_CTRL;
191 	wmt_params.flag = 3;
192 	wmt_params.dlen = sizeof(param);
193 	wmt_params.data = &param;
194 	wmt_params.status = NULL;
195 
196 	err = wmt_cmd_sync(hdev, &wmt_params);
197 	if (err < 0) {
198 		bt_dev_err(hdev, "Failed to power on data RAM (%d)", err);
199 		goto err_release_fw;
200 	}
201 
202 	fw_ptr = fw->data;
203 	fw_size = fw->size;
204 
205 	/* The size of patch header is 30 bytes, should be skip */
206 	if (fw_size < 30) {
207 		err = -EINVAL;
208 		goto err_release_fw;
209 	}
210 
211 	fw_size -= 30;
212 	fw_ptr += 30;
213 	flag = 1;
214 
215 	wmt_params.op = BTMTK_WMT_PATCH_DWNLD;
216 	wmt_params.status = NULL;
217 
218 	while (fw_size > 0) {
219 		dlen = min_t(int, 250, fw_size);
220 
221 		/* Tell device the position in sequence */
222 		if (fw_size - dlen <= 0)
223 			flag = 3;
224 		else if (fw_size < fw->size - 30)
225 			flag = 2;
226 
227 		wmt_params.flag = flag;
228 		wmt_params.dlen = dlen;
229 		wmt_params.data = fw_ptr;
230 
231 		err = wmt_cmd_sync(hdev, &wmt_params);
232 		if (err < 0) {
233 			bt_dev_err(hdev, "Failed to send wmt patch dwnld (%d)",
234 				   err);
235 			goto err_release_fw;
236 		}
237 
238 		fw_size -= dlen;
239 		fw_ptr += dlen;
240 	}
241 
242 	wmt_params.op = BTMTK_WMT_RST;
243 	wmt_params.flag = 4;
244 	wmt_params.dlen = 0;
245 	wmt_params.data = NULL;
246 	wmt_params.status = NULL;
247 
248 	/* Activate funciton the firmware providing to */
249 	err = wmt_cmd_sync(hdev, &wmt_params);
250 	if (err < 0) {
251 		bt_dev_err(hdev, "Failed to send wmt rst (%d)", err);
252 		goto err_release_fw;
253 	}
254 
255 	/* Wait a few moments for firmware activation done */
256 	usleep_range(10000, 12000);
257 
258 err_release_fw:
259 	release_firmware(fw);
260 
261 	return err;
262 }
263 EXPORT_SYMBOL_GPL(btmtk_setup_firmware);
264 
265 int btmtk_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
266 {
267 	struct sk_buff *skb;
268 	long ret;
269 
270 	skb = __hci_cmd_sync(hdev, 0xfc1a, 6, bdaddr, HCI_INIT_TIMEOUT);
271 	if (IS_ERR(skb)) {
272 		ret = PTR_ERR(skb);
273 		bt_dev_err(hdev, "changing Mediatek device address failed (%ld)",
274 			   ret);
275 		return ret;
276 	}
277 	kfree_skb(skb);
278 
279 	return 0;
280 }
281 EXPORT_SYMBOL_GPL(btmtk_set_bdaddr);
282 
283 MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
284 MODULE_AUTHOR("Mark Chen <mark-yw.chen@mediatek.com>");
285 MODULE_DESCRIPTION("Bluetooth support for MediaTek devices ver " VERSION);
286 MODULE_VERSION(VERSION);
287 MODULE_LICENSE("GPL");
288 MODULE_FIRMWARE(FIRMWARE_MT7663);
289 MODULE_FIRMWARE(FIRMWARE_MT7668);
290 MODULE_FIRMWARE(FIRMWARE_MT7961);
291