1414
1515#define VERSION "0.1"
1616
17- int qca_read_soc_version (struct hci_dev * hdev , u32 * soc_version )
17+ int qca_read_soc_version (struct hci_dev * hdev , u32 * soc_version ,
18+ enum qca_btsoc_type soc_type )
1819{
1920 struct sk_buff * skb ;
2021 struct edl_event_hdr * edl ;
2122 struct qca_btsoc_version * ver ;
2223 char cmd ;
2324 int err = 0 ;
25+ u8 event_type = HCI_EV_VENDOR ;
26+ u8 rlen = sizeof (* edl ) + sizeof (* ver );
27+ u8 rtype = EDL_APP_VER_RES_EVT ;
2428
2529 bt_dev_dbg (hdev , "QCA Version Request" );
2630
31+ /* Unlike other SoC's sending version command response as payload to
32+ * VSE event. WCN3991 sends version command response as a payload to
33+ * command complete event.
34+ */
35+ if (soc_type == QCA_WCN3991 ) {
36+ event_type = 0 ;
37+ rlen += 1 ;
38+ rtype = EDL_PATCH_VER_REQ_CMD ;
39+ }
40+
2741 cmd = EDL_PATCH_VER_REQ_CMD ;
2842 skb = __hci_cmd_sync_ev (hdev , EDL_PATCH_CMD_OPCODE , EDL_PATCH_CMD_LEN ,
29- & cmd , HCI_EV_VENDOR , HCI_INIT_TIMEOUT );
43+ & cmd , event_type , HCI_INIT_TIMEOUT );
3044 if (IS_ERR (skb )) {
3145 err = PTR_ERR (skb );
3246 bt_dev_err (hdev , "Reading QCA version information failed (%d)" ,
3347 err );
3448 return err ;
3549 }
3650
37- if (skb -> len != sizeof ( * edl ) + sizeof ( * ver ) ) {
51+ if (skb -> len != rlen ) {
3852 bt_dev_err (hdev , "QCA Version size mismatch len %d" , skb -> len );
3953 err = - EILSEQ ;
4054 goto out ;
@@ -48,13 +62,16 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version)
4862 }
4963
5064 if (edl -> cresp != EDL_CMD_REQ_RES_EVT ||
51- edl -> rtype != EDL_APP_VER_RES_EVT ) {
65+ edl -> rtype != rtype ) {
5266 bt_dev_err (hdev , "QCA Wrong packet received %d %d" , edl -> cresp ,
5367 edl -> rtype );
5468 err = - EIO ;
5569 goto out ;
5670 }
5771
72+ if (soc_type == QCA_WCN3991 )
73+ memmove (& edl -> data , & edl -> data [1 ], sizeof (* ver ));
74+
5875 ver = (struct qca_btsoc_version * )(edl -> data );
5976
6077 BT_DBG ("%s: Product:0x%08x" , hdev -> name , le32_to_cpu (ver -> product_id ));
@@ -223,13 +240,17 @@ static void qca_tlv_check_data(struct qca_fw_config *config,
223240}
224241
225242static int qca_tlv_send_segment (struct hci_dev * hdev , int seg_size ,
226- const u8 * data , enum qca_tlv_dnld_mode mode )
243+ const u8 * data , enum qca_tlv_dnld_mode mode ,
244+ enum qca_btsoc_type soc_type )
227245{
228246 struct sk_buff * skb ;
229247 struct edl_event_hdr * edl ;
230248 struct tlv_seg_resp * tlv_resp ;
231249 u8 cmd [MAX_SIZE_PER_TLV_SEGMENT + 2 ];
232250 int err = 0 ;
251+ u8 event_type = HCI_EV_VENDOR ;
252+ u8 rlen = (sizeof (* edl ) + sizeof (* tlv_resp ));
253+ u8 rtype = EDL_TVL_DNLD_RES_EVT ;
233254
234255 cmd [0 ] = EDL_PATCH_TLV_REQ_CMD ;
235256 cmd [1 ] = seg_size ;
@@ -239,15 +260,25 @@ static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size,
239260 return __hci_cmd_send (hdev , EDL_PATCH_CMD_OPCODE , seg_size + 2 ,
240261 cmd );
241262
263+ /* Unlike other SoC's sending version command response as payload to
264+ * VSE event. WCN3991 sends version command response as a payload to
265+ * command complete event.
266+ */
267+ if (soc_type == QCA_WCN3991 ) {
268+ event_type = 0 ;
269+ rlen = sizeof (* edl );
270+ rtype = EDL_PATCH_TLV_REQ_CMD ;
271+ }
272+
242273 skb = __hci_cmd_sync_ev (hdev , EDL_PATCH_CMD_OPCODE , seg_size + 2 , cmd ,
243- HCI_EV_VENDOR , HCI_INIT_TIMEOUT );
274+ event_type , HCI_INIT_TIMEOUT );
244275 if (IS_ERR (skb )) {
245276 err = PTR_ERR (skb );
246277 bt_dev_err (hdev , "QCA Failed to send TLV segment (%d)" , err );
247278 return err ;
248279 }
249280
250- if (skb -> len != sizeof ( * edl ) + sizeof ( * tlv_resp ) ) {
281+ if (skb -> len != rlen ) {
251282 bt_dev_err (hdev , "QCA TLV response size mismatch" );
252283 err = - EILSEQ ;
253284 goto out ;
@@ -260,13 +291,19 @@ static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size,
260291 goto out ;
261292 }
262293
263- tlv_resp = (struct tlv_seg_resp * )(edl -> data );
294+ if (edl -> cresp != EDL_CMD_REQ_RES_EVT || edl -> rtype != rtype ) {
295+ bt_dev_err (hdev , "QCA TLV with error stat 0x%x rtype 0x%x" ,
296+ edl -> cresp , edl -> rtype );
297+ err = - EIO ;
298+ }
264299
265- if (edl -> cresp != EDL_CMD_REQ_RES_EVT ||
266- edl -> rtype != EDL_TVL_DNLD_RES_EVT || tlv_resp -> result != 0x00 ) {
300+ if (soc_type == QCA_WCN3991 )
301+ goto out ;
302+
303+ tlv_resp = (struct tlv_seg_resp * )(edl -> data );
304+ if (tlv_resp -> result ) {
267305 bt_dev_err (hdev , "QCA TLV with error stat 0x%x rtype 0x%x (0x%x)" ,
268306 edl -> cresp , edl -> rtype , tlv_resp -> result );
269- err = - EIO ;
270307 }
271308
272309out :
@@ -301,7 +338,8 @@ static int qca_inject_cmd_complete_event(struct hci_dev *hdev)
301338}
302339
303340static int qca_download_firmware (struct hci_dev * hdev ,
304- struct qca_fw_config * config )
341+ struct qca_fw_config * config ,
342+ enum qca_btsoc_type soc_type )
305343{
306344 const struct firmware * fw ;
307345 const u8 * segment ;
@@ -331,7 +369,7 @@ static int qca_download_firmware(struct hci_dev *hdev,
331369 config -> dnld_mode = QCA_SKIP_EVT_NONE ;
332370
333371 ret = qca_tlv_send_segment (hdev , segsize , segment ,
334- config -> dnld_mode );
372+ config -> dnld_mode , soc_type );
335373 if (ret )
336374 goto out ;
337375
@@ -405,7 +443,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
405443 "qca/rampatch_%08x.bin" , soc_ver );
406444 }
407445
408- err = qca_download_firmware (hdev , & config );
446+ err = qca_download_firmware (hdev , & config , soc_type );
409447 if (err < 0 ) {
410448 bt_dev_err (hdev , "QCA Failed to download patch (%d)" , err );
411449 return err ;
@@ -426,7 +464,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
426464 snprintf (config .fwname , sizeof (config .fwname ),
427465 "qca/nvm_%08x.bin" , soc_ver );
428466
429- err = qca_download_firmware (hdev , & config );
467+ err = qca_download_firmware (hdev , & config , soc_type );
430468 if (err < 0 ) {
431469 bt_dev_err (hdev , "QCA Failed to download NVM (%d)" , err );
432470 return err ;
0 commit comments