@@ -3128,6 +3128,12 @@ static int btusb_shutdown_intel_new(struct hci_dev *hdev)
3128
3128
#define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin"
3129
3129
3130
3130
#define HCI_WMT_MAX_EVENT_SIZE 64
3131
+ /* It is for mt79xx download rom patch*/
3132
+ #define MTK_FW_ROM_PATCH_HEADER_SIZE 32
3133
+ #define MTK_FW_ROM_PATCH_GD_SIZE 64
3134
+ #define MTK_FW_ROM_PATCH_SEC_MAP_SIZE 64
3135
+ #define MTK_SEC_MAP_COMMON_SIZE 12
3136
+ #define MTK_SEC_MAP_NEED_SEND_SIZE 52
3131
3137
3132
3138
enum {
3133
3139
BTMTK_WMT_PATCH_DWNLD = 0x1 ,
@@ -3184,6 +3190,40 @@ struct btmtk_hci_wmt_params {
3184
3190
u32 * status ;
3185
3191
};
3186
3192
3193
+ struct btmtk_patch_header {
3194
+ u8 datetime [16 ];
3195
+ u8 platform [4 ];
3196
+ __le16 hwver ;
3197
+ __le16 swver ;
3198
+ __le32 magicnum ;
3199
+ } __packed ;
3200
+
3201
+ struct btmtk_global_desc {
3202
+ __le32 patch_ver ;
3203
+ __le32 sub_sys ;
3204
+ __le32 feature_opt ;
3205
+ __le32 section_num ;
3206
+ } __packed ;
3207
+
3208
+ struct btmtk_section_map {
3209
+ __le32 sectype ;
3210
+ __le32 secoffset ;
3211
+ __le32 secsize ;
3212
+ union {
3213
+ __le32 u4SecSpec [13 ];
3214
+ struct {
3215
+ __le32 dlAddr ;
3216
+ __le32 dlsize ;
3217
+ __le32 seckeyidx ;
3218
+ __le32 alignlen ;
3219
+ __le32 sectype ;
3220
+ __le32 dlmodecrctype ;
3221
+ __le32 crc ;
3222
+ __le32 reserved [6 ];
3223
+ } bin_info_spec ;
3224
+ };
3225
+ } __packed ;
3226
+
3187
3227
static void btusb_mtk_wmt_recv (struct urb * urb )
3188
3228
{
3189
3229
struct hci_dev * hdev = urb -> context ;
@@ -3407,6 +3447,14 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev,
3407
3447
else
3408
3448
status = BTMTK_WMT_ON_UNDONE ;
3409
3449
break ;
3450
+ case BTMTK_WMT_PATCH_DWNLD :
3451
+ if (wmt_evt -> whdr .flag == 2 )
3452
+ status = BTMTK_WMT_PATCH_DONE ;
3453
+ else if (wmt_evt -> whdr .flag == 1 )
3454
+ status = BTMTK_WMT_PATCH_PROGRESS ;
3455
+ else
3456
+ status = BTMTK_WMT_PATCH_UNDONE ;
3457
+ break ;
3410
3458
}
3411
3459
3412
3460
if (wmt_params -> status )
@@ -3419,6 +3467,122 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev,
3419
3467
return err ;
3420
3468
}
3421
3469
3470
+ static int btusb_mtk_setup_firmware_79xx (struct hci_dev * hdev , const char * fwname )
3471
+ {
3472
+ struct btmtk_hci_wmt_params wmt_params ;
3473
+ struct btmtk_patch_header * patchhdr = NULL ;
3474
+ struct btmtk_global_desc * globaldesc = NULL ;
3475
+ struct btmtk_section_map * sectionmap ;
3476
+ const struct firmware * fw ;
3477
+ const u8 * fw_ptr ;
3478
+ const u8 * fw_bin_ptr ;
3479
+ size_t fw_size ;
3480
+ int err , dlen , i , status ;
3481
+ u8 flag , first_block , retry ;
3482
+ u32 section_num , dl_size , section_offset ;
3483
+ u8 cmd [64 ];
3484
+
3485
+ err = request_firmware (& fw , fwname , & hdev -> dev );
3486
+ if (err < 0 ) {
3487
+ bt_dev_err (hdev , "Failed to load firmware file (%d)" , err );
3488
+ return err ;
3489
+ }
3490
+
3491
+ fw_ptr = fw -> data ;
3492
+ fw_bin_ptr = fw_ptr ;
3493
+ fw_size = fw -> size ;
3494
+ patchhdr = (struct btmtk_patch_header * )fw_ptr ;
3495
+ globaldesc = (struct btmtk_global_desc * )(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE );
3496
+ section_num = globaldesc -> section_num ;
3497
+
3498
+ for (i = 0 ; i < section_num ; i ++ ) {
3499
+ first_block = 1 ;
3500
+ fw_ptr = fw_bin_ptr ;
3501
+ sectionmap = (struct btmtk_section_map * )(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE +
3502
+ MTK_FW_ROM_PATCH_GD_SIZE + MTK_FW_ROM_PATCH_SEC_MAP_SIZE * i );
3503
+
3504
+ section_offset = sectionmap -> secoffset ;
3505
+ dl_size = sectionmap -> bin_info_spec .dlsize ;
3506
+
3507
+ if (dl_size > 0 ) {
3508
+ retry = 20 ;
3509
+ while (retry > 0 ) {
3510
+ cmd [0 ] = 0 ; /* 0 means legacy dl mode. */
3511
+ memcpy (cmd + 1 ,
3512
+ fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE +
3513
+ MTK_FW_ROM_PATCH_GD_SIZE + MTK_FW_ROM_PATCH_SEC_MAP_SIZE * i +
3514
+ MTK_SEC_MAP_COMMON_SIZE ,
3515
+ MTK_SEC_MAP_NEED_SEND_SIZE + 1 );
3516
+
3517
+ wmt_params .op = BTMTK_WMT_PATCH_DWNLD ;
3518
+ wmt_params .status = & status ;
3519
+ wmt_params .flag = 0 ;
3520
+ wmt_params .dlen = MTK_SEC_MAP_NEED_SEND_SIZE + 1 ;
3521
+ wmt_params .data = & cmd ;
3522
+
3523
+ err = btusb_mtk_hci_wmt_sync (hdev , & wmt_params );
3524
+ if (err < 0 ) {
3525
+ bt_dev_err (hdev , "Failed to send wmt patch dwnld (%d)" ,
3526
+ err );
3527
+ goto err_release_fw ;
3528
+ }
3529
+
3530
+ if (status == BTMTK_WMT_PATCH_UNDONE ) {
3531
+ break ;
3532
+ } else if (status == BTMTK_WMT_PATCH_PROGRESS ) {
3533
+ msleep (100 );
3534
+ retry -- ;
3535
+ } else if (status == BTMTK_WMT_PATCH_DONE ) {
3536
+ goto next_section ;
3537
+ } else {
3538
+ bt_dev_err (hdev , "Failed wmt patch dwnld status (%d)" ,
3539
+ status );
3540
+ goto err_release_fw ;
3541
+ }
3542
+ }
3543
+
3544
+ fw_ptr += section_offset ;
3545
+ wmt_params .op = BTMTK_WMT_PATCH_DWNLD ;
3546
+ wmt_params .status = NULL ;
3547
+
3548
+ while (dl_size > 0 ) {
3549
+ dlen = min_t (int , 250 , dl_size );
3550
+ if (first_block == 1 ) {
3551
+ flag = 1 ;
3552
+ first_block = 0 ;
3553
+ } else if (dl_size - dlen <= 0 ) {
3554
+ flag = 3 ;
3555
+ } else {
3556
+ flag = 2 ;
3557
+ }
3558
+
3559
+ wmt_params .flag = flag ;
3560
+ wmt_params .dlen = dlen ;
3561
+ wmt_params .data = fw_ptr ;
3562
+
3563
+ err = btusb_mtk_hci_wmt_sync (hdev , & wmt_params );
3564
+ if (err < 0 ) {
3565
+ bt_dev_err (hdev , "Failed to send wmt patch dwnld (%d)" ,
3566
+ err );
3567
+ goto err_release_fw ;
3568
+ }
3569
+
3570
+ dl_size -= dlen ;
3571
+ fw_ptr += dlen ;
3572
+ }
3573
+ }
3574
+ next_section :
3575
+ continue ;
3576
+ }
3577
+ /* Wait a few moments for firmware activation done */
3578
+ usleep_range (100000 , 120000 );
3579
+
3580
+ err_release_fw :
3581
+ release_firmware (fw );
3582
+
3583
+ return err ;
3584
+ }
3585
+
3422
3586
static int btusb_mtk_setup_firmware (struct hci_dev * hdev , const char * fwname )
3423
3587
{
3424
3588
struct btmtk_hci_wmt_params wmt_params ;
@@ -3573,6 +3737,8 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
3573
3737
const char * fwname ;
3574
3738
int err , status ;
3575
3739
u32 dev_id ;
3740
+ char fw_bin_name [64 ];
3741
+ u32 fw_version ;
3576
3742
u8 param ;
3577
3743
3578
3744
calltime = ktime_get ();
@@ -3583,13 +3749,46 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
3583
3749
return err ;
3584
3750
}
3585
3751
3752
+ if (!dev_id ) {
3753
+ err = btusb_mtk_id_get (data , 0x70010200 , & dev_id );
3754
+ if (err < 0 ) {
3755
+ bt_dev_err (hdev , "Failed to get device id (%d)" , err );
3756
+ return err ;
3757
+ }
3758
+ err = btusb_mtk_id_get (data , 0x80021004 , & fw_version );
3759
+ if (err < 0 ) {
3760
+ bt_dev_err (hdev , "Failed to get fw version (%d)" , err );
3761
+ return err ;
3762
+ }
3763
+ }
3764
+
3586
3765
switch (dev_id ) {
3587
3766
case 0x7663 :
3588
3767
fwname = FIRMWARE_MT7663 ;
3589
3768
break ;
3590
3769
case 0x7668 :
3591
3770
fwname = FIRMWARE_MT7668 ;
3592
3771
break ;
3772
+ case 0x7961 :
3773
+ snprintf (fw_bin_name , sizeof (fw_bin_name ),
3774
+ "mediatek/BT_RAM_CODE_MT%04x_1_%x_hdr.bin" ,
3775
+ dev_id & 0xffff , (fw_version & 0xff ) + 1 );
3776
+ err = btusb_mtk_setup_firmware_79xx (hdev , fw_bin_name );
3777
+
3778
+ /* Enable Bluetooth protocol */
3779
+ param = 1 ;
3780
+ wmt_params .op = BTMTK_WMT_FUNC_CTRL ;
3781
+ wmt_params .flag = 0 ;
3782
+ wmt_params .dlen = sizeof (param );
3783
+ wmt_params .data = & param ;
3784
+ wmt_params .status = NULL ;
3785
+
3786
+ err = btusb_mtk_hci_wmt_sync (hdev , & wmt_params );
3787
+ if (err < 0 ) {
3788
+ bt_dev_err (hdev , "Failed to send wmt func ctrl (%d)" , err );
3789
+ return err ;
3790
+ }
3791
+ goto done ;
3593
3792
default :
3594
3793
bt_dev_err (hdev , "Unsupported support hardware variant (%08x)" ,
3595
3794
dev_id );
@@ -3667,6 +3866,7 @@ static int btusb_mtk_setup(struct hci_dev *hdev)
3667
3866
}
3668
3867
kfree_skb (skb );
3669
3868
3869
+ done :
3670
3870
rettime = ktime_get ();
3671
3871
delta = ktime_sub (rettime , calltime );
3672
3872
duration = (unsigned long long )ktime_to_ns (delta ) >> 10 ;
0 commit comments