Enable Bluetooth functionality for WCN3991
cover Enable Bluetooth functionality for WCN3991
These patches enables Bluetooth functinalties for new Qualcomm Bluetooth chip wnc3991. As this is latest chip with new features, along with some common features to old chip "qcom,qcawcn3991-bt". Major difference between old BT SoC's with WCN3991 is WCN3991 will not send any VSE for the VSC instead is sends the data on CC packet.
Balakrishna Godavarthi (2):
Bluetooth: btqca: Rename ROME specific variables to generic variables
Bluetooth: hci_qca: Add support for Qualcomm Bluetooth SoC WCN3991
drivers/bluetooth/btqca.c | 92 ++++++++++++++++++++++++++----------- drivers/bluetooth/btqca.h | 32 +++++++------ drivers/bluetooth/hci_qca.c | 16 ++++++- 3 files changed, 97 insertions(+), 43 deletions(-)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
PATCH 1/2 Bluetooth: btqca: Rename ROME specific variables to generic variables
Variables which are named with rome are commonly used for all the BT SoC's. Instead of continuing further, renamed them to generic name.
--- drivers/bluetooth/btqca.c | 28 ++++++++++++++-------------- drivers/bluetooth/btqca.h | 22 +++++++++++----------- 2 files changed, 25 insertions(+), 25 deletions(-)
drivers/bluetooth/btqca.c +14 -14
@@ -18,7 +18,7 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version) {struct sk_buff *skb;struct edl_event_hdr *edl; -struct rome_version *ver; +struct qca_btsoc_version *ver;char cmd;int err =0 ;
@@ -55,11 +55,11 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version) goto out; } - ver = (struct rome_version *)(edl->data); + ver = (struct qca_btsoc_version *)(edl->data);BT_DBG ("%s: Product:0x%08x" , hdev->name,le32_to_cpu (ver->product_id));BT_DBG ("%s: Patch :0x%08x" , hdev->name,le16_to_cpu (ver->patch_ver)); -BT_DBG ("%s: ROM :0x%08x" , hdev->name,le16_to_cpu (ver->rome_ver)); +BT_DBG ("%s: ROM :0x%08x" , hdev->name,le16_to_cpu (ver->rom_ver));BT_DBG ("%s: SOC :0x%08x" , hdev->name,le32_to_cpu (ver->soc_id));/* QCA chipset version can be decided by patch and SoC
@@ -67,7 +67,7 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version)* and lower 2 bytes from patch will be used. */ *soc_version = (le32_to_cpu (ver->soc_id) <<16 ) | - (le16_to_cpu (ver->rome_ver) &0x0000ffff ); + (le16_to_cpu (ver->rom_ver) &0x0000ffff );if (*soc_version ==0 ) err = -EILSEQ ;
@@ -121,7 +121,7 @@ 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 rome_config *config, +static void qca_tlv_check_data (struct qca_fw_config *config,const struct firmware *fw) {const u8 *data;
@@ -140,8 +140,8 @@ static void qca_tlv_check_data(struct rome_config *config,BT_DBG ("TLV Type\t\t : 0x%x" , type_len &0x000000ff );BT_DBG ("Length\t\t : %d bytes" , length); - config->dnld_mode =ROME_SKIP_EVT_NONE ; - config->dnld_type =ROME_SKIP_EVT_NONE ; + config->dnld_mode =QCA_SKIP_EVT_NONE ; + config->dnld_type =QCA_SKIP_EVT_NONE ;switch (config->type) {case TLV_TYPE_PATCH :
@@ -223,7 +223,7 @@ static void qca_tlv_check_data(struct rome_config *config, }static int qca_tlv_send_segment (struct hci_dev *hdev,int seg_size, -const u8 *data,enum rome_tlv_dnld_mode mode) +const u8 *data,enum qca_tlv_dnld_mode mode) {struct sk_buff *skb;struct edl_event_hdr *edl;
@@ -235,7 +235,7 @@ static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size, cmd[1 ] = seg_size;memcpy (cmd +2 , data, seg_size); -if (mode ==ROME_SKIP_EVT_VSE_CC || mode ==ROME_SKIP_EVT_VSE ) +if (mode ==QCA_SKIP_EVT_VSE_CC || mode ==QCA_SKIP_EVT_VSE )return __hci_cmd_send (hdev,EDL_PATCH_CMD_OPCODE , seg_size +2 , cmd);
@@ -301,7 +301,7 @@ static int qca_inject_cmd_complete_event(struct hci_dev *hdev) }static int qca_download_firmware (struct hci_dev *hdev, -struct rome_config *config) +struct qca_fw_config *config) {const struct firmware *fw;const u8 *segment;
@@ -328,7 +328,7 @@ static int qca_download_firmware(struct hci_dev *hdev, remain -= segsize;/* The last segment is always acked regardless download mode */ if (!remain || segsize <MAX_SIZE_PER_TLV_SEGMENT ) - config->dnld_mode =ROME_SKIP_EVT_NONE ; + config->dnld_mode =QCA_SKIP_EVT_NONE ; ret =qca_tlv_send_segment (hdev, segsize, segment, config->dnld_mode);
@@ -344,8 +344,8 @@ static int qca_download_firmware(struct hci_dev *hdev,* decrease the BT in initialization time. Here we will inject a command * complete event to avoid a command timeout error message. */ -if (config->dnld_type ==ROME_SKIP_EVT_VSE_CC || - config->dnld_type ==ROME_SKIP_EVT_VSE ) +if (config->dnld_type ==QCA_SKIP_EVT_VSE_CC || + config->dnld_type ==QCA_SKIP_EVT_VSE ) ret =qca_inject_cmd_complete_event (hdev); out:
@@ -382,7 +382,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, enum qca_btsoc_type soc_type, u32 soc_ver, const char *firmware_name) { - struct rome_config config; + struct qca_fw_config config;int err;u8 rom_ver =0 ;
drivers/bluetooth/btqca.h +11 -11
@@ -56,24 +56,24 @@ enum qca_baudrate {QCA_BAUDRATE_RESERVED }; -enum rome_tlv_dnld_mode { -ROME_SKIP_EVT_NONE , -ROME_SKIP_EVT_VSE , -ROME_SKIP_EVT_CC , -ROME_SKIP_EVT_VSE_CC +enum qca_tlv_dnld_mode { +QCA_SKIP_EVT_NONE , +QCA_SKIP_EVT_VSE , +QCA_SKIP_EVT_CC , +QCA_SKIP_EVT_VSE_CC }; -enum rome_tlv_type { +enum qca_tlv_type {TLV_TYPE_PATCH =1 ,TLV_TYPE_NVM }; -struct rome_config { +struct qca_fw_config {u8 type;char fwname[64 ];uint8_t user_baud_rate; -enum rome_tlv_dnld_mode dnld_mode; -enum rome_tlv_dnld_mode dnld_type; +enum qca_tlv_dnld_mode dnld_mode; +enum qca_tlv_dnld_mode dnld_type; };struct edl_event_hdr {
@@ -82,10 +82,10 @@ struct edl_event_hdr {__u8 data[0 ]; } __packed; -struct rome_version { +struct qca_btsoc_version {__le32 product_id;__le16 patch_ver; -__le16 rome_ver; +__le16 rom_ver;__le32 soc_id; } __packed;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
PATCH 2/2 Bluetooth: hci_qca: Add support for Qualcomm Bluetooth SoC WCN3991
In reply to Balakrishna GodavarthiThis patch add support for WCN3991 i.e. current values and fw download support.
--- drivers/bluetooth/btqca.c | 68 +++++++++++++++++++++++++++++-------- drivers/bluetooth/btqca.h | 10 ++++-- drivers/bluetooth/hci_qca.c | 16 +++++++-- 3 files changed, 74 insertions(+), 20 deletions(-)
drivers/bluetooth/btqca.c +53 -15
@@ -14,19 +14,33 @@#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,u32 *soc_version, +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 ; +u8 rlen =sizeof (*edl) +sizeof (*ver); +u8 rtype =EDL_APP_VER_RES_EVT ;bt_dev_dbg (hdev,"QCA Version Request" ); +/* Unlike other SoC's sending version command response as payload to +* VSE event. WCN3991 sends version command response as a payload to +* command complete event. +*/ +if (soc_type ==QCA_WCN3991 ) { + event_type =0 ; + rlen +=1 ; + rtype =EDL_PATCH_VER_REQ_CMD ; + } + cmd =EDL_PATCH_VER_REQ_CMD ; skb =__hci_cmd_sync_ev (hdev,EDL_PATCH_CMD_OPCODE ,EDL_PATCH_CMD_LEN , - &cmd,HCI_EV_VENDOR ,HCI_INIT_TIMEOUT ); + &cmd, event_type,HCI_INIT_TIMEOUT );if (IS_ERR (skb)) { err =PTR_ERR (skb); bt_dev_err(hdev, "Reading QCA version information failed (%d)",
@@ -34,7 +48,7 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version)return err; } -if (skb->len !=sizeof (*edl) +sizeof (*ver)) { +if (skb->len != rlen) {bt_dev_err (hdev,"QCA Version size mismatch len %d" , skb->len); err = -EILSEQ ; goto out;
@@ -48,13 +62,16 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version) }if (edl->cresp !=EDL_CMD_REQ_RES_EVT || - edl->rtype !=EDL_APP_VER_RES_EVT ) { + edl->rtype != rtype) {bt_dev_err (hdev,"QCA Wrong packet received %d %d" , edl->cresp, edl->rtype); err = -EIO ; goto out; } +if (soc_type ==QCA_WCN3991 ) +memcpy (&edl->data, &edl->data[1 ],sizeof (*ver)); + ver = (struct qca_btsoc_version *)(edl->data);BT_DBG ("%s: Product:0x%08x" , hdev->name,le32_to_cpu (ver->product_id));
@@ -223,13 +240,17 @@ static void qca_tlv_check_data(struct qca_fw_config *config, }static int qca_tlv_send_segment (struct hci_dev *hdev,int seg_size, -const u8 *data,enum qca_tlv_dnld_mode mode) +const u8 *data,enum qca_tlv_dnld_mode mode, +enum qca_btsoc_type soc_type) {struct sk_buff *skb;struct edl_event_hdr *edl;struct tlv_seg_resp *tlv_resp;u8 cmd[MAX_SIZE_PER_TLV_SEGMENT +2 ];int err =0 ; +u8 event_type =HCI_EV_VENDOR ; +u8 rlen = (sizeof (*edl) +sizeof (*tlv_resp)); +u8 rtype =EDL_TVL_DNLD_RES_EVT ; cmd[0 ] =EDL_PATCH_TLV_REQ_CMD ; cmd[1 ] = seg_size;
@@ -239,15 +260,25 @@ static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size,return __hci_cmd_send (hdev,EDL_PATCH_CMD_OPCODE , seg_size +2 , cmd); +/* Unlike other SoC's sending version command response as payload to +* VSE event. WCN3991 sends version command response as a payload to +* command complete event. +*/ +if (soc_type ==QCA_WCN3991 ) { + event_type =0 ; + rlen =sizeof (*edl); + rtype =EDL_PATCH_TLV_REQ_CMD ; + } + skb =__hci_cmd_sync_ev (hdev,EDL_PATCH_CMD_OPCODE , seg_size +2 , cmd, -HCI_EV_VENDOR ,HCI_INIT_TIMEOUT ); + event_type,HCI_INIT_TIMEOUT );if (IS_ERR (skb)) { err =PTR_ERR (skb);bt_dev_err (hdev,"QCA Failed to send TLV segment (%d)" , err);return err; } -if (skb->len !=sizeof (*edl) +sizeof (*tlv_resp)) { +if (skb->len != rlen) {bt_dev_err (hdev,"QCA TLV response size mismatch" ); err = -EILSEQ ; goto out;
@@ -260,13 +291,19 @@ static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size, goto out; } - tlv_resp = (struct tlv_seg_resp *)(edl->data); +if (edl->cresp !=EDL_CMD_REQ_RES_EVT || edl->rtype != rtype) { +bt_dev_err (hdev,"QCA TLV with error stat 0x%x rtype 0x%x" , + edl->cresp, edl->rtype); + err = -EIO ; + } -if (edl->cresp !=EDL_CMD_REQ_RES_EVT || - edl->rtype !=EDL_TVL_DNLD_RES_EVT || tlv_resp->result !=0x00 ) { +if (soc_type ==QCA_WCN3991 ) + goto out; + + tlv_resp = (struct tlv_seg_resp *)(edl->data); +if (tlv_resp->result) {bt_dev_err (hdev,"QCA TLV with error stat 0x%x rtype 0x%x (0x%x)" , edl->cresp, edl->rtype, tlv_resp->result); - err = -EIO ; } out:
@@ -301,7 +338,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) +struct qca_fw_config *config, +enum qca_btsoc_type soc_type) {const struct firmware *fw;const u8 *segment;
@@ -331,7 +369,7 @@ static int qca_download_firmware(struct hci_dev *hdev, config->dnld_mode =QCA_SKIP_EVT_NONE ; ret =qca_tlv_send_segment (hdev, segsize, segment, - config->dnld_mode); + config->dnld_mode, soc_type);if (ret) goto out;
@@ -405,7 +443,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, "qca/rampatch_%08x.bin", soc_ver); } - err =qca_download_firmware (hdev, &config); + err =qca_download_firmware (hdev, &config, soc_type);if (err <0 ) {bt_dev_err (hdev,"QCA Failed to download patch (%d)" , err);return err;
@@ -426,7 +464,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,snprintf (config.fwname,sizeof (config.fwname),"qca/nvm_%08x.bin" , soc_ver); - err =qca_download_firmware (hdev, &config); + err =qca_download_firmware (hdev, &config, soc_type);if (err <0 ) {bt_dev_err (hdev,"QCA Failed to download NVM (%d)" , err);return err;
drivers/bluetooth/btqca.h +7 -3
@@ -126,6 +126,7 @@ enum qca_btsoc_type {QCA_ROME ,QCA_WCN3990 ,QCA_WCN3998 , + QCA_WCN3991, };#if IS_ENABLED (CONFIG_BT_QCA )
@@ -134,12 +135,14 @@ 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,const char *firmware_name); -int qca_read_soc_version (struct hci_dev *hdev,u32 *soc_version); +int qca_read_soc_version (struct hci_dev *hdev,u32 *soc_version, +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);static inline bool qca_is_wcn399x (enum qca_btsoc_type soc_type) { -return soc_type ==QCA_WCN3990 || soc_type ==QCA_WCN3998 ; +return soc_type ==QCA_WCN3990 || soc_type ==QCA_WCN3998 || + soc_type ==QCA_WCN3991 ; }#else
@@ -155,7 +158,8 @@ static inline int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,return -EOPNOTSUPP ; } -static inline int qca_read_soc_version (struct hci_dev *hdev,u32 *soc_version) +static inline int qca_read_soc_version (struct hci_dev *hdev,u32 *soc_version, +enum qca_btsoc_type ) {return -EOPNOTSUPP ; }
drivers/bluetooth/hci_qca.c +14 -2
@@ -1288,7 +1288,7 @@ static int qca_setup(struct hci_uart *hu)if (ret)return ret; - ret =qca_read_soc_version (hdev, &soc_ver); + ret =qca_read_soc_version (hdev, &soc_ver, soc_type);if (ret)return ret; }else {
@@ -1308,7 +1308,7 @@ static int qca_setup(struct hci_uart *hu)if (!qca_is_wcn399x (soc_type)) {/* Get QCA version information */ - ret =qca_read_soc_version (hdev, &soc_ver); + ret =qca_read_soc_version (hdev, &soc_ver, soc_type);if (ret)return ret; }
@@ -1377,6 +1377,17 @@ static const struct qca_vreg_data qca_soc_data_wcn3998 = { .num_vregs = 4, }; +static const struct qca_vreg_data qca_soc_data_wcn3991 = { + .soc_type =QCA_WCN3991 , + .vregs = (struct qca_vreg []) { + {"vddio" ,15000 }, + {"vddxo" ,80000 }, + {"vddrf" ,300000 }, + {"vddch0" ,450000 }, + }, + .num_vregs =4 , +}; +static void qca_power_shutdown (struct hci_uart *hu) {struct qca_serdev *qcadev;
@@ -1663,6 +1674,7 @@ static const struct of_device_id qca_bluetooth_of_match[] = { { .compatible = "qcom,qca6174-bt" }, { .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data_wcn3990}, { .compatible = "qcom,wcn3998-bt", .data = &qca_soc_data_wcn3998}, + { .compatible = "qcom,wcn3991-bt", .data = &qca_soc_data_wcn3991}, {/* sentinel */ } };MODULE_DEVICE_TABLE (of, qca_bluetooth_of_match);
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
Re: [PATCH v1 2/2] Bluetooth: hci_qca: Add support for Qualcomm Bluetooth SoC WCN3991
Quoted 11 lines · Balakrishna Godavarthi
This patch add support for WCN3991 i.e. current values and fw download support.
Signed-off-by Balakrishna Godavarthi <[email protected]>--- drivers/bluetooth/btqca.c | 68 +++++++++++++++++++++++++++++-------- drivers/bluetooth/btqca.h | 10 ++++-- drivers/bluetooth/hci_qca.c | 16 +++++++-- 3 files changed, 74 insertions(+), 20 deletions(-)drivers/bluetooth/btqca.c +0
-0
[..]
Quoted 4 lines
drivers/bluetooth/btqca.c +0
-0@@ -48,13 +62,16 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version) } if (edl->cresp != EDL_CMD_REQ_RES_EVT ||
drivers/bluetooth/btqca.c int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version) · line 73
Quoted 10 lines
drivers/bluetooth/btqca.c +3
-1- edl->rtype != EDL_APP_VER_RES_EVT) { + edl->rtype != rtype) {bt_dev_err (hdev,"QCA Wrong packet received %d %d" , edl->cresp, edl->rtype); err = -EIO ; goto out; } +if (soc_type ==QCA_WCN3991 ) +memcpy (&edl->data, &edl->data[1 ],sizeof (*ver));
memcpy() shouldn't be used when the two memory regions are overlapping, use memmove() for this.
[..]
drivers/bluetooth/btqca.h enum qca_btsoc_type { · line 129
Quoted 9 lines
drivers/bluetooth/btqca.h +1
-0@@ -126,6 +126,7 @@ enum qca_btsoc_type {QCA_ROME ,QCA_WCN3990 ,QCA_WCN3998 , + QCA_WCN3991,
Please maintain sort order.
[..]
Quoted 1 line
drivers/bluetooth/hci_qca.c +0
-0
[..]
drivers/bluetooth/hci_qca.c static const struct of_device_id qca_bluetooth_of_match[] = { · line 1677
Quoted 5 lines
drivers/bluetooth/hci_qca.c +1
-0@@ -1663,6 +1674,7 @@ static const struct of_device_id qca_bluetooth_of_match[] = { { .compatible = "qcom,qca6174-bt" }, { .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data_wcn3990}, { .compatible = "qcom,wcn3998-bt", .data = &qca_soc_data_wcn3998}, + { .compatible = "qcom,wcn3991-bt", .data = &qca_soc_data_wcn3991},
Ditto
Regards,
Bjorn
Re: [PATCH v1 2/2] Bluetooth: hci_qca: Add support for Qualcomm Bluetooth SoC WCN3991
Hi Jorn,
Quoted 28 lines · Bjorn Andersson
Quoted 12 lines · Balakrishna Godavarthi
This patch add support for WCN3991 i.e. current values and fw download support.
Signed-off-by Balakrishna Godavarthi <[email protected]>--- drivers/bluetooth/btqca.c | 68 +++++++++++++++++++++++++++++-------- drivers/bluetooth/btqca.h | 10 ++++-- drivers/bluetooth/hci_qca.c | 16 +++++++-- 3 files changed, 74 insertions(+), 20 deletions(-)drivers/bluetooth/btqca.c +0
-0[..]
Quoted 13 lines
drivers/bluetooth/btqca.c +1
-1@@ -48,13 +62,16 @@ int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version) }if (edl->cresp !=EDL_CMD_REQ_RES_EVT || - edl->rtype !=EDL_APP_VER_RES_EVT ) { + edl->rtype != rtype) {bt_dev_err (hdev,"QCA Wrong packet received %d %d" , edl->cresp, edl->rtype); err = -EIO ; goto out; }
Quoted 6 lines
drivers/bluetooth/btqca.c int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version) · line 73
Quoted 2 lines
drivers/bluetooth/btqca.c +2
-0+if (soc_type ==QCA_WCN3991 ) +memcpy (&edl->data, &edl->data[1 ],sizeof (*ver));
memcpy()shouldn't be used when the two memory regions are overlapping, usememmove()for this.
[Bala]: will update
Quoted 13 lines
[..]
drivers/bluetooth/btqca.h enum qca_btsoc_type { · line 129
Quoted 9 lines
drivers/bluetooth/btqca.h +1
-0@@ -126,6 +126,7 @@ enum qca_btsoc_type {QCA_ROME ,QCA_WCN3990 ,QCA_WCN3998 , + QCA_WCN3991,Please maintain sort order.
[Bala]: will update
Quoted 12 lines
[..]
Quoted 1 line
drivers/bluetooth/hci_qca.c +0
-0[..]
drivers/bluetooth/hci_qca.c static const struct of_device_id · line 1678
Quoted 6 lines
drivers/bluetooth/hci_qca.c +1
-0@@ -1663,6 +1674,7 @@ static const struct of_device_id qca_bluetooth_of_match[] = { { .compatible = "qcom,qca6174-bt" }, { .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data_wcn3990}, { .compatible = "qcom,wcn3998-bt", .data = &qca_soc_data_wcn3998}, + { .compatible = "qcom,wcn3991-bt", .data = &qca_soc_data_wcn3991},Ditto
[Bala]: will update
Quoted 2 lines
Regards,
Bjorn
Signature · 2 lines
Regards Balakrishna.