Bluetooth: qca: Add support new features

Support to Enable/Disable S-IBS.
Support to config BD Address when booting.

Change-Id: I960764d3c89e920e30f90e48acb697d0401ddfb5
Signed-off-by: Jesson Li <lifei@codeaurora.org>
This commit is contained in:
Jesson Li
2019-12-20 11:11:58 +08:00
parent 271e6f88e3
commit 06580e3fbb
3 changed files with 76 additions and 6 deletions

View File

@@ -23,6 +23,8 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <linux/ctype.h>
#include "btqca.h"
#include "hci_uart.h"
@@ -31,6 +33,12 @@
#define MAX_PATCH_FILE_SIZE (200*1024)
#define MAX_NVM_FILE_SIZE (10*1024)
#define QCA_BT_ADDR_FORMAT "%04x:%02x:%06x"
#define QCA_BT_ADDR_FIELD_COUNT 3
bdaddr_t qca_bdaddr = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
qca_enque_send_callback qca_enq_send_cb;
u32 qca_bt_version;
@@ -179,11 +187,19 @@ static void qca_tlv_check_data(struct rome_config *config,
/* Update NVM tags as needed */
switch (tag_id) {
case EDL_TAG_ID_BD_ADDRESS:
if (bacmp(&qca_bdaddr, BDADDR_NONE) != 0)
memcpy(tlv_nvm->data, &qca_bdaddr, 6);
break;
case EDL_TAG_ID_HCI:
if (qca_bt_version == ROME_VER_3_2) {
/* enable software inband sleep */
/* enable/disable software inband sleep */
#ifdef SUPPORT_BT_QCA_SIBS
tlv_nvm->data[0] |= 0x80;
#else
tlv_nvm->data[0] &= ~0x80;
#endif
/* UART Baud Rate */
tlv_nvm->data[2] =
config->user_baud_rate;
@@ -193,14 +209,21 @@ static void qca_tlv_check_data(struct rome_config *config,
break;
case EDL_TAG_ID_DEEP_SLEEP:
/* Sleep enable mask
* enabling deep sleep feature on controller.
*/
/* Sleep enable mask
* enabling/disabling deep sleep feature on controller.
*/
#ifdef SUPPORT_BT_QCA_SIBS
tlv_nvm->data[0] |= 0x01;
#else
tlv_nvm->data[0] &= ~0x01;
#endif
/* enable software inband sleep */
if (qca_bt_version == HST_VER_2_0)
#ifdef SUPPORT_BT_QCA_SIBS
tlv_nvm->data[1] |= 0x01;
#else
tlv_nvm->data[1] &= ~0x01;
#endif
break;
}
@@ -570,6 +593,43 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
}
EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome);
static char *qca_bda;
module_param_named(QCA_BDA, qca_bda, charp, 0444);
static void qca_get_bda(struct hci_dev *hdev, const char *str, bdaddr_t *bda)
{
u32 nap = 0, uap = 0, lap = 0;
if (!bda)
return;
BT_INFO("%s: QCA_BDA=%s", hdev->name, str);
if ((str != NULL) && (sscanf(str, QCA_BT_ADDR_FORMAT, &nap, &uap, &lap)
== QCA_BT_ADDR_FIELD_COUNT)) {
bda->b[0] = (u8)(lap & 0xff);
bda->b[1] = (u8)((lap >> 8) & 0xff);
bda->b[2] = (u8)((lap >> 16) & 0xff);
bda->b[3] = (u8)(uap & 0xff);
bda->b[4] = (u8)(nap & 0xff);
bda->b[5] = (u8)((nap >> 8) & 0xff);
} else {
BT_INFO("No valid BDA, create random one");
bda->b[5] = 0x00;
bda->b[4] = 0x02;
bda->b[3] = 0x5b;
get_random_bytes(bda, 3);
}
BT_INFO("%s: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", hdev->name, bda->b[5],
bda->b[4], bda->b[3], bda->b[2], bda->b[1], bda->b[0]);
}
int qca_uart_setup_rome(struct hci_dev *hdev, uint8_t baudrate,
qca_enque_send_callback callback)
{
@@ -589,6 +649,8 @@ int qca_uart_setup_rome(struct hci_dev *hdev, uint8_t baudrate,
config.user_baud_rate = baudrate;
qca_get_bda(hdev, qca_bda, &qca_bdaddr);
err = qca_patch_ver_req(hdev, &qca_ver);
if (err < 0 || qca_ver == 0) {
BT_ERR("%s: Failed to get version 0x%x", hdev->name, err);

View File

@@ -34,6 +34,7 @@
#define EDL_SET_BAUDRATE_RSP_EVT (0x92)
#define EDL_NVM_ACCESS_CODE_EVT (0x0B)
#define EDL_TAG_ID_BD_ADDRESS (2)
#define EDL_TAG_ID_HCI (17)
#define EDL_TAG_ID_DEEP_SLEEP (27)

View File

@@ -37,6 +37,7 @@
#include "hci_uart.h"
#include "btqca.h"
#include <linux/tty.h>
/* HCI_IBS protocol messages */
#define HCI_IBS_SLEEP_IND 0xFE
#define HCI_IBS_WAKE_IND 0xFD
@@ -457,6 +458,10 @@ static int qca_open(struct hci_uart *hu)
BT_DBG("HCI_UART_QCA open, tx_idle_delay=%u, wake_retrans=%u",
qca->tx_idle_delay, qca->wake_retrans);
#ifdef CONFIG_SERIAL_MSM_GENI
hu->tty->ops->ioctl(hu->tty, TIOCPMGET, 0);
#endif
return 0;
}
@@ -979,7 +984,9 @@ static int qca_setup(struct hci_uart *hu)
/* Setup patch / NVM configurations */
ret = qca_uart_setup_rome(hdev, qca_baudrate, qca_enqueue_and_send);
if (!ret) {
#ifdef SUPPORT_BT_QCA_SIBS
set_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags);
#endif
qca_debugfs_init(hdev);
} else if (ret == -ENOENT) {
/* No patch/nvm-config found, run with original fw/config */