|
| 1 | +From 6fce80e910d30edbaa59f30f6dd18f0ad1db653a Mon Sep 17 00:00:00 2001 |
| 2 | +From: Dmitry Baryshkov < [email protected]> |
| 3 | +Date: Fri, 7 Feb 2025 22:41:17 +0200 |
| 4 | +Subject: [PATCH] Bluetooth: qca: add WCN3950 support |
| 5 | + |
| 6 | +WCN3950 is another example of the WCN39xx BT/WiFI family of chips. It |
| 7 | +requires different firmware files and has different current |
| 8 | +requirements, so add it as a separate SoC type. |
| 9 | + |
| 10 | +The firmware for these chips has been recently added to the |
| 11 | +linux-firmware repository and will be a part of the upcoming release: |
| 12 | +- qca/cmbtfw12.tlv |
| 13 | +- qca/cmbtfw13.tlv |
| 14 | +- qca/cmnv12.bin |
| 15 | +- qca/cmnv13.bin |
| 16 | +- qca/cmnv13s.bin |
| 17 | +- qca/cmnv13t.bin |
| 18 | + |
| 19 | +Signed-off-by: Dmitry Baryshkov < [email protected]> |
| 20 | +Upstream-Status: Backport [https://git.kernel.org/bluetooth/bluetooth-next/c/f6d6a24db7b3] |
| 21 | +--- |
| 22 | + drivers/bluetooth/btqca.c | 14 ++++++++++++++ |
| 23 | + drivers/bluetooth/btqca.h | 4 ++++ |
| 24 | + drivers/bluetooth/hci_qca.c | 25 +++++++++++++++++++++++++ |
| 25 | + 3 files changed, 43 insertions(+) |
| 26 | + |
| 27 | +diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c |
| 28 | +index 7d6b02fe2040..3d6778b95e00 100644 |
| 29 | +--- a/drivers/bluetooth/btqca.c |
| 30 | ++++ b/drivers/bluetooth/btqca.c |
| 31 | +@@ -816,6 +816,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, |
| 32 | + snprintf(config.fwname, sizeof(config.fwname), "qca/%s", rampatch_name); |
| 33 | + } else { |
| 34 | + switch (soc_type) { |
| 35 | ++ case QCA_WCN3950: |
| 36 | ++ snprintf(config.fwname, sizeof(config.fwname), |
| 37 | ++ "qca/cmbtfw%02x.tlv", rom_ver); |
| 38 | ++ break; |
| 39 | + case QCA_WCN3990: |
| 40 | + case QCA_WCN3991: |
| 41 | + case QCA_WCN3998: |
| 42 | +@@ -881,6 +885,15 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, |
| 43 | + } |
| 44 | + } else { |
| 45 | + switch (soc_type) { |
| 46 | ++ case QCA_WCN3950: |
| 47 | ++ if (le32_to_cpu(ver.soc_id) == QCA_WCN3950_SOC_ID_T) |
| 48 | ++ variant = "t"; |
| 49 | ++ else if (le32_to_cpu(ver.soc_id) == QCA_WCN3950_SOC_ID_S) |
| 50 | ++ variant = "u"; |
| 51 | ++ |
| 52 | ++ snprintf(config.fwname, sizeof(config.fwname), |
| 53 | ++ "qca/cmnv%02x%s.bin", rom_ver, variant); |
| 54 | ++ break; |
| 55 | + case QCA_WCN3990: |
| 56 | + case QCA_WCN3991: |
| 57 | + case QCA_WCN3998: |
| 58 | +@@ -947,6 +960,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, |
| 59 | + * VsMsftOpCode. |
| 60 | + */ |
| 61 | + switch (soc_type) { |
| 62 | ++ case QCA_WCN3950: |
| 63 | + case QCA_WCN3988: |
| 64 | + case QCA_WCN3990: |
| 65 | + case QCA_WCN3991: |
| 66 | +diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h |
| 67 | +index 9d28c8800225..8f3c1b1c77b3 100644 |
| 68 | +--- a/drivers/bluetooth/btqca.h |
| 69 | ++++ b/drivers/bluetooth/btqca.h |
| 70 | +@@ -41,6 +41,9 @@ |
| 71 | + |
| 72 | + #define QCA_WCN3991_SOC_ID 0x40014320 |
| 73 | + |
| 74 | ++#define QCA_WCN3950_SOC_ID_T 0x40074130 |
| 75 | ++#define QCA_WCN3950_SOC_ID_S 0x40075130 |
| 76 | ++ |
| 77 | + /* QCA chipset version can be decided by patch and SoC |
| 78 | + * version, combination with upper 2 bytes from SoC |
| 79 | + * and lower 2 bytes from patch will be used. |
| 80 | +@@ -145,6 +148,7 @@ enum qca_btsoc_type { |
| 81 | + QCA_INVALID = -1, |
| 82 | + QCA_AR3002, |
| 83 | + QCA_ROME, |
| 84 | ++ QCA_WCN3950, |
| 85 | + QCA_WCN3988, |
| 86 | + QCA_WCN3990, |
| 87 | + QCA_WCN3998, |
| 88 | +diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c |
| 89 | +index 0ac2168f1dc4..b39889ce0e8f 100644 |
| 90 | +--- a/drivers/bluetooth/hci_qca.c |
| 91 | ++++ b/drivers/bluetooth/hci_qca.c |
| 92 | +@@ -623,6 +623,7 @@ static int qca_open(struct hci_uart *hu) |
| 93 | + qcadev = serdev_device_get_drvdata(hu->serdev); |
| 94 | + |
| 95 | + switch (qcadev->btsoc_type) { |
| 96 | ++ case QCA_WCN3950: |
| 97 | + case QCA_WCN3988: |
| 98 | + case QCA_WCN3990: |
| 99 | + case QCA_WCN3991: |
| 100 | +@@ -1366,6 +1367,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) |
| 101 | + |
| 102 | + /* Give the controller time to process the request */ |
| 103 | + switch (qca_soc_type(hu)) { |
| 104 | ++ case QCA_WCN3950: |
| 105 | + case QCA_WCN3988: |
| 106 | + case QCA_WCN3990: |
| 107 | + case QCA_WCN3991: |
| 108 | +@@ -1452,6 +1454,7 @@ static unsigned int qca_get_speed(struct hci_uart *hu, |
| 109 | + static int qca_check_speeds(struct hci_uart *hu) |
| 110 | + { |
| 111 | + switch (qca_soc_type(hu)) { |
| 112 | ++ case QCA_WCN3950: |
| 113 | + case QCA_WCN3988: |
| 114 | + case QCA_WCN3990: |
| 115 | + case QCA_WCN3991: |
| 116 | +@@ -1494,6 +1497,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) |
| 117 | + * changing the baudrate of chip and host. |
| 118 | + */ |
| 119 | + switch (soc_type) { |
| 120 | ++ case QCA_WCN3950: |
| 121 | + case QCA_WCN3988: |
| 122 | + case QCA_WCN3990: |
| 123 | + case QCA_WCN3991: |
| 124 | +@@ -1528,6 +1532,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) |
| 125 | + |
| 126 | + error: |
| 127 | + switch (soc_type) { |
| 128 | ++ case QCA_WCN3950: |
| 129 | + case QCA_WCN3988: |
| 130 | + case QCA_WCN3990: |
| 131 | + case QCA_WCN3991: |
| 132 | +@@ -1746,6 +1751,7 @@ static int qca_regulator_init(struct hci_uart *hu) |
| 133 | + } |
| 134 | + |
| 135 | + switch (soc_type) { |
| 136 | ++ case QCA_WCN3950: |
| 137 | + case QCA_WCN3988: |
| 138 | + case QCA_WCN3990: |
| 139 | + case QCA_WCN3991: |
| 140 | +@@ -1776,6 +1782,7 @@ static int qca_regulator_init(struct hci_uart *hu) |
| 141 | + qca_set_speed(hu, QCA_INIT_SPEED); |
| 142 | + |
| 143 | + switch (soc_type) { |
| 144 | ++ case QCA_WCN3950: |
| 145 | + case QCA_WCN3988: |
| 146 | + case QCA_WCN3990: |
| 147 | + case QCA_WCN3991: |
| 148 | +@@ -1807,6 +1814,7 @@ static int qca_power_on(struct hci_dev *hdev) |
| 149 | + return 0; |
| 150 | + |
| 151 | + switch (soc_type) { |
| 152 | ++ case QCA_WCN3950: |
| 153 | + case QCA_WCN3988: |
| 154 | + case QCA_WCN3990: |
| 155 | + case QCA_WCN3991: |
| 156 | +@@ -1891,6 +1899,7 @@ static int qca_setup(struct hci_uart *hu) |
| 157 | + soc_name = "qca2066"; |
| 158 | + break; |
| 159 | + |
| 160 | ++ case QCA_WCN3950: |
| 161 | + case QCA_WCN3988: |
| 162 | + case QCA_WCN3990: |
| 163 | + case QCA_WCN3991: |
| 164 | +@@ -1925,6 +1934,7 @@ static int qca_setup(struct hci_uart *hu) |
| 165 | + clear_bit(QCA_SSR_TRIGGERED, &qca->flags); |
| 166 | + |
| 167 | + switch (soc_type) { |
| 168 | ++ case QCA_WCN3950: |
| 169 | + case QCA_WCN3988: |
| 170 | + case QCA_WCN3990: |
| 171 | + case QCA_WCN3991: |
| 172 | +@@ -1958,6 +1968,7 @@ static int qca_setup(struct hci_uart *hu) |
| 173 | + } |
| 174 | + |
| 175 | + switch (soc_type) { |
| 176 | ++ case QCA_WCN3950: |
| 177 | + case QCA_WCN3988: |
| 178 | + case QCA_WCN3990: |
| 179 | + case QCA_WCN3991: |
| 180 | +@@ -2046,6 +2057,17 @@ static const struct hci_uart_proto qca_proto = { |
| 181 | + .dequeue = qca_dequeue, |
| 182 | + }; |
| 183 | + |
| 184 | ++static const struct qca_device_data qca_soc_data_wcn3950 __maybe_unused = { |
| 185 | ++ .soc_type = QCA_WCN3950, |
| 186 | ++ .vregs = (struct qca_vreg []) { |
| 187 | ++ { "vddio", 15000 }, |
| 188 | ++ { "vddxo", 60000 }, |
| 189 | ++ { "vddrf", 155000 }, |
| 190 | ++ { "vddch0", 585000 }, |
| 191 | ++ }, |
| 192 | ++ .num_vregs = 4, |
| 193 | ++}; |
| 194 | ++ |
| 195 | + static const struct qca_device_data qca_soc_data_wcn3988 __maybe_unused = { |
| 196 | + .soc_type = QCA_WCN3988, |
| 197 | + .vregs = (struct qca_vreg []) { |
| 198 | +@@ -2338,6 +2360,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) |
| 199 | + qcadev->btsoc_type = QCA_ROME; |
| 200 | + |
| 201 | + switch (qcadev->btsoc_type) { |
| 202 | ++ case QCA_WCN3950: |
| 203 | + case QCA_WCN3988: |
| 204 | + case QCA_WCN3990: |
| 205 | + case QCA_WCN3991: |
| 206 | +@@ -2374,6 +2397,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) |
| 207 | + break; |
| 208 | + } |
| 209 | + fallthrough; |
| 210 | ++ case QCA_WCN3950: |
| 211 | + case QCA_WCN3988: |
| 212 | + case QCA_WCN3990: |
| 213 | + case QCA_WCN3991: |
| 214 | +@@ -2683,6 +2707,7 @@ static const struct of_device_id qca_bluetooth_of_match[] = { |
| 215 | + { .compatible = "qcom,qca6174-bt" }, |
| 216 | + { .compatible = "qcom,qca6390-bt", .data = &qca_soc_data_qca6390}, |
| 217 | + { .compatible = "qcom,qca9377-bt" }, |
| 218 | ++ { .compatible = "qcom,wcn3950-bt", .data = &qca_soc_data_wcn3950}, |
| 219 | + { .compatible = "qcom,wcn3988-bt", .data = &qca_soc_data_wcn3988}, |
| 220 | + { .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data_wcn3990}, |
| 221 | + { .compatible = "qcom,wcn3991-bt", .data = &qca_soc_data_wcn3991}, |
0 commit comments