cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

btmtk.c (6787B)


      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
     56int 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		}
    159next_section:
    160		continue;
    161	}
    162	/* Wait a few moments for firmware activation done */
    163	usleep_range(100000, 120000);
    164
    165err_release_fw:
    166	release_firmware(fw);
    167
    168	return err;
    169}
    170EXPORT_SYMBOL_GPL(btmtk_setup_firmware_79xx);
    171
    172int 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
    258err_release_fw:
    259	release_firmware(fw);
    260
    261	return err;
    262}
    263EXPORT_SYMBOL_GPL(btmtk_setup_firmware);
    264
    265int 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}
    281EXPORT_SYMBOL_GPL(btmtk_set_bdaddr);
    282
    283MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
    284MODULE_AUTHOR("Mark Chen <mark-yw.chen@mediatek.com>");
    285MODULE_DESCRIPTION("Bluetooth support for MediaTek devices ver " VERSION);
    286MODULE_VERSION(VERSION);
    287MODULE_LICENSE("GPL");
    288MODULE_FIRMWARE(FIRMWARE_MT7622);
    289MODULE_FIRMWARE(FIRMWARE_MT7663);
    290MODULE_FIRMWARE(FIRMWARE_MT7668);
    291MODULE_FIRMWARE(FIRMWARE_MT7961);