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 = ¶m; 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