Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Bluetooth: hci_qca: Add support for QTI Bluetooth chip wcn6855

Add regulators, GPIOs and changes required to power on/off wcn6855.
Add support for firmware download for wcn6855 which is in the
linux-firmware repository as hpbtfw21.tlv and hpnv21.bin.

Based on the assumption that this is similar to the wcn6750

Tested-on: BTFW.HSP.2.1.0-00538-VER_PATCHZ-1

Signed-off-by: Steev Klimaszewski <steev@kali.org>
Reviewed-by: Bjorn Andersson <andersson@kernel.org>
Tested-by: Bjorn Andersson <andersson@kernel.org>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

authored by

Steev Klimaszewski and committed by
Luiz Augusto von Dentz
095327fe b1d00baa

+66 -15
+13 -1
drivers/bluetooth/btqca.c
··· 614 614 config.type = ELF_TYPE_PATCH; 615 615 snprintf(config.fwname, sizeof(config.fwname), 616 616 "qca/msbtfw%02x.mbn", rom_ver); 617 + } else if (soc_type == QCA_WCN6855) { 618 + snprintf(config.fwname, sizeof(config.fwname), 619 + "qca/hpbtfw%02x.tlv", rom_ver); 617 620 } else { 618 621 snprintf(config.fwname, sizeof(config.fwname), 619 622 "qca/rampatch_%08x.bin", soc_ver); ··· 651 648 else if (soc_type == QCA_WCN6750) 652 649 snprintf(config.fwname, sizeof(config.fwname), 653 650 "qca/msnv%02x.bin", rom_ver); 651 + else if (soc_type == QCA_WCN6855) 652 + snprintf(config.fwname, sizeof(config.fwname), 653 + "qca/hpnv%02x.bin", rom_ver); 654 654 else 655 655 snprintf(config.fwname, sizeof(config.fwname), 656 656 "qca/nvm_%08x.bin", soc_ver); ··· 691 685 return err; 692 686 } 693 687 694 - if (soc_type == QCA_WCN3991 || soc_type == QCA_WCN6750) { 688 + switch (soc_type) { 689 + case QCA_WCN3991: 690 + case QCA_WCN6750: 691 + case QCA_WCN6855: 695 692 /* get fw build info */ 696 693 err = qca_read_fw_build_info(hdev); 697 694 if (err < 0) 698 695 return err; 696 + break; 697 + default: 698 + break; 699 699 } 700 700 701 701 bt_dev_info(hdev, "QCA setup on UART is completed");
+10
drivers/bluetooth/btqca.h
··· 147 147 QCA_WCN3991, 148 148 QCA_QCA6390, 149 149 QCA_WCN6750, 150 + QCA_WCN6855, 150 151 }; 151 152 152 153 #if IS_ENABLED(CONFIG_BT_QCA) ··· 168 167 static inline bool qca_is_wcn6750(enum qca_btsoc_type soc_type) 169 168 { 170 169 return soc_type == QCA_WCN6750; 170 + } 171 + static inline bool qca_is_wcn6855(enum qca_btsoc_type soc_type) 172 + { 173 + return soc_type == QCA_WCN6855; 171 174 } 172 175 173 176 #else ··· 207 202 } 208 203 209 204 static inline bool qca_is_wcn6750(enum qca_btsoc_type soc_type) 205 + { 206 + return false; 207 + } 208 + 209 + static inline bool qca_is_wcn6855(enum qca_btsoc_type soc_type) 210 210 { 211 211 return false; 212 212 }
+43 -14
drivers/bluetooth/hci_qca.c
··· 1317 1317 1318 1318 /* Give the controller time to process the request */ 1319 1319 if (qca_is_wcn399x(qca_soc_type(hu)) || 1320 - qca_is_wcn6750(qca_soc_type(hu))) 1320 + qca_is_wcn6750(qca_soc_type(hu)) || 1321 + qca_is_wcn6855(qca_soc_type(hu))) 1321 1322 usleep_range(1000, 10000); 1322 1323 else 1323 1324 msleep(300); ··· 1395 1394 static int qca_check_speeds(struct hci_uart *hu) 1396 1395 { 1397 1396 if (qca_is_wcn399x(qca_soc_type(hu)) || 1398 - qca_is_wcn6750(qca_soc_type(hu))) { 1397 + qca_is_wcn6750(qca_soc_type(hu)) || 1398 + qca_is_wcn6855(qca_soc_type(hu))) { 1399 1399 if (!qca_get_speed(hu, QCA_INIT_SPEED) && 1400 1400 !qca_get_speed(hu, QCA_OPER_SPEED)) 1401 1401 return -EINVAL; ··· 1430 1428 * changing the baudrate of chip and host. 1431 1429 */ 1432 1430 if (qca_is_wcn399x(soc_type) || 1433 - qca_is_wcn6750(soc_type)) 1431 + qca_is_wcn6750(soc_type) || 1432 + qca_is_wcn6855(soc_type)) 1434 1433 hci_uart_set_flow_control(hu, true); 1435 1434 1436 1435 if (soc_type == QCA_WCN3990) { ··· 1449 1446 1450 1447 error: 1451 1448 if (qca_is_wcn399x(soc_type) || 1452 - qca_is_wcn6750(soc_type)) 1449 + qca_is_wcn6750(soc_type) || 1450 + qca_is_wcn6855(soc_type)) 1453 1451 hci_uart_set_flow_control(hu, false); 1454 1452 1455 1453 if (soc_type == QCA_WCN3990) { ··· 1686 1682 return 0; 1687 1683 1688 1684 if (qca_is_wcn399x(soc_type) || 1689 - qca_is_wcn6750(soc_type)) { 1685 + qca_is_wcn6750(soc_type) || 1686 + qca_is_wcn6855(soc_type)) { 1690 1687 ret = qca_regulator_init(hu); 1691 1688 } else { 1692 1689 qcadev = serdev_device_get_drvdata(hu->serdev); ··· 1728 1723 1729 1724 bt_dev_info(hdev, "setting up %s", 1730 1725 qca_is_wcn399x(soc_type) ? "wcn399x" : 1731 - (soc_type == QCA_WCN6750) ? "wcn6750" : "ROME/QCA6390"); 1726 + (soc_type == QCA_WCN6750) ? "wcn6750" : 1727 + (soc_type == QCA_WCN6855) ? "wcn6855" : "ROME/QCA6390"); 1732 1728 1733 1729 qca->memdump_state = QCA_MEMDUMP_IDLE; 1734 1730 ··· 1741 1735 clear_bit(QCA_SSR_TRIGGERED, &qca->flags); 1742 1736 1743 1737 if (qca_is_wcn399x(soc_type) || 1744 - qca_is_wcn6750(soc_type)) { 1738 + qca_is_wcn6750(soc_type) || 1739 + qca_is_wcn6855(soc_type)) { 1745 1740 set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); 1746 1741 hci_set_aosp_capable(hdev); 1747 1742 ··· 1764 1757 } 1765 1758 1766 1759 if (!(qca_is_wcn399x(soc_type) || 1767 - qca_is_wcn6750(soc_type))) { 1760 + qca_is_wcn6750(soc_type) || 1761 + qca_is_wcn6855(soc_type))) { 1768 1762 /* Get QCA version information */ 1769 1763 ret = qca_read_soc_version(hdev, &ver, soc_type); 1770 1764 if (ret) ··· 1891 1883 .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES, 1892 1884 }; 1893 1885 1886 + static const struct qca_device_data qca_soc_data_wcn6855 = { 1887 + .soc_type = QCA_WCN6855, 1888 + .vregs = (struct qca_vreg []) { 1889 + { "vddio", 5000 }, 1890 + { "vddbtcxmx", 126000 }, 1891 + { "vddrfacmn", 12500 }, 1892 + { "vddrfa0p8", 102000 }, 1893 + { "vddrfa1p7", 302000 }, 1894 + { "vddrfa1p2", 257000 }, 1895 + }, 1896 + .num_vregs = 6, 1897 + .capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES, 1898 + }; 1899 + 1894 1900 static void qca_power_shutdown(struct hci_uart *hu) 1895 1901 { 1896 1902 struct qca_serdev *qcadev; ··· 1934 1912 host_set_baudrate(hu, 2400); 1935 1913 qca_send_power_pulse(hu, false); 1936 1914 qca_regulator_disable(qcadev); 1937 - } else if (soc_type == QCA_WCN6750) { 1915 + } else if (soc_type == QCA_WCN6750 || soc_type == QCA_WCN6855) { 1938 1916 gpiod_set_value_cansleep(qcadev->bt_en, 0); 1939 1917 msleep(100); 1940 1918 qca_regulator_disable(qcadev); ··· 2069 2047 2070 2048 if (data && 2071 2049 (qca_is_wcn399x(data->soc_type) || 2072 - qca_is_wcn6750(data->soc_type))) { 2050 + qca_is_wcn6750(data->soc_type) || 2051 + qca_is_wcn6855(data->soc_type))) { 2073 2052 qcadev->btsoc_type = data->soc_type; 2074 2053 qcadev->bt_power = devm_kzalloc(&serdev->dev, 2075 2054 sizeof(struct qca_power), ··· 2090 2067 2091 2068 qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable", 2092 2069 GPIOD_OUT_LOW); 2093 - if (IS_ERR_OR_NULL(qcadev->bt_en) && data->soc_type == QCA_WCN6750) { 2070 + if (IS_ERR_OR_NULL(qcadev->bt_en) && 2071 + (data->soc_type == QCA_WCN6750 || 2072 + data->soc_type == QCA_WCN6855)) { 2094 2073 dev_err(&serdev->dev, "failed to acquire BT_EN gpio\n"); 2095 2074 power_ctrl_enabled = false; 2096 2075 } 2097 2076 2098 2077 qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl", 2099 2078 GPIOD_IN); 2100 - if (IS_ERR_OR_NULL(qcadev->sw_ctrl) && data->soc_type == QCA_WCN6750) 2079 + if (IS_ERR_OR_NULL(qcadev->sw_ctrl) && 2080 + (data->soc_type == QCA_WCN6750 || 2081 + data->soc_type == QCA_WCN6855)) 2101 2082 dev_warn(&serdev->dev, "failed to acquire SW_CTRL gpio\n"); 2102 2083 2103 2084 qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL); ··· 2177 2150 struct qca_power *power = qcadev->bt_power; 2178 2151 2179 2152 if ((qca_is_wcn399x(qcadev->btsoc_type) || 2180 - qca_is_wcn6750(qcadev->btsoc_type)) && 2181 - power->vregs_on) 2153 + qca_is_wcn6750(qcadev->btsoc_type) || 2154 + qca_is_wcn6855(qcadev->btsoc_type)) && 2155 + power->vregs_on) 2182 2156 qca_power_shutdown(&qcadev->serdev_hu); 2183 2157 else if (qcadev->susclk) 2184 2158 clk_disable_unprepare(qcadev->susclk); ··· 2363 2335 { .compatible = "qcom,wcn3991-bt", .data = &qca_soc_data_wcn3991}, 2364 2336 { .compatible = "qcom,wcn3998-bt", .data = &qca_soc_data_wcn3998}, 2365 2337 { .compatible = "qcom,wcn6750-bt", .data = &qca_soc_data_wcn6750}, 2338 + { .compatible = "qcom,wcn6855-bt", .data = &qca_soc_data_wcn6855}, 2366 2339 { /* sentinel */ } 2367 2340 }; 2368 2341 MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match);