diff options
author | Harish Bandi <c-hbandi@codeaurora.org> | 2019-04-26 09:56:01 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2019-05-03 09:53:27 -0400 |
commit | 523760b7ff8871281aaedc44c305926469ab47f8 (patch) | |
tree | f83451b6ff9d62261940367e540b712a100eca12 /drivers/bluetooth | |
parent | ff24e4980a68d83090a02fda081741a410fe8eef (diff) |
Bluetooth: hci_qca: Added support for WCN3998
Added new compatible for WCN3998 and corresponding voltage
and current values to WCN3998 compatible.
Changed driver code to support WCN3998
Signed-off-by: Harish Bandi <c-hbandi@codeaurora.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Reviewed-by: Balakrishna Godavarthi <bgodavar@codeaurora.org>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r-- | drivers/bluetooth/btqca.c | 7 | ||||
-rw-r--r-- | drivers/bluetooth/btqca.h | 11 | ||||
-rw-r--r-- | drivers/bluetooth/hci_qca.c | 40 |
3 files changed, 40 insertions, 18 deletions
diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 612268574fc7..cc12eecd9e4d 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c | |||
@@ -336,7 +336,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, | |||
336 | { | 336 | { |
337 | struct rome_config config; | 337 | struct rome_config config; |
338 | int err; | 338 | int err; |
339 | u8 rom_ver; | 339 | u8 rom_ver = 0; |
340 | 340 | ||
341 | bt_dev_dbg(hdev, "QCA setup on UART"); | 341 | bt_dev_dbg(hdev, "QCA setup on UART"); |
342 | 342 | ||
@@ -344,7 +344,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, | |||
344 | 344 | ||
345 | /* Download rampatch file */ | 345 | /* Download rampatch file */ |
346 | config.type = TLV_TYPE_PATCH; | 346 | config.type = TLV_TYPE_PATCH; |
347 | if (soc_type == QCA_WCN3990) { | 347 | if (qca_is_wcn399x(soc_type)) { |
348 | /* Firmware files to download are based on ROM version. | 348 | /* Firmware files to download are based on ROM version. |
349 | * ROM version is derived from last two bytes of soc_ver. | 349 | * ROM version is derived from last two bytes of soc_ver. |
350 | */ | 350 | */ |
@@ -365,7 +365,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, | |||
365 | 365 | ||
366 | /* Download NVM configuration */ | 366 | /* Download NVM configuration */ |
367 | config.type = TLV_TYPE_NVM; | 367 | config.type = TLV_TYPE_NVM; |
368 | if (soc_type == QCA_WCN3990) | 368 | if (qca_is_wcn399x(soc_type)) |
369 | snprintf(config.fwname, sizeof(config.fwname), | 369 | snprintf(config.fwname, sizeof(config.fwname), |
370 | "qca/crnv%02x.bin", rom_ver); | 370 | "qca/crnv%02x.bin", rom_ver); |
371 | else | 371 | else |
@@ -410,6 +410,7 @@ int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) | |||
410 | } | 410 | } |
411 | EXPORT_SYMBOL_GPL(qca_set_bdaddr); | 411 | EXPORT_SYMBOL_GPL(qca_set_bdaddr); |
412 | 412 | ||
413 | |||
413 | MODULE_AUTHOR("Ben Young Tae Kim <ytkim@qca.qualcomm.com>"); | 414 | MODULE_AUTHOR("Ben Young Tae Kim <ytkim@qca.qualcomm.com>"); |
414 | MODULE_DESCRIPTION("Bluetooth support for Qualcomm Atheros family ver " VERSION); | 415 | MODULE_DESCRIPTION("Bluetooth support for Qualcomm Atheros family ver " VERSION); |
415 | MODULE_VERSION(VERSION); | 416 | MODULE_VERSION(VERSION); |
diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h index 6fdc25d7bba7..4c4fe2b5b7b7 100644 --- a/drivers/bluetooth/btqca.h +++ b/drivers/bluetooth/btqca.h | |||
@@ -132,7 +132,8 @@ enum qca_btsoc_type { | |||
132 | QCA_INVALID = -1, | 132 | QCA_INVALID = -1, |
133 | QCA_AR3002, | 133 | QCA_AR3002, |
134 | QCA_ROME, | 134 | QCA_ROME, |
135 | QCA_WCN3990 | 135 | QCA_WCN3990, |
136 | QCA_WCN3998, | ||
136 | }; | 137 | }; |
137 | 138 | ||
138 | #if IS_ENABLED(CONFIG_BT_QCA) | 139 | #if IS_ENABLED(CONFIG_BT_QCA) |
@@ -142,6 +143,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, | |||
142 | enum qca_btsoc_type soc_type, u32 soc_ver); | 143 | enum qca_btsoc_type soc_type, u32 soc_ver); |
143 | int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version); | 144 | int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version); |
144 | int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); | 145 | int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); |
146 | static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type) | ||
147 | { | ||
148 | return soc_type == QCA_WCN3990 || soc_type == QCA_WCN3998; | ||
149 | } | ||
145 | #else | 150 | #else |
146 | 151 | ||
147 | static inline int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr) | 152 | static inline int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr) |
@@ -165,4 +170,8 @@ static inline int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) | |||
165 | return -EOPNOTSUPP; | 170 | return -EOPNOTSUPP; |
166 | } | 171 | } |
167 | 172 | ||
173 | static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type) | ||
174 | { | ||
175 | return false; | ||
176 | } | ||
168 | #endif | 177 | #endif |
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 7f75652686fe..c53ee8d8ca15 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c | |||
@@ -521,7 +521,7 @@ static int qca_open(struct hci_uart *hu) | |||
521 | if (hu->serdev) { | 521 | if (hu->serdev) { |
522 | 522 | ||
523 | qcadev = serdev_device_get_drvdata(hu->serdev); | 523 | qcadev = serdev_device_get_drvdata(hu->serdev); |
524 | if (qcadev->btsoc_type != QCA_WCN3990) { | 524 | if (!qca_is_wcn399x(qcadev->btsoc_type)) { |
525 | gpiod_set_value_cansleep(qcadev->bt_en, 1); | 525 | gpiod_set_value_cansleep(qcadev->bt_en, 1); |
526 | /* Controller needs time to bootup. */ | 526 | /* Controller needs time to bootup. */ |
527 | msleep(150); | 527 | msleep(150); |
@@ -629,7 +629,7 @@ static int qca_close(struct hci_uart *hu) | |||
629 | 629 | ||
630 | if (hu->serdev) { | 630 | if (hu->serdev) { |
631 | qcadev = serdev_device_get_drvdata(hu->serdev); | 631 | qcadev = serdev_device_get_drvdata(hu->serdev); |
632 | if (qcadev->btsoc_type == QCA_WCN3990) | 632 | if (qca_is_wcn399x(qcadev->btsoc_type)) |
633 | qca_power_shutdown(hu); | 633 | qca_power_shutdown(hu); |
634 | else | 634 | else |
635 | gpiod_set_value_cansleep(qcadev->bt_en, 0); | 635 | gpiod_set_value_cansleep(qcadev->bt_en, 0); |
@@ -1011,7 +1011,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) | |||
1011 | msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS)); | 1011 | msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS)); |
1012 | 1012 | ||
1013 | /* Give the controller time to process the request */ | 1013 | /* Give the controller time to process the request */ |
1014 | if (qca_soc_type(hu) == QCA_WCN3990) | 1014 | if (qca_is_wcn399x(qca_soc_type(hu))) |
1015 | msleep(10); | 1015 | msleep(10); |
1016 | else | 1016 | else |
1017 | msleep(300); | 1017 | msleep(300); |
@@ -1087,7 +1087,7 @@ static unsigned int qca_get_speed(struct hci_uart *hu, | |||
1087 | 1087 | ||
1088 | static int qca_check_speeds(struct hci_uart *hu) | 1088 | static int qca_check_speeds(struct hci_uart *hu) |
1089 | { | 1089 | { |
1090 | if (qca_soc_type(hu) == QCA_WCN3990) { | 1090 | if (qca_is_wcn399x(qca_soc_type(hu))) { |
1091 | if (!qca_get_speed(hu, QCA_INIT_SPEED) && | 1091 | if (!qca_get_speed(hu, QCA_INIT_SPEED) && |
1092 | !qca_get_speed(hu, QCA_OPER_SPEED)) | 1092 | !qca_get_speed(hu, QCA_OPER_SPEED)) |
1093 | return -EINVAL; | 1093 | return -EINVAL; |
@@ -1119,7 +1119,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) | |||
1119 | /* Disable flow control for wcn3990 to deassert RTS while | 1119 | /* Disable flow control for wcn3990 to deassert RTS while |
1120 | * changing the baudrate of chip and host. | 1120 | * changing the baudrate of chip and host. |
1121 | */ | 1121 | */ |
1122 | if (soc_type == QCA_WCN3990) | 1122 | if (qca_is_wcn399x(soc_type)) |
1123 | hci_uart_set_flow_control(hu, true); | 1123 | hci_uart_set_flow_control(hu, true); |
1124 | 1124 | ||
1125 | qca_baudrate = qca_get_baudrate_value(speed); | 1125 | qca_baudrate = qca_get_baudrate_value(speed); |
@@ -1131,7 +1131,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) | |||
1131 | host_set_baudrate(hu, speed); | 1131 | host_set_baudrate(hu, speed); |
1132 | 1132 | ||
1133 | error: | 1133 | error: |
1134 | if (soc_type == QCA_WCN3990) | 1134 | if (qca_is_wcn399x(soc_type)) |
1135 | hci_uart_set_flow_control(hu, false); | 1135 | hci_uart_set_flow_control(hu, false); |
1136 | } | 1136 | } |
1137 | 1137 | ||
@@ -1204,7 +1204,7 @@ static int qca_setup(struct hci_uart *hu) | |||
1204 | /* Patch downloading has to be done without IBS mode */ | 1204 | /* Patch downloading has to be done without IBS mode */ |
1205 | clear_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags); | 1205 | clear_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags); |
1206 | 1206 | ||
1207 | if (soc_type == QCA_WCN3990) { | 1207 | if (qca_is_wcn399x(soc_type)) { |
1208 | bt_dev_info(hdev, "setting up wcn3990"); | 1208 | bt_dev_info(hdev, "setting up wcn3990"); |
1209 | 1209 | ||
1210 | /* Enable NON_PERSISTENT_SETUP QUIRK to ensure to execute | 1210 | /* Enable NON_PERSISTENT_SETUP QUIRK to ensure to execute |
@@ -1235,7 +1235,7 @@ static int qca_setup(struct hci_uart *hu) | |||
1235 | qca_baudrate = qca_get_baudrate_value(speed); | 1235 | qca_baudrate = qca_get_baudrate_value(speed); |
1236 | } | 1236 | } |
1237 | 1237 | ||
1238 | if (soc_type != QCA_WCN3990) { | 1238 | if (!qca_is_wcn399x(soc_type)) { |
1239 | /* Get QCA version information */ | 1239 | /* Get QCA version information */ |
1240 | ret = qca_read_soc_version(hdev, &soc_ver); | 1240 | ret = qca_read_soc_version(hdev, &soc_ver); |
1241 | if (ret) | 1241 | if (ret) |
@@ -1260,7 +1260,7 @@ static int qca_setup(struct hci_uart *hu) | |||
1260 | } | 1260 | } |
1261 | 1261 | ||
1262 | /* Setup bdaddr */ | 1262 | /* Setup bdaddr */ |
1263 | if (soc_type == QCA_WCN3990) | 1263 | if (qca_is_wcn399x(soc_type)) |
1264 | hu->hdev->set_bdaddr = qca_set_bdaddr; | 1264 | hu->hdev->set_bdaddr = qca_set_bdaddr; |
1265 | else | 1265 | else |
1266 | hu->hdev->set_bdaddr = qca_set_bdaddr_rome; | 1266 | hu->hdev->set_bdaddr = qca_set_bdaddr_rome; |
@@ -1283,7 +1283,7 @@ static struct hci_uart_proto qca_proto = { | |||
1283 | .dequeue = qca_dequeue, | 1283 | .dequeue = qca_dequeue, |
1284 | }; | 1284 | }; |
1285 | 1285 | ||
1286 | static const struct qca_vreg_data qca_soc_data = { | 1286 | static const struct qca_vreg_data qca_soc_data_wcn3990 = { |
1287 | .soc_type = QCA_WCN3990, | 1287 | .soc_type = QCA_WCN3990, |
1288 | .vregs = (struct qca_vreg []) { | 1288 | .vregs = (struct qca_vreg []) { |
1289 | { "vddio", 1800000, 1900000, 15000 }, | 1289 | { "vddio", 1800000, 1900000, 15000 }, |
@@ -1294,6 +1294,17 @@ static const struct qca_vreg_data qca_soc_data = { | |||
1294 | .num_vregs = 4, | 1294 | .num_vregs = 4, |
1295 | }; | 1295 | }; |
1296 | 1296 | ||
1297 | static const struct qca_vreg_data qca_soc_data_wcn3998 = { | ||
1298 | .soc_type = QCA_WCN3998, | ||
1299 | .vregs = (struct qca_vreg []) { | ||
1300 | { "vddio", 1800000, 1900000, 10000 }, | ||
1301 | { "vddxo", 1800000, 1900000, 80000 }, | ||
1302 | { "vddrf", 1300000, 1352000, 300000 }, | ||
1303 | { "vddch0", 3300000, 3300000, 450000 }, | ||
1304 | }, | ||
1305 | .num_vregs = 4, | ||
1306 | }; | ||
1307 | |||
1297 | static void qca_power_shutdown(struct hci_uart *hu) | 1308 | static void qca_power_shutdown(struct hci_uart *hu) |
1298 | { | 1309 | { |
1299 | struct qca_data *qca = hu->priv; | 1310 | struct qca_data *qca = hu->priv; |
@@ -1427,8 +1438,8 @@ static int qca_serdev_probe(struct serdev_device *serdev) | |||
1427 | qcadev->serdev_hu.serdev = serdev; | 1438 | qcadev->serdev_hu.serdev = serdev; |
1428 | data = of_device_get_match_data(&serdev->dev); | 1439 | data = of_device_get_match_data(&serdev->dev); |
1429 | serdev_device_set_drvdata(serdev, qcadev); | 1440 | serdev_device_set_drvdata(serdev, qcadev); |
1430 | if (data && data->soc_type == QCA_WCN3990) { | 1441 | if (data && qca_is_wcn399x(data->soc_type)) { |
1431 | qcadev->btsoc_type = QCA_WCN3990; | 1442 | qcadev->btsoc_type = data->soc_type; |
1432 | qcadev->bt_power = devm_kzalloc(&serdev->dev, | 1443 | qcadev->bt_power = devm_kzalloc(&serdev->dev, |
1433 | sizeof(struct qca_power), | 1444 | sizeof(struct qca_power), |
1434 | GFP_KERNEL); | 1445 | GFP_KERNEL); |
@@ -1492,7 +1503,7 @@ static void qca_serdev_remove(struct serdev_device *serdev) | |||
1492 | { | 1503 | { |
1493 | struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); | 1504 | struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); |
1494 | 1505 | ||
1495 | if (qcadev->btsoc_type == QCA_WCN3990) | 1506 | if (qca_is_wcn399x(qcadev->btsoc_type)) |
1496 | qca_power_shutdown(&qcadev->serdev_hu); | 1507 | qca_power_shutdown(&qcadev->serdev_hu); |
1497 | else | 1508 | else |
1498 | clk_disable_unprepare(qcadev->susclk); | 1509 | clk_disable_unprepare(qcadev->susclk); |
@@ -1502,7 +1513,8 @@ static void qca_serdev_remove(struct serdev_device *serdev) | |||
1502 | 1513 | ||
1503 | static const struct of_device_id qca_bluetooth_of_match[] = { | 1514 | static const struct of_device_id qca_bluetooth_of_match[] = { |
1504 | { .compatible = "qcom,qca6174-bt" }, | 1515 | { .compatible = "qcom,qca6174-bt" }, |
1505 | { .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data}, | 1516 | { .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data_wcn3990}, |
1517 | { .compatible = "qcom,wcn3998-bt", .data = &qca_soc_data_wcn3998}, | ||
1506 | { /* sentinel */ } | 1518 | { /* sentinel */ } |
1507 | }; | 1519 | }; |
1508 | MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match); | 1520 | MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match); |