diff options
Diffstat (limited to 'drivers/bluetooth/hci_qca.c')
-rw-r--r-- | drivers/bluetooth/hci_qca.c | 91 |
1 files changed, 57 insertions, 34 deletions
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 237aea34b69f..57322c42bb2d 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -54,9 +54,6 @@ #define HCI_IBS_WAKE_ACK 0xFC #define HCI_MAX_IBS_SIZE 10 -/* Controller states */ -#define STATE_IN_BAND_SLEEP_ENABLED 1 - #define IBS_WAKE_RETRANS_TIMEOUT_MS 100 #define IBS_TX_IDLE_TIMEOUT_MS 2000 #define CMD_TRANS_TIMEOUT_MS 100 @@ -67,6 +64,10 @@ /* Controller debug log header */ #define QCA_DEBUG_HANDLE 0x2EDC +enum qca_flags { + QCA_IBS_ENABLED, +}; + /* HCI_IBS transmit side sleep protocol states */ enum tx_ibs_states { HCI_IBS_TX_ASLEEP, @@ -174,6 +175,21 @@ static int qca_power_setup(struct hci_uart *hu, bool on); static void qca_power_shutdown(struct hci_uart *hu); static int qca_power_off(struct hci_dev *hdev); +static enum qca_btsoc_type qca_soc_type(struct hci_uart *hu) +{ + enum qca_btsoc_type soc_type; + + if (hu->serdev) { + struct qca_serdev *qsd = serdev_device_get_drvdata(hu->serdev); + + soc_type = qsd->btsoc_type; + } else { + soc_type = QCA_ROME; + } + + return soc_type; +} + static void __serial_clock_on(struct tty_struct *tty) { /* TODO: Some chipset requires to enable UART clock on client @@ -506,8 +522,10 @@ static int qca_open(struct hci_uart *hu) if (hu->serdev) { qcadev = serdev_device_get_drvdata(hu->serdev); - if (qcadev->btsoc_type != QCA_WCN3990) { + if (!qca_is_wcn399x(qcadev->btsoc_type)) { gpiod_set_value_cansleep(qcadev->bt_en, 1); + /* Controller needs time to bootup. */ + msleep(150); } else { hu->init_speed = qcadev->init_speed; hu->oper_speed = qcadev->oper_speed; @@ -612,7 +630,7 @@ static int qca_close(struct hci_uart *hu) if (hu->serdev) { qcadev = serdev_device_get_drvdata(hu->serdev); - if (qcadev->btsoc_type == QCA_WCN3990) + if (qca_is_wcn399x(qcadev->btsoc_type)) qca_power_shutdown(hu); else gpiod_set_value_cansleep(qcadev->bt_en, 0); @@ -775,7 +793,7 @@ static int qca_enqueue(struct hci_uart *hu, struct sk_buff *skb) /* Don't go to sleep in middle of patch download or * Out-Of-Band(GPIOs control) sleep is selected. */ - if (!test_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags)) { + if (!test_bit(QCA_IBS_ENABLED, &qca->flags)) { skb_queue_tail(&qca->txq, skb); spin_unlock_irqrestore(&qca->hci_ibs_lock, flags); return 0; @@ -963,7 +981,6 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) { struct hci_uart *hu = hci_get_drvdata(hdev); struct qca_data *qca = hu->priv; - struct qca_serdev *qcadev; struct sk_buff *skb; u8 cmd[] = { 0x01, 0x48, 0xFC, 0x01, 0x00 }; @@ -985,18 +1002,17 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) skb_queue_tail(&qca->txq, skb); hci_uart_tx_wakeup(hu); - qcadev = serdev_device_get_drvdata(hu->serdev); - /* Wait for the baudrate change request to be sent */ while (!skb_queue_empty(&qca->txq)) usleep_range(100, 200); - serdev_device_wait_until_sent(hu->serdev, + if (hu->serdev) + serdev_device_wait_until_sent(hu->serdev, msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS)); /* Give the controller time to process the request */ - if (qcadev->btsoc_type == QCA_WCN3990) + if (qca_is_wcn399x(qca_soc_type(hu))) msleep(10); else msleep(300); @@ -1072,10 +1088,7 @@ static unsigned int qca_get_speed(struct hci_uart *hu, static int qca_check_speeds(struct hci_uart *hu) { - struct qca_serdev *qcadev; - - qcadev = serdev_device_get_drvdata(hu->serdev); - if (qcadev->btsoc_type == QCA_WCN3990) { + if (qca_is_wcn399x(qca_soc_type(hu))) { if (!qca_get_speed(hu, QCA_INIT_SPEED) && !qca_get_speed(hu, QCA_OPER_SPEED)) return -EINVAL; @@ -1091,7 +1104,6 @@ static int qca_check_speeds(struct hci_uart *hu) static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) { unsigned int speed, qca_baudrate; - struct qca_serdev *qcadev; int ret = 0; if (speed_type == QCA_INIT_SPEED) { @@ -1099,6 +1111,8 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) if (speed) host_set_baudrate(hu, speed); } else { + enum qca_btsoc_type soc_type = qca_soc_type(hu); + speed = qca_get_speed(hu, QCA_OPER_SPEED); if (!speed) return 0; @@ -1106,8 +1120,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) /* Disable flow control for wcn3990 to deassert RTS while * changing the baudrate of chip and host. */ - qcadev = serdev_device_get_drvdata(hu->serdev); - if (qcadev->btsoc_type == QCA_WCN3990) + if (qca_is_wcn399x(soc_type)) hci_uart_set_flow_control(hu, true); qca_baudrate = qca_get_baudrate_value(speed); @@ -1119,7 +1132,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) host_set_baudrate(hu, speed); error: - if (qcadev->btsoc_type == QCA_WCN3990) + if (qca_is_wcn399x(soc_type)) hci_uart_set_flow_control(hu, false); } @@ -1181,20 +1194,18 @@ static int qca_setup(struct hci_uart *hu) struct hci_dev *hdev = hu->hdev; struct qca_data *qca = hu->priv; unsigned int speed, qca_baudrate = QCA_BAUDRATE_115200; - struct qca_serdev *qcadev; + enum qca_btsoc_type soc_type = qca_soc_type(hu); int ret; int soc_ver = 0; - qcadev = serdev_device_get_drvdata(hu->serdev); - ret = qca_check_speeds(hu); if (ret) return ret; /* Patch downloading has to be done without IBS mode */ - clear_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags); + clear_bit(QCA_IBS_ENABLED, &qca->flags); - if (qcadev->btsoc_type == QCA_WCN3990) { + if (qca_is_wcn399x(soc_type)) { bt_dev_info(hdev, "setting up wcn3990"); /* Enable NON_PERSISTENT_SETUP QUIRK to ensure to execute @@ -1225,7 +1236,7 @@ static int qca_setup(struct hci_uart *hu) qca_baudrate = qca_get_baudrate_value(speed); } - if (qcadev->btsoc_type != QCA_WCN3990) { + if (!qca_is_wcn399x(soc_type)) { /* Get QCA version information */ ret = qca_read_soc_version(hdev, &soc_ver); if (ret) @@ -1234,9 +1245,9 @@ static int qca_setup(struct hci_uart *hu) bt_dev_info(hdev, "QCA controller version 0x%08x", soc_ver); /* Setup patch / NVM configurations */ - ret = qca_uart_setup(hdev, qca_baudrate, qcadev->btsoc_type, soc_ver); + ret = qca_uart_setup(hdev, qca_baudrate, soc_type, soc_ver); if (!ret) { - set_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags); + set_bit(QCA_IBS_ENABLED, &qca->flags); qca_debugfs_init(hdev); } else if (ret == -ENOENT) { /* No patch/nvm-config found, run with original fw/config */ @@ -1250,7 +1261,7 @@ static int qca_setup(struct hci_uart *hu) } /* Setup bdaddr */ - if (qcadev->btsoc_type == QCA_WCN3990) + if (qca_is_wcn399x(soc_type)) hu->hdev->set_bdaddr = qca_set_bdaddr; else hu->hdev->set_bdaddr = qca_set_bdaddr_rome; @@ -1273,7 +1284,7 @@ static struct hci_uart_proto qca_proto = { .dequeue = qca_dequeue, }; -static const struct qca_vreg_data qca_soc_data = { +static const struct qca_vreg_data qca_soc_data_wcn3990 = { .soc_type = QCA_WCN3990, .vregs = (struct qca_vreg []) { { "vddio", 1800000, 1900000, 15000 }, @@ -1284,6 +1295,17 @@ static const struct qca_vreg_data qca_soc_data = { .num_vregs = 4, }; +static const struct qca_vreg_data qca_soc_data_wcn3998 = { + .soc_type = QCA_WCN3998, + .vregs = (struct qca_vreg []) { + { "vddio", 1800000, 1900000, 10000 }, + { "vddxo", 1800000, 1900000, 80000 }, + { "vddrf", 1300000, 1352000, 300000 }, + { "vddch0", 3300000, 3300000, 450000 }, + }, + .num_vregs = 4, +}; + static void qca_power_shutdown(struct hci_uart *hu) { struct qca_data *qca = hu->priv; @@ -1294,7 +1316,7 @@ static void qca_power_shutdown(struct hci_uart *hu) * data in skb's. */ spin_lock_irqsave(&qca->hci_ibs_lock, flags); - clear_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags); + clear_bit(QCA_IBS_ENABLED, &qca->flags); qca_flush(hu); spin_unlock_irqrestore(&qca->hci_ibs_lock, flags); @@ -1417,8 +1439,8 @@ static int qca_serdev_probe(struct serdev_device *serdev) qcadev->serdev_hu.serdev = serdev; data = of_device_get_match_data(&serdev->dev); serdev_device_set_drvdata(serdev, qcadev); - if (data && data->soc_type == QCA_WCN3990) { - qcadev->btsoc_type = QCA_WCN3990; + if (data && qca_is_wcn399x(data->soc_type)) { + qcadev->btsoc_type = data->soc_type; qcadev->bt_power = devm_kzalloc(&serdev->dev, sizeof(struct qca_power), GFP_KERNEL); @@ -1482,7 +1504,7 @@ static void qca_serdev_remove(struct serdev_device *serdev) { struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); - if (qcadev->btsoc_type == QCA_WCN3990) + if (qca_is_wcn399x(qcadev->btsoc_type)) qca_power_shutdown(&qcadev->serdev_hu); else clk_disable_unprepare(qcadev->susclk); @@ -1492,7 +1514,8 @@ static void qca_serdev_remove(struct serdev_device *serdev) static const struct of_device_id qca_bluetooth_of_match[] = { { .compatible = "qcom,qca6174-bt" }, - { .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data}, + { .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data_wcn3990}, + { .compatible = "qcom,wcn3998-bt", .data = &qca_soc_data_wcn3998}, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match); |