diff options
author | Balakrishna Godavarthi <bgodavar@codeaurora.org> | 2018-08-03 08:16:32 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2018-08-03 08:44:07 -0400 |
commit | fa9ad876b8e0ebd2b4367ef1580f89be64ebd5d3 (patch) | |
tree | 2733211f90f82e8791cce80db17d0f8d497660ee | |
parent | 4219d4686875fdd83df3da00fda5ff0551e0a2d7 (diff) |
Bluetooth: hci_qca: Add support for Qualcomm Bluetooth chip wcn3990
Add support to set voltage/current of various regulators
to power up/down Bluetooth chip wcn3990.
Signed-off-by: Balakrishna Godavarthi <bgodavar@codeaurora.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r-- | drivers/bluetooth/btqca.h | 3 | ||||
-rw-r--r-- | drivers/bluetooth/hci_qca.c | 407 |
2 files changed, 363 insertions, 47 deletions
diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h index a9c2779f3e07..0c01f375fe83 100644 --- a/drivers/bluetooth/btqca.h +++ b/drivers/bluetooth/btqca.h | |||
@@ -37,6 +37,9 @@ | |||
37 | #define EDL_TAG_ID_HCI (17) | 37 | #define EDL_TAG_ID_HCI (17) |
38 | #define EDL_TAG_ID_DEEP_SLEEP (27) | 38 | #define EDL_TAG_ID_DEEP_SLEEP (27) |
39 | 39 | ||
40 | #define QCA_WCN3990_POWERON_PULSE 0xFC | ||
41 | #define QCA_WCN3990_POWEROFF_PULSE 0xC0 | ||
42 | |||
40 | enum qca_bardrate { | 43 | enum qca_bardrate { |
41 | QCA_BAUDRATE_115200 = 0, | 44 | QCA_BAUDRATE_115200 = 0, |
42 | QCA_BAUDRATE_57600, | 45 | QCA_BAUDRATE_57600, |
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 29adb95f0957..e182f6019f68 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * protocol extension to H4. | 5 | * protocol extension to H4. |
6 | * | 6 | * |
7 | * Copyright (C) 2007 Texas Instruments, Inc. | 7 | * Copyright (C) 2007 Texas Instruments, Inc. |
8 | * Copyright (c) 2010, 2012 The Linux Foundation. All rights reserved. | 8 | * Copyright (c) 2010, 2012, 2018 The Linux Foundation. All rights reserved. |
9 | * | 9 | * |
10 | * Acknowledgements: | 10 | * Acknowledgements: |
11 | * This file is based on hci_ll.c, which was... | 11 | * This file is based on hci_ll.c, which was... |
@@ -31,9 +31,14 @@ | |||
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/clk.h> | 32 | #include <linux/clk.h> |
33 | #include <linux/debugfs.h> | 33 | #include <linux/debugfs.h> |
34 | #include <linux/delay.h> | ||
35 | #include <linux/device.h> | ||
34 | #include <linux/gpio/consumer.h> | 36 | #include <linux/gpio/consumer.h> |
35 | #include <linux/mod_devicetable.h> | 37 | #include <linux/mod_devicetable.h> |
36 | #include <linux/module.h> | 38 | #include <linux/module.h> |
39 | #include <linux/of_device.h> | ||
40 | #include <linux/platform_device.h> | ||
41 | #include <linux/regulator/consumer.h> | ||
37 | #include <linux/serdev.h> | 42 | #include <linux/serdev.h> |
38 | 43 | ||
39 | #include <net/bluetooth/bluetooth.h> | 44 | #include <net/bluetooth/bluetooth.h> |
@@ -124,12 +129,46 @@ enum qca_speed_type { | |||
124 | QCA_OPER_SPEED | 129 | QCA_OPER_SPEED |
125 | }; | 130 | }; |
126 | 131 | ||
132 | /* | ||
133 | * Voltage regulator information required for configuring the | ||
134 | * QCA Bluetooth chipset | ||
135 | */ | ||
136 | struct qca_vreg { | ||
137 | const char *name; | ||
138 | unsigned int min_uV; | ||
139 | unsigned int max_uV; | ||
140 | unsigned int load_uA; | ||
141 | }; | ||
142 | |||
143 | struct qca_vreg_data { | ||
144 | enum qca_btsoc_type soc_type; | ||
145 | struct qca_vreg *vregs; | ||
146 | size_t num_vregs; | ||
147 | }; | ||
148 | |||
149 | /* | ||
150 | * Platform data for the QCA Bluetooth power driver. | ||
151 | */ | ||
152 | struct qca_power { | ||
153 | struct device *dev; | ||
154 | const struct qca_vreg_data *vreg_data; | ||
155 | struct regulator_bulk_data *vreg_bulk; | ||
156 | bool vregs_on; | ||
157 | }; | ||
158 | |||
127 | struct qca_serdev { | 159 | struct qca_serdev { |
128 | struct hci_uart serdev_hu; | 160 | struct hci_uart serdev_hu; |
129 | struct gpio_desc *bt_en; | 161 | struct gpio_desc *bt_en; |
130 | struct clk *susclk; | 162 | struct clk *susclk; |
163 | enum qca_btsoc_type btsoc_type; | ||
164 | struct qca_power *bt_power; | ||
165 | u32 init_speed; | ||
166 | u32 oper_speed; | ||
131 | }; | 167 | }; |
132 | 168 | ||
169 | static int qca_power_setup(struct hci_uart *hu, bool on); | ||
170 | static void qca_power_shutdown(struct hci_dev *hdev); | ||
171 | |||
133 | static void __serial_clock_on(struct tty_struct *tty) | 172 | static void __serial_clock_on(struct tty_struct *tty) |
134 | { | 173 | { |
135 | /* TODO: Some chipset requires to enable UART clock on client | 174 | /* TODO: Some chipset requires to enable UART clock on client |
@@ -407,6 +446,7 @@ static int qca_open(struct hci_uart *hu) | |||
407 | { | 446 | { |
408 | struct qca_serdev *qcadev; | 447 | struct qca_serdev *qcadev; |
409 | struct qca_data *qca; | 448 | struct qca_data *qca; |
449 | int ret; | ||
410 | 450 | ||
411 | BT_DBG("hu %p qca_open", hu); | 451 | BT_DBG("hu %p qca_open", hu); |
412 | 452 | ||
@@ -458,19 +498,32 @@ static int qca_open(struct hci_uart *hu) | |||
458 | 498 | ||
459 | hu->priv = qca; | 499 | hu->priv = qca; |
460 | 500 | ||
461 | timer_setup(&qca->wake_retrans_timer, hci_ibs_wake_retrans_timeout, 0); | ||
462 | qca->wake_retrans = IBS_WAKE_RETRANS_TIMEOUT_MS; | ||
463 | |||
464 | timer_setup(&qca->tx_idle_timer, hci_ibs_tx_idle_timeout, 0); | ||
465 | qca->tx_idle_delay = IBS_TX_IDLE_TIMEOUT_MS; | ||
466 | |||
467 | if (hu->serdev) { | 501 | if (hu->serdev) { |
468 | serdev_device_open(hu->serdev); | 502 | serdev_device_open(hu->serdev); |
469 | 503 | ||
470 | qcadev = serdev_device_get_drvdata(hu->serdev); | 504 | qcadev = serdev_device_get_drvdata(hu->serdev); |
471 | gpiod_set_value_cansleep(qcadev->bt_en, 1); | 505 | if (qcadev->btsoc_type != QCA_WCN3990) { |
506 | gpiod_set_value_cansleep(qcadev->bt_en, 1); | ||
507 | } else { | ||
508 | hu->init_speed = qcadev->init_speed; | ||
509 | hu->oper_speed = qcadev->oper_speed; | ||
510 | ret = qca_power_setup(hu, true); | ||
511 | if (ret) { | ||
512 | destroy_workqueue(qca->workqueue); | ||
513 | kfree_skb(qca->rx_skb); | ||
514 | hu->priv = NULL; | ||
515 | kfree(qca); | ||
516 | return ret; | ||
517 | } | ||
518 | } | ||
472 | } | 519 | } |
473 | 520 | ||
521 | timer_setup(&qca->wake_retrans_timer, hci_ibs_wake_retrans_timeout, 0); | ||
522 | qca->wake_retrans = IBS_WAKE_RETRANS_TIMEOUT_MS; | ||
523 | |||
524 | timer_setup(&qca->tx_idle_timer, hci_ibs_tx_idle_timeout, 0); | ||
525 | qca->tx_idle_delay = IBS_TX_IDLE_TIMEOUT_MS; | ||
526 | |||
474 | BT_DBG("HCI_UART_QCA open, tx_idle_delay=%u, wake_retrans=%u", | 527 | BT_DBG("HCI_UART_QCA open, tx_idle_delay=%u, wake_retrans=%u", |
475 | qca->tx_idle_delay, qca->wake_retrans); | 528 | qca->tx_idle_delay, qca->wake_retrans); |
476 | 529 | ||
@@ -554,10 +607,13 @@ static int qca_close(struct hci_uart *hu) | |||
554 | qca->hu = NULL; | 607 | qca->hu = NULL; |
555 | 608 | ||
556 | if (hu->serdev) { | 609 | if (hu->serdev) { |
557 | serdev_device_close(hu->serdev); | ||
558 | |||
559 | qcadev = serdev_device_get_drvdata(hu->serdev); | 610 | qcadev = serdev_device_get_drvdata(hu->serdev); |
560 | gpiod_set_value_cansleep(qcadev->bt_en, 0); | 611 | if (qcadev->btsoc_type == QCA_WCN3990) |
612 | qca_power_shutdown(hu->hdev); | ||
613 | else | ||
614 | gpiod_set_value_cansleep(qcadev->bt_en, 0); | ||
615 | |||
616 | serdev_device_close(hu->serdev); | ||
561 | } | 617 | } |
562 | 618 | ||
563 | kfree_skb(qca->rx_skb); | 619 | kfree_skb(qca->rx_skb); |
@@ -891,6 +947,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) | |||
891 | struct hci_uart *hu = hci_get_drvdata(hdev); | 947 | struct hci_uart *hu = hci_get_drvdata(hdev); |
892 | struct qca_data *qca = hu->priv; | 948 | struct qca_data *qca = hu->priv; |
893 | struct sk_buff *skb; | 949 | struct sk_buff *skb; |
950 | struct qca_serdev *qcadev; | ||
894 | u8 cmd[] = { 0x01, 0x48, 0xFC, 0x01, 0x00 }; | 951 | u8 cmd[] = { 0x01, 0x48, 0xFC, 0x01, 0x00 }; |
895 | 952 | ||
896 | if (baudrate > QCA_BAUDRATE_3200000) | 953 | if (baudrate > QCA_BAUDRATE_3200000) |
@@ -904,6 +961,13 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) | |||
904 | return -ENOMEM; | 961 | return -ENOMEM; |
905 | } | 962 | } |
906 | 963 | ||
964 | /* Disabling hardware flow control is mandatory while | ||
965 | * sending change baudrate request to wcn3990 SoC. | ||
966 | */ | ||
967 | qcadev = serdev_device_get_drvdata(hu->serdev); | ||
968 | if (qcadev->btsoc_type == QCA_WCN3990) | ||
969 | hci_uart_set_flow_control(hu, true); | ||
970 | |||
907 | /* Assign commands to change baudrate and packet type. */ | 971 | /* Assign commands to change baudrate and packet type. */ |
908 | skb_put_data(skb, cmd, sizeof(cmd)); | 972 | skb_put_data(skb, cmd, sizeof(cmd)); |
909 | hci_skb_pkt_type(skb) = HCI_COMMAND_PKT; | 973 | hci_skb_pkt_type(skb) = HCI_COMMAND_PKT; |
@@ -919,6 +983,9 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) | |||
919 | schedule_timeout(msecs_to_jiffies(BAUDRATE_SETTLE_TIMEOUT_MS)); | 983 | schedule_timeout(msecs_to_jiffies(BAUDRATE_SETTLE_TIMEOUT_MS)); |
920 | set_current_state(TASK_RUNNING); | 984 | set_current_state(TASK_RUNNING); |
921 | 985 | ||
986 | if (qcadev->btsoc_type == QCA_WCN3990) | ||
987 | hci_uart_set_flow_control(hu, false); | ||
988 | |||
922 | return 0; | 989 | return 0; |
923 | } | 990 | } |
924 | 991 | ||
@@ -930,6 +997,43 @@ static inline void host_set_baudrate(struct hci_uart *hu, unsigned int speed) | |||
930 | hci_uart_set_baudrate(hu, speed); | 997 | hci_uart_set_baudrate(hu, speed); |
931 | } | 998 | } |
932 | 999 | ||
1000 | static int qca_send_power_pulse(struct hci_dev *hdev, u8 cmd) | ||
1001 | { | ||
1002 | struct hci_uart *hu = hci_get_drvdata(hdev); | ||
1003 | struct qca_data *qca = hu->priv; | ||
1004 | struct sk_buff *skb; | ||
1005 | |||
1006 | /* These power pulses are single byte command which are sent | ||
1007 | * at required baudrate to wcn3990. On wcn3990, we have an external | ||
1008 | * circuit at Tx pin which decodes the pulse sent at specific baudrate. | ||
1009 | * For example, wcn3990 supports RF COEX antenna for both Wi-Fi/BT | ||
1010 | * and also we use the same power inputs to turn on and off for | ||
1011 | * Wi-Fi/BT. Powering up the power sources will not enable BT, until | ||
1012 | * we send a power on pulse at 115200 bps. This algorithm will help to | ||
1013 | * save power. Disabling hardware flow control is mandatory while | ||
1014 | * sending power pulses to SoC. | ||
1015 | */ | ||
1016 | bt_dev_dbg(hdev, "sending power pulse %02x to SoC", cmd); | ||
1017 | |||
1018 | skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL); | ||
1019 | if (!skb) | ||
1020 | return -ENOMEM; | ||
1021 | |||
1022 | hci_uart_set_flow_control(hu, true); | ||
1023 | |||
1024 | skb_put_u8(skb, cmd); | ||
1025 | hci_skb_pkt_type(skb) = HCI_COMMAND_PKT; | ||
1026 | |||
1027 | skb_queue_tail(&qca->txq, skb); | ||
1028 | hci_uart_tx_wakeup(hu); | ||
1029 | |||
1030 | /* Wait for 100 uS for SoC to settle down */ | ||
1031 | usleep_range(100, 200); | ||
1032 | hci_uart_set_flow_control(hu, false); | ||
1033 | |||
1034 | return 0; | ||
1035 | } | ||
1036 | |||
933 | static unsigned int qca_get_speed(struct hci_uart *hu, | 1037 | static unsigned int qca_get_speed(struct hci_uart *hu, |
934 | enum qca_speed_type speed_type) | 1038 | enum qca_speed_type speed_type) |
935 | { | 1039 | { |
@@ -952,9 +1056,18 @@ static unsigned int qca_get_speed(struct hci_uart *hu, | |||
952 | 1056 | ||
953 | static int qca_check_speeds(struct hci_uart *hu) | 1057 | static int qca_check_speeds(struct hci_uart *hu) |
954 | { | 1058 | { |
955 | if (!qca_get_speed(hu, QCA_INIT_SPEED) || | 1059 | struct qca_serdev *qcadev; |
956 | !qca_get_speed(hu, QCA_OPER_SPEED)) | 1060 | |
957 | return -EINVAL; | 1061 | qcadev = serdev_device_get_drvdata(hu->serdev); |
1062 | if (qcadev->btsoc_type == QCA_WCN3990) { | ||
1063 | if (!qca_get_speed(hu, QCA_INIT_SPEED) && | ||
1064 | !qca_get_speed(hu, QCA_OPER_SPEED)) | ||
1065 | return -EINVAL; | ||
1066 | } else { | ||
1067 | if (!qca_get_speed(hu, QCA_INIT_SPEED) || | ||
1068 | !qca_get_speed(hu, QCA_OPER_SPEED)) | ||
1069 | return -EINVAL; | ||
1070 | } | ||
958 | 1071 | ||
959 | return 0; | 1072 | return 0; |
960 | } | 1073 | } |
@@ -974,7 +1087,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) | |||
974 | return 0; | 1087 | return 0; |
975 | 1088 | ||
976 | qca_baudrate = qca_get_baudrate_value(speed); | 1089 | qca_baudrate = qca_get_baudrate_value(speed); |
977 | bt_dev_info(hu->hdev, "Set UART speed to %d", speed); | 1090 | bt_dev_dbg(hu->hdev, "Set UART speed to %d", speed); |
978 | ret = qca_set_baudrate(hu->hdev, qca_baudrate); | 1091 | ret = qca_set_baudrate(hu->hdev, qca_baudrate); |
979 | if (ret) | 1092 | if (ret) |
980 | return ret; | 1093 | return ret; |
@@ -985,15 +1098,52 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type) | |||
985 | return 0; | 1098 | return 0; |
986 | } | 1099 | } |
987 | 1100 | ||
1101 | static int qca_wcn3990_init(struct hci_uart *hu) | ||
1102 | { | ||
1103 | struct hci_dev *hdev = hu->hdev; | ||
1104 | int ret; | ||
1105 | |||
1106 | /* Forcefully enable wcn3990 to enter in to boot mode. */ | ||
1107 | host_set_baudrate(hu, 2400); | ||
1108 | ret = qca_send_power_pulse(hdev, QCA_WCN3990_POWEROFF_PULSE); | ||
1109 | if (ret) | ||
1110 | return ret; | ||
1111 | |||
1112 | qca_set_speed(hu, QCA_INIT_SPEED); | ||
1113 | ret = qca_send_power_pulse(hdev, QCA_WCN3990_POWERON_PULSE); | ||
1114 | if (ret) | ||
1115 | return ret; | ||
1116 | |||
1117 | /* Wait for 100 ms for SoC to boot */ | ||
1118 | msleep(100); | ||
1119 | |||
1120 | /* Now the device is in ready state to communicate with host. | ||
1121 | * To sync host with device we need to reopen port. | ||
1122 | * Without this, we will have RTS and CTS synchronization | ||
1123 | * issues. | ||
1124 | */ | ||
1125 | serdev_device_close(hu->serdev); | ||
1126 | ret = serdev_device_open(hu->serdev); | ||
1127 | if (ret) { | ||
1128 | bt_dev_err(hu->hdev, "failed to open port"); | ||
1129 | return ret; | ||
1130 | } | ||
1131 | |||
1132 | hci_uart_set_flow_control(hu, false); | ||
1133 | |||
1134 | return 0; | ||
1135 | } | ||
1136 | |||
988 | static int qca_setup(struct hci_uart *hu) | 1137 | static int qca_setup(struct hci_uart *hu) |
989 | { | 1138 | { |
990 | struct hci_dev *hdev = hu->hdev; | 1139 | struct hci_dev *hdev = hu->hdev; |
991 | struct qca_data *qca = hu->priv; | 1140 | struct qca_data *qca = hu->priv; |
992 | unsigned int speed, qca_baudrate = QCA_BAUDRATE_115200; | 1141 | unsigned int speed, qca_baudrate = QCA_BAUDRATE_115200; |
1142 | struct qca_serdev *qcadev; | ||
993 | int ret; | 1143 | int ret; |
994 | int soc_ver = 0; | 1144 | int soc_ver = 0; |
995 | 1145 | ||
996 | bt_dev_info(hdev, "ROME setup"); | 1146 | qcadev = serdev_device_get_drvdata(hu->serdev); |
997 | 1147 | ||
998 | ret = qca_check_speeds(hu); | 1148 | ret = qca_check_speeds(hu); |
999 | if (ret) | 1149 | if (ret) |
@@ -1002,8 +1152,19 @@ static int qca_setup(struct hci_uart *hu) | |||
1002 | /* Patch downloading has to be done without IBS mode */ | 1152 | /* Patch downloading has to be done without IBS mode */ |
1003 | clear_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags); | 1153 | clear_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags); |
1004 | 1154 | ||
1005 | /* Setup initial baudrate */ | 1155 | if (qcadev->btsoc_type == QCA_WCN3990) { |
1006 | qca_set_speed(hu, QCA_INIT_SPEED); | 1156 | bt_dev_info(hdev, "setting up wcn3990"); |
1157 | ret = qca_wcn3990_init(hu); | ||
1158 | if (ret) | ||
1159 | return ret; | ||
1160 | |||
1161 | ret = qca_read_soc_version(hdev, &soc_ver); | ||
1162 | if (ret) | ||
1163 | return ret; | ||
1164 | } else { | ||
1165 | bt_dev_info(hdev, "ROME setup"); | ||
1166 | qca_set_speed(hu, QCA_INIT_SPEED); | ||
1167 | } | ||
1007 | 1168 | ||
1008 | /* Setup user speed if needed */ | 1169 | /* Setup user speed if needed */ |
1009 | speed = qca_get_speed(hu, QCA_OPER_SPEED); | 1170 | speed = qca_get_speed(hu, QCA_OPER_SPEED); |
@@ -1015,15 +1176,16 @@ static int qca_setup(struct hci_uart *hu) | |||
1015 | qca_baudrate = qca_get_baudrate_value(speed); | 1176 | qca_baudrate = qca_get_baudrate_value(speed); |
1016 | } | 1177 | } |
1017 | 1178 | ||
1018 | /* Get QCA version information */ | 1179 | if (qcadev->btsoc_type != QCA_WCN3990) { |
1019 | ret = qca_read_soc_version(hdev, &soc_ver); | 1180 | /* Get QCA version information */ |
1020 | if (ret) | 1181 | ret = qca_read_soc_version(hdev, &soc_ver); |
1021 | return ret; | 1182 | if (ret) |
1183 | return ret; | ||
1184 | } | ||
1022 | 1185 | ||
1023 | bt_dev_info(hdev, "QCA controller version 0x%08x", soc_ver); | 1186 | bt_dev_info(hdev, "QCA controller version 0x%08x", soc_ver); |
1024 | |||
1025 | /* Setup patch / NVM configurations */ | 1187 | /* Setup patch / NVM configurations */ |
1026 | ret = qca_uart_setup(hdev, qca_baudrate, QCA_ROME, soc_ver); | 1188 | ret = qca_uart_setup(hdev, qca_baudrate, qcadev->btsoc_type, soc_ver); |
1027 | if (!ret) { | 1189 | if (!ret) { |
1028 | set_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags); | 1190 | set_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags); |
1029 | qca_debugfs_init(hdev); | 1191 | qca_debugfs_init(hdev); |
@@ -1059,9 +1221,123 @@ static struct hci_uart_proto qca_proto = { | |||
1059 | .dequeue = qca_dequeue, | 1221 | .dequeue = qca_dequeue, |
1060 | }; | 1222 | }; |
1061 | 1223 | ||
1224 | static const struct qca_vreg_data qca_soc_data = { | ||
1225 | .soc_type = QCA_WCN3990, | ||
1226 | .vregs = (struct qca_vreg []) { | ||
1227 | { "vddio", 1800000, 1900000, 15000 }, | ||
1228 | { "vddxo", 1800000, 1900000, 80000 }, | ||
1229 | { "vddrf", 1300000, 1350000, 300000 }, | ||
1230 | { "vddch0", 3300000, 3400000, 450000 }, | ||
1231 | }, | ||
1232 | .num_vregs = 4, | ||
1233 | }; | ||
1234 | |||
1235 | static void qca_power_shutdown(struct hci_dev *hdev) | ||
1236 | { | ||
1237 | struct hci_uart *hu = hci_get_drvdata(hdev); | ||
1238 | |||
1239 | host_set_baudrate(hu, 2400); | ||
1240 | qca_send_power_pulse(hdev, QCA_WCN3990_POWEROFF_PULSE); | ||
1241 | qca_power_setup(hu, false); | ||
1242 | } | ||
1243 | |||
1244 | static int qca_enable_regulator(struct qca_vreg vregs, | ||
1245 | struct regulator *regulator) | ||
1246 | { | ||
1247 | int ret; | ||
1248 | |||
1249 | ret = regulator_set_voltage(regulator, vregs.min_uV, | ||
1250 | vregs.max_uV); | ||
1251 | if (ret) | ||
1252 | return ret; | ||
1253 | |||
1254 | if (vregs.load_uA) | ||
1255 | ret = regulator_set_load(regulator, | ||
1256 | vregs.load_uA); | ||
1257 | |||
1258 | if (ret) | ||
1259 | return ret; | ||
1260 | |||
1261 | return regulator_enable(regulator); | ||
1262 | |||
1263 | } | ||
1264 | |||
1265 | static void qca_disable_regulator(struct qca_vreg vregs, | ||
1266 | struct regulator *regulator) | ||
1267 | { | ||
1268 | regulator_disable(regulator); | ||
1269 | regulator_set_voltage(regulator, 0, vregs.max_uV); | ||
1270 | if (vregs.load_uA) | ||
1271 | regulator_set_load(regulator, 0); | ||
1272 | |||
1273 | } | ||
1274 | |||
1275 | static int qca_power_setup(struct hci_uart *hu, bool on) | ||
1276 | { | ||
1277 | struct qca_vreg *vregs; | ||
1278 | struct regulator_bulk_data *vreg_bulk; | ||
1279 | struct qca_serdev *qcadev; | ||
1280 | int i, num_vregs, ret = 0; | ||
1281 | |||
1282 | qcadev = serdev_device_get_drvdata(hu->serdev); | ||
1283 | if (!qcadev || !qcadev->bt_power || !qcadev->bt_power->vreg_data || | ||
1284 | !qcadev->bt_power->vreg_bulk) | ||
1285 | return -EINVAL; | ||
1286 | |||
1287 | vregs = qcadev->bt_power->vreg_data->vregs; | ||
1288 | vreg_bulk = qcadev->bt_power->vreg_bulk; | ||
1289 | num_vregs = qcadev->bt_power->vreg_data->num_vregs; | ||
1290 | BT_DBG("on: %d", on); | ||
1291 | if (on && !qcadev->bt_power->vregs_on) { | ||
1292 | for (i = 0; i < num_vregs; i++) { | ||
1293 | ret = qca_enable_regulator(vregs[i], | ||
1294 | vreg_bulk[i].consumer); | ||
1295 | if (ret) | ||
1296 | break; | ||
1297 | } | ||
1298 | |||
1299 | if (ret) { | ||
1300 | BT_ERR("failed to enable regulator:%s", vregs[i].name); | ||
1301 | /* turn off regulators which are enabled */ | ||
1302 | for (i = i - 1; i >= 0; i--) | ||
1303 | qca_disable_regulator(vregs[i], | ||
1304 | vreg_bulk[i].consumer); | ||
1305 | } else { | ||
1306 | qcadev->bt_power->vregs_on = true; | ||
1307 | } | ||
1308 | } else if (!on && qcadev->bt_power->vregs_on) { | ||
1309 | /* turn off regulator in reverse order */ | ||
1310 | i = qcadev->bt_power->vreg_data->num_vregs - 1; | ||
1311 | for ( ; i >= 0; i--) | ||
1312 | qca_disable_regulator(vregs[i], vreg_bulk[i].consumer); | ||
1313 | |||
1314 | qcadev->bt_power->vregs_on = false; | ||
1315 | } | ||
1316 | |||
1317 | return ret; | ||
1318 | } | ||
1319 | |||
1320 | static int qca_init_regulators(struct qca_power *qca, | ||
1321 | const struct qca_vreg *vregs, size_t num_vregs) | ||
1322 | { | ||
1323 | int i; | ||
1324 | |||
1325 | qca->vreg_bulk = devm_kzalloc(qca->dev, num_vregs * | ||
1326 | sizeof(struct regulator_bulk_data), | ||
1327 | GFP_KERNEL); | ||
1328 | if (!qca->vreg_bulk) | ||
1329 | return -ENOMEM; | ||
1330 | |||
1331 | for (i = 0; i < num_vregs; i++) | ||
1332 | qca->vreg_bulk[i].supply = vregs[i].name; | ||
1333 | |||
1334 | return devm_regulator_bulk_get(qca->dev, num_vregs, qca->vreg_bulk); | ||
1335 | } | ||
1336 | |||
1062 | static int qca_serdev_probe(struct serdev_device *serdev) | 1337 | static int qca_serdev_probe(struct serdev_device *serdev) |
1063 | { | 1338 | { |
1064 | struct qca_serdev *qcadev; | 1339 | struct qca_serdev *qcadev; |
1340 | const struct qca_vreg_data *data; | ||
1065 | int err; | 1341 | int err; |
1066 | 1342 | ||
1067 | qcadev = devm_kzalloc(&serdev->dev, sizeof(*qcadev), GFP_KERNEL); | 1343 | qcadev = devm_kzalloc(&serdev->dev, sizeof(*qcadev), GFP_KERNEL); |
@@ -1069,47 +1345,84 @@ static int qca_serdev_probe(struct serdev_device *serdev) | |||
1069 | return -ENOMEM; | 1345 | return -ENOMEM; |
1070 | 1346 | ||
1071 | qcadev->serdev_hu.serdev = serdev; | 1347 | qcadev->serdev_hu.serdev = serdev; |
1348 | data = of_device_get_match_data(&serdev->dev); | ||
1072 | serdev_device_set_drvdata(serdev, qcadev); | 1349 | serdev_device_set_drvdata(serdev, qcadev); |
1350 | if (data && data->soc_type == QCA_WCN3990) { | ||
1351 | qcadev->btsoc_type = QCA_WCN3990; | ||
1352 | qcadev->bt_power = devm_kzalloc(&serdev->dev, | ||
1353 | sizeof(struct qca_power), | ||
1354 | GFP_KERNEL); | ||
1355 | if (!qcadev->bt_power) | ||
1356 | return -ENOMEM; | ||
1357 | |||
1358 | qcadev->bt_power->dev = &serdev->dev; | ||
1359 | qcadev->bt_power->vreg_data = data; | ||
1360 | err = qca_init_regulators(qcadev->bt_power, data->vregs, | ||
1361 | data->num_vregs); | ||
1362 | if (err) { | ||
1363 | BT_ERR("Failed to init regulators:%d", err); | ||
1364 | goto out; | ||
1365 | } | ||
1073 | 1366 | ||
1074 | qcadev->bt_en = devm_gpiod_get(&serdev->dev, "enable", | 1367 | qcadev->bt_power->vregs_on = false; |
1075 | GPIOD_OUT_LOW); | ||
1076 | if (IS_ERR(qcadev->bt_en)) { | ||
1077 | dev_err(&serdev->dev, "failed to acquire enable gpio\n"); | ||
1078 | return PTR_ERR(qcadev->bt_en); | ||
1079 | } | ||
1080 | 1368 | ||
1081 | qcadev->susclk = devm_clk_get(&serdev->dev, NULL); | 1369 | device_property_read_u32(&serdev->dev, "max-speed", |
1082 | if (IS_ERR(qcadev->susclk)) { | 1370 | &qcadev->oper_speed); |
1083 | dev_err(&serdev->dev, "failed to acquire clk\n"); | 1371 | if (!qcadev->oper_speed) |
1084 | return PTR_ERR(qcadev->susclk); | 1372 | BT_DBG("UART will pick default operating speed"); |
1085 | } | ||
1086 | 1373 | ||
1087 | err = clk_set_rate(qcadev->susclk, SUSCLK_RATE_32KHZ); | 1374 | err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto); |
1088 | if (err) | 1375 | if (err) { |
1089 | return err; | 1376 | BT_ERR("wcn3990 serdev registration failed"); |
1377 | goto out; | ||
1378 | } | ||
1379 | } else { | ||
1380 | qcadev->btsoc_type = QCA_ROME; | ||
1381 | qcadev->bt_en = devm_gpiod_get(&serdev->dev, "enable", | ||
1382 | GPIOD_OUT_LOW); | ||
1383 | if (IS_ERR(qcadev->bt_en)) { | ||
1384 | dev_err(&serdev->dev, "failed to acquire enable gpio\n"); | ||
1385 | return PTR_ERR(qcadev->bt_en); | ||
1386 | } | ||
1090 | 1387 | ||
1091 | err = clk_prepare_enable(qcadev->susclk); | 1388 | qcadev->susclk = devm_clk_get(&serdev->dev, NULL); |
1092 | if (err) | 1389 | if (IS_ERR(qcadev->susclk)) { |
1093 | return err; | 1390 | dev_err(&serdev->dev, "failed to acquire clk\n"); |
1391 | return PTR_ERR(qcadev->susclk); | ||
1392 | } | ||
1094 | 1393 | ||
1095 | err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto); | 1394 | err = clk_set_rate(qcadev->susclk, SUSCLK_RATE_32KHZ); |
1096 | if (err) | 1395 | if (err) |
1097 | clk_disable_unprepare(qcadev->susclk); | 1396 | return err; |
1397 | |||
1398 | err = clk_prepare_enable(qcadev->susclk); | ||
1399 | if (err) | ||
1400 | return err; | ||
1401 | |||
1402 | err = hci_uart_register_device(&qcadev->serdev_hu, &qca_proto); | ||
1403 | if (err) | ||
1404 | clk_disable_unprepare(qcadev->susclk); | ||
1405 | } | ||
1406 | |||
1407 | out: return err; | ||
1098 | 1408 | ||
1099 | return err; | ||
1100 | } | 1409 | } |
1101 | 1410 | ||
1102 | static void qca_serdev_remove(struct serdev_device *serdev) | 1411 | static void qca_serdev_remove(struct serdev_device *serdev) |
1103 | { | 1412 | { |
1104 | struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); | 1413 | struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); |
1105 | 1414 | ||
1106 | hci_uart_unregister_device(&qcadev->serdev_hu); | 1415 | if (qcadev->btsoc_type == QCA_WCN3990) |
1416 | qca_power_shutdown(qcadev->serdev_hu.hdev); | ||
1417 | else | ||
1418 | clk_disable_unprepare(qcadev->susclk); | ||
1107 | 1419 | ||
1108 | clk_disable_unprepare(qcadev->susclk); | 1420 | hci_uart_unregister_device(&qcadev->serdev_hu); |
1109 | } | 1421 | } |
1110 | 1422 | ||
1111 | static const struct of_device_id qca_bluetooth_of_match[] = { | 1423 | static const struct of_device_id qca_bluetooth_of_match[] = { |
1112 | { .compatible = "qcom,qca6174-bt" }, | 1424 | { .compatible = "qcom,qca6174-bt" }, |
1425 | { .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data}, | ||
1113 | { /* sentinel */ } | 1426 | { /* sentinel */ } |
1114 | }; | 1427 | }; |
1115 | MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match); | 1428 | MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match); |