diff mbox series

[v2] Bluetooth: btusb: Add Qualcomm Bluetooth SoC WCN6855 support

Message ID 20200914092744.17464-1-rjliao@codeaurora.org
State New
Headers show
Series [v2] Bluetooth: btusb: Add Qualcomm Bluetooth SoC WCN6855 support | expand

Commit Message

Rocky Liao Sept. 14, 2020, 9:27 a.m. UTC
This patch add support for WCN6855 i.e. patch and nvm download
support.

Signed-off-by: Rocky Liao <rjliao@codeaurora.org>
---
 drivers/bluetooth/btusb.c | 50 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 44 insertions(+), 6 deletions(-)

Comments

Rocky Liao Sept. 15, 2020, 9:29 a.m. UTC | #1
Hi Marcel,

在 2020-09-14 21:28,Marcel Holtmann 写道:
> Hi Rocky,

> 

>> This patch add support for WCN6855 i.e. patch and nvm download

>> support.

>> 

>> Signed-off-by: Rocky Liao <rjliao@codeaurora.org>

>> ---

>> drivers/bluetooth/btusb.c | 50 ++++++++++++++++++++++++++++++++++-----

>> 1 file changed, 44 insertions(+), 6 deletions(-)

>> 

>> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c

>> index fe80588c7bd3..789e8d5e829e 100644

>> --- a/drivers/bluetooth/btusb.c

>> +++ b/drivers/bluetooth/btusb.c

>> @@ -59,6 +59,7 @@ static struct usb_driver btusb_driver;

>> #define BTUSB_MEDIATEK		0x200000

>> #define BTUSB_WIDEBAND_SPEECH	0x400000

>> #define BTUSB_VALID_LE_STATES   0x800000

>> +#define BTUSB_QCA_WCN6855	0x1000000

>> 

>> static const struct usb_device_id btusb_table[] = {

>> 	/* Generic Bluetooth USB device */

>> @@ -273,6 +274,10 @@ static const struct usb_device_id 

>> blacklist_table[] = {

>> 	{ USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME },

>> 	{ USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME },

>> 

>> +	/* QCA WCN6855 chipset */

>> +	{ USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 |

>> +						     BTUSB_WIDEBAND_SPEECH },

>> +

>> 	/* Broadcom BCM2035 */

>> 	{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },

>> 	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },

>> @@ -3391,6 +3396,26 @@ static int btusb_set_bdaddr_ath3012(struct 

>> hci_dev *hdev,

>> 	return 0;

>> }

>> 

>> +static int btusb_set_bdaddr_wcn6855(struct hci_dev *hdev,

>> +				const bdaddr_t *bdaddr)

>> +{

>> +	struct sk_buff *skb;

>> +	u8 buf[6];

>> +	long ret;

>> +

>> +	memcpy(buf, bdaddr, sizeof(bdaddr_t));

>> +

>> +	skb = __hci_cmd_sync(hdev, 0xfc14, sizeof(buf), buf, 

>> HCI_INIT_TIMEOUT);

>> +	if (IS_ERR(skb)) {

>> +		ret = PTR_ERR(skb);

>> +		bt_dev_err(hdev, "Change address command failed (%ld)", ret);

>> +		return ret;

>> +	}

>> +	kfree_skb(skb);

>> +

>> +	return 0;

>> +}

>> +

>> #define QCA_DFU_PACKET_LEN	4096

>> 

>> #define QCA_GET_TARGET_VERSION	0x09

>> @@ -3428,6 +3453,8 @@ static const struct qca_device_info 

>> qca_devices_table[] = {

>> 	{ 0x00000201, 28, 4, 18 }, /* Rome 2.1 */

>> 	{ 0x00000300, 28, 4, 18 }, /* Rome 3.0 */

>> 	{ 0x00000302, 28, 4, 18 }, /* Rome 3.2 */

>> +	{ 0x00130100, 40, 4, 18 }, /* WCN6855 1.0 */

>> +	{ 0x00130200, 40, 4, 18 }  /* WCN6855 2.0 */

>> };

>> 

>> static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 

>> request,

>> @@ -3529,8 +3556,8 @@ static int btusb_setup_qca_load_rampatch(struct 

>> hci_dev *hdev,

>> {

>> 	struct qca_rampatch_version *rver;

>> 	const struct firmware *fw;

>> -	u32 ver_rom, ver_patch;

>> -	u16 rver_rom, rver_patch;

>> +	u32 ver_rom, ver_patch, rver_rom;

>> +	u16 rver_rom_low, rver_rom_high, rver_patch;

>> 	char fwname[64];

>> 	int err;

>> 

>> @@ -3549,9 +3576,16 @@ static int btusb_setup_qca_load_rampatch(struct 

>> hci_dev *hdev,

>> 	bt_dev_info(hdev, "using rampatch file: %s", fwname);

>> 

>> 	rver = (struct qca_rampatch_version *)(fw->data + info->ver_offset);

>> -	rver_rom = le16_to_cpu(rver->rom_version);

>> +	rver_rom_low = le16_to_cpu(rver->rom_version);

>> 	rver_patch = le16_to_cpu(rver->patch_version);

>> 

>> +	if (ver_rom & ~0xffffU) {

>> +		rver_rom_high = le16_to_cpu(*(__le16 *)(fw->data + 16));

>> +		rver_rom = le32_to_cpu(rver_rom_high << 16 | rver_rom_low);

>> +	} else {

>> +		rver_rom = (__force u32)rver_rom_low;

>> +	}

>> +

> 

> I don’t get this. Is anything wrong with get_unaligned_le32 etc.?

> 

> My brain just hurts with your casting and pointer magic. Maybe the

> whole rver logic needs a clean up first.

> 

It's not a 4 bytes le data, for example the version stream is 0x13, 
0x00, 0x00, 0x01 and we need to convert it to 0x00130100. So we have to 
convert it to 2 u16 value then combine them to a u32.

> Regards

> 

> Marcel
Marcel Holtmann Sept. 15, 2020, 1:57 p.m. UTC | #2
Hi Rocky,

>>> This patch add support for WCN6855 i.e. patch and nvm download

>>> support.

>>> Signed-off-by: Rocky Liao <rjliao@codeaurora.org>

>>> ---

>>> drivers/bluetooth/btusb.c | 50 ++++++++++++++++++++++++++++++++++-----

>>> 1 file changed, 44 insertions(+), 6 deletions(-)

>>> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c

>>> index fe80588c7bd3..789e8d5e829e 100644

>>> --- a/drivers/bluetooth/btusb.c

>>> +++ b/drivers/bluetooth/btusb.c

>>> @@ -59,6 +59,7 @@ static struct usb_driver btusb_driver;

>>> #define BTUSB_MEDIATEK		0x200000

>>> #define BTUSB_WIDEBAND_SPEECH	0x400000

>>> #define BTUSB_VALID_LE_STATES   0x800000

>>> +#define BTUSB_QCA_WCN6855	0x1000000

>>> static const struct usb_device_id btusb_table[] = {

>>> 	/* Generic Bluetooth USB device */

>>> @@ -273,6 +274,10 @@ static const struct usb_device_id blacklist_table[] = {

>>> 	{ USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME },

>>> 	{ USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME },

>>> +	/* QCA WCN6855 chipset */

>>> +	{ USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 |

>>> +						     BTUSB_WIDEBAND_SPEECH },

>>> +

>>> 	/* Broadcom BCM2035 */

>>> 	{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },

>>> 	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },

>>> @@ -3391,6 +3396,26 @@ static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev,

>>> 	return 0;

>>> }

>>> +static int btusb_set_bdaddr_wcn6855(struct hci_dev *hdev,

>>> +				const bdaddr_t *bdaddr)

>>> +{

>>> +	struct sk_buff *skb;

>>> +	u8 buf[6];

>>> +	long ret;

>>> +

>>> +	memcpy(buf, bdaddr, sizeof(bdaddr_t));

>>> +

>>> +	skb = __hci_cmd_sync(hdev, 0xfc14, sizeof(buf), buf, HCI_INIT_TIMEOUT);

>>> +	if (IS_ERR(skb)) {

>>> +		ret = PTR_ERR(skb);

>>> +		bt_dev_err(hdev, "Change address command failed (%ld)", ret);

>>> +		return ret;

>>> +	}

>>> +	kfree_skb(skb);

>>> +

>>> +	return 0;

>>> +}

>>> +

>>> #define QCA_DFU_PACKET_LEN	4096

>>> #define QCA_GET_TARGET_VERSION	0x09

>>> @@ -3428,6 +3453,8 @@ static const struct qca_device_info qca_devices_table[] = {

>>> 	{ 0x00000201, 28, 4, 18 }, /* Rome 2.1 */

>>> 	{ 0x00000300, 28, 4, 18 }, /* Rome 3.0 */

>>> 	{ 0x00000302, 28, 4, 18 }, /* Rome 3.2 */

>>> +	{ 0x00130100, 40, 4, 18 }, /* WCN6855 1.0 */

>>> +	{ 0x00130200, 40, 4, 18 }  /* WCN6855 2.0 */

>>> };

>>> static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request,

>>> @@ -3529,8 +3556,8 @@ static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,

>>> {

>>> 	struct qca_rampatch_version *rver;

>>> 	const struct firmware *fw;

>>> -	u32 ver_rom, ver_patch;

>>> -	u16 rver_rom, rver_patch;

>>> +	u32 ver_rom, ver_patch, rver_rom;

>>> +	u16 rver_rom_low, rver_rom_high, rver_patch;

>>> 	char fwname[64];

>>> 	int err;

>>> @@ -3549,9 +3576,16 @@ static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,

>>> 	bt_dev_info(hdev, "using rampatch file: %s", fwname);

>>> 	rver = (struct qca_rampatch_version *)(fw->data + info->ver_offset);

>>> -	rver_rom = le16_to_cpu(rver->rom_version);

>>> +	rver_rom_low = le16_to_cpu(rver->rom_version);

>>> 	rver_patch = le16_to_cpu(rver->patch_version);

>>> +	if (ver_rom & ~0xffffU) {

>>> +		rver_rom_high = le16_to_cpu(*(__le16 *)(fw->data + 16));

>>> +		rver_rom = le32_to_cpu(rver_rom_high << 16 | rver_rom_low);

>>> +	} else {

>>> +		rver_rom = (__force u32)rver_rom_low;

>>> +	}

>>> +

>> I don’t get this. Is anything wrong with get_unaligned_le32 etc.?

>> My brain just hurts with your casting and pointer magic. Maybe the

>> whole rver logic needs a clean up first.

> It's not a 4 bytes le data, for example the version stream is 0x13, 0x00, 0x00, 0x01 and we need to convert it to 0x00130100. So we have to convert it to 2 u16 value then combine them to a u32.


what is it then? Is it big endian formatted. If it is not a 32-bit value, then don’t store it as one.

Regards

Marcel
diff mbox series

Patch

diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index fe80588c7bd3..789e8d5e829e 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -59,6 +59,7 @@  static struct usb_driver btusb_driver;
 #define BTUSB_MEDIATEK		0x200000
 #define BTUSB_WIDEBAND_SPEECH	0x400000
 #define BTUSB_VALID_LE_STATES   0x800000
+#define BTUSB_QCA_WCN6855	0x1000000
 
 static const struct usb_device_id btusb_table[] = {
 	/* Generic Bluetooth USB device */
@@ -273,6 +274,10 @@  static const struct usb_device_id blacklist_table[] = {
 	{ USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME },
 	{ USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME },
 
+	/* QCA WCN6855 chipset */
+	{ USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 |
+						     BTUSB_WIDEBAND_SPEECH },
+
 	/* Broadcom BCM2035 */
 	{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
 	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
@@ -3391,6 +3396,26 @@  static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev,
 	return 0;
 }
 
+static int btusb_set_bdaddr_wcn6855(struct hci_dev *hdev,
+				const bdaddr_t *bdaddr)
+{
+	struct sk_buff *skb;
+	u8 buf[6];
+	long ret;
+
+	memcpy(buf, bdaddr, sizeof(bdaddr_t));
+
+	skb = __hci_cmd_sync(hdev, 0xfc14, sizeof(buf), buf, HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb)) {
+		ret = PTR_ERR(skb);
+		bt_dev_err(hdev, "Change address command failed (%ld)", ret);
+		return ret;
+	}
+	kfree_skb(skb);
+
+	return 0;
+}
+
 #define QCA_DFU_PACKET_LEN	4096
 
 #define QCA_GET_TARGET_VERSION	0x09
@@ -3428,6 +3453,8 @@  static const struct qca_device_info qca_devices_table[] = {
 	{ 0x00000201, 28, 4, 18 }, /* Rome 2.1 */
 	{ 0x00000300, 28, 4, 18 }, /* Rome 3.0 */
 	{ 0x00000302, 28, 4, 18 }, /* Rome 3.2 */
+	{ 0x00130100, 40, 4, 18 }, /* WCN6855 1.0 */
+	{ 0x00130200, 40, 4, 18 }  /* WCN6855 2.0 */
 };
 
 static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request,
@@ -3529,8 +3556,8 @@  static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
 {
 	struct qca_rampatch_version *rver;
 	const struct firmware *fw;
-	u32 ver_rom, ver_patch;
-	u16 rver_rom, rver_patch;
+	u32 ver_rom, ver_patch, rver_rom;
+	u16 rver_rom_low, rver_rom_high, rver_patch;
 	char fwname[64];
 	int err;
 
@@ -3549,9 +3576,16 @@  static int btusb_setup_qca_load_rampatch(struct hci_dev *hdev,
 	bt_dev_info(hdev, "using rampatch file: %s", fwname);
 
 	rver = (struct qca_rampatch_version *)(fw->data + info->ver_offset);
-	rver_rom = le16_to_cpu(rver->rom_version);
+	rver_rom_low = le16_to_cpu(rver->rom_version);
 	rver_patch = le16_to_cpu(rver->patch_version);
 
+	if (ver_rom & ~0xffffU) {
+		rver_rom_high = le16_to_cpu(*(__le16 *)(fw->data + 16));
+		rver_rom = le32_to_cpu(rver_rom_high << 16 | rver_rom_low);
+	} else {
+		rver_rom = (__force u32)rver_rom_low;
+	}
+
 	bt_dev_info(hdev, "QCA: patch rome 0x%x build 0x%x, "
 		    "firmware rome 0x%x build 0x%x",
 		    rver_rom, rver_patch, ver_rom, ver_patch);
@@ -3625,9 +3659,6 @@  static int btusb_setup_qca(struct hci_dev *hdev)
 		return err;
 
 	ver_rom = le32_to_cpu(ver.rom_version);
-	/* Don't care about high ROM versions */
-	if (ver_rom & ~0xffffU)
-		return 0;
 
 	for (i = 0; i < ARRAY_SIZE(qca_devices_table); i++) {
 		if (ver_rom == qca_devices_table[i].rom_version)
@@ -4063,6 +4094,13 @@  static int btusb_probe(struct usb_interface *intf,
 		btusb_check_needs_reset_resume(intf);
 	}
 
+	if (id->driver_info & BTUSB_QCA_WCN6855) {
+		data->setup_on_usb = btusb_setup_qca;
+		hdev->set_bdaddr = btusb_set_bdaddr_wcn6855;
+		hdev->cmd_timeout = btusb_qca_cmd_timeout;
+		set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
+	}
+
 	if (id->driver_info & BTUSB_AMP) {
 		/* AMP controllers do not support SCO packets */
 		data->isoc = NULL;