[PATCH v2 2/3] dt-bindings: net: bluetooth: Convert to DT schema

2021-04-20 Thread Venkata Lakshmi Narayana Gubba
Converted Qualcomm Bluetooth binidings to DT schema.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 .../devicetree/bindings/net/qualcomm-bluetooth.txt | 69 -
 .../bindings/net/qualcomm-bluetooth.yaml   | 87 ++
 2 files changed, 87 insertions(+), 69 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/net/qualcomm-bluetooth.txt
 create mode 100644 
Documentation/devicetree/bindings/net/qualcomm-bluetooth.yaml

diff --git a/Documentation/devicetree/bindings/net/qualcomm-bluetooth.txt 
b/Documentation/devicetree/bindings/net/qualcomm-bluetooth.txt
deleted file mode 100644
index 709ca6d..000
--- a/Documentation/devicetree/bindings/net/qualcomm-bluetooth.txt
+++ /dev/null
@@ -1,69 +0,0 @@
-Qualcomm Bluetooth Chips
--
-
-This documents the binding structure and common properties for serial
-attached Qualcomm devices.
-
-Serial attached Qualcomm devices shall be a child node of the host UART
-device the slave device is attached to.
-
-Required properties:
- - compatible: should contain one of the following:
-   * "qcom,qca6174-bt"
-   * "qcom,qca9377-bt"
-   * "qcom,wcn3990-bt"
-   * "qcom,wcn3991-bt"
-   * "qcom,wcn3998-bt"
-   * "qcom,qca6390-bt"
-
-Optional properties for compatible string qcom,qca6174-bt:
-
- - enable-gpios: gpio specifier used to enable chip
- - clocks: clock provided to the controller (SUSCLK_32KHZ)
- - firmware-name: specify the name of nvm firmware to load
-
-Optional properties for compatible string qcom,qca9377-bt:
-
- - max-speed: see Documentation/devicetree/bindings/serial/serial.yaml
-
-Required properties for compatible string qcom,wcn399x-bt:
-
- - vddio-supply: VDD_IO supply regulator handle.
- - vddxo-supply: VDD_XO supply regulator handle.
- - vddrf-supply: VDD_RF supply regulator handle.
- - vddch0-supply: VDD_CH0 supply regulator handle.
-
-Optional properties for compatible string qcom,wcn399x-bt:
-
- - max-speed: see Documentation/devicetree/bindings/serial/serial.yaml
- - firmware-name: specify the name of nvm firmware to load
- - clocks: clock provided to the controller
-
-Examples:
-
-serial@757 {
-   label = "BT-UART";
-   status = "okay";
-
-   bluetooth {
-   compatible = "qcom,qca6174-bt";
-
-   enable-gpios = <_gpios 19 GPIO_ACTIVE_HIGH>;
-   clocks = <>;
-   firmware-name = "nvm_00440302.bin";
-   };
-};
-
-serial@898000 {
-   bluetooth {
-   compatible = "qcom,wcn3990-bt";
-
-   vddio-supply = <_s4a_1p8>;
-   vddxo-supply = <_l7a_1p8>;
-   vddrf-supply = <_l17a_1p3>;
-   vddch0-supply = <_l25a_3p3>;
-   max-speed = <320>;
-   firmware-name = "crnv21.bin";
-   clocks = < RPMH_RF_CLK2>;
-   };
-};
diff --git a/Documentation/devicetree/bindings/net/qualcomm-bluetooth.yaml 
b/Documentation/devicetree/bindings/net/qualcomm-bluetooth.yaml
new file mode 100644
index 000..55cd995
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/qualcomm-bluetooth.yaml
@@ -0,0 +1,87 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/qualcomm-bluetooth.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Bluetooth Chips
+
+maintainers:
+  - Rob Herring 
+  - Marcel Holtmann 
+
+description:
+  This binding describes Qualcomm UART-attached bluetooth chips.
+
+properties:
+  compatible:
+enum:
+  - qcom,qca6174-bt
+  - qcom,qca9377-bt
+  - qcom,wcn3990-bt
+  - qcom,wcn3991-bt
+  - qcom,wcn3998-bt
+  - qcom,qca6390-bt  
+
+  enable-gpios:
+maxItems: 1
+description: gpio specifier used to enable chip
+   
+  clocks:
+maxItems: 1
+description: clock provided to the controller (SUSCLK_32KHZ)
+
+  vddio-supply:
+description: VDD_IO supply regulator handle
+
+  vddxo-supply:
+description: VDD_XO supply regulator handle
+
+  vddrf-supply:
+description: VDD_RF supply regulator handle
+
+  vddch0-supply:
+description: VDD_CH0 supply regulator handle
+
+  max-speed: 
+description: see Documentation/devicetree/bindings/serial/serial.yaml
+
+  firmware-name:
+description: specify the name of nvm firmware to load
+
+  local-bd-address:
+description: see Documentation/devicetree/bindings/net/bluetooth.txt
+
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+uart {
+label = "BT-UART";
+status = "okay";
+
+bluetooth {
+compatible = "qcom,qca6174-bt";
+enable-gpios = <_gpios 19 GPIO_ACTIVE_HIGH>;
+clocks = <>;
+firmware-name = "nvm_00440302.bin

[PATCH v2 0/3] Enable Bluetooth functinality for WCN6750

2021-04-20 Thread Venkata Lakshmi Narayana Gubba
These patches enables Bluetooth functinalties for new Qualcomm
Bluetooth SoC wcn6750.

Changes in v2:

* Converted Qualcomm bluetooth bindings to DT schema.
* Added device tree bindings for QTI chip wcn6750 in converted DT schema.

Venkata Lakshmi Narayana Gubba (3):
  Bluetooth: hci_qca: Add support for QTI Bluetooth chip wcn6750
  dt-bindings: net: bluetooth: Convert to DT schema
  dt-bindings: net: bluetooth: Add device tree bindings for QTI chip
wcn6750

 .../devicetree/bindings/net/qualcomm-bluetooth.txt |  69 --
 .../bindings/net/qualcomm-bluetooth.yaml   | 139 +
 drivers/bluetooth/btqca.c  |  88 +
 drivers/bluetooth/btqca.h  |  15 ++-
 drivers/bluetooth/hci_qca.c| 106 
 5 files changed, 300 insertions(+), 117 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/net/qualcomm-bluetooth.txt
 create mode 100644 
Documentation/devicetree/bindings/net/qualcomm-bluetooth.yaml

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v2 3/3] dt-bindings: net: bluetooth: Add device tree bindings for QTI chip wcn6750

2021-04-20 Thread Venkata Lakshmi Narayana Gubba
This patch enables regulators and gpios for the Qualcomm Bluetooth wcn6750
controller.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 .../bindings/net/qualcomm-bluetooth.yaml   | 54 +-
 1 file changed, 53 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/qualcomm-bluetooth.yaml 
b/Documentation/devicetree/bindings/net/qualcomm-bluetooth.yaml
index 55cd995..1ceb02b 100644
--- a/Documentation/devicetree/bindings/net/qualcomm-bluetooth.yaml
+++ b/Documentation/devicetree/bindings/net/qualcomm-bluetooth.yaml
@@ -21,11 +21,17 @@ properties:
   - qcom,wcn3990-bt
   - qcom,wcn3991-bt
   - qcom,wcn3998-bt
-  - qcom,qca6390-bt  
+  - qcom,qca6390-bt
+  - qcom,wcn6750-bt
 
   enable-gpios:
 maxItems: 1
 description: gpio specifier used to enable chip
+
+  swctrl-gpios:
+maxItems: 1
+description: gpio specifier is used to find status
+ of clock supply to SoC

   clocks:
 maxItems: 1
@@ -43,6 +49,30 @@ properties:
   vddch0-supply:
 description: VDD_CH0 supply regulator handle
 
+  vddaon-supply:
+description: VDD_AON supply regulator handle
+
+  vddbtcxmx-supply:
+description: VDD_BT_CXMX supply regualtor handle
+
+  vddrfacmn-supply:
+description: VDD_RFA_CMN supply regulator handle
+
+  vddrfa0p8-supply:
+description: VDD_RFA_0P8 suppply regulator handle
+
+  vddrfa1p7-supply:
+description: VDD_RFA_1P7 supply regulator handle
+
+  vddrfa1p2-supply:
+description: VDD_RFA_1P2 supply regulator handle
+
+  vddrfa2p2-supply:
+description: VDD_RFA_2P2 supply regulator handle
+
+  vddasd-supply:
+description: VDD_ASD supply regulator handle
+
   max-speed: 
 description: see Documentation/devicetree/bindings/serial/serial.yaml
 
@@ -85,3 +115,25 @@ examples:
 firmware-name = "crnv21.bin";  
 };
 };
+  - |
+uart {
+
+bluetooth {
+compatible = "qcom,wcn6750-bt";
+pinctrl-names = "default";
+pinctrl-0 = <_en_default>;
+enable-gpios = < 85 GPIO_ACTIVE_HIGH>;
+swctrl-gpios = < 86 GPIO_ACTIVE_HIGH>;
+vddio-supply = <_l19b_1p8>;
+vddaon-supply = <_s7b_0p9>;
+vddbtcxmx-supply = <_s7b_0p9>;
+vddrfacmn-supply = <_s7b_0p9>;
+vddrfa0p8-supply = <_s7b_0p9>;
+vddrfa1p7-supply = <_s1b_1p8>;
+vddrfa1p2-supply = <_s8b_1p2>;
+vddrfa2p2-supply = <_s1c_2p2>;
+vddasd-supply = <_l11c_2p8>;
+max-speed = <320>;
+firmware-name = "msnv11.bin";
+};
+};
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v2 1/3] Bluetooth: hci_qca: Add support for QTI Bluetooth chip wcn6750

2021-04-20 Thread Venkata Lakshmi Narayana Gubba
Added regulators,GPIOs and changes required to power on/off wcn6750.
Added support for firmware download for wcn6750.

Changes done in detail:
1. Added regulators and corresponding current values.
2. Added sw_ctrl GPIO pin which is output from BT SoC and indicates
   status of clock supply to BT SoC.
3. Added inline function to check if the SoC type is wcn399x or wcn6750.
4. Modified the function qca_wcn3990_init() to support wcn6750 and
   renamed it to qca_regulator_init().
5. Added BT_ON and BT_OFF macros.
6. Added support to download mbn type firmware image as wcn6750 supports
   mbn type image.
7. If mbn type image is not present then we will check for tlv type image.
8. Moved extracting rom version info to common place as this code is
   common in all if else ladder in qca_uart_setup.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/btqca.c   |  88 ++--
 drivers/bluetooth/btqca.h   |  15 ++-
 drivers/bluetooth/hci_qca.c | 106 ++--
 3 files changed, 161 insertions(+), 48 deletions(-)

diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index 25114f0..eec391a 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -182,7 +182,8 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
 }
 EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd);
 
-static void qca_tlv_check_data(struct qca_fw_config *config,
+static void qca_tlv_check_data(struct hci_dev *hdev,
+  struct qca_fw_config *config,
const struct firmware *fw, enum qca_btsoc_type soc_type)
 {
const u8 *data;
@@ -194,19 +195,21 @@ static void qca_tlv_check_data(struct qca_fw_config 
*config,
struct tlv_type_nvm *tlv_nvm;
uint8_t nvm_baud_rate = config->user_baud_rate;
 
-   tlv = (struct tlv_type_hdr *)fw->data;
-
-   type_len = le32_to_cpu(tlv->type_len);
-   length = (type_len >> 8) & 0x00ff;
-
-   BT_DBG("TLV Type\t\t : 0x%x", type_len & 0x00ff);
-   BT_DBG("Length\t\t : %d bytes", length);
-
config->dnld_mode = QCA_SKIP_EVT_NONE;
config->dnld_type = QCA_SKIP_EVT_NONE;
 
switch (config->type) {
+   case ELF_TYPE_PATCH:
+   config->dnld_mode = QCA_SKIP_EVT_VSE_CC;
+   config->dnld_type = QCA_SKIP_EVT_VSE_CC;
+
+   bt_dev_dbg(hdev, "File Class: 0x%x", fw->data[4]);
+   bt_dev_dbg(hdev, "Data Encoding : 0x%x", fw->data[5]);
+   bt_dev_dbg(hdev, "File version  : 0x%x", fw->data[6]);
+   break;
case TLV_TYPE_PATCH:
+   tlv = (struct tlv_type_hdr *)fw->data;
+   type_len = le32_to_cpu(tlv->type_len);
tlv_patch = (struct tlv_type_patch *)tlv->data;
 
/* For Rome version 1.1 to 3.1, all segment commands
@@ -218,6 +221,7 @@ static void qca_tlv_check_data(struct qca_fw_config *config,
config->dnld_mode = tlv_patch->download_mode;
config->dnld_type = config->dnld_mode;
 
+   BT_DBG("TLV Type\t\t : 0x%x", type_len & 0x00ff);
BT_DBG("Total Length   : %d bytes",
   le32_to_cpu(tlv_patch->total_size));
BT_DBG("Patch Data Length  : %d bytes",
@@ -243,6 +247,14 @@ static void qca_tlv_check_data(struct qca_fw_config 
*config,
break;
 
case TLV_TYPE_NVM:
+   tlv = (struct tlv_type_hdr *)fw->data;
+
+   type_len = le32_to_cpu(tlv->type_len);
+   length = (type_len >> 8) & 0x00ff;
+
+   BT_DBG("TLV Type\t\t : 0x%x", type_len & 0x00ff);
+   BT_DBG("Length\t\t : %d bytes", length);
+
idx = 0;
data = tlv->data;
while (idx < length) {
@@ -387,7 +399,8 @@ static int qca_inject_cmd_complete_event(struct hci_dev 
*hdev)
 
 static int qca_download_firmware(struct hci_dev *hdev,
 struct qca_fw_config *config,
-enum qca_btsoc_type soc_type)
+enum qca_btsoc_type soc_type,
+u8 rom_ver)
 {
const struct firmware *fw;
const u8 *segment;
@@ -397,12 +410,29 @@ static int qca_download_firmware(struct hci_dev *hdev,
 
ret = request_firmware(, config->fwname, >dev);
if (ret) {
-   bt_dev_err(hdev, "QCA Failed to request file: %s (%d)",
-  config->fwname, ret);
-   return ret;
+   /* For WCN6750, if mbn file is not present then check for
+* tlv file.
+*/
+   if (soc_type

[PATCH v1 0/2] Enable Bluetooth functinality for WCN6750

2021-03-11 Thread Venkata Lakshmi Narayana Gubba
These patches enables Bluetooth functinalties for new Qualcomm
Bluetooth SoC wcn6750. 

This SoC requires both regulators and GPIO to turn on/off.
This SoC supports mbn format image for firmware download.

Venkata Lakshmi Narayana Gubba (2):
  Bluetooth: hci_qca: Add support for QTI Bluetooth chip wcn6750
  dt-bindings: net: bluetooth: Add device tree bindings for QTI chip
wcn6750

 .../devicetree/bindings/net/qualcomm-bluetooth.txt |  43 +
 drivers/bluetooth/btqca.c  |  85 -
 drivers/bluetooth/btqca.h  |  15 ++-
 drivers/bluetooth/hci_qca.c| 106 -
 4 files changed, 202 insertions(+), 47 deletions(-)

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v1 1/2] Bluetooth: hci_qca: Add support for QTI Bluetooth chip wcn6750

2021-03-11 Thread Venkata Lakshmi Narayana Gubba
Added regulators,GPIOs and changes required to power on/off wcn6750.
Added support for firmware download for wcn6750.

Changes done in detail:
1. Added regulators and corresponding current values.
2. Added sw_ctrl GPIO pin which is output from BT SoC and indicates
   status of clock supply to BT SoC.
3. Added inline function to check if the SoC type is wcn399x or wcn6750.
4. Modified the function qca_wcn3990_init() to support wcn6750 and
   renamed it to qca_regulator_init().
5. Added BT_ON and BT_OFF macros.
6. Added support to download mbn type firmware image as wcn6750 supports
   mbn type image.
7. If mbn type image is not present then we will check for tlv type image.
8. Moved extracting rom version info to common place as this code is
   common in all if else ladder in qca_uart_setup.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/btqca.c   |  85 +--
 drivers/bluetooth/btqca.h   |  15 ++-
 drivers/bluetooth/hci_qca.c | 106 ++--
 3 files changed, 159 insertions(+), 47 deletions(-)

diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index 25114f0..00ce0e9 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -182,7 +182,8 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
 }
 EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd);
 
-static void qca_tlv_check_data(struct qca_fw_config *config,
+static void qca_tlv_check_data(struct hci_dev *hdev,
+  struct qca_fw_config *config,
const struct firmware *fw, enum qca_btsoc_type soc_type)
 {
const u8 *data;
@@ -194,19 +195,21 @@ static void qca_tlv_check_data(struct qca_fw_config 
*config,
struct tlv_type_nvm *tlv_nvm;
uint8_t nvm_baud_rate = config->user_baud_rate;
 
-   tlv = (struct tlv_type_hdr *)fw->data;
-
-   type_len = le32_to_cpu(tlv->type_len);
-   length = (type_len >> 8) & 0x00ff;
-
-   BT_DBG("TLV Type\t\t : 0x%x", type_len & 0x00ff);
-   BT_DBG("Length\t\t : %d bytes", length);
-
config->dnld_mode = QCA_SKIP_EVT_NONE;
config->dnld_type = QCA_SKIP_EVT_NONE;
 
switch (config->type) {
+   case ELF_TYPE_PATCH:
+   config->dnld_mode = QCA_SKIP_EVT_VSE_CC;
+   config->dnld_type = QCA_SKIP_EVT_VSE_CC;
+
+   bt_dev_dbg(hdev, "File Class: 0x%x", fw->data[4]);
+   bt_dev_dbg(hdev, "Data Encoding : 0x%x", fw->data[5]);
+   bt_dev_dbg(hdev, "File version  : 0x%x", fw->data[6]);
+   break;
case TLV_TYPE_PATCH:
+   tlv = (struct tlv_type_hdr *)fw->data;
+   type_len = le32_to_cpu(tlv->type_len);
tlv_patch = (struct tlv_type_patch *)tlv->data;
 
/* For Rome version 1.1 to 3.1, all segment commands
@@ -218,6 +221,7 @@ static void qca_tlv_check_data(struct qca_fw_config *config,
config->dnld_mode = tlv_patch->download_mode;
config->dnld_type = config->dnld_mode;
 
+   BT_DBG("TLV Type\t\t : 0x%x", type_len & 0x00ff);
BT_DBG("Total Length   : %d bytes",
   le32_to_cpu(tlv_patch->total_size));
BT_DBG("Patch Data Length  : %d bytes",
@@ -243,6 +247,14 @@ static void qca_tlv_check_data(struct qca_fw_config 
*config,
break;
 
case TLV_TYPE_NVM:
+   tlv = (struct tlv_type_hdr *)fw->data;
+
+   type_len = le32_to_cpu(tlv->type_len);
+   length = (type_len >> 8) & 0x00ff;
+
+   BT_DBG("TLV Type\t\t : 0x%x", type_len & 0x00ff);
+   BT_DBG("Length\t\t : %d bytes", length);
+
idx = 0;
data = tlv->data;
while (idx < length) {
@@ -387,7 +399,8 @@ static int qca_inject_cmd_complete_event(struct hci_dev 
*hdev)
 
 static int qca_download_firmware(struct hci_dev *hdev,
 struct qca_fw_config *config,
-enum qca_btsoc_type soc_type)
+enum qca_btsoc_type soc_type,
+u8 rom_ver)
 {
const struct firmware *fw;
const u8 *segment;
@@ -397,12 +410,29 @@ static int qca_download_firmware(struct hci_dev *hdev,
 
ret = request_firmware(, config->fwname, >dev);
if (ret) {
-   bt_dev_err(hdev, "QCA Failed to request file: %s (%d)",
-  config->fwname, ret);
-   return ret;
+   /* For WCN6750, if mbn file is not present then check for
+* tlv file.
+*/
+   if (soc_type

[PATCH v1 2/2] dt-bindings: net: bluetooth: Add device tree bindings for QTI chip wcn6750

2021-03-11 Thread Venkata Lakshmi Narayana Gubba
This patch enables regulators and gpios for the Qualcomm Bluetooth wcn6750
controller.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 .../devicetree/bindings/net/qualcomm-bluetooth.txt | 43 ++
 1 file changed, 43 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/qualcomm-bluetooth.txt 
b/Documentation/devicetree/bindings/net/qualcomm-bluetooth.txt
index 709ca6d..e70fcb7 100644
--- a/Documentation/devicetree/bindings/net/qualcomm-bluetooth.txt
+++ b/Documentation/devicetree/bindings/net/qualcomm-bluetooth.txt
@@ -15,6 +15,7 @@ Required properties:
* "qcom,wcn3991-bt"
* "qcom,wcn3998-bt"
* "qcom,qca6390-bt"
+   * "qcom,wcn6750-bt"
 
 Optional properties for compatible string qcom,qca6174-bt:
 
@@ -39,6 +40,26 @@ Optional properties for compatible string qcom,wcn399x-bt:
  - firmware-name: specify the name of nvm firmware to load
  - clocks: clock provided to the controller
 
+Required properties for compatible string qcom,wcn6750-bt:
+
+ - enable-gpios: gpio specifier used to enable chip
+ - swctrl-gpios: gpio specifier is output from SoC,used to find status
+of clock supply to SoC.
+ - vddio-supply: VDD_IO supply regulator handle.
+ - vddaon-supply: VDD_AON supply regulator handle.
+ - vddbtcxmx-suppl: VDD_BT_CXMX supply regualtor handle.
+ - vddrfacmn-supply: VDD_RFA_CMN supply regulator handle.
+ - vddrfa0p8-supply: VDD_RFA_0P8 suppply regulator handle.
+ - vddrfa1p7-supply: VDD_RFA_1P7 supply regulator handle.
+ - vddrfa1p2-supply: VDD_RFA_1P2 supply regulator handle.
+ - vddrfa2p2-supply: VDD_RFA_2P2 supply regulator handle.
+ - vddasd-supply: VDD_ASD supply regulator handle.
+
+Optional properties for compatible string qcom,wcn6750-bt:
+
+ - max-speed: see Documentation/devicetree/bindings/serial/serial.yaml
+ - firmware-name: specify the name of nvm firmware to load
+
 Examples:
 
 serial@757 {
@@ -67,3 +88,25 @@ serial@898000 {
clocks = < RPMH_RF_CLK2>;
};
 };
+
+serial@99c000 {
+   bluetooth {
+   compatible = "qcom,wcn6750-bt";
+
+   pinctrl-names = "default";
+   pinctrl-0 = <_en_default>;
+   enable-gpios = < 85 GPIO_ACTIVE_HIGH>;
+   swctrl-gpios = < 86 GPIO_ACTIVE_HIGH>;
+   vddio-supply = <_l19b_1p8>;
+   vddaon-supply = <_s7b_0p9>;
+   vddbtcxmx-supply = <_s7b_0p9>;
+   vddrfacmn-supply = <_s7b_0p9>;
+   vddrfa0p8-supply = <_s7b_0p9>;
+   vddrfa1p7-supply = <_s1b_1p8>;
+   vddrfa1p2-supply = <_s8b_1p2>;
+   vddrfa2p2-supply = <_s1c_2p2>;
+   vddasd-supply = <_l11c_2p8>;
+   max-speed = <320>;
+   firmware-name = "msnv11.bin";
+   };
+};
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[RFC PATCH v2] Bluetooth: hci_qca: Add device_may_wakeup support

2021-03-10 Thread Venkata Lakshmi Narayana Gubba
Based on device may wakeup status, Bluez stack will enable/disable
passive scanning with whitelist in BT controller while suspending.
As interrupt from BT SoC is handled by UART driver,we need to use
device handle of UART driver to get the status of device may wakeup

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/hci_qca.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index de36af6..73af901 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -1571,6 +1571,20 @@ static void qca_cmd_timeout(struct hci_dev *hdev)
mutex_unlock(>hci_memdump_lock);
 }
 
+static bool qca_prevent_wake(struct hci_dev *hdev)
+{
+   struct hci_uart *hu = hci_get_drvdata(hdev);
+   bool wakeup;
+
+   /* UART driver handles the interrupt from BT SoC.So we need to use
+* device handle of UART driver to get the status of device may wakeup.
+*/
+   wakeup = device_may_wakeup(hu->serdev->ctrl->dev.parent);
+   bt_dev_dbg(hu->hdev, "wakeup status : %d", wakeup);
+
+   return !wakeup;
+}
+
 static int qca_wcn3990_init(struct hci_uart *hu)
 {
struct qca_serdev *qcadev;
@@ -1721,6 +1735,7 @@ static int qca_setup(struct hci_uart *hu)
qca_debugfs_init(hdev);
hu->hdev->hw_error = qca_hw_error;
hu->hdev->cmd_timeout = qca_cmd_timeout;
+   hu->hdev->prevent_wake = qca_prevent_wake;
} else if (ret == -ENOENT) {
/* No patch/nvm-config found, run with original fw/config */
set_bit(QCA_ROM_FW, >flags);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[RFC PATCH v1] Bluetooth: hci_qca: Add device_may_wakeup support

2021-03-10 Thread Venkata Lakshmi Narayana Gubba
Added device_may_wakeup() support.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/hci_qca.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index de36af6..73af901 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -1571,6 +1571,20 @@ static void qca_cmd_timeout(struct hci_dev *hdev)
mutex_unlock(>hci_memdump_lock);
 }
 
+static bool qca_prevent_wake(struct hci_dev *hdev)
+{
+   struct hci_uart *hu = hci_get_drvdata(hdev);
+   bool wakeup;
+
+   /* UART driver handles the interrupt from BT SoC.So we need to use
+* device handle of UART driver to get the status of device may wakeup.
+*/
+   wakeup = device_may_wakeup(hu->serdev->ctrl->dev.parent);
+   bt_dev_dbg(hu->hdev, "wakeup status : %d", wakeup);
+
+   return !wakeup;
+}
+
 static int qca_wcn3990_init(struct hci_uart *hu)
 {
struct qca_serdev *qcadev;
@@ -1721,6 +1735,7 @@ static int qca_setup(struct hci_uart *hu)
qca_debugfs_init(hdev);
hu->hdev->hw_error = qca_hw_error;
hu->hdev->cmd_timeout = qca_cmd_timeout;
+   hu->hdev->prevent_wake = qca_prevent_wake;
} else if (ret == -ENOENT) {
/* No patch/nvm-config found, run with original fw/config */
set_bit(QCA_ROM_FW, >flags);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v1] Bluetooth: hci_qca:Fixed issue during suspend

2021-02-05 Thread Venkata Lakshmi Narayana Gubba
If BT SoC is running with ROM FW then just return in
qca_suspend function as ROM FW does not support
in-band sleep.

Fixes: 2be43abac5a8 ("Bluetooth: hci_qca: Wait for timeout during suspend")
Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/hci_qca.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index ff2fb68..de36af6 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -77,7 +77,8 @@ enum qca_flags {
QCA_MEMDUMP_COLLECTION,
QCA_HW_ERROR_EVENT,
QCA_SSR_TRIGGERED,
-   QCA_BT_OFF
+   QCA_BT_OFF,
+   QCA_ROM_FW
 };
 
 enum qca_capabilities {
@@ -1664,6 +1665,7 @@ static int qca_setup(struct hci_uart *hu)
if (ret)
return ret;
 
+   clear_bit(QCA_ROM_FW, >flags);
/* Patch downloading has to be done without IBS mode */
set_bit(QCA_IBS_DISABLED, >flags);
 
@@ -1721,12 +1723,14 @@ static int qca_setup(struct hci_uart *hu)
hu->hdev->cmd_timeout = qca_cmd_timeout;
} else if (ret == -ENOENT) {
/* No patch/nvm-config found, run with original fw/config */
+   set_bit(QCA_ROM_FW, >flags);
ret = 0;
} else if (ret == -EAGAIN) {
/*
 * Userspace firmware loader will return -EAGAIN in case no
 * patch/nvm-config is found, so run with original fw/config.
 */
+   set_bit(QCA_ROM_FW, >flags);
ret = 0;
}
 
@@ -2103,6 +2107,12 @@ static int __maybe_unused qca_suspend(struct device *dev)
 
set_bit(QCA_SUSPENDING, >flags);
 
+   /* if BT SoC is running with default firmware then it does not
+* support in-band sleep
+*/
+   if (test_bit(QCA_ROM_FW, >flags))
+   return 0;
+
/* During SSR after memory dump collection, controller will be
 * powered off and then powered on.If controller is powered off
 * during SSR then we should wait until SSR is completed.
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v2] Bluetooth: hci_qca: check for SSR triggered flag while suspend

2021-02-02 Thread Venkata Lakshmi Narayana Gubba
QCA_IBS_DISABLED flag will be set after memorydump started from
controller.Currently qca_suspend() is waiting for SSR to complete
based on flag QCA_IBS_DISABLED.Added to check for QCA_SSR_TRIGGERED
flag too.

Fixes: 2be43abac5a8 ("Bluetooth: hci_qca: Wait for timeout during suspend")
Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/hci_qca.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 17a3859..ff2fb68 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -2111,7 +2111,8 @@ static int __maybe_unused qca_suspend(struct device *dev)
!test_bit(QCA_SSR_TRIGGERED, >flags))
return 0;
 
-   if (test_bit(QCA_IBS_DISABLED, >flags)) {
+   if (test_bit(QCA_IBS_DISABLED, >flags) ||
+   test_bit(QCA_SSR_TRIGGERED, >flags)) {
wait_timeout = test_bit(QCA_SSR_TRIGGERED, >flags) ?
IBS_DISABLE_SSR_TIMEOUT_MS :
FW_DOWNLOAD_TIMEOUT_MS;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v1] Bluetooth: hci_qca: check for SSR triggered flag while suspend

2021-02-02 Thread Venkata Lakshmi Narayana Gubba
QCA_IBS_DISABLED flag will be set after memorydump started from
controller.Currently qca_suspend() is waiting for SSR to complete
based on flag QCA_IBS_DISABLED.Added to check for QCA_SSR_TRIGGERED
flag too.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/hci_qca.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 17a3859..ff2fb68 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -2111,7 +2111,8 @@ static int __maybe_unused qca_suspend(struct device *dev)
!test_bit(QCA_SSR_TRIGGERED, >flags))
return 0;
 
-   if (test_bit(QCA_IBS_DISABLED, >flags)) {
+   if (test_bit(QCA_IBS_DISABLED, >flags) ||
+   test_bit(QCA_SSR_TRIGGERED, >flags)) {
wait_timeout = test_bit(QCA_SSR_TRIGGERED, >flags) ?
IBS_DISABLE_SSR_TIMEOUT_MS :
FW_DOWNLOAD_TIMEOUT_MS;
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v1] Bluetooth: hci_qca: Wait for SSR completion during suspend

2020-12-30 Thread Venkata Lakshmi Narayana Gubba
During SSR after memory dump collection,BT controller will be powered off,
powered on and then FW will be downloaded.During suspend if BT controller
is powered off due to SSR then we should wait until SSR is completed and
then suspend.

Fixes: 2be43abac5a8 ("Bluetooth: hci_qca: Wait for timeout during suspend")
Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/hci_qca.c | 16 +---
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 4a96368..6ad4079 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -50,7 +50,8 @@
 #define IBS_HOST_TX_IDLE_TIMEOUT_MS2000
 #define CMD_TRANS_TIMEOUT_MS   100
 #define MEMDUMP_TIMEOUT_MS 8000
-#define IBS_DISABLE_SSR_TIMEOUT_MS (MEMDUMP_TIMEOUT_MS + 1000)
+#define IBS_DISABLE_SSR_TIMEOUT_MS \
+   (MEMDUMP_TIMEOUT_MS + FW_DOWNLOAD_TIMEOUT_MS)
 #define FW_DOWNLOAD_TIMEOUT_MS 3000
 
 /* susclk rate */
@@ -2100,7 +2101,12 @@ static int __maybe_unused qca_suspend(struct device *dev)
 
set_bit(QCA_SUSPENDING, >flags);
 
-   if (test_bit(QCA_BT_OFF, >flags))
+   /* During SSR after memory dump collection, controller will be
+* powered off and then powered on.If controller is powered off
+* during SSR then we should wait until SSR is completed.
+*/
+   if (test_bit(QCA_BT_OFF, >flags) &&
+   !test_bit(QCA_SSR_TRIGGERED, >flags))
return 0;
 
if (test_bit(QCA_IBS_DISABLED, >flags)) {
@@ -2110,7 +2116,7 @@ static int __maybe_unused qca_suspend(struct device *dev)
 
/* QCA_IBS_DISABLED flag is set to true, During FW download
 * and during memory dump collection. It is reset to false,
-* After FW download complete and after memory dump collections.
+* After FW download complete.
 */
wait_on_bit_timeout(>flags, QCA_IBS_DISABLED,
TASK_UNINTERRUPTIBLE, 
msecs_to_jiffies(wait_timeout));
@@ -2122,10 +2128,6 @@ static int __maybe_unused qca_suspend(struct device *dev)
}
}
 
-   /* After memory dump collection, Controller is powered off.*/
-   if (test_bit(QCA_BT_OFF, >flags))
-   return 0;
-
cancel_work_sync(>ws_awake_device);
cancel_work_sync(>ws_awake_rx);
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v4] Bluetooth: btqca: Add support to read FW build version for WCN3991 BTSoC

2020-12-08 Thread Venkata Lakshmi Narayana Gubba
Add support to read FW build version from debugfs node.
This info can be read from
/sys/kernel/debug/bluetooth/hci0/firmware_info

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/btqca.c | 54 +++
 drivers/bluetooth/btqca.h |  1 +
 2 files changed, 55 insertions(+)

diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index f85a55a..f6256a3 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -94,6 +94,53 @@ int qca_read_soc_version(struct hci_dev *hdev, struct 
qca_btsoc_version *ver,
 }
 EXPORT_SYMBOL_GPL(qca_read_soc_version);
 
+static int qca_read_fw_build_info(struct hci_dev *hdev)
+{
+   struct sk_buff *skb;
+   struct edl_event_hdr *edl;
+   char cmd, build_label[QCA_FW_BUILD_VER_LEN];
+   int build_lbl_len, err = 0;
+
+   bt_dev_dbg(hdev, "QCA read fw build info");
+
+   cmd = EDL_GET_BUILD_INFO_CMD;
+   skb = __hci_cmd_sync_ev(hdev, EDL_PATCH_CMD_OPCODE, EDL_PATCH_CMD_LEN,
+   , 0, HCI_INIT_TIMEOUT);
+   if (IS_ERR(skb)) {
+   err = PTR_ERR(skb);
+   bt_dev_err(hdev, "Reading QCA fw build info failed (%d)",
+  err);
+   return err;
+   }
+
+   edl = (struct edl_event_hdr *)(skb->data);
+   if (!edl) {
+   bt_dev_err(hdev, "QCA read fw build info with no header");
+   err = -EILSEQ;
+   goto out;
+   }
+
+   if (edl->cresp != EDL_CMD_REQ_RES_EVT ||
+   edl->rtype != EDL_GET_BUILD_INFO_CMD) {
+   bt_dev_err(hdev, "QCA Wrong packet received %d %d", edl->cresp,
+  edl->rtype);
+   err = -EIO;
+   goto out;
+   }
+
+   build_lbl_len = edl->data[0];
+   if (build_lbl_len <= QCA_FW_BUILD_VER_LEN - 1) {
+   memcpy(build_label, edl->data + 1, build_lbl_len);
+   *(build_label + build_lbl_len) = '\0';
+   }
+
+   hci_set_fw_info(hdev, "%s", build_label);
+
+out:
+   kfree_skb(skb);
+   return err;
+}
+
 static int qca_send_reset(struct hci_dev *hdev)
 {
struct sk_buff *skb;
@@ -524,6 +571,13 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
return err;
}
 
+   if (soc_type == QCA_WCN3991) {
+   /* get fw build info */
+   err = qca_read_fw_build_info(hdev);
+   if (err < 0)
+   return err;
+   }
+
bt_dev_info(hdev, "QCA setup on UART is completed");
 
return 0;
diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h
index e73b8f8..b19add7 100644
--- a/drivers/bluetooth/btqca.h
+++ b/drivers/bluetooth/btqca.h
@@ -11,6 +11,7 @@
 #define EDL_PATCH_CMD_LEN  (1)
 #define EDL_PATCH_VER_REQ_CMD  (0x19)
 #define EDL_PATCH_TLV_REQ_CMD  (0x1E)
+#define EDL_GET_BUILD_INFO_CMD (0x20)
 #define EDL_NVM_ACCESS_SET_REQ_CMD (0x01)
 #define MAX_SIZE_PER_TLV_SEGMENT   (243)
 #define QCA_PRE_SHUTDOWN_CMD   (0xFC08)
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v3] Bluetooth: hci_qca: Add support to read FW build version for WCN3991 BTSoC

2020-12-03 Thread Venkata Lakshmi Narayana Gubba
Add support to read FW build version from debugfs node.
This info can be read from
/sys/kernel/debug/bluetooth/hci0/ibs/fw_build_info

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/btqca.c   | 48 +
 drivers/bluetooth/btqca.h   |  8 
 drivers/bluetooth/hci_qca.c | 34 
 3 files changed, 90 insertions(+)

diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index f85a55a..660eea5 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -94,6 +94,54 @@ int qca_read_soc_version(struct hci_dev *hdev, struct 
qca_btsoc_version *ver,
 }
 EXPORT_SYMBOL_GPL(qca_read_soc_version);
 
+int qca_read_fw_build_info(struct hci_dev *hdev, u8 *fw_build)
+{
+   struct sk_buff *skb;
+   struct edl_event_hdr *edl;
+   char cmd;
+   int err = 0;
+   int build_lbl_len;
+
+   bt_dev_dbg(hdev, "QCA read fw build info");
+
+   cmd = EDL_GET_BUILD_INFO_CMD;
+   skb = __hci_cmd_sync_ev(hdev, EDL_PATCH_CMD_OPCODE, EDL_PATCH_CMD_LEN,
+   , 0, HCI_INIT_TIMEOUT);
+   if (IS_ERR(skb)) {
+   err = PTR_ERR(skb);
+   bt_dev_err(hdev, "Reading QCA fw build info failed (%d)",
+  err);
+   return err;
+   }
+
+   edl = (struct edl_event_hdr *)(skb->data);
+   if (!edl) {
+   bt_dev_err(hdev, "QCA read fw build info with no header");
+   err = -EILSEQ;
+   goto out;
+   }
+
+   if (edl->cresp != EDL_CMD_REQ_RES_EVT ||
+   edl->rtype != EDL_GET_BUILD_INFO_CMD) {
+   bt_dev_err(hdev, "QCA Wrong packet received %d %d", edl->cresp,
+  edl->rtype);
+   err = -EIO;
+   goto out;
+   }
+
+   build_lbl_len = edl->data[0];
+   if (build_lbl_len <= QCA_FW_BUILD_VER_LEN - 2) {
+   memcpy(fw_build, >data[1], build_lbl_len);
+   *(fw_build + build_lbl_len) = '\n';
+   *(fw_build + build_lbl_len + 1) = '\0';
+   }
+
+out:
+   kfree_skb(skb);
+   return err;
+}
+EXPORT_SYMBOL_GPL(qca_read_fw_build_info);
+
 static int qca_send_reset(struct hci_dev *hdev)
 {
struct sk_buff *skb;
diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h
index e73b8f8..ac1b76a 100644
--- a/drivers/bluetooth/btqca.h
+++ b/drivers/bluetooth/btqca.h
@@ -11,6 +11,7 @@
 #define EDL_PATCH_CMD_LEN  (1)
 #define EDL_PATCH_VER_REQ_CMD  (0x19)
 #define EDL_PATCH_TLV_REQ_CMD  (0x1E)
+#define EDL_GET_BUILD_INFO_CMD (0x20)
 #define EDL_NVM_ACCESS_SET_REQ_CMD (0x01)
 #define MAX_SIZE_PER_TLV_SEGMENT   (243)
 #define QCA_PRE_SHUTDOWN_CMD   (0xFC08)
@@ -154,6 +155,7 @@ int qca_read_soc_version(struct hci_dev *hdev, struct 
qca_btsoc_version *ver,
 enum qca_btsoc_type);
 int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
 int qca_send_pre_shutdown_cmd(struct hci_dev *hdev);
+int qca_read_fw_build_info(struct hci_dev *hdev, u8 *fw_build);
 static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
 {
return soc_type == QCA_WCN3990 || soc_type == QCA_WCN3991 ||
@@ -195,4 +197,10 @@ static inline int qca_send_pre_shutdown_cmd(struct hci_dev 
*hdev)
 {
return -EOPNOTSUPP;
 }
+
+static inline int qca_read_fw_build_info(struct hci_dev *hdev, u8 *fw_build)
+{
+   return -EOPNOTSUPP;
+}
+
 #endif
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 4a96368..56616b0 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -180,6 +180,7 @@ struct qca_data {
u64 rx_votes_off;
u64 votes_on;
u64 votes_off;
+   u8 fw_build[QCA_FW_BUILD_VER_LEN];
 };
 
 enum qca_speed_type {
@@ -621,12 +622,33 @@ static int qca_open(struct hci_uart *hu)
return 0;
 }
 
+static ssize_t fw_build_read(struct file *file, char __user *user_buf,
+size_t count, loff_t *ppos)
+{
+   struct hci_dev *hdev = file->private_data;
+   struct hci_uart *hu = hci_get_drvdata(hdev);
+   struct qca_data *qca = hu->priv;
+   u8 length = 0;
+
+   length = strlen(qca->fw_build);
+
+   return simple_read_from_buffer(user_buf, count, ppos, qca->fw_build,
+  length);
+}
+
+static const struct file_operations fw_build_fops = {
+   .open = simple_open,
+   .read = fw_build_read,
+};
+
 static void qca_debugfs_init(struct hci_dev *hdev)
 {
struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv;
struct dentry *ibs_dir;
umode_t mode;
+   enum qca_btsoc_type soc_type = qca_soc_type(hu);
+   int ret;
 
if (!hdev->debugfs)
return;
@@ -659,12 +681,2

[PATCH v2] Bluetooth: Use NVM files based on SoC ID for WCN3991

2020-11-19 Thread Venkata Lakshmi Narayana Gubba
This change will allow to use different NVM file based
on WCN3991 BT SoC ID.Need to use different NVM file based on
fab location for WCN3991 BT SoC.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/btqca.c   | 36 
 drivers/bluetooth/btqca.h   | 22 ++
 drivers/bluetooth/hci_qca.c |  9 -
 3 files changed, 42 insertions(+), 25 deletions(-)

diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index ce9dcff..f85a55a 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -14,12 +14,11 @@
 
 #define VERSION "0.1"
 
-int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version,
+int qca_read_soc_version(struct hci_dev *hdev, struct qca_btsoc_version *ver,
 enum qca_btsoc_type soc_type)
 {
struct sk_buff *skb;
struct edl_event_hdr *edl;
-   struct qca_btsoc_version *ver;
char cmd;
int err = 0;
u8 event_type = HCI_EV_VENDOR;
@@ -70,9 +69,9 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 
*soc_version,
}
 
if (soc_type >= QCA_WCN3991)
-   memmove(>data, >data[1], sizeof(*ver));
-
-   ver = (struct qca_btsoc_version *)(edl->data);
+   memcpy(ver, edl->data + 1, sizeof(*ver));
+   else
+   memcpy(ver, >data, sizeof(*ver));
 
bt_dev_info(hdev, "QCA Product ID   :0x%08x",
le32_to_cpu(ver->product_id));
@@ -83,13 +82,7 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 
*soc_version,
bt_dev_info(hdev, "QCA Patch Version:0x%08x",
le16_to_cpu(ver->patch_ver));
 
-   /* QCA chipset version can be decided by patch and SoC
-* version, combination with upper 2 bytes from SoC
-* and lower 2 bytes from patch will be used.
-*/
-   *soc_version = (le32_to_cpu(ver->soc_id) << 16) |
-  (le16_to_cpu(ver->rom_ver) & 0x);
-   if (*soc_version == 0)
+   if (ver->soc_id == 0 || ver->rom_ver == 0)
err = -EILSEQ;
 
 out:
@@ -446,15 +439,20 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const 
bdaddr_t *bdaddr)
 EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome);
 
 int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
-  enum qca_btsoc_type soc_type, u32 soc_ver,
+  enum qca_btsoc_type soc_type, struct qca_btsoc_version ver,
   const char *firmware_name)
 {
struct qca_fw_config config;
int err;
u8 rom_ver = 0;
+   u32 soc_ver;
 
bt_dev_dbg(hdev, "QCA setup on UART");
 
+   soc_ver = get_soc_ver(ver.soc_id, ver.rom_ver);
+
+   bt_dev_info(hdev, "QCA controller version 0x%08x", soc_ver);
+
config.user_baud_rate = baudrate;
 
/* Download rampatch file */
@@ -491,9 +489,15 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
if (firmware_name)
snprintf(config.fwname, sizeof(config.fwname),
 "qca/%s", firmware_name);
-   else if (qca_is_wcn399x(soc_type))
-   snprintf(config.fwname, sizeof(config.fwname),
-"qca/crnv%02x.bin", rom_ver);
+   else if (qca_is_wcn399x(soc_type)) {
+   if (ver.soc_id == QCA_WCN3991_SOC_ID) {
+   snprintf(config.fwname, sizeof(config.fwname),
+"qca/crnv%02xu.bin", rom_ver);
+   } else {
+   snprintf(config.fwname, sizeof(config.fwname),
+"qca/crnv%02x.bin", rom_ver);
+   }
+   }
else if (soc_type == QCA_QCA6390)
snprintf(config.fwname, sizeof(config.fwname),
 "qca/htnv%02x.bin", rom_ver);
diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h
index d81b74c..e73b8f8 100644
--- a/drivers/bluetooth/btqca.h
+++ b/drivers/bluetooth/btqca.h
@@ -34,6 +34,18 @@
 #define QCA_HCI_CC_OPCODE  0xFC00
 #define QCA_HCI_CC_SUCCESS 0x00
 
+#define QCA_WCN3991_SOC_ID (0x40014320)
+
+/* QCA chipset version can be decided by patch and SoC
+ * version, combination with upper 2 bytes from SoC
+ * and lower 2 bytes from patch will be used.
+ */
+#define get_soc_ver(soc_id, rom_ver)   \
+   ((le32_to_cpu(soc_id) << 16) | (le16_to_cpu(rom_ver)))
+
+#define QCA_FW_BUILD_VER_LEN   255
+
+
 enum qca_baudrate {
QCA_BAUDRATE_115200 = 0,
QCA_BAUDRATE_57600,
@@ -136,9 +148,9 @@ enum qca_btsoc_type {
 
 int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr);
 int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
-  enum qca_btsoc_type soc_type, u32 soc_ver,
+  enum qca_btsoc_type soc_t

[PATCH v2] Bluetooth: btqca: Add support to read FW build version for WCN3991 BTSoC

2020-11-18 Thread Venkata Lakshmi Narayana Gubba
Add support to read FW build version for WCN3991 BTSoC

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/btqca.c | 57 +++
 drivers/bluetooth/btqca.h |  3 +++
 2 files changed, 60 insertions(+)

diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index ce9dcff..dfd7ff7 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -101,6 +101,56 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 
*soc_version,
 }
 EXPORT_SYMBOL_GPL(qca_read_soc_version);
 
+static int qca_read_fw_build_info(struct hci_dev *hdev)
+{
+   struct sk_buff *skb;
+   struct edl_event_hdr *edl;
+   char cmd;
+   int err = 0;
+   char build_label[QCA_FW_BUILD_VER_LEN];
+   int build_lbl_len;
+
+   bt_dev_dbg(hdev, "QCA read fw build info");
+
+   cmd = EDL_GET_BUILD_INFO_CMD;
+   skb = __hci_cmd_sync_ev(hdev, EDL_PATCH_CMD_OPCODE, EDL_PATCH_CMD_LEN,
+   , HCI_EV_VENDOR, HCI_INIT_TIMEOUT);
+   if (IS_ERR(skb)) {
+   err = PTR_ERR(skb);
+   bt_dev_err(hdev, "Reading QCA fw build info failed (%d)",
+  err);
+   return err;
+   }
+
+   edl = (struct edl_event_hdr *)(skb->data);
+   if (!edl) {
+   bt_dev_err(hdev, "QCA read fw build info with no header");
+   err = -EILSEQ;
+   goto out;
+   }
+
+   if (edl->cresp != EDL_CMD_REQ_RES_EVT ||
+   edl->rtype != EDL_GET_BUILD_INFO_CMD) {
+   bt_dev_err(hdev, "QCA Wrong packet received %d %d", edl->cresp,
+  edl->rtype);
+   err = -EIO;
+   goto out;
+   }
+
+   build_lbl_len = edl->data[0];
+   memcpy(build_label, >data[1], build_lbl_len);
+   *(build_label + build_lbl_len) = '\0';
+
+   bt_dev_info(hdev, "BT SoC FW Build info: %s", build_label);
+
+out:
+   kfree_skb(skb);
+   if (err)
+   bt_dev_err(hdev, "QCA read fw build info failed (%d)", err);
+
+   return err;
+}
+
 static int qca_send_reset(struct hci_dev *hdev)
 {
struct sk_buff *skb;
@@ -520,6 +570,13 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
return err;
}
 
+   if (soc_type == QCA_WCN3991) {
+   /* get fw build info */
+   err = qca_read_fw_build_info(hdev);
+   if (err < 0)
+   return err;
+   }
+
bt_dev_info(hdev, "QCA setup on UART is completed");
 
return 0;
diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h
index d81b74c..375c7fc 100644
--- a/drivers/bluetooth/btqca.h
+++ b/drivers/bluetooth/btqca.h
@@ -11,6 +11,7 @@
 #define EDL_PATCH_CMD_LEN  (1)
 #define EDL_PATCH_VER_REQ_CMD  (0x19)
 #define EDL_PATCH_TLV_REQ_CMD  (0x1E)
+#define EDL_GET_BUILD_INFO_CMD (0x20)
 #define EDL_NVM_ACCESS_SET_REQ_CMD (0x01)
 #define MAX_SIZE_PER_TLV_SEGMENT   (243)
 #define QCA_PRE_SHUTDOWN_CMD   (0xFC08)
@@ -34,6 +35,8 @@
 #define QCA_HCI_CC_OPCODE  0xFC00
 #define QCA_HCI_CC_SUCCESS 0x00
 
+#define QCA_FW_BUILD_VER_LEN   255
+
 enum qca_baudrate {
QCA_BAUDRATE_115200 = 0,
QCA_BAUDRATE_57600,
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v1] Bluetooth: btqca: Add support to read FW build version for WCN3991 BTSoC

2020-11-17 Thread Venkata Lakshmi Narayana Gubba
Add support to read FW build version for WCN3991 BTSoC

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/btqca.c | 57 +++
 drivers/bluetooth/btqca.h |  3 +++
 2 files changed, 60 insertions(+)

diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index ce9dcff..70f6cc5 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -101,6 +101,56 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 
*soc_version,
 }
 EXPORT_SYMBOL_GPL(qca_read_soc_version);
 
+int qca_read_fw_build_info(struct hci_dev *hdev)
+{
+   struct sk_buff *skb;
+   struct edl_event_hdr *edl;
+   char cmd;
+   int err = 0;
+   char build_label[QCA_FW_BUILD_VER_LEN];
+   int build_lbl_len;
+
+   bt_dev_dbg(hdev, "QCA read fw build info");
+
+   cmd = EDL_GET_BUILD_INFO_CMD;
+   skb = __hci_cmd_sync_ev(hdev, EDL_PATCH_CMD_OPCODE, EDL_PATCH_CMD_LEN,
+   , HCI_EV_VENDOR, HCI_INIT_TIMEOUT);
+   if (IS_ERR(skb)) {
+   err = PTR_ERR(skb);
+   bt_dev_err(hdev, "Reading QCA fw build info failed (%d)",
+  err);
+   return err;
+   }
+
+   edl = (struct edl_event_hdr *)(skb->data);
+   if (!edl) {
+   bt_dev_err(hdev, "QCA read fw build info with no header");
+   err = -EILSEQ;
+   goto out;
+   }
+
+   if (edl->cresp != EDL_CMD_REQ_RES_EVT ||
+   edl->rtype != EDL_GET_BUILD_INFO_CMD) {
+   bt_dev_err(hdev, "QCA Wrong packet received %d %d", edl->cresp,
+  edl->rtype);
+   err = -EIO;
+   goto out;
+   }
+
+   build_lbl_len = edl->data[0];
+   memcpy(build_label, >data[1], build_lbl_len);
+   *(build_label + build_lbl_len) = '\0';
+
+   bt_dev_info(hdev, "BT SoC FW Build info: %s", build_label);
+
+out:
+   kfree_skb(skb);
+   if (err)
+   bt_dev_err(hdev, "QCA read fw build info failed (%d)", err);
+
+   return err;
+}
+
 static int qca_send_reset(struct hci_dev *hdev)
 {
struct sk_buff *skb;
@@ -520,6 +570,13 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
return err;
}
 
+   if (soc_type == QCA_WCN3991) {
+   /* get fw build info */
+   qca_read_fw_build_info(hdev);
+   if (err < 0)
+   return err;
+   }
+
bt_dev_info(hdev, "QCA setup on UART is completed");
 
return 0;
diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h
index d81b74c..375c7fc 100644
--- a/drivers/bluetooth/btqca.h
+++ b/drivers/bluetooth/btqca.h
@@ -11,6 +11,7 @@
 #define EDL_PATCH_CMD_LEN  (1)
 #define EDL_PATCH_VER_REQ_CMD  (0x19)
 #define EDL_PATCH_TLV_REQ_CMD  (0x1E)
+#define EDL_GET_BUILD_INFO_CMD (0x20)
 #define EDL_NVM_ACCESS_SET_REQ_CMD (0x01)
 #define MAX_SIZE_PER_TLV_SEGMENT   (243)
 #define QCA_PRE_SHUTDOWN_CMD   (0xFC08)
@@ -34,6 +35,8 @@
 #define QCA_HCI_CC_OPCODE  0xFC00
 #define QCA_HCI_CC_SUCCESS 0x00
 
+#define QCA_FW_BUILD_VER_LEN   255
+
 enum qca_baudrate {
QCA_BAUDRATE_115200 = 0,
QCA_BAUDRATE_57600,
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v1] Bluetooth: hci_qca: Handle spurious wakeup from SoC

2020-11-15 Thread Venkata Lakshmi Narayana Gubba
Added timer to handle spurious wakeup from SoC.
Timer is started when wake indicator is received from SoC.
Timer is restarted when valid data is received from SoC.
Timer is stopped when sleep indicator is received from SoC.
SSR is triggered upon timer expiry.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/hci_qca.c | 99 -
 1 file changed, 97 insertions(+), 2 deletions(-)

diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 5cc7b16..6953001 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -48,6 +48,7 @@
 #define IBS_WAKE_RETRANS_TIMEOUT_MS100
 #define IBS_BTSOC_TX_IDLE_TIMEOUT_MS   200
 #define IBS_HOST_TX_IDLE_TIMEOUT_MS2000
+#define IBS_SOC_SPURIOUS_WAKE_TIMEOUT_MS 1
 #define CMD_TRANS_TIMEOUT_MS   100
 #define MEMDUMP_TIMEOUT_MS 8000
 #define IBS_DISABLE_SSR_TIMEOUT_MS (MEMDUMP_TIMEOUT_MS + 1000)
@@ -147,7 +148,9 @@ struct qca_data {
bool tx_vote;   /* Clock must be on for TX */
bool rx_vote;   /* Clock must be on for RX */
struct timer_list tx_idle_timer;
+   struct timer_list spurious_wake_timer;
u32 tx_idle_delay;
+   u32 spurious_wake;
struct timer_list wake_retrans_timer;
u32 wake_retrans;
struct workqueue_struct *workqueue;
@@ -156,6 +159,7 @@ struct qca_data {
struct work_struct ws_rx_vote_off;
struct work_struct ws_tx_vote_off;
struct work_struct ctrl_memdump_evt;
+   struct work_struct spurious_wake_timeout;
struct delayed_work ctrl_memdump_timeout;
struct qca_memdump_data *qca_memdump;
unsigned long flags;
@@ -229,6 +233,7 @@ static void qca_regulator_disable(struct qca_serdev 
*qcadev);
 static void qca_power_shutdown(struct hci_uart *hu);
 static int qca_power_off(struct hci_dev *hdev);
 static void qca_controller_memdump(struct work_struct *work);
+static void qca_wq_spurious_wake_timeout(struct work_struct *work);
 
 static enum qca_btsoc_type qca_soc_type(struct hci_uart *hu)
 {
@@ -530,6 +535,15 @@ static void hci_ibs_wake_retrans_timeout(struct timer_list 
*t)
hci_uart_tx_wakeup(hu);
 }
 
+static void hci_ibs_spurious_wake_timeout(struct timer_list *t)
+{
+   struct qca_data *qca = from_timer(qca, t, spurious_wake_timer);
+   struct hci_uart *hu = qca->hu;
+
+   bt_dev_warn(hu->hdev, "hu %p spurious wake timeout in %d state", hu, 
qca->rx_ibs_state);
+
+   queue_work(qca->workqueue, >spurious_wake_timeout);
+}
 
 static void qca_controller_memdump_timeout(struct work_struct *work)
 {
@@ -584,6 +598,7 @@ static int qca_open(struct hci_uart *hu)
INIT_WORK(>ws_rx_vote_off, qca_wq_serial_rx_clock_vote_off);
INIT_WORK(>ws_tx_vote_off, qca_wq_serial_tx_clock_vote_off);
INIT_WORK(>ctrl_memdump_evt, qca_controller_memdump);
+   INIT_WORK(>spurious_wake_timeout, qca_wq_spurious_wake_timeout);
INIT_DELAYED_WORK(>ctrl_memdump_timeout,
  qca_controller_memdump_timeout);
init_waitqueue_head(>suspend_wait_q);
@@ -615,6 +630,9 @@ static int qca_open(struct hci_uart *hu)
timer_setup(>tx_idle_timer, hci_ibs_tx_idle_timeout, 0);
qca->tx_idle_delay = IBS_HOST_TX_IDLE_TIMEOUT_MS;
 
+   timer_setup(>spurious_wake_timer, hci_ibs_spurious_wake_timeout, 
0);
+   qca->spurious_wake = IBS_SOC_SPURIOUS_WAKE_TIMEOUT_MS;
+
BT_DBG("HCI_UART_QCA open, tx_idle_delay=%u, wake_retrans=%u",
   qca->tx_idle_delay, qca->wake_retrans);
 
@@ -694,6 +712,7 @@ static int qca_close(struct hci_uart *hu)
skb_queue_purge(>rx_memdump_q);
del_timer(>tx_idle_timer);
del_timer(>wake_retrans_timer);
+   del_timer(>spurious_wake_timer);
destroy_workqueue(qca->workqueue);
qca->hu = NULL;
 
@@ -710,7 +729,7 @@ static int qca_close(struct hci_uart *hu)
  */
 static void device_want_to_wakeup(struct hci_uart *hu)
 {
-   unsigned long flags;
+   unsigned long flags, wake_timeout;
struct qca_data *qca = hu->priv;
 
BT_DBG("hu %p want to wake up", hu);
@@ -731,6 +750,10 @@ static void device_want_to_wakeup(struct hci_uart *hu)
 * receiving the wake up indicator awake rx clock.
 */
queue_work(qca->workqueue, >ws_awake_rx);
+   if (!test_bit(QCA_SSR_TRIGGERED, >flags)) {
+   wake_timeout = msecs_to_jiffies(qca->spurious_wake);
+   mod_timer(>spurious_wake_timer, jiffies + 
wake_timeout);
+   }
spin_unlock_irqrestore(>hci_ibs_lock, flags);
return;
 
@@ -777,9 +800,11 @@ static void device_want_to_sleep(struct hci_uart *hu)
qca->rx_ibs_state = HCI_IBS_RX

[PATCH v1] Bluetooth: Use NVM files based on SoC ID for WCN3991

2020-09-15 Thread Venkata Lakshmi Narayana Gubba
This change will allow to use different NVM file based
on WCN3991 BT SoC ID.Need to use different NVM file based on
fab location for WCN3991 BT SoC.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/btqca.c   | 41 +
 drivers/bluetooth/btqca.h   | 13 -
 drivers/bluetooth/hci_qca.c | 11 +--
 3 files changed, 38 insertions(+), 27 deletions(-)

diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index ce9dcff..a7e72f1 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -14,12 +14,11 @@
 
 #define VERSION "0.1"
 
-int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version,
+int qca_read_soc_version(struct hci_dev *hdev, struct qca_btsoc_version *ver,
 enum qca_btsoc_type soc_type)
 {
struct sk_buff *skb;
struct edl_event_hdr *edl;
-   struct qca_btsoc_version *ver;
char cmd;
int err = 0;
u8 event_type = HCI_EV_VENDOR;
@@ -70,9 +69,9 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 
*soc_version,
}
 
if (soc_type >= QCA_WCN3991)
-   memmove(>data, >data[1], sizeof(*ver));
-
-   ver = (struct qca_btsoc_version *)(edl->data);
+   memcpy(ver, >data[1], sizeof(*ver));
+   else
+   memcpy(ver, >data, sizeof(*ver));
 
bt_dev_info(hdev, "QCA Product ID   :0x%08x",
le32_to_cpu(ver->product_id));
@@ -83,13 +82,7 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 
*soc_version,
bt_dev_info(hdev, "QCA Patch Version:0x%08x",
le16_to_cpu(ver->patch_ver));
 
-   /* QCA chipset version can be decided by patch and SoC
-* version, combination with upper 2 bytes from SoC
-* and lower 2 bytes from patch will be used.
-*/
-   *soc_version = (le32_to_cpu(ver->soc_id) << 16) |
-  (le16_to_cpu(ver->rom_ver) & 0x);
-   if (*soc_version == 0)
+   if (le32_to_cpu(ver->soc_id) == 0 || le16_to_cpu(ver->rom_ver) == 0)
err = -EILSEQ;
 
 out:
@@ -446,15 +439,25 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const 
bdaddr_t *bdaddr)
 EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome);
 
 int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
-  enum qca_btsoc_type soc_type, u32 soc_ver,
+  enum qca_btsoc_type soc_type, struct qca_btsoc_version ver,
   const char *firmware_name)
 {
struct qca_fw_config config;
int err;
u8 rom_ver = 0;
+   u32 soc_ver;
 
bt_dev_dbg(hdev, "QCA setup on UART");
 
+   /* QCA chipset version can be decided by patch and SoC
+* version, combination with upper 2 bytes from SoC
+* and lower 2 bytes from patch will be used.
+*/
+   soc_ver = (le32_to_cpu(ver.soc_id) << 16) |
+  (le16_to_cpu(ver.rom_ver) & 0x);
+
+   bt_dev_info(hdev, "QCA controller version 0x%08x", soc_ver);
+
config.user_baud_rate = baudrate;
 
/* Download rampatch file */
@@ -491,9 +494,15 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
if (firmware_name)
snprintf(config.fwname, sizeof(config.fwname),
 "qca/%s", firmware_name);
-   else if (qca_is_wcn399x(soc_type))
-   snprintf(config.fwname, sizeof(config.fwname),
-"qca/crnv%02x.bin", rom_ver);
+   else if (qca_is_wcn399x(soc_type)) {
+   if (ver.soc_id == QCA_WCN3991_SOC_ID) {
+   snprintf(config.fwname, sizeof(config.fwname),
+"qca/crnv%02xu.bin", rom_ver);
+   } else {
+   snprintf(config.fwname, sizeof(config.fwname),
+"qca/crnv%02x.bin", rom_ver);
+   }
+   }
else if (soc_type == QCA_QCA6390)
snprintf(config.fwname, sizeof(config.fwname),
 "qca/htnv%02x.bin", rom_ver);
diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h
index d81b74c..d01a9f5 100644
--- a/drivers/bluetooth/btqca.h
+++ b/drivers/bluetooth/btqca.h
@@ -34,6 +34,8 @@
 #define QCA_HCI_CC_OPCODE  0xFC00
 #define QCA_HCI_CC_SUCCESS 0x00
 
+#define QCA_WCN3991_SOC_ID (0x40014320)
+
 enum qca_baudrate {
QCA_BAUDRATE_115200 = 0,
QCA_BAUDRATE_57600,
@@ -136,9 +138,9 @@ enum qca_btsoc_type {
 
 int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr);
 int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
-  enum qca_btsoc_type soc_type, u32 soc_ver,
+  enum qca_btsoc_type soc_type, struct qca_btsoc_version ver,
   

[RESEND v1] arm64: dts: qcom: sc7180: Remove clock for bluetooth on SC7180 IDP board

2020-09-10 Thread Venkata Lakshmi Narayana Gubba
Removed voting for RPMH_RF_CLK2 which is not required as it is
getting managed by BT SoC through SW_CTRL line.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 arch/arm64/boot/dts/qcom/sc7180-idp.dts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/sc7180-idp.dts 
b/arch/arm64/boot/dts/qcom/sc7180-idp.dts
index 4e9149d..b295d01 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-idp.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-idp.dts
@@ -348,7 +348,6 @@
vddrf-supply = <_l2c_1p3>;
vddch0-supply = <_l10c_3p3>;
max-speed = <320>;
-   clocks = < RPMH_RF_CLK2>;
};
 };
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[RESEND v1 2/2] Bluetooth: hci_qca: Remove duplicate power off in proto close

2020-09-10 Thread Venkata Lakshmi Narayana Gubba
During serdev unregister, hdev->shutdown is called before
proto close. Removing duplicates power OFF call.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/hci_qca.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 20e1ded..f0d9ee3 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -693,8 +693,6 @@ static int qca_close(struct hci_uart *hu)
destroy_workqueue(qca->workqueue);
qca->hu = NULL;
 
-   qca_power_shutdown(hu);
-
kfree_skb(qca->rx_skb);
 
hu->priv = NULL;
@@ -2032,8 +2030,9 @@ static int qca_serdev_probe(struct serdev_device *serdev)
 static void qca_serdev_remove(struct serdev_device *serdev)
 {
struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
+   struct qca_power *power = qcadev->bt_power;
 
-   if (qca_is_wcn399x(qcadev->btsoc_type))
+   if (qca_is_wcn399x(qcadev->btsoc_type) && power->vregs_on)
qca_power_shutdown(>serdev_hu);
else if (qcadev->susclk)
clk_disable_unprepare(qcadev->susclk);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[RESEND v1 0/2] Close UART port if NON_PERSISTENT_SETUP is set

2020-09-10 Thread Venkata Lakshmi Narayana Gubba
When HCI_QUIRK_NON_PERSISTENT_SETUP is set by drivers,
it indicates that BT SoC will be completely powered OFF
during BT OFF. On next BT ON firmware must be downloaded
again. Holding UART port open during BT OFF is draining
the battery. Now during BT OFF, UART port is closed if
qurik HCI_QUIRK_NON_PERSISTENT_SETUP is set by clearing
HCI_UART_PROTO_READY proto flag. On next BT ON, UART
port is opened if HCI_UART_PROTO_READY proto flag is cleared.

Venkata Lakshmi Narayana Gubba (2):
  Bluetooth: hci_serdev: Close UART port if NON_PERSISTENT_SETUP is set
  Bluetooth: hci_qca: Remove duplicate power off in proto close

 drivers/bluetooth/hci_qca.c|  5 ++---
 drivers/bluetooth/hci_serdev.c | 36 +---
 2 files changed, 35 insertions(+), 6 deletions(-)

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[RESEND v1 1/2] Bluetooth: hci_serdev: Close UART port if NON_PERSISTENT_SETUP is set

2020-09-10 Thread Venkata Lakshmi Narayana Gubba
When HCI_QUIRK_NON_PERSISTENT_SETUP is set by drivers,
it indicates that BT SoC will be completely powered OFF
during BT OFF. On next BT ON firmware must be downloaded
again. Holding UART port open during BT OFF is draining
the battery. Now during BT OFF, UART port is closed if
qurik HCI_QUIRK_NON_PERSISTENT_SETUP is set by clearing
HCI_UART_PROTO_READY proto flag. On next BT ON, UART
port is opened if HCI_UART_PROTO_READY proto flag is cleared.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/hci_serdev.c | 36 +---
 1 file changed, 33 insertions(+), 3 deletions(-)

diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c
index 3977bba..ef96ad0 100644
--- a/drivers/bluetooth/hci_serdev.c
+++ b/drivers/bluetooth/hci_serdev.c
@@ -113,8 +113,22 @@ static int hci_uart_flush(struct hci_dev *hdev)
 /* Initialize device */
 static int hci_uart_open(struct hci_dev *hdev)
 {
+   struct hci_uart *hu = hci_get_drvdata(hdev);
+   int err;
+
BT_DBG("%s %p", hdev->name, hdev);
 
+   /* When Quirk HCI_QUIRK_NON_PERSISTENT_SETUP is set by
+* driver, BT SoC is completely turned OFF during
+* BT OFF. Upon next BT ON UART port should be opened.
+*/
+   if (!test_bit(HCI_UART_PROTO_READY, >flags)) {
+   err = serdev_device_open(hu->serdev);
+   if (err)
+   return err;
+   set_bit(HCI_UART_PROTO_READY, >flags);
+   }
+
/* Undo clearing this from hci_uart_close() */
hdev->flush = hci_uart_flush;
 
@@ -124,11 +138,25 @@ static int hci_uart_open(struct hci_dev *hdev)
 /* Close device */
 static int hci_uart_close(struct hci_dev *hdev)
 {
+   struct hci_uart *hu = hci_get_drvdata(hdev);
+
BT_DBG("hdev %p", hdev);
 
+   if (!test_bit(HCI_UART_PROTO_READY, >flags))
+   return 0;
+
hci_uart_flush(hdev);
hdev->flush = NULL;
 
+   /* When QUIRK HCI_QUIRK_NON_PERSISTENT_SETUP is set by driver,
+* BT SOC is completely powered OFF during BT OFF, holding port
+* open may drain the battery.
+*/
+   if (test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, >quirks)) {
+   clear_bit(HCI_UART_PROTO_READY, >flags);
+   serdev_device_close(hu->serdev);
+   }
+
return 0;
 }
 
@@ -354,8 +382,6 @@ void hci_uart_unregister_device(struct hci_uart *hu)
 {
struct hci_dev *hdev = hu->hdev;
 
-   clear_bit(HCI_UART_PROTO_READY, >flags);
-
cancel_work_sync(>init_ready);
if (test_bit(HCI_UART_REGISTERED, >flags))
hci_unregister_dev(hdev);
@@ -364,6 +390,10 @@ void hci_uart_unregister_device(struct hci_uart *hu)
cancel_work_sync(>write_work);
 
hu->proto->close(hu);
-   serdev_device_close(hu->serdev);
+
+   if (test_bit(HCI_UART_PROTO_READY, >flags)) {
+   clear_bit(HCI_UART_PROTO_READY, >flags);
+   serdev_device_close(hu->serdev);
+   }
 }
 EXPORT_SYMBOL_GPL(hci_uart_unregister_device);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v1] arm64: dts: qcom: sc7180: Remove clock for bluetooth on SC7180 IDP board

2020-09-02 Thread Venkata Lakshmi Narayana Gubba
Removed voting for RPMH_RF_CLK2 which is not required as it is
getting managed by BT SoC through SW_CTRL line.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 arch/arm64/boot/dts/qcom/sc7180-idp.dts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/sc7180-idp.dts 
b/arch/arm64/boot/dts/qcom/sc7180-idp.dts
index 4e9149d..b295d01 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-idp.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-idp.dts
@@ -348,7 +348,6 @@
vddrf-supply = <_l2c_1p3>;
vddch0-supply = <_l10c_3p3>;
max-speed = <320>;
-   clocks = < RPMH_RF_CLK2>;
};
 };
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v1 2/2] Bluetooth: hci_qca: Remove duplicate power off in proto close

2020-09-01 Thread Venkata Lakshmi Narayana Gubba
During serdev unregister, hdev->shutdown is called before
proto close. Removing duplicates power OFF call.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/hci_qca.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 20e1ded..f0d9ee3 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -693,8 +693,6 @@ static int qca_close(struct hci_uart *hu)
destroy_workqueue(qca->workqueue);
qca->hu = NULL;
 
-   qca_power_shutdown(hu);
-
kfree_skb(qca->rx_skb);
 
hu->priv = NULL;
@@ -2032,8 +2030,9 @@ static int qca_serdev_probe(struct serdev_device *serdev)
 static void qca_serdev_remove(struct serdev_device *serdev)
 {
struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
+   struct qca_power *power = qcadev->bt_power;
 
-   if (qca_is_wcn399x(qcadev->btsoc_type))
+   if (qca_is_wcn399x(qcadev->btsoc_type) && power->vregs_on)
qca_power_shutdown(>serdev_hu);
else if (qcadev->susclk)
clk_disable_unprepare(qcadev->susclk);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v1 0/2] Close UART port if NON_PERSISTENT_SETUP is set

2020-09-01 Thread Venkata Lakshmi Narayana Gubba
When HCI_QUIRK_NON_PERSISTENT_SETUP is set by drivers,
it indicates that BT SoC will be completely powered OFF
during BT OFF. On next BT ON firmware must be downloaded
again. Holding UART port open during BT OFF is draining
the battery. Now during BT OFF, UART port is closed if
qurik HCI_QUIRK_NON_PERSISTENT_SETUP is set by clearing
HCI_UART_PROTO_READY proto flag. On next BT ON, UART
port is opened if HCI_UART_PROTO_READY proto flag is cleared.

Venkata Lakshmi Narayana Gubba (2):
  Bluetooth: hci_serdev: Close UART port if NON_PERSISTENT_SETUP is set
  Bluetooth: hci_qca: Remove duplicate power off in proto close

 drivers/bluetooth/hci_qca.c|  5 ++---
 drivers/bluetooth/hci_serdev.c | 36 +---
 2 files changed, 35 insertions(+), 6 deletions(-)

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v1 1/2] Bluetooth: hci_serdev: Close UART port if NON_PERSISTENT_SETUP is set

2020-09-01 Thread Venkata Lakshmi Narayana Gubba
When HCI_QUIRK_NON_PERSISTENT_SETUP is set by drivers,
it indicates that BT SoC will be completely powered OFF
during BT OFF. On next BT ON firmware must be downloaded
again. Holding UART port open during BT OFF is draining
the battery. Now during BT OFF, UART port is closed if
qurik HCI_QUIRK_NON_PERSISTENT_SETUP is set by clearing
HCI_UART_PROTO_READY proto flag. On next BT ON, UART
port is opened if HCI_UART_PROTO_READY proto flag is cleared.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/hci_serdev.c | 36 +---
 1 file changed, 33 insertions(+), 3 deletions(-)

diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c
index 3977bba..ef96ad0 100644
--- a/drivers/bluetooth/hci_serdev.c
+++ b/drivers/bluetooth/hci_serdev.c
@@ -113,8 +113,22 @@ static int hci_uart_flush(struct hci_dev *hdev)
 /* Initialize device */
 static int hci_uart_open(struct hci_dev *hdev)
 {
+   struct hci_uart *hu = hci_get_drvdata(hdev);
+   int err;
+
BT_DBG("%s %p", hdev->name, hdev);
 
+   /* When Quirk HCI_QUIRK_NON_PERSISTENT_SETUP is set by
+* driver, BT SoC is completely turned OFF during
+* BT OFF. Upon next BT ON UART port should be opened.
+*/
+   if (!test_bit(HCI_UART_PROTO_READY, >flags)) {
+   err = serdev_device_open(hu->serdev);
+   if (err)
+   return err;
+   set_bit(HCI_UART_PROTO_READY, >flags);
+   }
+
/* Undo clearing this from hci_uart_close() */
hdev->flush = hci_uart_flush;
 
@@ -124,11 +138,25 @@ static int hci_uart_open(struct hci_dev *hdev)
 /* Close device */
 static int hci_uart_close(struct hci_dev *hdev)
 {
+   struct hci_uart *hu = hci_get_drvdata(hdev);
+
BT_DBG("hdev %p", hdev);
 
+   if (!test_bit(HCI_UART_PROTO_READY, >flags))
+   return 0;
+
hci_uart_flush(hdev);
hdev->flush = NULL;
 
+   /* When QUIRK HCI_QUIRK_NON_PERSISTENT_SETUP is set by driver,
+* BT SOC is completely powered OFF during BT OFF, holding port
+* open may drain the battery.
+*/
+   if (test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, >quirks)) {
+   clear_bit(HCI_UART_PROTO_READY, >flags);
+   serdev_device_close(hu->serdev);
+   }
+
return 0;
 }
 
@@ -354,8 +382,6 @@ void hci_uart_unregister_device(struct hci_uart *hu)
 {
struct hci_dev *hdev = hu->hdev;
 
-   clear_bit(HCI_UART_PROTO_READY, >flags);
-
cancel_work_sync(>init_ready);
if (test_bit(HCI_UART_REGISTERED, >flags))
hci_unregister_dev(hdev);
@@ -364,6 +390,10 @@ void hci_uart_unregister_device(struct hci_uart *hu)
cancel_work_sync(>write_work);
 
hu->proto->close(hu);
-   serdev_device_close(hu->serdev);
+
+   if (test_bit(HCI_UART_PROTO_READY, >flags)) {
+   clear_bit(HCI_UART_PROTO_READY, >flags);
+   serdev_device_close(hu->serdev);
+   }
 }
 EXPORT_SYMBOL_GPL(hci_uart_unregister_device);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v1] Bluetooth: hci_qca: Stop collecting memdump again for command timeout during SSR

2020-07-28 Thread Venkata Lakshmi Narayana Gubba
Setting memdump state to idle prior to setting of callback function
pointer for command timeout to NULL,causing the issue.Now moved the
initialisation of memdump state to qca_setup().

Fixes: d841502c79e3 ("Bluetooth: hci_qca: Collect controller memory dump during 
SSR")
Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/hci_qca.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 3d13002..20e1ded 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -1668,6 +1668,8 @@ static int qca_setup(struct hci_uart *hu)
bt_dev_info(hdev, "setting up %s",
qca_is_wcn399x(soc_type) ? "wcn399x" : "ROME/QCA6390");
 
+   qca->memdump_state = QCA_MEMDUMP_IDLE;
+
 retry:
ret = qca_power_on(hdev);
if (ret)
@@ -1817,9 +1819,6 @@ static void qca_power_shutdown(struct hci_uart *hu)
qca_flush(hu);
spin_unlock_irqrestore(>hci_ibs_lock, flags);
 
-   hu->hdev->hw_error = NULL;
-   hu->hdev->cmd_timeout = NULL;
-
/* Non-serdev device usually is powered by external power
 * and don't need additional action in driver for power down
 */
@@ -1841,6 +1840,9 @@ static int qca_power_off(struct hci_dev *hdev)
struct qca_data *qca = hu->priv;
enum qca_btsoc_type soc_type = qca_soc_type(hu);
 
+   hu->hdev->hw_error = NULL;
+   hu->hdev->cmd_timeout = NULL;
+
/* Stop sending shutdown command if soc crashes. */
if (soc_type != QCA_ROME
&& qca->memdump_state == QCA_MEMDUMP_IDLE) {
@@ -1848,7 +1850,6 @@ static int qca_power_off(struct hci_dev *hdev)
usleep_range(8000, 1);
}
 
-   qca->memdump_state = QCA_MEMDUMP_IDLE;
qca_power_shutdown(hu);
return 0;
 }
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v1] Bluetooth: hci_qca: Bug fixes for SSR

2020-07-11 Thread Venkata Lakshmi Narayana Gubba
1.During SSR for command time out if BT SoC goes to inresponsive
state, power cycling of BT SoC was not happening.Given the fix by
sending hw error event to reset the BT SoC.

2.If SSR is triggered then ignore the transmit data requests to
BT SoC until SSR is completed.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/hci_qca.c | 40 
 1 file changed, 36 insertions(+), 4 deletions(-)

diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 7e39546..bfebefa 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -72,7 +72,8 @@ enum qca_flags {
QCA_DROP_VENDOR_EVENT,
QCA_SUSPENDING,
QCA_MEMDUMP_COLLECTION,
-   QCA_HW_ERROR_EVENT
+   QCA_HW_ERROR_EVENT,
+   QCA_SSR_TRIGGERED
 };
 
 enum qca_capabilities {
@@ -854,6 +855,13 @@ static int qca_enqueue(struct hci_uart *hu, struct sk_buff 
*skb)
BT_DBG("hu %p qca enq skb %p tx_ibs_state %d", hu, skb,
   qca->tx_ibs_state);
 
+   if (test_bit(QCA_SSR_TRIGGERED, >flags)) {
+   /* As SSR is in progress,Ignore the packets */
+   bt_dev_dbg(hu->hdev, "SSR is in progress");
+   kfree_skb(skb);
+   return 0;
+   }
+
/* Prepend skb with frame type */
memcpy(skb_push(skb, 1), _skb_pkt_type(skb), 1);
 
@@ -1123,6 +1131,7 @@ static int qca_controller_memdump_event(struct hci_dev 
*hdev,
struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv;
 
+   set_bit(QCA_SSR_TRIGGERED, >flags);
skb_queue_tail(>rx_memdump_q, skb);
queue_work(qca->workqueue, >ctrl_memdump_evt);
 
@@ -1481,6 +1490,7 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code)
struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv;
 
+   set_bit(QCA_SSR_TRIGGERED, >flags);
set_bit(QCA_HW_ERROR_EVENT, >flags);
bt_dev_info(hdev, "mem_dump_status: %d", qca->memdump_state);
 
@@ -1529,10 +1539,30 @@ static void qca_cmd_timeout(struct hci_dev *hdev)
struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv;
 
-   if (qca->memdump_state == QCA_MEMDUMP_IDLE)
+   set_bit(QCA_SSR_TRIGGERED, >flags);
+   if (qca->memdump_state == QCA_MEMDUMP_IDLE) {
+   set_bit(QCA_MEMDUMP_COLLECTION, >flags);
qca_send_crashbuffer(hu);
-   else
-   bt_dev_info(hdev, "Dump collection is in process");
+   qca_wait_for_dump_collection(hdev);
+   } else if (qca->memdump_state == QCA_MEMDUMP_COLLECTING) {
+   /* Let us wait here until memory dump collected or
+* memory dump timer expired.
+*/
+   bt_dev_info(hdev, "waiting for dump to complete");
+   qca_wait_for_dump_collection(hdev);
+   }
+
+   mutex_lock(>hci_memdump_lock);
+   if (qca->memdump_state != QCA_MEMDUMP_COLLECTED) {
+   qca->memdump_state = QCA_MEMDUMP_TIMEOUT;
+   if (!test_bit(QCA_HW_ERROR_EVENT, >flags)) {
+   /* Inject hw error event to reset the device
+* and driver.
+*/
+   hci_reset_dev(hu->hdev);
+   }
+   }
+   mutex_unlock(>hci_memdump_lock);
 }
 
 static int qca_wcn3990_init(struct hci_uart *hu)
@@ -1643,6 +1673,8 @@ static int qca_setup(struct hci_uart *hu)
if (ret)
return ret;
 
+   clear_bit(QCA_SSR_TRIGGERED, >flags);
+
if (qca_is_wcn399x(soc_type)) {
set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, >quirks);
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v2] Bluetooth: hci_qca: Bug fix during SSR timeout

2020-06-09 Thread Venkata Lakshmi Narayana Gubba
Due to race conditions between qca_hw_error and qca_controller_memdump
during SSR timeout,the same pointer is freed twice. This results in a
double free. Now a lock is acquired before checking the stauts of SSR
state.

Fixes: d841502c79e3 ("Bluetooth: hci_qca: Collect controller memory dump during 
SSR")
Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/hci_qca.c | 29 +
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 28c34a1..f3fde99 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -981,8 +981,11 @@ static void qca_controller_memdump(struct work_struct 
*work)
while ((skb = skb_dequeue(>rx_memdump_q))) {
 
mutex_lock(>hci_memdump_lock);
-   /* Skip processing the received packets if timeout detected. */
-   if (qca->memdump_state == QCA_MEMDUMP_TIMEOUT) {
+   /* Skip processing the received packets if timeout detected
+* or memdump collection completed.
+*/
+   if (qca->memdump_state == QCA_MEMDUMP_TIMEOUT ||
+   qca->memdump_state == QCA_MEMDUMP_COLLECTED) {
mutex_unlock(>hci_memdump_lock);
return;
}
@@ -1483,8 +1486,6 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code)
 {
struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv;
-   struct qca_memdump_data *qca_memdump = qca->qca_memdump;
-   char *memdump_buf = NULL;
 
set_bit(QCA_HW_ERROR_EVENT, >flags);
bt_dev_info(hdev, "mem_dump_status: %d", qca->memdump_state);
@@ -1507,19 +1508,23 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code)
qca_wait_for_dump_collection(hdev);
}
 
+   mutex_lock(>hci_memdump_lock);
if (qca->memdump_state != QCA_MEMDUMP_COLLECTED) {
bt_dev_err(hu->hdev, "clearing allocated memory due to memdump 
timeout");
-   mutex_lock(>hci_memdump_lock);
-   if (qca_memdump)
-   memdump_buf = qca_memdump->memdump_buf_head;
-   vfree(memdump_buf);
-   kfree(qca_memdump);
-   qca->qca_memdump = NULL;
+   if (qca->qca_memdump) {
+   vfree(qca->qca_memdump->memdump_buf_head);
+   kfree(qca->qca_memdump);
+   qca->qca_memdump = NULL;
+   }
qca->memdump_state = QCA_MEMDUMP_TIMEOUT;
cancel_delayed_work(>ctrl_memdump_timeout);
-   skb_queue_purge(>rx_memdump_q);
-   mutex_unlock(>hci_memdump_lock);
+   }
+   mutex_unlock(>hci_memdump_lock);
+
+   if (qca->memdump_state == QCA_MEMDUMP_TIMEOUT ||
+   qca->memdump_state == QCA_MEMDUMP_COLLECTED) {
cancel_work_sync(>ctrl_memdump_evt);
+   skb_queue_purge(>rx_memdump_q);
}
 
clear_bit(QCA_HW_ERROR_EVENT, >flags);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation



[PATCH v1] Bluetooth: hci_qca: Fix double free during SSR timeout

2020-06-04 Thread Venkata Lakshmi Narayana Gubba
Due to race conditions between qca_hw_error and qca_controller_memdump
during SSR timeout,the same pointer is freed twice. Which results to
double free error. Now a lock is acquired while SSR state moved to timeout.

Signed-off-by: Venkata Lakshmi Narayana Gubba 
---
 drivers/bluetooth/hci_qca.c | 19 ++-
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 836949d..9110775 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -983,8 +983,11 @@ static void qca_controller_memdump(struct work_struct 
*work)
while ((skb = skb_dequeue(>rx_memdump_q))) {
 
mutex_lock(>hci_memdump_lock);
-   /* Skip processing the received packets if timeout detected. */
-   if (qca->memdump_state == QCA_MEMDUMP_TIMEOUT) {
+   /* Skip processing the received packets if timeout detected
+* or memdump collection completed.
+*/
+   if (qca->memdump_state == QCA_MEMDUMP_TIMEOUT ||
+   qca->memdump_state == QCA_MEMDUMP_COLLECTED) {
mutex_unlock(>hci_memdump_lock);
return;
}
@@ -1485,7 +1488,7 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code)
 {
struct hci_uart *hu = hci_get_drvdata(hdev);
struct qca_data *qca = hu->priv;
-   struct qca_memdump_data *qca_memdump = qca->qca_memdump;
+   struct qca_memdump_data *qca_memdump = NULL;
char *memdump_buf = NULL;
 
set_bit(QCA_HW_ERROR_EVENT, >flags);
@@ -1509,9 +1512,10 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code)
qca_wait_for_dump_collection(hdev);
}
 
+   mutex_lock(>hci_memdump_lock);
if (qca->memdump_state != QCA_MEMDUMP_COLLECTED) {
bt_dev_err(hu->hdev, "clearing allocated memory due to memdump 
timeout");
-   mutex_lock(>hci_memdump_lock);
+   qca_memdump = qca->qca_memdump;
if (qca_memdump)
memdump_buf = qca_memdump->memdump_buf_head;
vfree(memdump_buf);
@@ -1520,8 +1524,13 @@ static void qca_hw_error(struct hci_dev *hdev, u8 code)
qca->memdump_state = QCA_MEMDUMP_TIMEOUT;
cancel_delayed_work(>ctrl_memdump_timeout);
skb_queue_purge(>rx_memdump_q);
-   mutex_unlock(>hci_memdump_lock);
+   }
+   mutex_unlock(>hci_memdump_lock);
+
+   if (qca->memdump_state == QCA_MEMDUMP_TIMEOUT ||
+   qca->memdump_state == QCA_MEMDUMP_COLLECTED) {
cancel_work_sync(>ctrl_memdump_evt);
+   skb_queue_purge(>rx_memdump_q);
}
 
clear_bit(QCA_HW_ERROR_EVENT, >flags);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member 
of Code Aurora Forum, hosted by The Linux Foundation