mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 04:34:08 +08:00
Bluetooth: btmtksdio: add MT7921s Bluetooth support
add MT7921s Bluetooth support Co-developed-by: Mark-yw Chen <mark-yw.chen@mediatek.com> Signed-off-by: Mark-yw Chen <mark-yw.chen@mediatek.com> Signed-off-by: Sean Wang <sean.wang@mediatek.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
1705643fae
commit
c603bf1f94
@ -7,6 +7,8 @@
|
||||
|
||||
#define HCI_WMT_MAX_EVENT_SIZE 64
|
||||
|
||||
#define BTMTK_WMT_REG_READ 0x2
|
||||
|
||||
enum {
|
||||
BTMTK_WMT_PATCH_DWNLD = 0x1,
|
||||
BTMTK_WMT_TEST = 0x2,
|
||||
@ -14,6 +16,7 @@ enum {
|
||||
BTMTK_WMT_HIF = 0x4,
|
||||
BTMTK_WMT_FUNC_CTRL = 0x6,
|
||||
BTMTK_WMT_RST = 0x7,
|
||||
BTMTK_WMT_REGISTER = 0x8,
|
||||
BTMTK_WMT_SEMAPHORE = 0x17,
|
||||
};
|
||||
|
||||
@ -49,6 +52,14 @@ struct btmtk_hci_wmt_evt_funcc {
|
||||
__be16 status;
|
||||
} __packed;
|
||||
|
||||
struct btmtk_hci_wmt_evt_reg {
|
||||
struct btmtk_hci_wmt_evt hwhdr;
|
||||
u8 rsv[2];
|
||||
u8 num;
|
||||
__le32 addr;
|
||||
__le32 val;
|
||||
} __packed;
|
||||
|
||||
struct btmtk_tci_sleep {
|
||||
u8 mode;
|
||||
__le16 duration;
|
||||
|
@ -37,14 +37,22 @@ static bool enable_autosuspend;
|
||||
|
||||
struct btmtksdio_data {
|
||||
const char *fwname;
|
||||
u16 chipid;
|
||||
};
|
||||
|
||||
static const struct btmtksdio_data mt7663_data = {
|
||||
.fwname = FIRMWARE_MT7663,
|
||||
.chipid = 0x7663,
|
||||
};
|
||||
|
||||
static const struct btmtksdio_data mt7668_data = {
|
||||
.fwname = FIRMWARE_MT7668,
|
||||
.chipid = 0x7668,
|
||||
};
|
||||
|
||||
static const struct btmtksdio_data mt7921_data = {
|
||||
.fwname = FIRMWARE_MT7961,
|
||||
.chipid = 0x7921,
|
||||
};
|
||||
|
||||
static const struct sdio_device_id btmtksdio_table[] = {
|
||||
@ -52,6 +60,8 @@ static const struct sdio_device_id btmtksdio_table[] = {
|
||||
.driver_data = (kernel_ulong_t)&mt7663_data },
|
||||
{SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, SDIO_DEVICE_ID_MEDIATEK_MT7668),
|
||||
.driver_data = (kernel_ulong_t)&mt7668_data },
|
||||
{SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, SDIO_DEVICE_ID_MEDIATEK_MT7961),
|
||||
.driver_data = (kernel_ulong_t)&mt7921_data },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdio, btmtksdio_table);
|
||||
@ -115,6 +125,7 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
|
||||
{
|
||||
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
|
||||
struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc;
|
||||
struct btmtk_hci_wmt_evt_reg *wmt_evt_reg;
|
||||
u32 hlen, status = BTMTK_WMT_INVALID;
|
||||
struct btmtk_hci_wmt_evt *wmt_evt;
|
||||
struct btmtk_hci_wmt_cmd *wc;
|
||||
@ -194,6 +205,19 @@ static int mtk_hci_wmt_sync(struct hci_dev *hdev,
|
||||
else
|
||||
status = BTMTK_WMT_ON_UNDONE;
|
||||
break;
|
||||
case BTMTK_WMT_PATCH_DWNLD:
|
||||
if (wmt_evt->whdr.flag == 2)
|
||||
status = BTMTK_WMT_PATCH_DONE;
|
||||
else if (wmt_evt->whdr.flag == 1)
|
||||
status = BTMTK_WMT_PATCH_PROGRESS;
|
||||
else
|
||||
status = BTMTK_WMT_PATCH_UNDONE;
|
||||
break;
|
||||
case BTMTK_WMT_REGISTER:
|
||||
wmt_evt_reg = (struct btmtk_hci_wmt_evt_reg *)wmt_evt;
|
||||
if (le16_to_cpu(wmt_evt->whdr.dlen) == 12)
|
||||
status = le32_to_cpu(wmt_evt_reg->val);
|
||||
break;
|
||||
}
|
||||
|
||||
if (wmt_params->status)
|
||||
@ -634,20 +658,14 @@ static int btmtksdio_func_query(struct hci_dev *hdev)
|
||||
return status;
|
||||
}
|
||||
|
||||
static int btmtksdio_setup(struct hci_dev *hdev)
|
||||
static int mt76xx_setup(struct hci_dev *hdev, const char *fwname)
|
||||
{
|
||||
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
|
||||
struct btmtk_hci_wmt_params wmt_params;
|
||||
ktime_t calltime, delta, rettime;
|
||||
struct btmtk_tci_sleep tci_sleep;
|
||||
unsigned long long duration;
|
||||
struct sk_buff *skb;
|
||||
int err, status;
|
||||
u8 param = 0x1;
|
||||
|
||||
calltime = ktime_get();
|
||||
bdev->hw_tx_ready = true;
|
||||
|
||||
/* Query whether the firmware is already download */
|
||||
wmt_params.op = BTMTK_WMT_SEMAPHORE;
|
||||
wmt_params.flag = 1;
|
||||
@ -667,7 +685,7 @@ static int btmtksdio_setup(struct hci_dev *hdev)
|
||||
}
|
||||
|
||||
/* Setup a firmware which the device definitely requires */
|
||||
err = btmtk_setup_firmware(hdev, bdev->data->fwname, mtk_hci_wmt_sync);
|
||||
err = btmtk_setup_firmware(hdev, fwname, mtk_hci_wmt_sync);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@ -719,6 +737,113 @@ ignore_func_on:
|
||||
}
|
||||
kfree_skb(skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt79xx_setup(struct hci_dev *hdev, const char *fwname)
|
||||
{
|
||||
struct btmtk_hci_wmt_params wmt_params;
|
||||
u8 param = 0x1;
|
||||
int err;
|
||||
|
||||
err = btmtk_setup_firmware_79xx(hdev, fwname, mtk_hci_wmt_sync);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to setup 79xx firmware (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Enable Bluetooth protocol */
|
||||
wmt_params.op = BTMTK_WMT_FUNC_CTRL;
|
||||
wmt_params.flag = 0;
|
||||
wmt_params.dlen = sizeof(param);
|
||||
wmt_params.data = ¶m;
|
||||
wmt_params.status = NULL;
|
||||
|
||||
err = mtk_hci_wmt_sync(hdev, &wmt_params);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int btsdio_mtk_reg_read(struct hci_dev *hdev, u32 reg, u32 *val)
|
||||
{
|
||||
struct btmtk_hci_wmt_params wmt_params;
|
||||
struct reg_read_cmd {
|
||||
u8 type;
|
||||
u8 rsv;
|
||||
u8 num;
|
||||
__le32 addr;
|
||||
} __packed reg_read = {
|
||||
.type = 1,
|
||||
.num = 1,
|
||||
};
|
||||
u32 status;
|
||||
int err;
|
||||
|
||||
reg_read.addr = cpu_to_le32(reg);
|
||||
wmt_params.op = BTMTK_WMT_REGISTER;
|
||||
wmt_params.flag = BTMTK_WMT_REG_READ;
|
||||
wmt_params.dlen = sizeof(reg_read);
|
||||
wmt_params.data = ®_read;
|
||||
wmt_params.status = &status;
|
||||
|
||||
err = mtk_hci_wmt_sync(hdev, &wmt_params);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to read reg(%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
*val = status;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int btmtksdio_setup(struct hci_dev *hdev)
|
||||
{
|
||||
struct btmtksdio_dev *bdev = hci_get_drvdata(hdev);
|
||||
ktime_t calltime, delta, rettime;
|
||||
unsigned long long duration;
|
||||
char fwname[64];
|
||||
int err, dev_id;
|
||||
u32 fw_version = 0;
|
||||
|
||||
calltime = ktime_get();
|
||||
bdev->hw_tx_ready = true;
|
||||
|
||||
switch (bdev->data->chipid) {
|
||||
case 0x7921:
|
||||
err = btsdio_mtk_reg_read(hdev, 0x70010200, &dev_id);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to get device id (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = btsdio_mtk_reg_read(hdev, 0x80021004, &fw_version);
|
||||
if (err < 0) {
|
||||
bt_dev_err(hdev, "Failed to get fw version (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
snprintf(fwname, sizeof(fwname),
|
||||
"mediatek/BT_RAM_CODE_MT%04x_1_%x_hdr.bin",
|
||||
dev_id & 0xffff, (fw_version & 0xff) + 1);
|
||||
err = mt79xx_setup(hdev, fwname);
|
||||
if (err < 0)
|
||||
return err;
|
||||
break;
|
||||
case 0x7663:
|
||||
case 0x7668:
|
||||
err = mt76xx_setup(hdev, bdev->data->fwname);
|
||||
if (err < 0)
|
||||
return err;
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rettime = ktime_get();
|
||||
delta = ktime_sub(rettime, calltime);
|
||||
duration = (unsigned long long)ktime_to_ns(delta) >> 10;
|
||||
|
Loading…
Reference in New Issue
Block a user