blob: 51533662b4d5a99d0fc30fab65266ef020d93538 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/* Copyright Statement:
2 *
3 * This software/firmware and related documentation ("MediaTek Software") are
4 * protected under relevant copyright laws. The information contained herein is
5 * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
6 * the prior written permission of MediaTek inc. and/or its licensors, any
7 * reproduction, modification, use or disclosure of MediaTek Software, and
8 * information contained herein, in whole or in part, shall be strictly
9 * prohibited.
10 *
11 * MediaTek Inc. (C) 2016~2017. All rights reserved.
12 *
13 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
14 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
15 * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
16 * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
17 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
19 * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
20 * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
21 * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
22 * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
23 * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
24 * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
25 * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
26 * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
27 * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
28 * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
29 * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
30 * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
31 * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
32 *
33 * The following software/firmware and/or related documentation ("MediaTek
34 * Software") have been modified by MediaTek Inc. All revisions are subject to
35 * any receiver's applicable license agreements with MediaTek Inc.
36 */
37
38//- vim: set ts=4 sts=4 sw=4 et: --------------------------------------------
39#include <stdio.h>
40#include <stdlib.h>
41#include <time.h>
42#include <sys/time.h>
43#include <fcntl.h>
44#include <string.h>
45#include <errno.h>
46#include <unistd.h>
47
48#include "boots.h"
49#include "boots_osi.h"
50#include "boots_mt6xx.h"
51
52/**************************************************************************
53 * D E F I N I T I O N S *
54***************************************************************************/
55#define LOG_TAG "boots_mt6xx"
56 /* BT NVRAM FILE */
57#define BT_NVRAM_MANUFACTURE "bt_init_value"
58
59/**************************************************************************
60 * G L O B A L V A R I A B L E S *
61***************************************************************************/
62
63static HCI_CMD_T hciCmd;
64static BT_INIT_VAR_T btinit[1];
65static INT32 bt_com_port;
66
67/**************************************************************************
68 * F U N C T I O N D E C L A R A T I O N S *
69***************************************************************************/
70// Common
71static ENUM_BT_STATUS_T GORMcmd_HCC_Set_Local_BD_Addr(VOID);
72static ENUM_BT_STATUS_T GORMcmd_HCC_Set_PCM(VOID);
73static ENUM_BT_STATUS_T GORMcmd_HCC_Set_Radio(VOID);
74static ENUM_BT_STATUS_T GORMcmd_HCC_Set_TX_Power_Offset(VOID);
75static ENUM_BT_STATUS_T GORMcmd_HCC_Set_Sleep_Timeout(VOID);
76static ENUM_BT_STATUS_T GORMcmd_HCC_RESET(VOID);
77static ENUM_BT_STATUS_T GORMcmd_HCC_Coex_Performance_Adjust(VOID);
78
79//===================================================================
80// Combo chip
81HCI_SEQ_T bt_init_script_6630[] =
82{
83 { GORMcmd_HCC_Set_Local_BD_Addr }, /*0xFC1A*/
84 { GORMcmd_HCC_Set_PCM }, /*0xFC72*/
85 { GORMcmd_HCC_Set_Radio }, /*0xFC79*/
86 { GORMcmd_HCC_Set_TX_Power_Offset }, /*0xFC93*/
87 { GORMcmd_HCC_Set_Sleep_Timeout }, /*0xFC7A*/
88 { GORMcmd_HCC_Coex_Performance_Adjust }, /*0xFC22*/
89 { 0 },
90};
91
92HCI_SEQ_T bt_init_script_8167[] =
93{
94 { GORMcmd_HCC_Set_Local_BD_Addr }, /*0xFC1A*/
95 { GORMcmd_HCC_Set_Radio }, /*0xFC79*/
96 { GORMcmd_HCC_Set_TX_Power_Offset }, /*0xFC93*/
97 { GORMcmd_HCC_Set_Sleep_Timeout }, /*0xFC7A*/
98 { GORMcmd_HCC_RESET }, /*0x0C03*/
99 { 0 },
100};
101
102static ap_nvram_btradio_struct stBtDefault_6630 =
103{
104 {0x00, 0x00, 0x46, 0x66, 0x30, 0x01},
105 {0x60, 0x00}, //not used
106#if defined(__MTK_MERGE_INTERFACE_SUPPORT__)
107 {0x63, 0x10, 0x00, 0x00},
108#elif defined(__MTK_BT_I2S_SUPPORT__)
109 {0x03, 0x10, 0x00, 0x02},
110#else
111 {0x23, 0x10, 0x00, 0x00},
112#endif
113 {0x06, 0x80, 0x00, 0x06, 0x05, 0x06}, // Align 8516 others product
114 {0x03, 0x40, 0x1F, 0x40, 0x1F, 0x00, 0x04},
115 {0x80, 0x00}, //not used
116 {0xFF, 0xFF, 0xFF},
117 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
118 {0x00, 0x00}, // not used
119 {0x00, 0x00, 0x00, 0x00}, // not used
120 ///////////// Reserved /////////////
121 {0x00, 0x00},
122 {0x00, 0x00, 0x00, 0x00},
123 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
124 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
125};
126
127static ap_nvram_btradio_struct stBtDefault_8167 =
128{
129 {0x00, 0x00, 0x46, 0x81, 0x67, 0x01},
130 {0x60, 0x00}, //not used
131#if defined(__MTK_MERGE_INTERFACE_SUPPORT__)
132 {0x63, 0x10, 0x00, 0x00},
133#elif defined(__MTK_BT_I2S_SUPPORT__)
134 {0x03, 0x10, 0x00, 0x02},
135#else
136 {0x23, 0x10, 0x00, 0x00},
137#endif
138 {0x07, 0x80, 0x00, 0x06, 0x05, 0x07},
139 {0x03, 0x40, 0x1F, 0x40, 0x1F, 0x00, 0x04},
140 {0x80, 0x00}, //not used
141 {0xFF, 0xFF, 0xFF},
142 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
143 {0x00, 0x00}, // not used
144 {0x00, 0x00, 0x00, 0x00}, // not used
145 ///////////// Reserved /////////////
146 {0x00, 0x00},
147 {0x00, 0x00, 0x00, 0x00},
148 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
149 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
150};
151
152/**************************************************************************
153 * F U N C T I O N S *
154***************************************************************************/
155static BOOL is_memzero(unsigned char *buf, int size)
156{
157 int i;
158 for (i = 0; i < size; i++) {
159 if (*(buf+i) != 0) return FALSE;
160 }
161 return TRUE;
162}
163
164static void get_bt_structure(unsigned char *pucBTStructure)
165{
166 int fd = -1;
167 int i;
168 char bt_structure[128] = {0};
169 char buf[3] = {0};
170 int size = 0;
171 BPRINT_D("Get BT structure");
172
173 fd = open(BT_NVRAM_MANUFACTURE, O_RDONLY);
174 if (fd < 0) {
175 BPRINT_E("Open BT structure fails");
176 return;
177 }
178
179 size = read(fd, bt_structure, sizeof(bt_structure));
180
181 if (size < 0 || size != 128) {
182 BPRINT_E("Read BT structure fails, size:%d", size);
183 close(fd);
184 return;
185 }
186
187 for (i = 0; i < 128; i += 2) {
188 buf[0] = bt_structure[i];
189 buf[1] = bt_structure[i + 1];
190 pucBTStructure[i >> 1] = (unsigned char)strtoul(buf, NULL, 16);
191 }
192
193 close(fd);
194 BPRINT_D("Get BT structure PASS");
195}
196
197static int write_com_port(int fd, unsigned char *buf, unsigned int len)
198{
199 int nWritten = 0;
200 unsigned int bytesToWrite = len;
201
202 if (fd < 0) {
203 BPRINT_E("No available com port");
204 return -EIO;
205 }
206
207 while (bytesToWrite > 0) {
208 nWritten = write(fd, buf, bytesToWrite);
209 if (nWritten < 0) {
210 if (errno == EINTR || errno == EAGAIN)
211 break;
212 else
213 return -errno; /* errno used for whole chip reset */
214 }
215 bytesToWrite -= nWritten;
216 buf += nWritten;
217 }
218
219 return (len - bytesToWrite);
220}
221
222static int read_com_port(int fd, unsigned char *buf, unsigned int len)
223{
224 int nRead = 0;
225 unsigned int bytesToRead = len;
226
227 if (fd < 0) {
228 BPRINT_E("No available com port");
229 return -EIO;
230 }
231
232 nRead = read(fd, buf, bytesToRead);
233 if (nRead < 0) {
234 if(errno == EINTR || errno == EAGAIN)
235 return 0;
236 else
237 return -errno; /* errno used for whole chip reset */
238 }
239
240 return nRead;
241}
242
243static int bt_send_data(int fd, unsigned char *buf, unsigned int len)
244{
245 int bytesWritten = 0;
246 unsigned int bytesToWrite = len;
247
248 /* Try to send len bytes data in buffer */
249 while (bytesToWrite > 0) {
250 bytesWritten = write_com_port(fd, buf, bytesToWrite);
251 if (bytesWritten < 0) {
252 return -1;
253 }
254 bytesToWrite -= bytesWritten;
255 buf += bytesWritten;
256 }
257
258 return 0;
259}
260
261static int bt_receive_data(int fd, unsigned char *buf, unsigned int len)
262{
263 int bytesRead = 0;
264 unsigned int bytesToRead = len;
265
266 int ret = 0;
267 struct timeval tv;
268 fd_set readfd;
269
270 tv.tv_sec = 5; /* SECOND */
271 tv.tv_usec = 0; /* USECOND */
272 FD_ZERO(&readfd);
273
274 /* Try to receive len bytes */
275 while (bytesToRead > 0) {
276
277 FD_SET(fd, &readfd);
278 ret = select(fd + 1, &readfd, NULL, NULL, &tv);
279
280 if (ret > 0) {
281 bytesRead = read_com_port(fd, buf, bytesToRead);
282 if (bytesRead < 0) {
283 return -1;
284 }
285 else {
286 bytesToRead -= bytesRead;
287 buf += bytesRead;
288 }
289 }
290 else if (ret == 0) {
291 BPRINT_E("Read com port timeout 5000ms!");
292 return -1;
293 }
294 else if ((ret == -1) && (errno == EINTR)) {
295 BPRINT_E("select error EINTR");
296 }
297 else {
298 BPRINT_E("select error %s(%d)!", strerror(errno), errno);
299 return -1;
300 }
301 }
302
303 return 0;
304}
305
306static BOOL BT_SendHciCommand(INT32 comPort, HCI_CMD_T *pHciCommand)
307{
308 UINT8 ucHciCmd[256+4] = {0x01, 0x00, 0x00, 0x00};
309
310 ucHciCmd[1] = (UINT8)pHciCommand->opCode;
311 ucHciCmd[2] = (UINT8)(pHciCommand->opCode >> 8);
312 ucHciCmd[3] = pHciCommand->len;
313
314 BPRINT_D("OpCode 0x%04x len %d", pHciCommand->opCode, (INT32)pHciCommand->len);
315
316 if (pHciCommand->len) {
317 memcpy(&ucHciCmd[4], pHciCommand->parms, pHciCommand->len);
318 }
319
320 if (bt_send_data(comPort, ucHciCmd, pHciCommand->len + 4) < 0) {
321 BPRINT_E("Write HCI command fails errno %d", errno);
322 return FALSE;
323 }
324
325 return TRUE;
326}
327
328static BOOL BT_ReadPacketHeader(
329 INT32 comPort,
330 UINT8* pPacketType, /* Command, Event, ACL data, SCO data */
331 UINT16* pRemainLen, /* Remaining len for parameters */
332 UINT16* pOpCode, /* Command OpCode */
333 UINT16* pConnHandle, /* Connection handle */
334 UINT8* pEventCode /* Event code */
335 )
336{
337 UINT8 ucCmdHdr[3];
338 UINT8 ucAclHdr[4];
339 UINT8 ucScoHdr[3];
340 UINT8 ucEventHdr[2];
341 UINT8 type = 0;
342
343 /* Read UART header */
344 if (bt_receive_data(comPort, &type, 1) < 0) {
345 BPRINT_E("Read packet header fails");
346 return FALSE;
347 }
348
349 *pPacketType = type;
350
351 switch (type) {
352 case 1: /* Command */
353 if (bt_receive_data(comPort, ucCmdHdr, 3) < 0) {
354 BPRINT_E("Read command header fails %d", errno);
355 return FALSE;
356 }
357
358 *pOpCode = (((UINT16)ucCmdHdr[0]) | (((UINT16)ucCmdHdr[1]) << 8));
359 *pRemainLen = ucCmdHdr[2];
360 break;
361
362 case 2: /* ACL data */
363 if (bt_receive_data(comPort, ucAclHdr, 4) < 0) {
364 BPRINT_E("Read ACL header fails %d", errno);
365 return FALSE;
366 }
367
368 *pConnHandle = (((UINT16)ucAclHdr[0]) | (((UINT16)ucAclHdr[1]) << 8));
369 *pRemainLen = (((UINT16)ucAclHdr[2]) | (((UINT16)ucAclHdr[3]) << 8));
370 break;
371
372 case 3: /* SCO data */
373 if (bt_receive_data(comPort, ucScoHdr, 3) < 0) {
374 BPRINT_E("Read SCO header fails %d", errno);
375 return FALSE;
376 }
377
378 *pConnHandle = (((UINT16)ucScoHdr[0]) | (((UINT16)ucScoHdr[1]) << 8));
379 *pRemainLen = ucScoHdr[2];
380 break;
381
382 case 4: /* Event */
383 if (bt_receive_data(comPort, ucEventHdr, 2) < 0) {
384 BPRINT_E("Read event header fails %d", errno);
385 return FALSE;
386 }
387
388 *pEventCode = ucEventHdr[0];
389 *pRemainLen = ucEventHdr[1];
390 break;
391
392 default: /* other */
393 BPRINT_E("Unknown packet type %02x", type);
394 return FALSE;
395 break;
396 }
397
398 return TRUE;
399}
400
401static BOOL BT_ReadPacket(
402 INT32 comPort,
403 UINT8* pPacket,
404 UINT32 u4MaxBufSz,
405 UINT32* pu4PktLen
406 )
407{
408 UINT8 packetType;
409 UINT16 remainLen;
410 UINT16 opCode = 0, connHandle = 0;
411 UINT8 eventCode = 0;
412 UINT32 u4PktLen = 0;
413
414 if (u4MaxBufSz == 0) {
415 BPRINT_E("Read buffer size is zero!");
416 return FALSE;
417 }
418
419 if (BT_ReadPacketHeader(
420 comPort,
421 &packetType,
422 &remainLen,
423 &opCode,
424 &connHandle,
425 &eventCode) == FALSE) {
426
427 BPRINT_E("Read packet header fails");
428 return FALSE;
429 }
430
431 pPacket[0] = packetType;
432 u4PktLen ++;
433
434 /* Command packet */
435 if (packetType == 1) {
436 if (u4MaxBufSz < (UINT32)(4 + remainLen)) {
437 BPRINT_E("Read command buffer is too short!");
438 return FALSE;
439 }
440
441 pPacket[u4PktLen] = (UINT8)opCode;
442 pPacket[u4PktLen + 1] = (UINT8)(opCode >> 8);
443 u4PktLen += 2;
444
445 pPacket[u4PktLen] = (UINT8)remainLen;
446 u4PktLen ++;
447
448 if (bt_receive_data(comPort, pPacket + u4PktLen, remainLen) < 0) {
449 BPRINT_E("Read remain packet fails %d", errno);
450 return FALSE;
451 }
452
453 u4PktLen += remainLen;
454 *pu4PktLen = u4PktLen;
455
456 return TRUE;
457 }
458
459 /* ACL data */
460 if (packetType == 2) {
461 if (u4MaxBufSz < (UINT32)(5 + remainLen)) {
462 BPRINT_E("Read ACL buffer is too short!");
463 return FALSE;
464 }
465
466 pPacket[u4PktLen] = (UINT8)connHandle;
467 pPacket[u4PktLen + 1] = (UINT8)(connHandle >> 8);
468 u4PktLen += 2;
469
470 pPacket[u4PktLen] = (UINT8)remainLen;
471 pPacket[u4PktLen + 1] = (UINT8)(remainLen >> 8);
472 u4PktLen += 2;
473
474 if (bt_receive_data(comPort, pPacket + u4PktLen, remainLen) < 0) {
475 BPRINT_E("Read remain packet fails %d", errno);
476 return FALSE;
477 }
478
479 u4PktLen += remainLen;
480 *pu4PktLen = u4PktLen;
481
482 return TRUE;
483 }
484
485 /* SCO data */
486 if (packetType == 3) {
487 if (u4MaxBufSz < (UINT32)(4 + remainLen)) {
488 BPRINT_E("Read SCO buffer is too short!");
489 return FALSE;
490 }
491
492 pPacket[u4PktLen] = (UINT8)connHandle;
493 pPacket[u4PktLen + 1] = (UINT8)(connHandle >> 8);
494 u4PktLen += 2;
495
496 pPacket[u4PktLen] = (UINT8)remainLen;
497 u4PktLen ++;
498
499 if (bt_receive_data(comPort, pPacket + u4PktLen, remainLen) < 0) {
500 BPRINT_E("Read remain packet fails %d", errno);
501 return FALSE;
502 }
503
504 u4PktLen += remainLen;
505 *pu4PktLen = u4PktLen;
506
507 return TRUE;
508 }
509
510 /* Event packet */
511 if (packetType == 4) {
512 if(u4MaxBufSz < (UINT32)(3 + remainLen)) {
513 BPRINT_E("Read event buffer is too short!");
514 return FALSE;
515 }
516
517 pPacket[u4PktLen] = eventCode;
518 pPacket[u4PktLen + 1] = (UINT8)remainLen;
519 u4PktLen += 2;
520
521 if (bt_receive_data(comPort, pPacket + u4PktLen, remainLen) < 0) {
522 BPRINT_E("Read remain packet fails %d", errno);
523 return FALSE;
524 }
525
526 u4PktLen += remainLen;
527 *pu4PktLen = u4PktLen;
528
529 return TRUE;
530 }
531
532 BPRINT_E("Unknown packet type");
533
534 return FALSE;
535}
536
537BOOL BT_ReadExpectedEvent(
538 INT32 comPort,
539 UINT8* pEventPacket,
540 UINT32 u4MaxBufSz,
541 UINT32* pu4PktLen,
542 UINT8 ucExpectedEventCode,
543 BOOL fCheckCompleteOpCode,/* whether to check command OpCode */
544 UINT16 u2ExpectedOpCode,
545 BOOL fCheckCommandStatus, /* whether to check command status */
546 UINT8 ucExpectedStatus
547 )
548{
549 UINT16 u2OpCode;
550 UINT8 ucEventCode, ucStatus;
551
552 if (BT_ReadPacket(
553 comPort,
554 pEventPacket,
555 u4MaxBufSz,
556 pu4PktLen) == FALSE) {
557
558 BPRINT_E("Read packet fails");
559 return FALSE;
560 }
561
562 /* Expect Event only */
563 if (pEventPacket[0] != 4) {
564 BPRINT_E("Unexpected packet type");
565 return FALSE;
566 }
567
568 ucEventCode = pEventPacket[1];
569
570 if (ucEventCode != ucExpectedEventCode) {
571 BPRINT_E("Unexpected event code");
572 return FALSE;
573 }
574
575 if (ucEventCode == 0x0E) {
576 if (fCheckCompleteOpCode) {
577 u2OpCode = ((UINT16)pEventPacket[4]) | (((UINT16)pEventPacket[5]) << 8);
578
579 if (u2OpCode != u2ExpectedOpCode) {
580 BPRINT_E("Unexpected OpCode");
581 return FALSE;
582 }
583 }
584 if (fCheckCommandStatus) {
585 ucStatus = pEventPacket[6];
586
587 if (ucStatus != ucExpectedStatus) {
588 BPRINT_E("Unexpected status %02x", ucStatus);
589 return FALSE;
590 }
591 }
592 }
593
594 if (ucEventCode == 0x0F) {
595 if (fCheckCompleteOpCode) {
596 u2OpCode = ((UINT16)pEventPacket[5]) | (((UINT16)pEventPacket[6]) << 8);
597
598 if (u2OpCode != u2ExpectedOpCode) {
599 BPRINT_E("Unexpected OpCode");
600 return FALSE;
601 }
602 }
603
604 if (fCheckCommandStatus) {
605 ucStatus = pEventPacket[3];
606
607 if (ucStatus != ucExpectedStatus) {
608 BPRINT_E("Unexpected status %02x", ucStatus);
609 return FALSE;
610 }
611 }
612 }
613
614 return TRUE;
615}
616
617static BOOL WriteBDAddrToNvram(UCHAR *pucBDAddr)
618{
619 UNUSED(pucBDAddr);
620 // TODO
621 return TRUE;
622}
623
624static BOOL BT_Get_Local_BD_Addr(UCHAR *pucBDAddr)
625{
626 HCI_CMD_T cmd;
627 UINT32 u4ReadLen = 0;
628 UINT8 ucAckEvent[20];
629
630 cmd.opCode = 0x1009;
631 cmd.len = 0;
632
633 BPRINT_D("BT_Get_Local_BD_Addr");
634
635 if (BT_SendHciCommand(bt_com_port, &cmd) == FALSE) {
636 BPRINT_E("Write get BD address command fails");
637 return FALSE;
638 }
639
640 /* Read local BD address from F/W */
641 if (BT_ReadExpectedEvent(
642 bt_com_port,
643 ucAckEvent,
644 sizeof(ucAckEvent),
645 &u4ReadLen,
646 0x0E,
647 TRUE,
648 0x1009,
649 TRUE,
650 0x00) == FALSE) {
651
652 BPRINT_E("Read local BD address fails");
653 return FALSE;
654 }
655
656 BPRINT_W("Local BD address: %02x-%02x-%02x-%02x-%02x-%02x",
657 ucAckEvent[12], ucAckEvent[11], ucAckEvent[10],
658 ucAckEvent[9], ucAckEvent[8], ucAckEvent[7]);
659
660 pucBDAddr[0] = ucAckEvent[12];
661 pucBDAddr[1] = ucAckEvent[11];
662 pucBDAddr[2] = ucAckEvent[10];
663 pucBDAddr[3] = ucAckEvent[9];
664 pucBDAddr[4] = ucAckEvent[8];
665 pucBDAddr[5] = ucAckEvent[7];
666
667 return TRUE;
668}
669
670#ifdef BD_ADDR_AUTOGEN
671static VOID GetRandomValue(UCHAR string[6])
672{
673 INT32 iRandom = 0;
674 INT32 fd = 0;
675 UINT32 seed;
676
677 BPRINT_W("Enable random generation");
678
679 /* Initialize random seed */
680 srand(time(NULL));
681 iRandom = rand();
682 BPRINT_W("iRandom = [%d]", iRandom);
683 string[0] = (((iRandom>>24|iRandom>>16) & (0xFE)) | (0x02)); /* Must use private bit(1) and no BCMC bit(0) */
684
685 /* second seed */
686 struct timeval tv;
687 gettimeofday(&tv, NULL);
688 srand(tv.tv_usec);
689 iRandom = rand();
690 BPRINT_W("iRandom = [%d]", iRandom);
691 string[1] = ((iRandom>>8) & 0xFF);
692
693 /* third seed */
694 fd = open("/dev/urandom", O_RDONLY);
695 if (fd >= 0) {
696 if (read(fd, &seed, sizeof(UINT32)) > 0) {
697 srand(seed);
698 iRandom = rand();
699 }
700 close(fd);
701 }
702
703 BPRINT_W("iRandom = [%d]", iRandom);
704 string[5] = (iRandom & 0xFF);
705
706 return;
707}
708#endif // BD_ADDR_AUTOGEN
709
710static ENUM_BT_STATUS_T GORMcmd_HCC_Set_Local_BD_Addr(VOID)
711{
712 UCHAR ucDefaultAddr[6] = {0};
713 UCHAR ucZeroAddr[6] = {0};
714
715 hciCmd.opCode = 0xFC1A;
716 hciCmd.len = 6;
717
718 BPRINT_D("GORMcmd_HCC_Set_Local_BD_Addr");
719
720 switch (btinit->chip_id) {
721 case 0x6630:
722 memcpy(ucDefaultAddr, stBtDefault_6630.addr, 6);
723 break;
724 case 0x8167:
725 memcpy(ucDefaultAddr, stBtDefault_8167.addr, 6);
726 break;
727 default:
728 BPRINT_E("Unknown combo chip id: %04x", btinit->chip_id);
729 break;
730 }
731
732 if ((0 == memcmp(btinit->bt_nvram.fields.addr, ucDefaultAddr, 6)) ||
733 (0 == memcmp(btinit->bt_nvram.fields.addr, ucZeroAddr, 6))) {
734 BPRINT_W("NVRAM BD address default value");
735 /* Want to retrieve module eFUSE address on combo chip */
736 BT_Get_Local_BD_Addr(btinit->bt_nvram.fields.addr);
737
738 if ((0 == memcmp(btinit->bt_nvram.fields.addr, ucDefaultAddr, 6)) ||
739 (0 == memcmp(btinit->bt_nvram.fields.addr, ucZeroAddr, 6))) {
740 BPRINT_W("eFUSE address default value");
741 #ifdef BD_ADDR_AUTOGEN
742 GetRandomValue(btinit->bt_nvram.fields.addr);
743 #endif
744 }
745 else {
746 BPRINT_W("eFUSE address has valid value");
747 }
748
749 /* Save BD address to NVRAM */
750 WriteBDAddrToNvram(btinit->bt_nvram.fields.addr);
751 }
752 else {
753 BPRINT_W("NVRAM BD address has valid value");
754 }
755
756 hciCmd.parms[0] = btinit->bt_nvram.fields.addr[5];
757 hciCmd.parms[1] = btinit->bt_nvram.fields.addr[4];
758 hciCmd.parms[2] = btinit->bt_nvram.fields.addr[3];
759 hciCmd.parms[3] = btinit->bt_nvram.fields.addr[2];
760 hciCmd.parms[4] = btinit->bt_nvram.fields.addr[1];
761 hciCmd.parms[5] = btinit->bt_nvram.fields.addr[0];
762
763 BPRINT_W("Write BD address: %02x-%02x-%02x-%02x-%02x-%02x",
764 hciCmd.parms[5], hciCmd.parms[4], hciCmd.parms[3],
765 hciCmd.parms[2], hciCmd.parms[1], hciCmd.parms[0]);
766
767
768 if (BT_SendHciCommand(bt_com_port, &hciCmd) == TRUE) {
769 return BT_STATUS_SUCCESS;
770 }
771 else {
772 return BT_STATUS_FAILED;
773 }
774}
775
776static ENUM_BT_STATUS_T GORMcmd_HCC_Set_PCM(VOID)
777{
778 hciCmd.opCode = 0xFC72;
779 hciCmd.len = 4;
780
781 hciCmd.parms[0] = btinit->bt_nvram.fields.Codec[0];
782 hciCmd.parms[1] = btinit->bt_nvram.fields.Codec[1];
783 hciCmd.parms[2] = btinit->bt_nvram.fields.Codec[2];
784 hciCmd.parms[3] = btinit->bt_nvram.fields.Codec[3];
785
786 BPRINT_D("GORMcmd_HCC_Set_PCM");
787
788 if (BT_SendHciCommand(bt_com_port, &hciCmd) == TRUE) {
789 return BT_STATUS_SUCCESS;
790 }
791 else {
792 return BT_STATUS_FAILED;
793 }
794}
795
796static ENUM_BT_STATUS_T GORMcmd_HCC_Set_Radio(VOID)
797{
798 hciCmd.opCode = 0xFC79;
799
800 if (btinit->chip_id != 0x6632) {
801 hciCmd.len = 6;
802 hciCmd.parms[0] = btinit->bt_nvram.fields.Radio[0];
803 hciCmd.parms[1] = btinit->bt_nvram.fields.Radio[1];
804 hciCmd.parms[2] = btinit->bt_nvram.fields.Radio[2];
805 hciCmd.parms[3] = btinit->bt_nvram.fields.Radio[3];
806 hciCmd.parms[4] = btinit->bt_nvram.fields.Radio[4];
807 hciCmd.parms[5] = btinit->bt_nvram.fields.Radio[5];
808 } else {
809 hciCmd.len = 8;
810 hciCmd.parms[0] = btinit->bt_nvram.fields.Radio[0];
811 hciCmd.parms[1] = btinit->bt_nvram.fields.Radio[1];
812 hciCmd.parms[2] = btinit->bt_nvram.fields.Radio[2];
813 hciCmd.parms[3] = btinit->bt_nvram.fields.Radio[3];
814 hciCmd.parms[4] = btinit->bt_nvram.fields.Radio[4];
815 hciCmd.parms[5] = btinit->bt_nvram.fields.Radio[5];
816 hciCmd.parms[6] = btinit->bt_nvram.fields.Radio_ext[0];
817 hciCmd.parms[7] = btinit->bt_nvram.fields.Radio_ext[1];
818 }
819
820 BPRINT_D("GORMcmd_HCC_Set_Radio");
821
822 if (BT_SendHciCommand(bt_com_port, &hciCmd) == TRUE) {
823 return BT_STATUS_SUCCESS;
824 }
825 else {
826 return BT_STATUS_FAILED;
827 }
828}
829
830static ENUM_BT_STATUS_T GORMcmd_HCC_Set_TX_Power_Offset(VOID)
831{
832 hciCmd.opCode = 0xFC93;
833
834 if (btinit->chip_id != 0x6632) {
835 hciCmd.len = 3;
836 hciCmd.parms[0] = btinit->bt_nvram.fields.TxPWOffset[0];
837 hciCmd.parms[1] = btinit->bt_nvram.fields.TxPWOffset[1];
838 hciCmd.parms[2] = btinit->bt_nvram.fields.TxPWOffset[2];
839 } else {
840 hciCmd.len = 6;
841 hciCmd.parms[0] = btinit->bt_nvram.fields.TxPWOffset[0];
842 hciCmd.parms[1] = btinit->bt_nvram.fields.TxPWOffset[1];
843 hciCmd.parms[2] = btinit->bt_nvram.fields.TxPWOffset[2];
844 hciCmd.parms[3] = btinit->bt_nvram.fields.TxPWOffset_ext[0];
845 hciCmd.parms[4] = btinit->bt_nvram.fields.TxPWOffset_ext[1];
846 hciCmd.parms[5] = btinit->bt_nvram.fields.TxPWOffset_ext[2];
847 }
848
849 BPRINT_D("GORMcmd_HCC_Set_TX_Power_Offset");
850
851 if (BT_SendHciCommand(bt_com_port, &hciCmd) == TRUE) {
852 return BT_STATUS_SUCCESS;
853 }
854 else {
855 return BT_STATUS_FAILED;
856 }
857}
858
859static ENUM_BT_STATUS_T GORMcmd_HCC_Set_Sleep_Timeout(VOID)
860{
861 hciCmd.opCode = 0xFC7A;
862 hciCmd.len = 7;
863
864 hciCmd.parms[0] = btinit->bt_nvram.fields.Sleep[0];
865 hciCmd.parms[1] = btinit->bt_nvram.fields.Sleep[1];
866 hciCmd.parms[2] = btinit->bt_nvram.fields.Sleep[2];
867 hciCmd.parms[3] = btinit->bt_nvram.fields.Sleep[3];
868 hciCmd.parms[4] = btinit->bt_nvram.fields.Sleep[4];
869 hciCmd.parms[5] = btinit->bt_nvram.fields.Sleep[5];
870 hciCmd.parms[6] = btinit->bt_nvram.fields.Sleep[6];
871
872 BPRINT_D("GORMcmd_HCC_Set_Sleep_Timeout");
873
874 if (BT_SendHciCommand(bt_com_port, &hciCmd) == TRUE) {
875 return BT_STATUS_SUCCESS;
876 }
877 else {
878 return BT_STATUS_FAILED;
879 }
880}
881
882static ENUM_BT_STATUS_T GORMcmd_HCC_RESET(VOID)
883{
884 hciCmd.opCode = 0x0C03;
885 hciCmd.len = 0;
886
887 BPRINT_D("GORMcmd_HCC_RESET");
888
889 if (BT_SendHciCommand(bt_com_port, &hciCmd) == TRUE) {
890 return BT_STATUS_SUCCESS;
891 }
892 else {
893 return BT_STATUS_FAILED;
894 }
895}
896
897static ENUM_BT_STATUS_T GORMcmd_HCC_Coex_Performance_Adjust(VOID)
898{
899 hciCmd.opCode = 0xFC22;
900 hciCmd.len = 6;
901
902 hciCmd.parms[0] = btinit->bt_nvram.fields.CoexAdjust[0];
903 hciCmd.parms[1] = btinit->bt_nvram.fields.CoexAdjust[1];
904 hciCmd.parms[2] = btinit->bt_nvram.fields.CoexAdjust[2];
905 hciCmd.parms[3] = btinit->bt_nvram.fields.CoexAdjust[3];
906 hciCmd.parms[4] = btinit->bt_nvram.fields.CoexAdjust[4];
907 hciCmd.parms[5] = btinit->bt_nvram.fields.CoexAdjust[5];
908
909 BPRINT_D("GORMcmd_HCC_Coex_Performance_Adjust");
910
911 if (BT_SendHciCommand(bt_com_port, &hciCmd) == TRUE) {
912 return BT_STATUS_SUCCESS;
913 }
914 else{
915 return BT_STATUS_FAILED;
916 }
917}
918
919static ENUM_BT_STATUS_T GORM_Init(
920 INT32 comPort,
921 UINT32 chipId,
922 PUCHAR pucPatchExtData,
923 UINT32 u4PatchExtLen,
924 PUCHAR pucPatchData,
925 UINT32 u4PatchLen,
926 PUCHAR pucNvRamData,
927 UINT32 u4Baud,
928 UINT32 u4HostBaud,
929 UINT32 u4FlowControl
930 )
931{
932 INT32 i = 0;
933 ENUM_BT_STATUS_T status;
934 UINT8 ucEventBuf[MAX_EVENT_SIZE];
935 UINT32 u4EventLen;
936 UNUSED(pucPatchExtData);
937 UNUSED(u4PatchExtLen);
938 UNUSED(pucPatchData);
939 UNUSED(u4PatchLen);
940 UNUSED(u4Baud);
941 UNUSED(u4HostBaud);
942 UNUSED(u4FlowControl);
943
944 BPRINT_D("GORM_Init");
945
946 /* Save com port fd for GORMcmds */
947 bt_com_port = comPort;
948 /* Save chip id */
949 btinit->chip_id = chipId;
950 /* Copy NVRAM data */
951 memcpy(btinit->bt_nvram.raw, pucNvRamData, sizeof(ap_nvram_btradio_struct));
952
953 /* General init script */
954 switch (btinit->chip_id) {
955 case 0x6630:
956 btinit->cur_script = bt_init_script_6630;
957 break;
958 case 0x8167:
959 btinit->cur_script = bt_init_script_8167;
960 break;
961 default:
962 BPRINT_E("Unknown combo chip id: %04x", btinit->chip_id);
963 break;
964 }
965
966 /* Can not find matching script, simply skip */
967 if ((btinit->cur_script) == NULL) {
968 BPRINT_E("No matching init script");
969 return BT_STATUS_FAILED;
970 }
971
972 i = 0;
973
974 while (btinit->cur_script[i].command_func)
975 {
976 status = btinit->cur_script[i].command_func();
977 if (status == BT_STATUS_CANCELLED) {
978 i ++;
979 continue; /*skip*/
980 }
981
982 if (status == BT_STATUS_FAILED) {
983 BPRINT_E("Command %d fails", i);
984 return status;
985 }
986
987 if (BT_ReadExpectedEvent(
988 comPort,
989 ucEventBuf,
990 MAX_EVENT_SIZE,
991 &u4EventLen,
992 0x0E,
993 TRUE,
994 hciCmd.opCode,
995 TRUE,
996 0x00) == FALSE) {
997
998 BPRINT_E("Read event of command %d fails", i);
999 return BT_STATUS_FAILED;
1000 }
1001
1002 i ++;
1003 }
1004
1005 return BT_STATUS_SUCCESS;
1006}
1007
1008uint32_t mtk_66xx_detect(void)
1009{
1010 uint32_t chipId = 0;
1011#ifdef MTK_ANDROID_PLATFORM
1012 char chipId_val[64];
1013
1014 if (osi_property_get(WCN_COMBO_LOADER_CHIP_ID_PROP, chipId_val, NULL) &&
1015 strcmp(chipId_val, "-1") != 0)
1016 chipId = (uint32_t)strtoul(chipId_val, NULL, 16);
1017 else
1018 BPRINT_D("Can't find \"%s\" property for chip ID",
1019 WCN_COMBO_LOADER_CHIP_ID_PROP);
1020#elif defined(MTK_CHIP_COMBO)
1021 chipId = 0x6630;
1022#elif defined(MTK_CHIP_CONSYS)
1023 chipId = 0x8167;
1024#else
1025 // Pure Linux system detect chip id
1026 char *chipId_val = getenv(WCN_COMBO_LOADER_CHIP_ID_PROP);
1027 if (chipId_val)
1028 chipId = (uint32_t)strtoul(chipId_val, NULL, 16);
1029 else
1030 BPRINT_D("Can't find \"%s\" environment variable for chip ID",
1031 WCN_COMBO_LOADER_CHIP_ID_PROP);
1032#endif
1033
1034 BPRINT_D("chip id %x", chipId);
1035 return chipId;
1036}
1037
1038int mtk_66xx_Init(int comPort, unsigned int chipId)
1039{
1040 UNUSED(boots_btif);
1041 ENUM_BT_STATUS_T status;
1042 unsigned char ucNvRamData[sizeof(ap_nvram_btradio_struct)] = {0};
1043
1044 get_bt_structure(ucNvRamData);
1045
1046 if (is_memzero(ucNvRamData, sizeof(ap_nvram_btradio_struct))) {
1047 BPRINT_E("Read NVRAM data fails or NVRAM data all zero!!");
1048 BPRINT_W("Use %x default value", chipId);
1049 switch (chipId) {
1050 case 0x6630:
1051 /* Use MT6630 default value */
1052 memcpy(ucNvRamData, &stBtDefault_6630, sizeof(ap_nvram_btradio_struct));
1053 break;
1054 case 0x8167:
1055 /* Use MT8167 default value */
1056 memcpy(ucNvRamData, &stBtDefault_8167, sizeof(ap_nvram_btradio_struct));
1057 break;
1058 default:
1059 BPRINT_E("Unknown combo chip id: %04x\n", chipId);
1060 return -1;
1061 }
1062 }
1063
1064 BPRINT_I("[BDAddr:%02x-%02x-%02x-%02x-%02x-%02x]",
1065 ucNvRamData[0], ucNvRamData[1], ucNvRamData[2],
1066 ucNvRamData[3], ucNvRamData[4], ucNvRamData[5]);
1067 BPRINT_I("[Voice :%02x %02x]", ucNvRamData[6], ucNvRamData[7]);
1068 BPRINT_I("[Codec :%02x %02x %02x %02x]",
1069 ucNvRamData[8], ucNvRamData[9], ucNvRamData[10], ucNvRamData[11]);
1070 BPRINT_I("[Radio :%02x %02x %02x %02x %02x %02x]",
1071 ucNvRamData[12], ucNvRamData[13], ucNvRamData[14],
1072 ucNvRamData[15], ucNvRamData[16], ucNvRamData[17]);
1073 BPRINT_I("[Sleep :%02x %02x %02x %02x %02x %02x %02x]",
1074 ucNvRamData[18], ucNvRamData[19], ucNvRamData[20], ucNvRamData[21],
1075 ucNvRamData[22], ucNvRamData[23], ucNvRamData[24]);
1076 BPRINT_I("[BtFTR: %02x %02x]", ucNvRamData[25], ucNvRamData[26]);
1077 BPRINT_I("[TxPWOffset:%02x %02x %02x]", ucNvRamData[27], ucNvRamData[28], ucNvRamData[29]);
1078 BPRINT_I("[CoexAdjust:%02x %02x %02x %02x %02x %02x]",
1079 ucNvRamData[30], ucNvRamData[31], ucNvRamData[32],
1080 ucNvRamData[33], ucNvRamData[34], ucNvRamData[35]);
1081 BPRINT_I("[Radio_ext :%02x %02x]", ucNvRamData[36], ucNvRamData[37]);
1082 BPRINT_I("[TxPWOffset_ext:%02x %02x %02x]", ucNvRamData[38], ucNvRamData[39], ucNvRamData[40]);
1083
1084 status = GORM_Init(comPort, chipId, NULL, 0, NULL, 0, ucNvRamData, 0, 0, 0);
1085
1086 return (int)status;
1087}
1088
1089//---------------------------------------------------------------------------