mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-10-26 10:57:38 +08:00
QCC2072 has a Peripheral (PERI) subsystem to support the BT function
unit, the transport wire is owned by PERI and carries both BT-HCI and
PERI-HCI frames, as shown below:
_______________________________
USB I/F | internal link |
BTHOST -------- |---- PERI -------------- BT |
|_______________________________|
(other on-chip subsystems omitted)
PERI has its own command/event/ACL traffic, memdump, and firmware
(PATCH and NVM), all different from BT's own, and BTHOST needs to
interact with PERI directly.
To support multi-subsystem controllers, add btusb_qcom.c/.h as a new
transport-specific design:
- Multi-subsystem memdump collection.
- Generic PERI event handling, and sending a PERI frame then
syncing an event sequence.
- Downloading PERI firmware (rampatch and NVM).
- Recovery on command timeout or hardware error event.
BTW, it also supports BT-only chips.
/sys/kernel/debug/usb/devices:
T: Bus=03 Lev=02 Prnt=02 Port=02 Cnt=01 Dev#= 5 Spd=12 MxCh= 0
D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1
P: Vendor=0cf3 ProdID=ea00 Rev= 0.01
C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=81(I) Atr=03(Int.) MxPS= 64 Ivl=1ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms
I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms
I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms
I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms
I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms
I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
I: If#= 1 Alt= 6 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 63 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 63 Ivl=1ms
I: If#= 1 Alt= 7 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=83(I) Atr=01(Isoc) MxPS= 65 Ivl=1ms
E: Ad=03(O) Atr=01(Isoc) MxPS= 65 Ivl=1ms
Signed-off-by: Zijun Hu <zijun.hu@oss.qualcomm.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
100 lines
2.3 KiB
C
100 lines
2.3 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Qualcomm Bluetooth USB transport-specific support
|
|
*
|
|
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
|
*/
|
|
|
|
#ifndef __BTUSB_QCOM_H
|
|
#define __BTUSB_QCOM_H
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/skbuff.h>
|
|
#include <linux/usb.h>
|
|
|
|
#include <net/bluetooth/hci_core.h>
|
|
|
|
#define QPERI_COMMAND_PKT 0x31
|
|
#define QPERI_ACLDATA_PKT 0x32
|
|
#define QPERI_EVENT_PKT 0x34
|
|
|
|
struct btusb_qcom {
|
|
__u16 idVendor;
|
|
__u16 idProduct;
|
|
struct usb_device *udev;
|
|
struct usb_interface *intf;
|
|
struct gpio_desc *reset_gpio;
|
|
|
|
/* serializes sending BT and vendor frames to the transport */
|
|
struct mutex tx_mutex;
|
|
|
|
void (*prepare_reset)(struct hci_dev *hdev);
|
|
int (*recv_bt_frame)(struct hci_dev *hdev, struct sk_buff *skb);
|
|
int (*send_bt_frame)(struct hci_dev *hdev, struct sk_buff *skb);
|
|
int (*send_vendor_frame)(struct hci_dev *hdev, struct sk_buff *skb);
|
|
};
|
|
|
|
#if IS_ENABLED(CONFIG_BT_HCIBTUSB_QCOM)
|
|
|
|
int btusb_qcom_hdev_priv_size(void);
|
|
struct btusb_qcom *btusb_qcom_xport_data(struct hci_dev *hdev);
|
|
|
|
int btusb_qcom_setup(struct hci_dev *hdev);
|
|
int btusb_qcom_disconnect(struct hci_dev *hdev);
|
|
int btusb_qcom_send_frame(struct hci_dev *hdev, struct sk_buff *skb);
|
|
|
|
struct sk_buff *btusb_qcom_recv_intr(struct hci_dev *hdev, struct sk_buff *skb,
|
|
void *buffer, int count, int *err);
|
|
|
|
struct sk_buff *btusb_qcom_recv_bulk(struct hci_dev *hdev, struct sk_buff *skb,
|
|
void *buffer, int count, int *err);
|
|
|
|
#else
|
|
|
|
static inline int btusb_qcom_hdev_priv_size(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline struct btusb_qcom *btusb_qcom_xport_data(struct hci_dev *hdev)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static inline int btusb_qcom_setup(struct hci_dev *hdev)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int btusb_qcom_disconnect(struct hci_dev *hdev)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int btusb_qcom_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline struct sk_buff *btusb_qcom_recv_intr(struct hci_dev *hdev,
|
|
struct sk_buff *skb,
|
|
void *buffer, int count,
|
|
int *err)
|
|
{
|
|
*err = -EOPNOTSUPP;
|
|
return NULL;
|
|
}
|
|
|
|
static inline struct sk_buff *btusb_qcom_recv_bulk(struct hci_dev *hdev,
|
|
struct sk_buff *skb,
|
|
void *buffer, int count,
|
|
int *err)
|
|
{
|
|
*err = -EOPNOTSUPP;
|
|
return NULL;
|
|
}
|
|
|
|
#endif
|
|
#endif
|