603 lines
15 KiB
C
603 lines
15 KiB
C
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
|
/*
|
|
* common/rtk_fw.c
|
|
*
|
|
* Copyright (C) 2020 Amlogic, Inc. All rights reserved.
|
|
*
|
|
*/
|
|
|
|
/******************************************************************************
|
|
* Copyright (c) 2020-2022 by Hisi.
|
|
* All rights reserved.
|
|
*
|
|
* Create by zengqiu. 2022-1-10
|
|
*
|
|
******************************************************************************/
|
|
#include <common.h>
|
|
#include <command.h>
|
|
#include <asm/processor.h>
|
|
#include <linux/compiler.h>
|
|
#include <linux/ctype.h>
|
|
#include <asm/byteorder.h>
|
|
#include <asm/unaligned.h>
|
|
#include <dm/uclass.h>
|
|
#include <dm/device.h>
|
|
#include <dm/uclass-internal.h>
|
|
|
|
#include <malloc.h>
|
|
#include <usb.h>
|
|
#include <rtk_fw.h>
|
|
|
|
#define USB_ERROR(fmt, args...) {if (log_level) printf(fmt, ##args); }
|
|
#define USB_DEBUG(fmt, args...) {if (log_level) printf(fmt, ##args); }
|
|
|
|
//patch txt formate: total length(2 bytes) || fw patch || config patch
|
|
static unsigned char lu8Code_RTL8723BU[CODE_MAXSIZE_24K] = {
|
|
#include CHIP_TYPE_RTL8723BU
|
|
};
|
|
|
|
static unsigned char lu8Code_RTL8723DU[CODE_MAXSIZE_40K] = {
|
|
#include CHIP_TYPE_RTL8723DU
|
|
};
|
|
|
|
static unsigned char lu8Code_RTL8822BU[CODE_MAXSIZE_23K] = {
|
|
#include CHIP_TYPE_RTL8822BU
|
|
};
|
|
|
|
static unsigned char lu8Code_RTL88X2CU[CODE_MAXSIZE_40K] = {
|
|
#include CHIP_TYPE_RTL88X2CU
|
|
};
|
|
|
|
static const bluetooth_dongle usb_dongle[] = {
|
|
{0x0bda, 0xb720, "8723bu", CHIP_TYPE_RTL8723BU, CODE_MAXSIZE_24K, lu8Code_RTL8723BU},
|
|
{0x0bda, 0xd723, "8723du", CHIP_TYPE_RTL8723DU, CODE_MAXSIZE_40K, lu8Code_RTL8723DU},
|
|
{0x0bda, 0xb82c, "8822bu", CHIP_TYPE_RTL8822BU, CODE_MAXSIZE_23K, lu8Code_RTL8822BU},
|
|
{0x0bda, 0xc82c, "88x2cu", CHIP_TYPE_RTL88X2CU, CODE_MAXSIZE_40K, lu8Code_RTL88X2CU}
|
|
};
|
|
|
|
static int num = -1;
|
|
|
|
firmware_info *firmware_info_init(struct usb_device *dev)
|
|
{
|
|
struct usb_device *udev = dev;
|
|
firmware_info *fw_info;
|
|
|
|
USB_DEBUG("%s[%d]: start.\n", __func__, __LINE__);
|
|
|
|
fw_info = malloc(sizeof(*fw_info));
|
|
memset(fw_info, 0, sizeof(*fw_info));
|
|
if (!fw_info)
|
|
return NULL;
|
|
|
|
fw_info->fw_data = malloc(usb_dongle[num].fw_size);
|
|
memset(fw_info->fw_data, 0, usb_dongle[num].fw_size);
|
|
if (!fw_info->fw_data) {
|
|
free(fw_info);
|
|
return NULL;
|
|
}
|
|
|
|
fw_info->send_pkt = malloc(PKT_LEN);
|
|
memset(fw_info->send_pkt, 0, PKT_LEN);
|
|
if (!fw_info->send_pkt) {
|
|
free(fw_info->fw_data);
|
|
free(fw_info);
|
|
return NULL;
|
|
}
|
|
|
|
fw_info->rcv_pkt = malloc(PKT_LEN);
|
|
memset(fw_info->rcv_pkt, 0, PKT_LEN);
|
|
if (!fw_info->rcv_pkt) {
|
|
free(fw_info->fw_data);
|
|
free(fw_info->send_pkt);
|
|
free(fw_info);
|
|
return NULL;
|
|
}
|
|
|
|
fw_info->patch_entry = NULL;
|
|
fw_info->intf = NULL;
|
|
fw_info->udev = udev;
|
|
fw_info->pipe_in = usb_rcvintpipe(fw_info->udev, INTR_EP);
|
|
fw_info->pipe_out = usb_sndctrlpipe(fw_info->udev, CTRL_EP);
|
|
fw_info->cmd_hdr = (struct hci_command_hdr *)(fw_info->send_pkt);
|
|
fw_info->evt_hdr = (struct hci_event_hdr *)(fw_info->rcv_pkt);
|
|
fw_info->cmd_cmp = (struct hci_ev_cmd_complete *)(fw_info->rcv_pkt + EVT_HDR_LEN);
|
|
fw_info->req_para = fw_info->send_pkt + CMD_HDR_LEN;
|
|
fw_info->rsp_para = fw_info->rcv_pkt + EVT_HDR_LEN + CMD_CMP_LEN;
|
|
|
|
return fw_info;
|
|
}
|
|
|
|
void firmware_info_destroy(firmware_info *fw_info)
|
|
{
|
|
free(fw_info->fw_data);
|
|
free(fw_info->rcv_pkt);
|
|
free(fw_info->send_pkt);
|
|
free(fw_info);
|
|
}
|
|
|
|
int load_firmware(firmware_info *fw_info, unsigned char **buff)
|
|
{
|
|
unsigned int size;
|
|
|
|
size = usb_dongle[num].fw_buf[0] | (usb_dongle[num].fw_buf[1] << 8);
|
|
USB_DEBUG("%s,%s size is %d\n", __func__, usb_dongle[num].fw_name, size);
|
|
|
|
if (size > usb_dongle[num].fw_size) {
|
|
USB_ERROR("%s,size is %d firmware is larger than %d\n",
|
|
__func__, size, usb_dongle[num].fw_size);
|
|
num = -1;
|
|
return -1;
|
|
}
|
|
memcpy(*buff, &usb_dongle[num].fw_buf[2], size);
|
|
return size;
|
|
}
|
|
|
|
int send_hci_cmd(firmware_info *fw_info)
|
|
{
|
|
int ret_val;
|
|
|
|
ret_val = usb_control_msg(fw_info->udev, fw_info->pipe_out,
|
|
0, USB_TYPE_CLASS, 0, 0, (void *)(fw_info->send_pkt),
|
|
fw_info->pkt_len, MSG_TO);
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
int rcv_hci_evt(firmware_info *fw_info)
|
|
{
|
|
int /*ret_len = 0,*/ ret_val = 0;
|
|
int i;
|
|
|
|
while (1) {
|
|
for (i = 0; i < 5; i++) {
|
|
ret_val = usb_submit_int_msg(fw_info->udev,
|
|
fw_info->pipe_in,
|
|
(void *)(fw_info->rcv_pkt), PKT_LEN,
|
|
MSG_TO);
|
|
if (ret_val >= 0)
|
|
break;
|
|
}
|
|
|
|
//USB_DEBUG("fw_info->rcv_pkt:0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
|
|
// fw_info->rcv_pkt[0], fw_info->rcv_pkt[1],
|
|
// fw_info->rcv_pkt[2], fw_info->rcv_pkt[3],
|
|
// fw_info->rcv_pkt[4], fw_info->rcv_pkt[5],
|
|
// fw_info->rcv_pkt[6]);
|
|
|
|
if (ret_val < 0)
|
|
return ret_val;
|
|
|
|
if (fw_info->evt_hdr->evt == CMD_CMP_EVT) {
|
|
if (fw_info->cmd_hdr->opcode == fw_info->cmd_cmp->opcode)
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
int get_firmware(firmware_info *fw_info)
|
|
{
|
|
/* patch_info *patch_entry = fw_info->patch_entry; */
|
|
|
|
fw_info->fw_len = load_firmware(fw_info, &fw_info->fw_data);
|
|
USB_DEBUG("%s[%d]: fw_len=%d\n", __func__, __LINE__, fw_info->fw_len);
|
|
if (fw_info->fw_len <= 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int reset_controller(firmware_info *fw_info)
|
|
{
|
|
int ret_val;
|
|
|
|
USB_DEBUG("%s\n", __func__);
|
|
if (!fw_info)
|
|
return -ENODEV;
|
|
|
|
fw_info->cmd_hdr->opcode = cpu_to_le16(HCI_VENDOR_FORCE_RESET_AND_PATCHABLE);
|
|
fw_info->cmd_hdr->plen = 0;
|
|
fw_info->pkt_len = CMD_HDR_LEN;
|
|
ret_val = send_hci_cmd(fw_info);
|
|
if (ret_val < 0) {
|
|
USB_DEBUG("%s: Failed to send hci cmd 0x%04x, errno %d\n",
|
|
__func__, fw_info->cmd_hdr->opcode, ret_val);
|
|
return ret_val;
|
|
}
|
|
|
|
mdelay(200);
|
|
USB_DEBUG("%s: Wait fw reset for 200ms\n", __func__);
|
|
return ret_val;
|
|
}
|
|
|
|
int download_data(firmware_info *fw_info)
|
|
{
|
|
download_cp *cmd_para;
|
|
download_rp *evt_para;
|
|
unsigned char *pcur;
|
|
int pkt_len, frag_num, frag_len;
|
|
int i, ret_val;
|
|
int ncmd = 1, step = 1;
|
|
|
|
USB_DEBUG("%s: start\n", __func__);
|
|
|
|
cmd_para = (download_cp *)fw_info->req_para;
|
|
evt_para = (download_rp *)fw_info->rsp_para;
|
|
pcur = fw_info->fw_data;
|
|
pkt_len = CMD_HDR_LEN + sizeof(download_cp);
|
|
frag_num = fw_info->fw_len / PATCH_SEG_MAX + 1;
|
|
frag_len = PATCH_SEG_MAX;
|
|
|
|
cmd_para->index = 0;
|
|
for (i = 0; i < frag_num; i++) {
|
|
if (i == (frag_num - 1)) {
|
|
cmd_para->index |= DATA_END;
|
|
frag_len = fw_info->fw_len % PATCH_SEG_MAX;
|
|
pkt_len -= (PATCH_SEG_MAX - frag_len);
|
|
if (pkt_len == (CMD_HDR_LEN + sizeof(unsigned char)))
|
|
goto end;
|
|
}
|
|
fw_info->cmd_hdr->opcode = cpu_to_le16(DOWNLOAD_OPCODE);
|
|
fw_info->cmd_hdr->plen = sizeof(unsigned char) + frag_len;
|
|
fw_info->pkt_len = pkt_len;
|
|
memcpy(cmd_para->data, pcur, frag_len);
|
|
|
|
if (step > 0) {
|
|
ret_val = send_hci_cmd(fw_info);
|
|
if (ret_val < 0)
|
|
//USB_ERROR("%s: Failed to send frag num %d\n",
|
|
// __func__, cmd_para->index);
|
|
return ret_val;
|
|
|
|
if (--step > 0 && i < frag_num - 1) {
|
|
//USB_DEBUG("%s: Continue to send frag num %d\n",
|
|
// __func__, cmd_para->index + 1);
|
|
pcur += PATCH_SEG_MAX;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
while (ncmd > 0) {
|
|
ret_val = rcv_hci_evt(fw_info);
|
|
if (ret_val < 0) {
|
|
//USB_ERROR("%s: rcv_hci_evt err %d\n", __func__, ret_val);
|
|
return ret_val;
|
|
}
|
|
|
|
//USB_DEBUG("%s: Receive acked frag num %d\n", __func__, evt_para->index);
|
|
ncmd--;
|
|
|
|
if (evt_para->status != 0) {
|
|
//USB_ERROR("%s: Receive acked frag num %d, err status %d\n",
|
|
// __func__, ret_val, evt_para->status);
|
|
return -1;
|
|
}
|
|
|
|
if ((evt_para->index & DATA_END) || (evt_para->index == frag_num - 1)) {
|
|
//USB_DEBUG("%s: Receive last acked index %d\n",
|
|
// __func__, evt_para->index);
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
cmd_para->index++;
|
|
if (cmd_para->index == 0x80)
|
|
cmd_para->index = 1;
|
|
ncmd = fw_info->cmd_cmp->ncmd;
|
|
step = fw_info->cmd_cmp->ncmd;
|
|
pcur += PATCH_SEG_MAX;
|
|
//USB_DEBUG("%s: HCI command packet num %d\n", __func__, ncmd);
|
|
}
|
|
|
|
/*
|
|
* It is tricky that Host cannot receive DATA_END index from BT
|
|
* controller, at least for 8723au. We are doomed if failed.
|
|
*/
|
|
|
|
end:
|
|
// USB_DEBUG("%s: done, sent %d frag pkts, received %d frag events\n",
|
|
// __func__, cmd_para->index, evt_para->index);
|
|
return fw_info->fw_len;
|
|
}
|
|
|
|
int set_wakeup_device(firmware_info *fw_info)
|
|
{
|
|
struct rtk_eversion_evt *ever_evt;
|
|
int ret_val;
|
|
static unsigned char bdaddr[7] = {0x00, 0xd7, 0xe3, 0x3e, 0xf8, 0xe6, 0xa0};
|
|
|
|
if (!fw_info)
|
|
return -ENODEV;
|
|
|
|
fw_info->cmd_hdr->opcode = cpu_to_le16(HCI_VENDOR_SET_WAKE_UP_DEVICE);
|
|
fw_info->cmd_hdr->plen = 7;
|
|
memcpy(fw_info->req_para, bdaddr, 7);
|
|
fw_info->pkt_len = CMD_HDR_LEN + 7;
|
|
|
|
ret_val = send_hci_cmd(fw_info);
|
|
if (ret_val < 0) {
|
|
USB_ERROR("%s: Failed to send hci cmd 0x%04x, errno %d\n",
|
|
__func__, fw_info->cmd_hdr->opcode, ret_val);
|
|
return ret_val;
|
|
}
|
|
|
|
ret_val = rcv_hci_evt(fw_info);
|
|
if (ret_val < 0) {
|
|
USB_ERROR("%s: Failed to receive hci event, errno %d\n",
|
|
__func__, ret_val);
|
|
return ret_val;
|
|
}
|
|
|
|
ever_evt = (struct rtk_eversion_evt *)(fw_info->rsp_para);
|
|
|
|
USB_DEBUG("%s: status %d, eversion %d\n", __func__, ever_evt->status, ever_evt->version);
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
int reset_chip_dev(firmware_info *fw_info)
|
|
{
|
|
int ret_val;
|
|
|
|
if (!fw_info)
|
|
return -ENODEV;
|
|
|
|
fw_info->cmd_hdr->opcode = cpu_to_le16(HCI_VENDOR_CHIP_RESET);
|
|
fw_info->cmd_hdr->plen = 0;
|
|
fw_info->pkt_len = CMD_HDR_LEN;
|
|
|
|
ret_val = send_hci_cmd(fw_info);
|
|
if (ret_val < 0) {
|
|
USB_ERROR("%s: Failed to send hci cmd 0x%04x, errno %d\n",
|
|
__func__, fw_info->cmd_hdr->opcode, ret_val);
|
|
return ret_val;
|
|
}
|
|
|
|
ret_val = rcv_hci_evt(fw_info);
|
|
if (ret_val < 0) {
|
|
USB_ERROR("%s: Failed to receive hci event, errno %d\n",
|
|
__func__, ret_val);
|
|
return ret_val;
|
|
}
|
|
|
|
if (!*fw_info->rsp_para)
|
|
printf("%s success\n", __func__);
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
int check_chip_fw_version(firmware_info *fw_info)
|
|
{
|
|
struct rtk_localversion_evt *ever_evt;
|
|
int ret_val;
|
|
|
|
if (!fw_info)
|
|
return -ENODEV;
|
|
|
|
fw_info->cmd_hdr->opcode = cpu_to_le16(HCI_VENDOR_READ_LMP_VERSION);
|
|
fw_info->cmd_hdr->plen = 0;
|
|
fw_info->pkt_len = CMD_HDR_LEN;
|
|
|
|
ret_val = send_hci_cmd(fw_info);
|
|
if (ret_val < 0) {
|
|
USB_ERROR("%s: Failed to send hci cmd 0x%04x, errno %d\n",
|
|
__func__, fw_info->cmd_hdr->opcode, ret_val);
|
|
return ret_val;
|
|
}
|
|
|
|
ret_val = rcv_hci_evt(fw_info);
|
|
if (ret_val < 0) {
|
|
USB_ERROR("%s: Failed to receive hci event, errno %d\n",
|
|
__func__, ret_val);
|
|
return ret_val;
|
|
}
|
|
|
|
ever_evt = (struct rtk_localversion_evt *)(fw_info->rsp_para);
|
|
|
|
USB_DEBUG("%s: status %x\n", __func__, ever_evt->status);
|
|
USB_DEBUG("%s: hci_version %x\n", __func__, ever_evt->hci_version);
|
|
USB_DEBUG("%s: hci_revision %x\n", __func__, ever_evt->hci_revision);
|
|
USB_DEBUG("%s: lmp_version %x\n", __func__, ever_evt->lmp_version);
|
|
USB_DEBUG("%s: lmp_subversion %x\n", __func__, ever_evt->lmp_subversion);
|
|
USB_DEBUG("%s: lmp_manufacture %x\n", __func__, ever_evt->lmp_manufacture);
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
#if DEL_CODE // just fro reference
|
|
void load_rtl_firmware(void)
|
|
{
|
|
firmware_info *fw_info;
|
|
int ret_val, i;
|
|
struct usb_device *dev;
|
|
|
|
usb_init();
|
|
|
|
/* scan all USB Devices */
|
|
dev = NULL;
|
|
for (i = 0; i < USB_MAX_DEVICE; i++) {
|
|
dev = usb_get_dev_index(i); /* get device */
|
|
if (!dev)
|
|
return;
|
|
if (dev->devnum != -1) {
|
|
if (!strcmp(dev->mf, "Realtek") && !strcmp(dev->prod, "Bluetooth Radio")) {
|
|
/* Download BT Fireware */
|
|
printf("Now Download BT Firmware.\n");
|
|
fw_info = firmware_info_init(dev);
|
|
get_firmware(fw_info);
|
|
ret_val = download_data(fw_info);
|
|
if (ret_val > 0)
|
|
printf("Download fw patch done, fw len %d\n", ret_val);
|
|
mdelay(10);
|
|
set_wakeup_device(fw_info);
|
|
//set_bt_wakeup(fw_info);
|
|
firmware_info_destroy(fw_info);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static struct usb_device *qiu_usb_find_device(int devnum)
|
|
{
|
|
#ifdef CONFIG_DM_USB
|
|
struct usb_device *udev;
|
|
struct udevice *hub;
|
|
struct uclass *uc;
|
|
int ret;
|
|
|
|
/* Device addresses start at 1 */
|
|
devnum++;
|
|
ret = uclass_get(UCLASS_USB_HUB, &uc);
|
|
if (ret)
|
|
return NULL;
|
|
|
|
uclass_foreach_dev(hub, uc) {
|
|
struct udevice *dev;
|
|
|
|
if (!device_active(hub))
|
|
continue;
|
|
udev = dev_get_parent_priv(hub);
|
|
if (udev->devnum == devnum)
|
|
return udev;
|
|
|
|
for (device_find_first_child(hub, &dev);
|
|
dev;
|
|
device_find_next_child(&dev)) {
|
|
if (!device_active(hub))
|
|
continue;
|
|
|
|
udev = dev_get_parent_priv(dev);
|
|
if (udev->devnum == devnum)
|
|
return udev;
|
|
}
|
|
}
|
|
#else
|
|
struct usb_device *udev;
|
|
int d;
|
|
|
|
for (d = 0; d < USB_MAX_DEVICE; d++) {
|
|
udev = usb_get_dev_index(d);
|
|
if (!udev)
|
|
return NULL;
|
|
if (udev->devnum == devnum)
|
|
return udev;
|
|
}
|
|
#endif
|
|
|
|
return NULL;
|
|
}
|
|
|
|
struct usb_device *get_rtl_dev(void)
|
|
{
|
|
int i = 0;
|
|
int size, usb_size;
|
|
struct usb_device *dev;
|
|
/* scan all USB Devices */
|
|
dev = NULL;
|
|
|
|
for (i = 0; i < USB_MAX_DEVICE; i++) {
|
|
dev = qiu_usb_find_device(i);
|
|
if (!dev) {
|
|
printf("usb dev is null!!!!\n");
|
|
return NULL;
|
|
}
|
|
|
|
printf("i=%d dev->devnum:%d dev->mf:%s dev->prod:%s\n",
|
|
i, dev->devnum, dev->mf, dev->prod);
|
|
USB_DEBUG("vid is %x, pid is %x\n",
|
|
le16_to_cpu(dev->descriptor.idVendor),
|
|
le16_to_cpu(dev->descriptor.idProduct));
|
|
/* AML change for haier to match 8723bu bt */
|
|
if (dev->devnum != -1) {
|
|
size = sizeof(usb_dongle) / sizeof(bluetooth_dongle);
|
|
for (usb_size = 0; usb_size < size; usb_size++) {
|
|
if (le16_to_cpu(dev->descriptor.idVendor ==
|
|
usb_dongle[usb_size].idVendor) &&
|
|
le16_to_cpu(dev->descriptor.idProduct) ==
|
|
usb_dongle[usb_size].idProduct) {
|
|
num = usb_size;
|
|
return dev;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
printf("dou't find device\n");
|
|
return NULL;
|
|
}
|
|
|
|
int load_rtl_firmware_dev(struct usb_device *dev)
|
|
{
|
|
#if DEL_CODE
|
|
char *reboot_mode = getenv("reboot_mode");
|
|
|
|
if (!reboot_mode)
|
|
return 0;
|
|
|
|
if (reboot_mode && strcmp("cold_boot", reboot_mode))
|
|
return 0;
|
|
#endif
|
|
firmware_info *fw_info;
|
|
int ret_val = -1;
|
|
|
|
/* Download BT Fireware */
|
|
USB_DEBUG("Now Download RTK BT Firmware. (version 20221220i_1)\n");
|
|
|
|
fw_info = firmware_info_init(dev);
|
|
if (!fw_info)
|
|
return -1;
|
|
|
|
ret_val = get_firmware(fw_info);
|
|
printf("++++ZQ:{%s}[%d]...(get_firmware = [%d]).\n",
|
|
__func__, __LINE__, fw_info->fw_len);
|
|
if (-1 == ret_val) {
|
|
printf("++++ZQ:{%s}[%d]...get firmware, errno %d\n",
|
|
__func__, __LINE__, ret_val);
|
|
return ret_val;
|
|
}
|
|
|
|
ret_val = reset_chip_dev(fw_info);
|
|
if (ret_val < 0) {
|
|
printf("++++ZQ:{%s}[%d]...chip fail", __func__, __LINE__);
|
|
return ret_val;
|
|
}
|
|
|
|
ret_val = check_chip_fw_version(fw_info);
|
|
USB_DEBUG("++++ZQ:{%s}[%d]...(check_chip_fw_version = [%d]).\n",
|
|
__func__, __LINE__, ret_val);
|
|
|
|
if (ret_val < 0) {
|
|
printf("++++ZQ:{%s}[%d]...Failed to check chip fw version, errno %d\n",
|
|
__func__, __LINE__, ret_val);
|
|
return ret_val;
|
|
}
|
|
|
|
ret_val = reset_controller(fw_info);
|
|
USB_DEBUG("++++ZQ:{%s}[%d]...(reset_controller = [%d]).\n",
|
|
__func__, __LINE__, ret_val);
|
|
|
|
if (ret_val < 0) {
|
|
printf("++++ZQ:{%s}[%d]...(reset controller error = [%d]).\n",
|
|
__func__, __LINE__, ret_val);
|
|
return ret_val;
|
|
}
|
|
|
|
ret_val = download_data(fw_info);
|
|
USB_DEBUG("++++ZQ:{%s}[%d]...(download_data = [%d]).\n",
|
|
__func__, __LINE__, ret_val);
|
|
|
|
if (ret_val > 0) {
|
|
printf("Download fw patch done, fw len %d\n", ret_val);
|
|
} else {
|
|
firmware_info_destroy(fw_info);
|
|
return ret_val;
|
|
}
|
|
mdelay(10);
|
|
ret_val = set_wakeup_device(fw_info);
|
|
USB_DEBUG("++++ZQ:{%s}[%d]...(set_wakeup_device = [%d]).\n",
|
|
__func__, __LINE__, ret_val);
|
|
//set_bt_wakeup(fw_info);
|
|
firmware_info_destroy(fw_info);
|
|
return ret_val;
|
|
}
|
|
|