mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-14 15:54:15 +08:00
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Johan Hedberg says: ==================== pull request: bluetooth-next 2019-05-05 Here's one more bluetooth-next pull request for 5.2: - Fixed Command Complete event handling check for matching opcode - Added support for Qualcomm WCN3998 controller, along with DT bindings - Added default address for Broadcom BCM2076B1 controllers Please let me know if there are any issues pulling. Thanks. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
19ab5f4023
@ -11,20 +11,21 @@ Required properties:
|
||||
- compatible: should contain one of the following:
|
||||
* "qcom,qca6174-bt"
|
||||
* "qcom,wcn3990-bt"
|
||||
* "qcom,wcn3998-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)
|
||||
|
||||
Required properties for compatible string qcom,wcn3990-bt:
|
||||
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,wcn3990-bt:
|
||||
Optional properties for compatible string qcom,wcn399x-bt:
|
||||
|
||||
- max-speed: see Documentation/devicetree/bindings/serial/slave-device.txt
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}})
|
||||
#define BDADDR_BCM20702A1 (&(bdaddr_t) {{0x00, 0x00, 0xa0, 0x02, 0x70, 0x20}})
|
||||
#define BDADDR_BCM2076B1 (&(bdaddr_t) {{0x79, 0x56, 0x00, 0xa0, 0x76, 0x20}})
|
||||
#define BDADDR_BCM43430A0 (&(bdaddr_t) {{0xac, 0x1f, 0x12, 0xa0, 0x43, 0x43}})
|
||||
#define BDADDR_BCM4324B3 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb3, 0x24, 0x43}})
|
||||
#define BDADDR_BCM4330B1 (&(bdaddr_t) {{0x00, 0x00, 0x00, 0xb1, 0x30, 0x43}})
|
||||
@ -70,6 +71,9 @@ int btbcm_check_bdaddr(struct hci_dev *hdev)
|
||||
* The address 20:70:02:A0:00:00 indicates a BCM20702A1 controller
|
||||
* with no configured address.
|
||||
*
|
||||
* The address 20:76:A0:00:56:79 indicates a BCM2076B1 controller
|
||||
* with no configured address.
|
||||
*
|
||||
* The address 43:24:B3:00:00:00 indicates a BCM4324B3 controller
|
||||
* with waiting for configuration state.
|
||||
*
|
||||
@ -81,6 +85,7 @@ int btbcm_check_bdaddr(struct hci_dev *hdev)
|
||||
*/
|
||||
if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0) ||
|
||||
!bacmp(&bda->bdaddr, BDADDR_BCM20702A1) ||
|
||||
!bacmp(&bda->bdaddr, BDADDR_BCM2076B1) ||
|
||||
!bacmp(&bda->bdaddr, BDADDR_BCM4324B3) ||
|
||||
!bacmp(&bda->bdaddr, BDADDR_BCM4330B1) ||
|
||||
!bacmp(&bda->bdaddr, BDADDR_BCM43430A0) ||
|
||||
|
@ -336,7 +336,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
|
||||
{
|
||||
struct rome_config config;
|
||||
int err;
|
||||
u8 rom_ver;
|
||||
u8 rom_ver = 0;
|
||||
|
||||
bt_dev_dbg(hdev, "QCA setup on UART");
|
||||
|
||||
@ -344,7 +344,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
|
||||
|
||||
/* Download rampatch file */
|
||||
config.type = TLV_TYPE_PATCH;
|
||||
if (soc_type == QCA_WCN3990) {
|
||||
if (qca_is_wcn399x(soc_type)) {
|
||||
/* Firmware files to download are based on ROM version.
|
||||
* ROM version is derived from last two bytes of soc_ver.
|
||||
*/
|
||||
@ -365,7 +365,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
|
||||
|
||||
/* Download NVM configuration */
|
||||
config.type = TLV_TYPE_NVM;
|
||||
if (soc_type == QCA_WCN3990)
|
||||
if (qca_is_wcn399x(soc_type))
|
||||
snprintf(config.fwname, sizeof(config.fwname),
|
||||
"qca/crnv%02x.bin", rom_ver);
|
||||
else
|
||||
@ -410,6 +410,7 @@ int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qca_set_bdaddr);
|
||||
|
||||
|
||||
MODULE_AUTHOR("Ben Young Tae Kim <ytkim@qca.qualcomm.com>");
|
||||
MODULE_DESCRIPTION("Bluetooth support for Qualcomm Atheros family ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
|
@ -132,7 +132,8 @@ enum qca_btsoc_type {
|
||||
QCA_INVALID = -1,
|
||||
QCA_AR3002,
|
||||
QCA_ROME,
|
||||
QCA_WCN3990
|
||||
QCA_WCN3990,
|
||||
QCA_WCN3998,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_BT_QCA)
|
||||
@ -142,6 +143,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
|
||||
enum qca_btsoc_type soc_type, u32 soc_ver);
|
||||
int qca_read_soc_version(struct hci_dev *hdev, u32 *soc_version);
|
||||
int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
|
||||
static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
|
||||
{
|
||||
return soc_type == QCA_WCN3990 || soc_type == QCA_WCN3998;
|
||||
}
|
||||
#else
|
||||
|
||||
static inline int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
|
||||
@ -165,4 +170,8 @@ static inline int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline bool qca_is_wcn399x(enum qca_btsoc_type soc_type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
@ -54,9 +54,6 @@
|
||||
#define HCI_IBS_WAKE_ACK 0xFC
|
||||
#define HCI_MAX_IBS_SIZE 10
|
||||
|
||||
/* Controller states */
|
||||
#define STATE_IN_BAND_SLEEP_ENABLED 1
|
||||
|
||||
#define IBS_WAKE_RETRANS_TIMEOUT_MS 100
|
||||
#define IBS_TX_IDLE_TIMEOUT_MS 2000
|
||||
#define CMD_TRANS_TIMEOUT_MS 100
|
||||
@ -67,6 +64,10 @@
|
||||
/* Controller debug log header */
|
||||
#define QCA_DEBUG_HANDLE 0x2EDC
|
||||
|
||||
enum qca_flags {
|
||||
QCA_IBS_ENABLED,
|
||||
};
|
||||
|
||||
/* HCI_IBS transmit side sleep protocol states */
|
||||
enum tx_ibs_states {
|
||||
HCI_IBS_TX_ASLEEP,
|
||||
@ -521,7 +522,7 @@ static int qca_open(struct hci_uart *hu)
|
||||
if (hu->serdev) {
|
||||
|
||||
qcadev = serdev_device_get_drvdata(hu->serdev);
|
||||
if (qcadev->btsoc_type != QCA_WCN3990) {
|
||||
if (!qca_is_wcn399x(qcadev->btsoc_type)) {
|
||||
gpiod_set_value_cansleep(qcadev->bt_en, 1);
|
||||
/* Controller needs time to bootup. */
|
||||
msleep(150);
|
||||
@ -629,7 +630,7 @@ static int qca_close(struct hci_uart *hu)
|
||||
|
||||
if (hu->serdev) {
|
||||
qcadev = serdev_device_get_drvdata(hu->serdev);
|
||||
if (qcadev->btsoc_type == QCA_WCN3990)
|
||||
if (qca_is_wcn399x(qcadev->btsoc_type))
|
||||
qca_power_shutdown(hu);
|
||||
else
|
||||
gpiod_set_value_cansleep(qcadev->bt_en, 0);
|
||||
@ -792,7 +793,7 @@ static int qca_enqueue(struct hci_uart *hu, struct sk_buff *skb)
|
||||
/* Don't go to sleep in middle of patch download or
|
||||
* Out-Of-Band(GPIOs control) sleep is selected.
|
||||
*/
|
||||
if (!test_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags)) {
|
||||
if (!test_bit(QCA_IBS_ENABLED, &qca->flags)) {
|
||||
skb_queue_tail(&qca->txq, skb);
|
||||
spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
|
||||
return 0;
|
||||
@ -1011,7 +1012,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
|
||||
msecs_to_jiffies(CMD_TRANS_TIMEOUT_MS));
|
||||
|
||||
/* Give the controller time to process the request */
|
||||
if (qca_soc_type(hu) == QCA_WCN3990)
|
||||
if (qca_is_wcn399x(qca_soc_type(hu)))
|
||||
msleep(10);
|
||||
else
|
||||
msleep(300);
|
||||
@ -1087,7 +1088,7 @@ static unsigned int qca_get_speed(struct hci_uart *hu,
|
||||
|
||||
static int qca_check_speeds(struct hci_uart *hu)
|
||||
{
|
||||
if (qca_soc_type(hu) == QCA_WCN3990) {
|
||||
if (qca_is_wcn399x(qca_soc_type(hu))) {
|
||||
if (!qca_get_speed(hu, QCA_INIT_SPEED) &&
|
||||
!qca_get_speed(hu, QCA_OPER_SPEED))
|
||||
return -EINVAL;
|
||||
@ -1119,7 +1120,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
|
||||
/* Disable flow control for wcn3990 to deassert RTS while
|
||||
* changing the baudrate of chip and host.
|
||||
*/
|
||||
if (soc_type == QCA_WCN3990)
|
||||
if (qca_is_wcn399x(soc_type))
|
||||
hci_uart_set_flow_control(hu, true);
|
||||
|
||||
qca_baudrate = qca_get_baudrate_value(speed);
|
||||
@ -1131,7 +1132,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
|
||||
host_set_baudrate(hu, speed);
|
||||
|
||||
error:
|
||||
if (soc_type == QCA_WCN3990)
|
||||
if (qca_is_wcn399x(soc_type))
|
||||
hci_uart_set_flow_control(hu, false);
|
||||
}
|
||||
|
||||
@ -1202,9 +1203,9 @@ static int qca_setup(struct hci_uart *hu)
|
||||
return ret;
|
||||
|
||||
/* Patch downloading has to be done without IBS mode */
|
||||
clear_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags);
|
||||
clear_bit(QCA_IBS_ENABLED, &qca->flags);
|
||||
|
||||
if (soc_type == QCA_WCN3990) {
|
||||
if (qca_is_wcn399x(soc_type)) {
|
||||
bt_dev_info(hdev, "setting up wcn3990");
|
||||
|
||||
/* Enable NON_PERSISTENT_SETUP QUIRK to ensure to execute
|
||||
@ -1235,7 +1236,7 @@ static int qca_setup(struct hci_uart *hu)
|
||||
qca_baudrate = qca_get_baudrate_value(speed);
|
||||
}
|
||||
|
||||
if (soc_type != QCA_WCN3990) {
|
||||
if (!qca_is_wcn399x(soc_type)) {
|
||||
/* Get QCA version information */
|
||||
ret = qca_read_soc_version(hdev, &soc_ver);
|
||||
if (ret)
|
||||
@ -1246,7 +1247,7 @@ static int qca_setup(struct hci_uart *hu)
|
||||
/* Setup patch / NVM configurations */
|
||||
ret = qca_uart_setup(hdev, qca_baudrate, soc_type, soc_ver);
|
||||
if (!ret) {
|
||||
set_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags);
|
||||
set_bit(QCA_IBS_ENABLED, &qca->flags);
|
||||
qca_debugfs_init(hdev);
|
||||
} else if (ret == -ENOENT) {
|
||||
/* No patch/nvm-config found, run with original fw/config */
|
||||
@ -1260,7 +1261,7 @@ static int qca_setup(struct hci_uart *hu)
|
||||
}
|
||||
|
||||
/* Setup bdaddr */
|
||||
if (soc_type == QCA_WCN3990)
|
||||
if (qca_is_wcn399x(soc_type))
|
||||
hu->hdev->set_bdaddr = qca_set_bdaddr;
|
||||
else
|
||||
hu->hdev->set_bdaddr = qca_set_bdaddr_rome;
|
||||
@ -1283,7 +1284,7 @@ static struct hci_uart_proto qca_proto = {
|
||||
.dequeue = qca_dequeue,
|
||||
};
|
||||
|
||||
static const struct qca_vreg_data qca_soc_data = {
|
||||
static const struct qca_vreg_data qca_soc_data_wcn3990 = {
|
||||
.soc_type = QCA_WCN3990,
|
||||
.vregs = (struct qca_vreg []) {
|
||||
{ "vddio", 1800000, 1900000, 15000 },
|
||||
@ -1294,6 +1295,17 @@ static const struct qca_vreg_data qca_soc_data = {
|
||||
.num_vregs = 4,
|
||||
};
|
||||
|
||||
static const struct qca_vreg_data qca_soc_data_wcn3998 = {
|
||||
.soc_type = QCA_WCN3998,
|
||||
.vregs = (struct qca_vreg []) {
|
||||
{ "vddio", 1800000, 1900000, 10000 },
|
||||
{ "vddxo", 1800000, 1900000, 80000 },
|
||||
{ "vddrf", 1300000, 1352000, 300000 },
|
||||
{ "vddch0", 3300000, 3300000, 450000 },
|
||||
},
|
||||
.num_vregs = 4,
|
||||
};
|
||||
|
||||
static void qca_power_shutdown(struct hci_uart *hu)
|
||||
{
|
||||
struct qca_data *qca = hu->priv;
|
||||
@ -1304,7 +1316,7 @@ static void qca_power_shutdown(struct hci_uart *hu)
|
||||
* data in skb's.
|
||||
*/
|
||||
spin_lock_irqsave(&qca->hci_ibs_lock, flags);
|
||||
clear_bit(STATE_IN_BAND_SLEEP_ENABLED, &qca->flags);
|
||||
clear_bit(QCA_IBS_ENABLED, &qca->flags);
|
||||
qca_flush(hu);
|
||||
spin_unlock_irqrestore(&qca->hci_ibs_lock, flags);
|
||||
|
||||
@ -1427,8 +1439,8 @@ static int qca_serdev_probe(struct serdev_device *serdev)
|
||||
qcadev->serdev_hu.serdev = serdev;
|
||||
data = of_device_get_match_data(&serdev->dev);
|
||||
serdev_device_set_drvdata(serdev, qcadev);
|
||||
if (data && data->soc_type == QCA_WCN3990) {
|
||||
qcadev->btsoc_type = QCA_WCN3990;
|
||||
if (data && qca_is_wcn399x(data->soc_type)) {
|
||||
qcadev->btsoc_type = data->soc_type;
|
||||
qcadev->bt_power = devm_kzalloc(&serdev->dev,
|
||||
sizeof(struct qca_power),
|
||||
GFP_KERNEL);
|
||||
@ -1492,7 +1504,7 @@ static void qca_serdev_remove(struct serdev_device *serdev)
|
||||
{
|
||||
struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
|
||||
|
||||
if (qcadev->btsoc_type == QCA_WCN3990)
|
||||
if (qca_is_wcn399x(qcadev->btsoc_type))
|
||||
qca_power_shutdown(&qcadev->serdev_hu);
|
||||
else
|
||||
clk_disable_unprepare(qcadev->susclk);
|
||||
@ -1502,7 +1514,8 @@ static void qca_serdev_remove(struct serdev_device *serdev)
|
||||
|
||||
static const struct of_device_id qca_bluetooth_of_match[] = {
|
||||
{ .compatible = "qcom,qca6174-bt" },
|
||||
{ .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data},
|
||||
{ .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data_wcn3990},
|
||||
{ .compatible = "qcom,wcn3998-bt", .data = &qca_soc_data_wcn3998},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match);
|
||||
|
@ -282,6 +282,7 @@ enum {
|
||||
HCI_FORCE_BREDR_SMP,
|
||||
HCI_FORCE_STATIC_ADDR,
|
||||
HCI_LL_RPA_RESOLUTION,
|
||||
HCI_CMD_PENDING,
|
||||
|
||||
__HCI_NUM_FLAGS,
|
||||
};
|
||||
|
@ -4381,6 +4381,9 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status,
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we reach this point this event matches the last command sent */
|
||||
hci_dev_clear_flag(hdev, HCI_CMD_PENDING);
|
||||
|
||||
/* If the command succeeded and there's still more commands in
|
||||
* this request the request is not yet complete.
|
||||
*/
|
||||
@ -4491,6 +4494,8 @@ static void hci_cmd_work(struct work_struct *work)
|
||||
|
||||
hdev->sent_cmd = skb_clone(skb, GFP_KERNEL);
|
||||
if (hdev->sent_cmd) {
|
||||
if (hci_req_status_pend(hdev))
|
||||
hci_dev_set_flag(hdev, HCI_CMD_PENDING);
|
||||
atomic_dec(&hdev->cmd_cnt);
|
||||
hci_send_frame(hdev, skb);
|
||||
if (test_bit(HCI_RESET, &hdev->flags))
|
||||
|
@ -3404,6 +3404,12 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
|
||||
hci_req_cmd_complete(hdev, *opcode, *status, req_complete,
|
||||
req_complete_skb);
|
||||
|
||||
if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) {
|
||||
bt_dev_err(hdev,
|
||||
"unexpected event for opcode 0x%4.4x", *opcode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q))
|
||||
queue_work(hdev->workqueue, &hdev->cmd_work);
|
||||
}
|
||||
@ -3511,6 +3517,12 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb,
|
||||
hci_req_cmd_complete(hdev, *opcode, ev->status, req_complete,
|
||||
req_complete_skb);
|
||||
|
||||
if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) {
|
||||
bt_dev_err(hdev,
|
||||
"unexpected event for opcode 0x%4.4x", *opcode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q))
|
||||
queue_work(hdev->workqueue, &hdev->cmd_work);
|
||||
}
|
||||
|
@ -46,6 +46,11 @@ void hci_req_purge(struct hci_request *req)
|
||||
skb_queue_purge(&req->cmd_q);
|
||||
}
|
||||
|
||||
bool hci_req_status_pend(struct hci_dev *hdev)
|
||||
{
|
||||
return hdev->req_status == HCI_REQ_PEND;
|
||||
}
|
||||
|
||||
static int req_run(struct hci_request *req, hci_req_complete_t complete,
|
||||
hci_req_complete_skb_t complete_skb)
|
||||
{
|
||||
|
@ -37,6 +37,7 @@ struct hci_request {
|
||||
|
||||
void hci_req_init(struct hci_request *req, struct hci_dev *hdev);
|
||||
void hci_req_purge(struct hci_request *req);
|
||||
bool hci_req_status_pend(struct hci_dev *hdev);
|
||||
int hci_req_run(struct hci_request *req, hci_req_complete_t complete);
|
||||
int hci_req_run_skb(struct hci_request *req, hci_req_complete_skb_t complete);
|
||||
void hci_req_add(struct hci_request *req, u16 opcode, u32 plen,
|
||||
|
Loading…
Reference in New Issue
Block a user