mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 06:01:57 +00:00
bluetooth-next pull request for net-next:
- btusb: Add MediaTek MT7925-B22M support ID 0x13d3:0x3604 - btusb: Add Realtek RTL8852C support ID 0x0489:0xe122 - btrtl: Add the support for RTL8922A - btusb: Add 2 USB HW IDs for MT7925 (0xe118/e) - btnxpuart: Add support for ISO packets - btusb: Add Mediatek MT7925 support ID 0x13d3:0x3608 - btsdio: Do not bind to non-removable CYW4373 - hci_uart: Add support for Amlogic HCI UART -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE7E6oRXp8w05ovYr/9JCA4xAyCykFAmbjX78ZHGx1aXoudm9u LmRlbnR6QGludGVsLmNvbQAKCRD0kIDjEDILKV52D/kBW6yn3MSXX/pOUz0Hqwrp kbsetne4MtGdLOtGe5sSJn5e2Cd8FIPkF25vyEm0q6Xj6mttuLiP+JZJWHM/2DK/ 9U9uK6eYZeiAiSZCa16G0Ql0lJJ4i5tvTLiXwnmWbXEsw6HZPu0YwUGHgLseOU62 lnL1ujWtiM34vOWXWU0j/4BfIwyNh7gnYCeDwiCWqOa2Lvt7SotYMjYJVkcQ/DNw xjU9OUVKjW4XuE+VTtQNeoI3xr0DXXySbho+pUWcUFhUcMtMwdZRLyQQ4709Cv3Y 4IduIklug2ayRyYifTGzbYGMSF7K5VxRxPbdvI1JfYwnmz/k+fgZ5GVfEmnB7rLl 9Z5Ekidc1eTF3GB/Bx85T9tiFF3PvZQs+Zbik5Lsh/YHCoZ2RYVciCpCpNVriiMf 95bdFUCiPTB/dOxYGO81L6mi1HKvrr34B2AXDt4eV12ur7CujASOKpxi7hThbe6u exATswFkShB4lSuIRme6JkMy102JiFI18ICaMxN3RVUZWtCIJSs4Nyg187A6HsoV 0iIDfCAAU2Y0rPaEQ6YnDrJEawBM4vZdfFGlJtgfyA/sZM1lyPA8Ml7MCGYZNMA5 YFl3ZNz3tbkWyV6v1hRNJ6/bf/FkDqBnT0GBy3jpgW19YsozE6IGzzYkLKgUaCFs 7OdzSoRfmcShbtxSMFjSwQ== =ZAan -----END PGP SIGNATURE----- Merge tag 'for-net-next-2024-09-12' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next Luiz Augusto von Dentz says: ==================== bluetooth-next pull request for net-next: - btusb: Add MediaTek MT7925-B22M support ID 0x13d3:0x3604 - btusb: Add Realtek RTL8852C support ID 0x0489:0xe122 - btrtl: Add the support for RTL8922A - btusb: Add 2 USB HW IDs for MT7925 (0xe118/e) - btnxpuart: Add support for ISO packets - btusb: Add Mediatek MT7925 support ID 0x13d3:0x3608 - btsdio: Do not bind to non-removable CYW4373 - hci_uart: Add support for Amlogic HCI UART * tag 'for-net-next-2024-09-12' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next: (27 commits) Bluetooth: btintel_pcie: Allocate memory for driver private data Bluetooth: btusb: Fix not handling ZPL/short-transfer Bluetooth: btusb: Add 2 USB HW IDs for MT7925 (0xe118/e) Bluetooth: btsdio: Do not bind to non-removable CYW4373 Bluetooth: hci_sync: Ignore errors from HCI_OP_REMOTE_NAME_REQ_CANCEL Bluetooth: CMTP: Mark BT_CMTP as DEPRECATED Bluetooth: replace deprecated strncpy with strscpy_pad Bluetooth: hci_core: Fix sending MGMT_EV_CONNECT_FAILED Bluetooth: btrtl: Set msft ext address filter quirk for RTL8852B Bluetooth: Use led_set_brightness() in LED trigger activate() callback Bluetooth: btrtl: Use kvmemdup to simplify the code Bluetooth: btusb: Add Mediatek MT7925 support ID 0x13d3:0x3608 Bluetooth: btrtl: Add the support for RTL8922A Bluetooth: hci_ldisc: Use speed set by btattach as oper_speed Bluetooth: hci_conn: Remove redundant memset after kzalloc Bluetooth: L2CAP: Remove unused declarations dt-bindings: bluetooth: bring the HW description closer to reality for wcn6855 Bluetooth: btnxpuart: Add support for ISO packets Bluetooth: hci_h4: Add support for ISO packets in h4_recv.h Bluetooth: btusb: Add Realtek RTL8852C support ID 0x0489:0xe122 ... ==================== Link: https://patch.msgid.link/20240912214317.3054060-1-luiz.dentz@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
ef17c3d22c
@ -0,0 +1,63 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (C) 2024 Amlogic, Inc. All rights reserved
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/bluetooth/amlogic,w155s2-bt.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Amlogic Bluetooth chips
|
||||
|
||||
description:
|
||||
The W155S2 is an Amlogic Bluetooth and Wi-Fi combo chip. It works on
|
||||
the standard H4 protocol via a 4-wire UART interface, with baud rates
|
||||
up to 4 Mbps.
|
||||
|
||||
maintainers:
|
||||
- Yang Li <yang.li@amlogic.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- amlogic,w265s1-bt
|
||||
- amlogic,w265p1-bt
|
||||
- const: amlogic,w155s2-bt
|
||||
- enum:
|
||||
- amlogic,w155s2-bt
|
||||
- amlogic,w265s2-bt
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
description: clock provided to the controller (32.768KHz)
|
||||
|
||||
enable-gpios:
|
||||
maxItems: 1
|
||||
|
||||
vddio-supply:
|
||||
description: VDD_IO supply regulator handle
|
||||
|
||||
firmware-name:
|
||||
maxItems: 1
|
||||
description: specify the path of firmware bin to load
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- clocks
|
||||
- enable-gpios
|
||||
- vddio-supply
|
||||
- firmware-name
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
bluetooth {
|
||||
compatible = "amlogic,w155s2-bt";
|
||||
clocks = <&extclk>;
|
||||
enable-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
|
||||
vddio-supply = <&wcn_3v3>;
|
||||
firmware-name = "amlogic/aml_w155s2_bt_uart.bin";
|
||||
};
|
||||
|
@ -172,14 +172,14 @@ allOf:
|
||||
- qcom,wcn6855-bt
|
||||
then:
|
||||
required:
|
||||
- enable-gpios
|
||||
- swctrl-gpios
|
||||
- vddio-supply
|
||||
- vddbtcxmx-supply
|
||||
- vddrfacmn-supply
|
||||
- vddaon-supply
|
||||
- vddwlcx-supply
|
||||
- vddwlmx-supply
|
||||
- vddbtcmx-supply
|
||||
- vddrfa0p8-supply
|
||||
- vddrfa1p2-supply
|
||||
- vddrfa1p7-supply
|
||||
- vddrfa1p8-supply
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
@ -1153,6 +1153,13 @@ S: Supported
|
||||
F: arch/arm64/boot/dts/amd/amd-seattle-xgbe*.dtsi
|
||||
F: drivers/net/ethernet/amd/xgbe/
|
||||
|
||||
AMLOGIC BLUETOOTH DRIVER
|
||||
M: Yang Li <yang.li@amlogic.com>
|
||||
L: linux-bluetooth@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/bluetooth/amlogic,w155s2-bt.yaml
|
||||
F: drivers/bluetooth/hci_aml.c
|
||||
|
||||
AMLOGIC DDR PMU DRIVER
|
||||
M: Jiucheng Xu <jiucheng.xu@amlogic.com>
|
||||
L: linux-amlogic@lists.infradead.org
|
||||
|
@ -274,6 +274,18 @@ config BT_HCIUART_MRVL
|
||||
|
||||
Say Y here to compile support for HCI MRVL protocol.
|
||||
|
||||
config BT_HCIUART_AML
|
||||
bool "Amlogic protocol support"
|
||||
depends on BT_HCIUART
|
||||
depends on BT_HCIUART_SERDEV
|
||||
select BT_HCIUART_H4
|
||||
select FW_LOADER
|
||||
help
|
||||
The Amlogic protocol support enables Bluetooth HCI over serial
|
||||
port interface for Amlogic Bluetooth controllers.
|
||||
|
||||
Say Y here to compile support for HCI AML protocol.
|
||||
|
||||
config BT_HCIBCM203X
|
||||
tristate "HCI BCM203x USB driver"
|
||||
depends on USB
|
||||
|
@ -51,4 +51,5 @@ hci_uart-$(CONFIG_BT_HCIUART_BCM) += hci_bcm.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_QCA) += hci_qca.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_AG6XX) += hci_ag6xx.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_MRVL) += hci_mrvl.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_AML) += hci_aml.o
|
||||
hci_uart-objs := $(hci_uart-y)
|
||||
|
@ -46,6 +46,7 @@ MODULE_DEVICE_TABLE(pci, btintel_pcie_table);
|
||||
#define BTINTEL_PCIE_HCI_ACL_PKT 0x00000002
|
||||
#define BTINTEL_PCIE_HCI_SCO_PKT 0x00000003
|
||||
#define BTINTEL_PCIE_HCI_EVT_PKT 0x00000004
|
||||
#define BTINTEL_PCIE_HCI_ISO_PKT 0x00000005
|
||||
|
||||
static inline void ipc_print_ia_ring(struct hci_dev *hdev, struct ia *ia,
|
||||
u16 queue_num)
|
||||
@ -423,6 +424,18 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
|
||||
goto exit_error;
|
||||
}
|
||||
break;
|
||||
|
||||
case BTINTEL_PCIE_HCI_ISO_PKT:
|
||||
if (skb->len >= HCI_ISO_HDR_SIZE) {
|
||||
plen = HCI_ISO_HDR_SIZE + __le16_to_cpu(hci_iso_hdr(skb)->dlen);
|
||||
pkt_type = HCI_ISODATA_PKT;
|
||||
} else {
|
||||
bt_dev_err(hdev, "ISO packet is too short");
|
||||
ret = -EILSEQ;
|
||||
goto exit_error;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
bt_dev_err(hdev, "Invalid packet type received: 0x%4.4x",
|
||||
pcie_pkt_type);
|
||||
@ -1082,6 +1095,9 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev,
|
||||
type = BTINTEL_PCIE_HCI_SCO_PKT;
|
||||
hdev->stat.sco_tx++;
|
||||
break;
|
||||
case HCI_ISODATA_PKT:
|
||||
type = BTINTEL_PCIE_HCI_ISO_PKT;
|
||||
break;
|
||||
default:
|
||||
bt_dev_err(hdev, "Unknown HCI packet type");
|
||||
return -EILSEQ;
|
||||
@ -1208,7 +1224,7 @@ static int btintel_pcie_setup_hdev(struct btintel_pcie_data *data)
|
||||
int err;
|
||||
struct hci_dev *hdev;
|
||||
|
||||
hdev = hci_alloc_dev();
|
||||
hdev = hci_alloc_dev_priv(sizeof(struct btintel_data));
|
||||
if (!hdev)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1412,6 +1412,7 @@ static const struct h4_recv_pkt nxp_recv_pkts[] = {
|
||||
{ H4_RECV_ACL, .recv = hci_recv_frame },
|
||||
{ H4_RECV_SCO, .recv = hci_recv_frame },
|
||||
{ H4_RECV_EVENT, .recv = hci_recv_frame },
|
||||
{ H4_RECV_ISO, .recv = hci_recv_frame },
|
||||
{ NXP_RECV_CHIP_VER_V1, .recv = nxp_recv_chip_ver_v1 },
|
||||
{ NXP_RECV_FW_REQ_V1, .recv = nxp_recv_fw_req_v1 },
|
||||
{ NXP_RECV_CHIP_VER_V3, .recv = nxp_recv_chip_ver_v3 },
|
||||
|
@ -30,6 +30,7 @@
|
||||
#define RTL_ROM_LMP_8822B 0x8822
|
||||
#define RTL_ROM_LMP_8852A 0x8852
|
||||
#define RTL_ROM_LMP_8851B 0x8851
|
||||
#define RTL_ROM_LMP_8922A 0x8922
|
||||
#define RTL_CONFIG_MAGIC 0x8723ab55
|
||||
|
||||
#define RTL_VSC_OP_COREDUMP 0xfcff
|
||||
@ -69,6 +70,7 @@ enum btrtl_chip_id {
|
||||
CHIP_ID_8852B = 20,
|
||||
CHIP_ID_8852C = 25,
|
||||
CHIP_ID_8851B = 36,
|
||||
CHIP_ID_8922A = 44,
|
||||
CHIP_ID_8852BT = 47,
|
||||
};
|
||||
|
||||
@ -309,6 +311,15 @@ static const struct id_table ic_id_table[] = {
|
||||
.cfg_name = "rtl_bt/rtl8851bu_config",
|
||||
.hw_info = "rtl8851bu" },
|
||||
|
||||
/* 8922A */
|
||||
{ IC_INFO(RTL_ROM_LMP_8922A, 0xa, 0xc, HCI_USB),
|
||||
.config_needed = false,
|
||||
.has_rom_version = true,
|
||||
.has_msft_ext = true,
|
||||
.fw_name = "rtl_bt/rtl8922au_fw",
|
||||
.cfg_name = "rtl_bt/rtl8922au_config",
|
||||
.hw_info = "rtl8922au" },
|
||||
|
||||
/* 8852BT/8852BE-VT */
|
||||
{ IC_INFO(RTL_ROM_LMP_8852A, 0x87, 0xc, HCI_USB),
|
||||
.config_needed = false,
|
||||
@ -655,6 +666,7 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev,
|
||||
{ RTL_ROM_LMP_8852A, 20 }, /* 8852B */
|
||||
{ RTL_ROM_LMP_8852A, 25 }, /* 8852C */
|
||||
{ RTL_ROM_LMP_8851B, 36 }, /* 8851B */
|
||||
{ RTL_ROM_LMP_8922A, 44 }, /* 8922A */
|
||||
{ RTL_ROM_LMP_8852A, 47 }, /* 8852BT */
|
||||
};
|
||||
|
||||
@ -878,10 +890,8 @@ static int rtl_load_file(struct hci_dev *hdev, const char *name, u8 **buff)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = fw->size;
|
||||
*buff = kvmalloc(fw->size, GFP_KERNEL);
|
||||
if (*buff)
|
||||
memcpy(*buff, fw->data, ret);
|
||||
else
|
||||
*buff = kvmemdup(fw->data, fw->size, GFP_KERNEL);
|
||||
if (!*buff)
|
||||
ret = -ENOMEM;
|
||||
|
||||
release_firmware(fw);
|
||||
@ -1255,6 +1265,7 @@ int btrtl_download_firmware(struct hci_dev *hdev,
|
||||
case RTL_ROM_LMP_8852A:
|
||||
case RTL_ROM_LMP_8703B:
|
||||
case RTL_ROM_LMP_8851B:
|
||||
case RTL_ROM_LMP_8922A:
|
||||
err = btrtl_setup_rtl8723b(hdev, btrtl_dev);
|
||||
break;
|
||||
default:
|
||||
@ -1286,6 +1297,7 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev)
|
||||
case CHIP_ID_8852B:
|
||||
case CHIP_ID_8852C:
|
||||
case CHIP_ID_8851B:
|
||||
case CHIP_ID_8922A:
|
||||
case CHIP_ID_8852BT:
|
||||
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
|
||||
|
||||
@ -1296,6 +1308,7 @@ void btrtl_set_quirks(struct hci_dev *hdev, struct btrtl_device_info *btrtl_dev)
|
||||
btrealtek_set_flag(hdev, REALTEK_ALT6_CONTINUOUS_TX_CHIP);
|
||||
|
||||
if (btrtl_dev->project_id == CHIP_ID_8852A ||
|
||||
btrtl_dev->project_id == CHIP_ID_8852B ||
|
||||
btrtl_dev->project_id == CHIP_ID_8852C)
|
||||
set_bit(HCI_QUIRK_USE_MSFT_EXT_ADDRESS_FILTER, &hdev->quirks);
|
||||
|
||||
@ -1528,3 +1541,5 @@ MODULE_FIRMWARE("rtl_bt/rtl8852btu_config.bin");
|
||||
MODULE_FIRMWARE("rtl_bt/rtl8852cu_fw.bin");
|
||||
MODULE_FIRMWARE("rtl_bt/rtl8852cu_fw_v2.bin");
|
||||
MODULE_FIRMWARE("rtl_bt/rtl8852cu_config.bin");
|
||||
MODULE_FIRMWARE("rtl_bt/rtl8922au_fw.bin");
|
||||
MODULE_FIRMWARE("rtl_bt/rtl8922au_config.bin");
|
||||
|
@ -295,6 +295,7 @@ static int btsdio_probe(struct sdio_func *func,
|
||||
case SDIO_DEVICE_ID_BROADCOM_4345:
|
||||
case SDIO_DEVICE_ID_BROADCOM_43455:
|
||||
case SDIO_DEVICE_ID_BROADCOM_4356:
|
||||
case SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373:
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ static struct usb_driver btusb_driver;
|
||||
#define BTUSB_CW6622 BIT(19)
|
||||
#define BTUSB_MEDIATEK BIT(20)
|
||||
#define BTUSB_WIDEBAND_SPEECH BIT(21)
|
||||
#define BTUSB_VALID_LE_STATES BIT(22)
|
||||
#define BTUSB_INVALID_LE_STATES BIT(22)
|
||||
#define BTUSB_QCA_WCN6855 BIT(23)
|
||||
#define BTUSB_INTEL_BROKEN_SHUTDOWN_LED BIT(24)
|
||||
#define BTUSB_INTEL_BROKEN_INITIAL_NCMD BIT(25)
|
||||
@ -298,115 +298,79 @@ static const struct usb_device_id quirks_table[] = {
|
||||
|
||||
/* QCA WCN6855 chipset */
|
||||
{ USB_DEVICE(0x0cf3, 0xe600), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0cc), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0d6), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0e3), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x10ab, 0x9309), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x10ab, 0x9409), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0d0), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x10ab, 0x9108), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x10ab, 0x9109), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x10ab, 0x9208), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x10ab, 0x9209), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x10ab, 0x9308), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x10ab, 0x9408), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x10ab, 0x9508), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x10ab, 0x9509), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x10ab, 0x9608), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x10ab, 0x9609), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x10ab, 0x9f09), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x04ca, 0x3022), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0c7), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0c9), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0ca), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0cb), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0ce), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0de), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0df), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0e1), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0ea), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0ec), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x04ca, 0x3023), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x04ca, 0x3024), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x04ca, 0x3a22), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x04ca, 0x3a24), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x04ca, 0x3a26), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x04ca, 0x3a27), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* QCA WCN785x chipset */
|
||||
{ USB_DEVICE(0x0cf3, 0xe700), .driver_info = BTUSB_QCA_WCN6855 |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* Broadcom BCM2035 */
|
||||
{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
|
||||
@ -540,6 +504,8 @@ static const struct usb_device_id quirks_table[] = {
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3592), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe122), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* Realtek 8852BE Bluetooth devices */
|
||||
{ USB_DEVICE(0x0cb8, 0xc559), .driver_info = BTUSB_REALTEK |
|
||||
@ -564,6 +530,17 @@ static const struct usb_device_id quirks_table[] = {
|
||||
/* Realtek 8852BT/8852BE-VT Bluetooth devices */
|
||||
{ USB_DEVICE(0x0bda, 0x8520), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* Realtek 8922AE Bluetooth devices */
|
||||
{ USB_DEVICE(0x0bda, 0x8922), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3617), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3616), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe130), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* Realtek Bluetooth devices */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01),
|
||||
.driver_info = BTUSB_REALTEK },
|
||||
@ -571,131 +548,102 @@ static const struct usb_device_id quirks_table[] = {
|
||||
/* MediaTek Bluetooth devices */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x0e8d, 0xe0, 0x01, 0x01),
|
||||
.driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* Additional MediaTek MT7615E Bluetooth devices */
|
||||
{ USB_DEVICE(0x13d3, 0x3560), .driver_info = BTUSB_MEDIATEK},
|
||||
|
||||
/* Additional MediaTek MT7663 Bluetooth devices */
|
||||
{ USB_DEVICE(0x043e, 0x310c), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x04ca, 0x3801), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* Additional MediaTek MT7668 Bluetooth devices */
|
||||
{ USB_DEVICE(0x043e, 0x3109), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* Additional MediaTek MT7921 Bluetooth devices */
|
||||
{ USB_DEVICE(0x0489, 0xe0c8), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0cd), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0e0), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0f2), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x04ca, 0x3802), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0e8d, 0x0608), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3563), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3564), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3567), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3578), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3583), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3606), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* MediaTek MT7922 Bluetooth devices */
|
||||
{ USB_DEVICE(0x13d3, 0x3585), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* MediaTek MT7922A Bluetooth devices */
|
||||
{ USB_DEVICE(0x0489, 0xe0d8), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0d9), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0e2), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0e4), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0f1), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0f2), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0f5), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe0f6), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe102), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x04ca, 0x3804), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x04ca, 0x38e4), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3568), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3605), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3607), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3614), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3615), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x35f5, 0x7922), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* Additional MediaTek MT7925 Bluetooth devices */
|
||||
{ USB_DEVICE(0x0489, 0xe113), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe118), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x0489, 0xe11e), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3602), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3603), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH |
|
||||
BTUSB_VALID_LE_STATES },
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3604), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
{ USB_DEVICE(0x13d3, 0x3608), .driver_info = BTUSB_MEDIATEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* Additional Realtek 8723AE Bluetooth devices */
|
||||
{ USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
|
||||
@ -1397,7 +1345,10 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
|
||||
size = le16_to_cpu(data->intr_ep->wMaxPacketSize);
|
||||
/* Use maximum HCI Event size so the USB stack handles
|
||||
* ZPL/short-transfer automatically.
|
||||
*/
|
||||
size = HCI_MAX_EVENT_SIZE;
|
||||
|
||||
buf = kmalloc(size, mem_flags);
|
||||
if (!buf) {
|
||||
@ -3956,7 +3907,7 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
if (id->driver_info & BTUSB_WIDEBAND_SPEECH)
|
||||
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
|
||||
|
||||
if (!(id->driver_info & BTUSB_VALID_LE_STATES))
|
||||
if (id->driver_info & BTUSB_INVALID_LE_STATES)
|
||||
set_bit(HCI_QUIRK_BROKEN_LE_STATES, &hdev->quirks);
|
||||
|
||||
if (id->driver_info & BTUSB_DIGIANSWER) {
|
||||
|
@ -38,6 +38,13 @@ struct h4_recv_pkt {
|
||||
.lsize = 1, \
|
||||
.maxlen = HCI_MAX_EVENT_SIZE
|
||||
|
||||
#define H4_RECV_ISO \
|
||||
.type = HCI_ISODATA_PKT, \
|
||||
.hlen = HCI_ISO_HDR_SIZE, \
|
||||
.loff = 2, \
|
||||
.lsize = 2, \
|
||||
.maxlen = HCI_MAX_FRAME_SIZE
|
||||
|
||||
static inline struct sk_buff *h4_recv_buf(struct hci_dev *hdev,
|
||||
struct sk_buff *skb,
|
||||
const unsigned char *buffer,
|
||||
|
755
drivers/bluetooth/hci_aml.c
Normal file
755
drivers/bluetooth/hci_aml.c
Normal file
@ -0,0 +1,755 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
|
||||
/*
|
||||
* Copyright (C) 2024 Amlogic, Inc. All rights reserved
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/serdev.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
#include <net/bluetooth/hci.h>
|
||||
|
||||
#include "hci_uart.h"
|
||||
|
||||
#define AML_EVT_HEAD_SIZE 4
|
||||
#define AML_BDADDR_DEFAULT (&(bdaddr_t) {{ 0x00, 0xff, 0x00, 0x22, 0x2d, 0xae }})
|
||||
|
||||
#define AML_FIRMWARE_OPERATION_SIZE (248)
|
||||
#define AML_FIRMWARE_MAX_SIZE (512 * 1024)
|
||||
|
||||
/* TCI command */
|
||||
#define AML_TCI_CMD_READ 0xFEF0
|
||||
#define AML_TCI_CMD_WRITE 0xFEF1
|
||||
#define AML_TCI_CMD_UPDATE_BAUDRATE 0xFEF2
|
||||
#define AML_TCI_CMD_HARDWARE_RESET 0xFEF2
|
||||
#define AML_TCI_CMD_DOWNLOAD_BT_FW 0xFEF3
|
||||
|
||||
/* Vendor command */
|
||||
#define AML_BT_HCI_VENDOR_CMD 0xFC1A
|
||||
|
||||
/* TCI operation parameter in controller chip */
|
||||
#define AML_OP_UART_MODE 0x00A30128
|
||||
#define AML_OP_EVT_ENABLE 0x00A70014
|
||||
#define AML_OP_MEM_HARD_TRANS_EN 0x00A7000C
|
||||
#define AML_OP_RF_CFG 0x00F03040
|
||||
#define AML_OP_RAM_POWER_CTR 0x00F03050
|
||||
#define AML_OP_HARDWARE_RST 0x00F03058
|
||||
#define AML_OP_ICCM_RAM_BASE 0x00000000
|
||||
#define AML_OP_DCCM_RAM_BASE 0x00D00000
|
||||
|
||||
/* UART configuration */
|
||||
#define AML_UART_XMIT_EN BIT(12)
|
||||
#define AML_UART_RECV_EN BIT(13)
|
||||
#define AML_UART_TIMEOUT_INT_EN BIT(14)
|
||||
#define AML_UART_CLK_SOURCE 40000000
|
||||
|
||||
/* Controller event */
|
||||
#define AML_EVT_EN BIT(24)
|
||||
|
||||
/* RAM power control */
|
||||
#define AML_RAM_POWER_ON (0)
|
||||
#define AML_RAM_POWER_OFF (1)
|
||||
|
||||
/* RF configuration */
|
||||
#define AML_RF_ANT_SINGLE BIT(28)
|
||||
#define AML_RF_ANT_DOUBLE BIT(29)
|
||||
|
||||
/* Memory transaction */
|
||||
#define AML_MM_CTR_HARD_TRAS_EN BIT(27)
|
||||
|
||||
/* Controller reset */
|
||||
#define AML_CTR_CPU_RESET BIT(8)
|
||||
#define AML_CTR_MAC_RESET BIT(9)
|
||||
#define AML_CTR_PHY_RESET BIT(10)
|
||||
|
||||
enum {
|
||||
FW_ICCM,
|
||||
FW_DCCM
|
||||
};
|
||||
|
||||
struct aml_fw_len {
|
||||
u32 iccm_len;
|
||||
u32 dccm_len;
|
||||
};
|
||||
|
||||
struct aml_tci_rsp {
|
||||
u8 num_cmd_packet;
|
||||
u16 opcode;
|
||||
u8 status;
|
||||
} __packed;
|
||||
|
||||
struct aml_device_data {
|
||||
int iccm_offset;
|
||||
int dccm_offset;
|
||||
bool is_coex;
|
||||
};
|
||||
|
||||
struct aml_serdev {
|
||||
struct hci_uart serdev_hu;
|
||||
struct device *dev;
|
||||
struct gpio_desc *bt_en_gpio;
|
||||
struct regulator *bt_supply;
|
||||
struct clk *lpo_clk;
|
||||
const struct aml_device_data *aml_dev_data;
|
||||
const char *firmware_name;
|
||||
};
|
||||
|
||||
struct aml_data {
|
||||
struct sk_buff *rx_skb;
|
||||
struct sk_buff_head txq;
|
||||
};
|
||||
|
||||
static const struct h4_recv_pkt aml_recv_pkts[] = {
|
||||
{ H4_RECV_ACL, .recv = hci_recv_frame },
|
||||
{ H4_RECV_SCO, .recv = hci_recv_frame },
|
||||
{ H4_RECV_EVENT, .recv = hci_recv_frame },
|
||||
{ H4_RECV_ISO, .recv = hci_recv_frame },
|
||||
};
|
||||
|
||||
/* The TCI command is a private command, which is for setting baud rate,
|
||||
* downloading firmware, initiating RAM.
|
||||
*
|
||||
* op_code | op_len | op_addr | parameter |
|
||||
* --------|-----------------------|---------|-------------|
|
||||
* 2B | 1B len(addr+param) | 4B | len(param) |
|
||||
*/
|
||||
static int aml_send_tci_cmd(struct hci_dev *hdev, u16 op_code, u32 op_addr,
|
||||
u32 *param, u32 param_len)
|
||||
{
|
||||
struct aml_tci_rsp *rsp = NULL;
|
||||
struct sk_buff *skb = NULL;
|
||||
size_t buf_len = 0;
|
||||
u8 *buf = NULL;
|
||||
int err = 0;
|
||||
|
||||
buf_len = sizeof(op_addr) + param_len;
|
||||
buf = kmalloc(buf_len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(buf, &op_addr, sizeof(op_addr));
|
||||
if (param && param_len > 0)
|
||||
memcpy(buf + sizeof(op_addr), param, param_len);
|
||||
|
||||
skb = __hci_cmd_sync_ev(hdev, op_code, buf_len, buf,
|
||||
HCI_EV_CMD_COMPLETE, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
err = PTR_ERR(skb);
|
||||
bt_dev_err(hdev, "Failed to send TCI cmd (error: %d)", err);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rsp = skb_pull_data(skb, sizeof(struct aml_tci_rsp));
|
||||
if (!rsp)
|
||||
goto skb_free;
|
||||
|
||||
if (rsp->opcode != op_code || rsp->status != 0x00) {
|
||||
bt_dev_err(hdev, "send TCI cmd (0x%04X), response (0x%04X):(%d)",
|
||||
op_code, rsp->opcode, rsp->status);
|
||||
err = -EINVAL;
|
||||
goto skb_free;
|
||||
}
|
||||
|
||||
skb_free:
|
||||
kfree_skb(skb);
|
||||
|
||||
exit:
|
||||
kfree(buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int aml_update_chip_baudrate(struct hci_dev *hdev, u32 baud)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
value = ((AML_UART_CLK_SOURCE / baud) - 1) & 0x0FFF;
|
||||
value |= AML_UART_XMIT_EN | AML_UART_RECV_EN | AML_UART_TIMEOUT_INT_EN;
|
||||
|
||||
return aml_send_tci_cmd(hdev, AML_TCI_CMD_UPDATE_BAUDRATE,
|
||||
AML_OP_UART_MODE, &value, sizeof(value));
|
||||
}
|
||||
|
||||
static int aml_start_chip(struct hci_dev *hdev)
|
||||
{
|
||||
u32 value = 0;
|
||||
int ret;
|
||||
|
||||
value = AML_MM_CTR_HARD_TRAS_EN;
|
||||
ret = aml_send_tci_cmd(hdev, AML_TCI_CMD_WRITE,
|
||||
AML_OP_MEM_HARD_TRANS_EN,
|
||||
&value, sizeof(value));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* controller hardware reset */
|
||||
value = AML_CTR_CPU_RESET | AML_CTR_MAC_RESET | AML_CTR_PHY_RESET;
|
||||
ret = aml_send_tci_cmd(hdev, AML_TCI_CMD_HARDWARE_RESET,
|
||||
AML_OP_HARDWARE_RST,
|
||||
&value, sizeof(value));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aml_send_firmware_segment(struct hci_dev *hdev,
|
||||
u8 fw_type,
|
||||
u8 *seg,
|
||||
u32 seg_size,
|
||||
u32 offset)
|
||||
{
|
||||
u32 op_addr = 0;
|
||||
|
||||
if (fw_type == FW_ICCM)
|
||||
op_addr = AML_OP_ICCM_RAM_BASE + offset;
|
||||
else if (fw_type == FW_DCCM)
|
||||
op_addr = AML_OP_DCCM_RAM_BASE + offset;
|
||||
|
||||
return aml_send_tci_cmd(hdev, AML_TCI_CMD_DOWNLOAD_BT_FW,
|
||||
op_addr, (u32 *)seg, seg_size);
|
||||
}
|
||||
|
||||
static int aml_send_firmware(struct hci_dev *hdev, u8 fw_type,
|
||||
u8 *fw, u32 fw_size, u32 offset)
|
||||
{
|
||||
u32 seg_size = 0;
|
||||
u32 seg_off = 0;
|
||||
|
||||
if (fw_size > AML_FIRMWARE_MAX_SIZE) {
|
||||
bt_dev_err(hdev,
|
||||
"Firmware size %d kB is larger than the maximum of 512 kB. Aborting.",
|
||||
fw_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
while (fw_size > 0) {
|
||||
seg_size = (fw_size > AML_FIRMWARE_OPERATION_SIZE) ?
|
||||
AML_FIRMWARE_OPERATION_SIZE : fw_size;
|
||||
if (aml_send_firmware_segment(hdev, fw_type, (fw + seg_off),
|
||||
seg_size, offset)) {
|
||||
bt_dev_err(hdev, "Failed send firmware, type: %d, offset: 0x%x",
|
||||
fw_type, offset);
|
||||
return -EINVAL;
|
||||
}
|
||||
seg_off += seg_size;
|
||||
fw_size -= seg_size;
|
||||
offset += seg_size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aml_download_firmware(struct hci_dev *hdev, const char *fw_name)
|
||||
{
|
||||
struct hci_uart *hu = hci_get_drvdata(hdev);
|
||||
struct aml_serdev *amldev = serdev_device_get_drvdata(hu->serdev);
|
||||
const struct firmware *firmware = NULL;
|
||||
struct aml_fw_len *fw_len = NULL;
|
||||
u8 *iccm_start = NULL, *dccm_start = NULL;
|
||||
u32 iccm_len, dccm_len;
|
||||
u32 value = 0;
|
||||
int ret = 0;
|
||||
|
||||
/* Enable firmware download event */
|
||||
value = AML_EVT_EN;
|
||||
ret = aml_send_tci_cmd(hdev, AML_TCI_CMD_WRITE,
|
||||
AML_OP_EVT_ENABLE,
|
||||
&value, sizeof(value));
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
/* RAM power on */
|
||||
value = AML_RAM_POWER_ON;
|
||||
ret = aml_send_tci_cmd(hdev, AML_TCI_CMD_WRITE,
|
||||
AML_OP_RAM_POWER_CTR,
|
||||
&value, sizeof(value));
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
/* Check RAM power status */
|
||||
ret = aml_send_tci_cmd(hdev, AML_TCI_CMD_READ,
|
||||
AML_OP_RAM_POWER_CTR, NULL, 0);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
ret = request_firmware(&firmware, fw_name, &hdev->dev);
|
||||
if (ret < 0) {
|
||||
bt_dev_err(hdev, "Failed to load <%s>:(%d)", fw_name, ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
fw_len = (struct aml_fw_len *)firmware->data;
|
||||
|
||||
/* Download ICCM */
|
||||
iccm_start = (u8 *)(firmware->data) + sizeof(struct aml_fw_len)
|
||||
+ amldev->aml_dev_data->iccm_offset;
|
||||
iccm_len = fw_len->iccm_len - amldev->aml_dev_data->iccm_offset;
|
||||
ret = aml_send_firmware(hdev, FW_ICCM, iccm_start, iccm_len,
|
||||
amldev->aml_dev_data->iccm_offset);
|
||||
if (ret) {
|
||||
bt_dev_err(hdev, "Failed to send FW_ICCM (%d)", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Download DCCM */
|
||||
dccm_start = (u8 *)(firmware->data) + sizeof(struct aml_fw_len) + fw_len->iccm_len;
|
||||
dccm_len = fw_len->dccm_len;
|
||||
ret = aml_send_firmware(hdev, FW_DCCM, dccm_start, dccm_len,
|
||||
amldev->aml_dev_data->dccm_offset);
|
||||
if (ret) {
|
||||
bt_dev_err(hdev, "Failed to send FW_DCCM (%d)", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Disable firmware download event */
|
||||
value = 0;
|
||||
ret = aml_send_tci_cmd(hdev, AML_TCI_CMD_WRITE,
|
||||
AML_OP_EVT_ENABLE,
|
||||
&value, sizeof(value));
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
exit:
|
||||
if (firmware)
|
||||
release_firmware(firmware);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aml_send_reset(struct hci_dev *hdev)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
|
||||
skb = __hci_cmd_sync_ev(hdev, HCI_OP_RESET, 0, NULL,
|
||||
HCI_EV_CMD_COMPLETE, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
err = PTR_ERR(skb);
|
||||
bt_dev_err(hdev, "Failed to send hci reset cmd (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aml_dump_fw_version(struct hci_dev *hdev)
|
||||
{
|
||||
struct aml_tci_rsp *rsp = NULL;
|
||||
struct sk_buff *skb;
|
||||
u8 value[6] = {0};
|
||||
u8 *fw_ver = NULL;
|
||||
int err = 0;
|
||||
|
||||
skb = __hci_cmd_sync_ev(hdev, AML_BT_HCI_VENDOR_CMD, sizeof(value), value,
|
||||
HCI_EV_CMD_COMPLETE, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
err = PTR_ERR(skb);
|
||||
bt_dev_err(hdev, "Failed to get fw version (error: %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
rsp = skb_pull_data(skb, sizeof(struct aml_tci_rsp));
|
||||
if (!rsp)
|
||||
goto exit;
|
||||
|
||||
if (rsp->opcode != AML_BT_HCI_VENDOR_CMD || rsp->status != 0x00) {
|
||||
bt_dev_err(hdev, "dump version, error response (0x%04X):(%d)",
|
||||
rsp->opcode, rsp->status);
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
fw_ver = (u8 *)rsp + AML_EVT_HEAD_SIZE;
|
||||
bt_dev_info(hdev, "fw_version: date = %02x.%02x, number = 0x%02x%02x",
|
||||
*(fw_ver + 1), *fw_ver, *(fw_ver + 3), *(fw_ver + 2));
|
||||
|
||||
exit:
|
||||
kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int aml_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
|
||||
{
|
||||
struct aml_tci_rsp *rsp = NULL;
|
||||
struct sk_buff *skb;
|
||||
int err = 0;
|
||||
|
||||
bt_dev_info(hdev, "set bdaddr (%pM)", bdaddr);
|
||||
skb = __hci_cmd_sync_ev(hdev, AML_BT_HCI_VENDOR_CMD,
|
||||
sizeof(bdaddr_t), bdaddr,
|
||||
HCI_EV_CMD_COMPLETE, HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
err = PTR_ERR(skb);
|
||||
bt_dev_err(hdev, "Failed to set bdaddr (error: %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
rsp = skb_pull_data(skb, sizeof(struct aml_tci_rsp));
|
||||
if (!rsp)
|
||||
goto exit;
|
||||
|
||||
if (rsp->opcode != AML_BT_HCI_VENDOR_CMD || rsp->status != 0x00) {
|
||||
bt_dev_err(hdev, "error response (0x%x):(%d)", rsp->opcode, rsp->status);
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int aml_check_bdaddr(struct hci_dev *hdev)
|
||||
{
|
||||
struct hci_rp_read_bd_addr *paddr;
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
|
||||
if (bacmp(&hdev->public_addr, BDADDR_ANY))
|
||||
return 0;
|
||||
|
||||
skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
|
||||
HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
err = PTR_ERR(skb);
|
||||
bt_dev_err(hdev, "Failed to read bdaddr (error: %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
paddr = skb_pull_data(skb, sizeof(struct hci_rp_read_bd_addr));
|
||||
if (!paddr)
|
||||
goto exit;
|
||||
|
||||
if (!bacmp(&paddr->bdaddr, AML_BDADDR_DEFAULT)) {
|
||||
bt_dev_info(hdev, "amlbt using default bdaddr (%pM)", &paddr->bdaddr);
|
||||
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
|
||||
}
|
||||
|
||||
exit:
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aml_config_rf(struct hci_dev *hdev, bool is_coex)
|
||||
{
|
||||
u32 value = AML_RF_ANT_DOUBLE;
|
||||
|
||||
/* Use a single antenna when co-existing with wifi */
|
||||
if (is_coex)
|
||||
value = AML_RF_ANT_SINGLE;
|
||||
|
||||
return aml_send_tci_cmd(hdev, AML_TCI_CMD_WRITE,
|
||||
AML_OP_RF_CFG,
|
||||
&value, sizeof(value));
|
||||
}
|
||||
|
||||
static int aml_parse_dt(struct aml_serdev *amldev)
|
||||
{
|
||||
struct device *pdev = amldev->dev;
|
||||
|
||||
amldev->bt_en_gpio = devm_gpiod_get(pdev, "enable",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(amldev->bt_en_gpio)) {
|
||||
dev_err(pdev, "Failed to acquire enable gpios");
|
||||
return PTR_ERR(amldev->bt_en_gpio);
|
||||
}
|
||||
|
||||
if (device_property_read_string(pdev, "firmware-name",
|
||||
&amldev->firmware_name)) {
|
||||
dev_err(pdev, "Failed to acquire firmware path");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
amldev->bt_supply = devm_regulator_get(pdev, "vddio");
|
||||
if (IS_ERR(amldev->bt_supply)) {
|
||||
dev_err(pdev, "Failed to acquire regulator");
|
||||
return PTR_ERR(amldev->bt_supply);
|
||||
}
|
||||
|
||||
amldev->lpo_clk = devm_clk_get(pdev, NULL);
|
||||
if (IS_ERR(amldev->lpo_clk)) {
|
||||
dev_err(pdev, "Failed to acquire clock source");
|
||||
return PTR_ERR(amldev->lpo_clk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aml_power_on(struct aml_serdev *amldev)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = regulator_enable(amldev->bt_supply);
|
||||
if (err) {
|
||||
dev_err(amldev->dev, "Failed to enable regulator: (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = clk_prepare_enable(amldev->lpo_clk);
|
||||
if (err) {
|
||||
dev_err(amldev->dev, "Failed to enable lpo clock: (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
gpiod_set_value_cansleep(amldev->bt_en_gpio, 1);
|
||||
|
||||
/* Wait 20ms for bluetooth controller power on */
|
||||
msleep(20);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aml_power_off(struct aml_serdev *amldev)
|
||||
{
|
||||
gpiod_set_value_cansleep(amldev->bt_en_gpio, 0);
|
||||
|
||||
clk_disable_unprepare(amldev->lpo_clk);
|
||||
|
||||
regulator_disable(amldev->bt_supply);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aml_set_baudrate(struct hci_uart *hu, unsigned int speed)
|
||||
{
|
||||
/* update controller baudrate */
|
||||
if (aml_update_chip_baudrate(hu->hdev, speed) != 0) {
|
||||
bt_dev_err(hu->hdev, "Failed to update baud rate");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* update local baudrate */
|
||||
serdev_device_set_baudrate(hu->serdev, speed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initialize protocol */
|
||||
static int aml_open(struct hci_uart *hu)
|
||||
{
|
||||
struct aml_serdev *amldev = serdev_device_get_drvdata(hu->serdev);
|
||||
struct aml_data *aml_data;
|
||||
int err;
|
||||
|
||||
err = aml_parse_dt(amldev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!hci_uart_has_flow_control(hu)) {
|
||||
bt_dev_err(hu->hdev, "no flow control");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
aml_data = kzalloc(sizeof(*aml_data), GFP_KERNEL);
|
||||
if (!aml_data)
|
||||
return -ENOMEM;
|
||||
|
||||
skb_queue_head_init(&aml_data->txq);
|
||||
|
||||
hu->priv = aml_data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aml_close(struct hci_uart *hu)
|
||||
{
|
||||
struct aml_serdev *amldev = serdev_device_get_drvdata(hu->serdev);
|
||||
struct aml_data *aml_data = hu->priv;
|
||||
|
||||
skb_queue_purge(&aml_data->txq);
|
||||
kfree_skb(aml_data->rx_skb);
|
||||
kfree(aml_data);
|
||||
|
||||
hu->priv = NULL;
|
||||
|
||||
return aml_power_off(amldev);
|
||||
}
|
||||
|
||||
static int aml_flush(struct hci_uart *hu)
|
||||
{
|
||||
struct aml_data *aml_data = hu->priv;
|
||||
|
||||
skb_queue_purge(&aml_data->txq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aml_setup(struct hci_uart *hu)
|
||||
{
|
||||
struct aml_serdev *amldev = serdev_device_get_drvdata(hu->serdev);
|
||||
struct hci_dev *hdev = amldev->serdev_hu.hdev;
|
||||
int err;
|
||||
|
||||
/* Setup bdaddr */
|
||||
hdev->set_bdaddr = aml_set_bdaddr;
|
||||
|
||||
err = aml_power_on(amldev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = aml_set_baudrate(hu, amldev->serdev_hu.proto->oper_speed);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = aml_download_firmware(hdev, amldev->firmware_name);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = aml_config_rf(hdev, amldev->aml_dev_data->is_coex);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = aml_start_chip(hdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Wait 60ms for controller startup */
|
||||
msleep(60);
|
||||
|
||||
err = aml_dump_fw_version(hdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = aml_send_reset(hdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = aml_check_bdaddr(hdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aml_enqueue(struct hci_uart *hu, struct sk_buff *skb)
|
||||
{
|
||||
struct aml_data *aml_data = hu->priv;
|
||||
|
||||
skb_queue_tail(&aml_data->txq, skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sk_buff *aml_dequeue(struct hci_uart *hu)
|
||||
{
|
||||
struct aml_data *aml_data = hu->priv;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = skb_dequeue(&aml_data->txq);
|
||||
|
||||
/* Prepend skb with frame type */
|
||||
if (skb)
|
||||
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static int aml_recv(struct hci_uart *hu, const void *data, int count)
|
||||
{
|
||||
struct aml_data *aml_data = hu->priv;
|
||||
int err;
|
||||
|
||||
aml_data->rx_skb = h4_recv_buf(hu->hdev, aml_data->rx_skb, data, count,
|
||||
aml_recv_pkts,
|
||||
ARRAY_SIZE(aml_recv_pkts));
|
||||
if (IS_ERR(aml_data->rx_skb)) {
|
||||
err = PTR_ERR(aml_data->rx_skb);
|
||||
bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err);
|
||||
aml_data->rx_skb = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct hci_uart_proto aml_hci_proto = {
|
||||
.id = HCI_UART_AML,
|
||||
.name = "AML",
|
||||
.init_speed = 115200,
|
||||
.oper_speed = 4000000,
|
||||
.open = aml_open,
|
||||
.close = aml_close,
|
||||
.setup = aml_setup,
|
||||
.flush = aml_flush,
|
||||
.recv = aml_recv,
|
||||
.enqueue = aml_enqueue,
|
||||
.dequeue = aml_dequeue,
|
||||
};
|
||||
|
||||
static void aml_device_driver_shutdown(struct device *dev)
|
||||
{
|
||||
struct aml_serdev *amldev = dev_get_drvdata(dev);
|
||||
|
||||
aml_power_off(amldev);
|
||||
}
|
||||
|
||||
static int aml_serdev_probe(struct serdev_device *serdev)
|
||||
{
|
||||
struct aml_serdev *amldev;
|
||||
int err;
|
||||
|
||||
amldev = devm_kzalloc(&serdev->dev, sizeof(*amldev), GFP_KERNEL);
|
||||
if (!amldev)
|
||||
return -ENOMEM;
|
||||
|
||||
amldev->serdev_hu.serdev = serdev;
|
||||
amldev->dev = &serdev->dev;
|
||||
serdev_device_set_drvdata(serdev, amldev);
|
||||
|
||||
err = hci_uart_register_device(&amldev->serdev_hu, &aml_hci_proto);
|
||||
if (err)
|
||||
return dev_err_probe(amldev->dev, err,
|
||||
"Failed to register hci uart device");
|
||||
|
||||
amldev->aml_dev_data = device_get_match_data(&serdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void aml_serdev_remove(struct serdev_device *serdev)
|
||||
{
|
||||
struct aml_serdev *amldev = serdev_device_get_drvdata(serdev);
|
||||
|
||||
hci_uart_unregister_device(&amldev->serdev_hu);
|
||||
}
|
||||
|
||||
static const struct aml_device_data data_w155s2 = {
|
||||
.iccm_offset = 256 * 1024,
|
||||
};
|
||||
|
||||
static const struct aml_device_data data_w265s2 = {
|
||||
.iccm_offset = 384 * 1024,
|
||||
};
|
||||
|
||||
static const struct of_device_id aml_bluetooth_of_match[] = {
|
||||
{ .compatible = "amlogic,w155s2-bt", .data = &data_w155s2 },
|
||||
{ .compatible = "amlogic,w265s2-bt", .data = &data_w265s2 },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, aml_bluetooth_of_match);
|
||||
|
||||
static struct serdev_device_driver aml_serdev_driver = {
|
||||
.probe = aml_serdev_probe,
|
||||
.remove = aml_serdev_remove,
|
||||
.driver = {
|
||||
.name = "hci_uart_aml",
|
||||
.of_match_table = aml_bluetooth_of_match,
|
||||
.shutdown = aml_device_driver_shutdown,
|
||||
},
|
||||
};
|
||||
|
||||
int __init aml_init(void)
|
||||
{
|
||||
serdev_device_driver_register(&aml_serdev_driver);
|
||||
|
||||
return hci_uart_register_proto(&aml_hci_proto);
|
||||
}
|
||||
|
||||
int __exit aml_deinit(void)
|
||||
{
|
||||
serdev_device_driver_unregister(&aml_serdev_driver);
|
||||
|
||||
return hci_uart_unregister_proto(&aml_hci_proto);
|
||||
}
|
@ -507,6 +507,9 @@ static int hci_uart_tty_open(struct tty_struct *tty)
|
||||
hu->alignment = 1;
|
||||
hu->padding = 0;
|
||||
|
||||
/* Use serial port speed as oper_speed */
|
||||
hu->oper_speed = tty->termios.c_ospeed;
|
||||
|
||||
INIT_WORK(&hu->init_ready, hci_uart_init_work);
|
||||
INIT_WORK(&hu->write_work, hci_uart_write_work);
|
||||
|
||||
@ -870,7 +873,9 @@ static int __init hci_uart_init(void)
|
||||
#ifdef CONFIG_BT_HCIUART_MRVL
|
||||
mrvl_init();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_AML
|
||||
aml_init();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -906,7 +911,9 @@ static void __exit hci_uart_exit(void)
|
||||
#ifdef CONFIG_BT_HCIUART_MRVL
|
||||
mrvl_deinit();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_AML
|
||||
aml_deinit();
|
||||
#endif
|
||||
tty_unregister_ldisc(&hci_uart_ldisc);
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#define HCIUARTGETFLAGS _IOR('U', 204, int)
|
||||
|
||||
/* UART protocols */
|
||||
#define HCI_UART_MAX_PROTO 12
|
||||
#define HCI_UART_MAX_PROTO 13
|
||||
|
||||
#define HCI_UART_H4 0
|
||||
#define HCI_UART_BCSP 1
|
||||
@ -34,6 +34,7 @@
|
||||
#define HCI_UART_AG6XX 9
|
||||
#define HCI_UART_NOKIA 10
|
||||
#define HCI_UART_MRVL 11
|
||||
#define HCI_UART_AML 12
|
||||
|
||||
#define HCI_UART_RAW_DEVICE 0
|
||||
#define HCI_UART_RESET_ON_INIT 1
|
||||
@ -209,3 +210,8 @@ int ag6xx_deinit(void);
|
||||
int mrvl_init(void);
|
||||
int mrvl_deinit(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_AML
|
||||
int aml_init(void);
|
||||
int aml_deinit(void);
|
||||
#endif
|
||||
|
@ -2901,6 +2901,11 @@ static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb)
|
||||
return (struct hci_sco_hdr *) skb->data;
|
||||
}
|
||||
|
||||
static inline struct hci_iso_hdr *hci_iso_hdr(const struct sk_buff *skb)
|
||||
{
|
||||
return (struct hci_iso_hdr *)skb->data;
|
||||
}
|
||||
|
||||
/* Command opcode pack/unpack */
|
||||
#define hci_opcode_pack(ogf, ocf) ((__u16) ((ocf & 0x03ff)|(ogf << 10)))
|
||||
#define hci_opcode_ogf(op) (op >> 10)
|
||||
|
@ -2257,8 +2257,8 @@ void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
||||
bool mgmt_connected);
|
||||
void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
||||
u8 link_type, u8 addr_type, u8 status);
|
||||
void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
||||
u8 addr_type, u8 status);
|
||||
void mgmt_connect_failed(struct hci_dev *hdev, struct hci_conn *conn,
|
||||
u8 status);
|
||||
void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure);
|
||||
void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
||||
u8 status);
|
||||
|
@ -968,10 +968,6 @@ void l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
|
||||
void *data);
|
||||
void l2cap_chan_del(struct l2cap_chan *chan, int err);
|
||||
void l2cap_send_conn_req(struct l2cap_chan *chan);
|
||||
void l2cap_move_start(struct l2cap_chan *chan);
|
||||
void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
|
||||
u8 status);
|
||||
void __l2cap_physical_cfm(struct l2cap_chan *chan, int result);
|
||||
|
||||
struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn);
|
||||
void l2cap_conn_put(struct l2cap_conn *conn);
|
||||
|
@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config BT_CMTP
|
||||
tristate "CMTP protocol support"
|
||||
depends on BT_BREDR && ISDN_CAPI
|
||||
tristate "CMTP protocol support (DEPRECATED)"
|
||||
depends on BT_BREDR && ISDN_CAPI && DEPRECATED
|
||||
help
|
||||
CMTP (CAPI Message Transport Protocol) is a transport layer
|
||||
for CAPI messages. CMTP is required for the Bluetooth Common
|
||||
|
@ -248,18 +248,10 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
|
||||
break;
|
||||
|
||||
case CAPI_FUNCTION_GET_MANUFACTURER:
|
||||
if (skb->len < CAPI_MSG_BASELEN + 15)
|
||||
break;
|
||||
|
||||
if (!info && ctrl) {
|
||||
int len = min_t(uint, CAPI_MANUFACTURER_LEN,
|
||||
if (!info && ctrl && skb->len > CAPI_MSG_BASELEN + 14)
|
||||
strscpy_pad(ctrl->manu,
|
||||
skb->data + CAPI_MSG_BASELEN + 15,
|
||||
skb->data[CAPI_MSG_BASELEN + 14]);
|
||||
|
||||
memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN);
|
||||
strncpy(ctrl->manu,
|
||||
skb->data + CAPI_MSG_BASELEN + 15, len);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CAPI_FUNCTION_GET_VERSION:
|
||||
@ -276,18 +268,10 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s
|
||||
break;
|
||||
|
||||
case CAPI_FUNCTION_GET_SERIAL_NUMBER:
|
||||
if (skb->len < CAPI_MSG_BASELEN + 17)
|
||||
break;
|
||||
|
||||
if (!info && ctrl) {
|
||||
int len = min_t(uint, CAPI_SERIAL_LEN,
|
||||
if (!info && ctrl && skb->len > CAPI_MSG_BASELEN + 16)
|
||||
strscpy_pad(ctrl->serial,
|
||||
skb->data + CAPI_MSG_BASELEN + 17,
|
||||
skb->data[CAPI_MSG_BASELEN + 16]);
|
||||
|
||||
memset(ctrl->serial, 0, CAPI_SERIAL_LEN);
|
||||
strncpy(ctrl->serial,
|
||||
skb->data + CAPI_MSG_BASELEN + 17, len);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -106,8 +106,7 @@ void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status)
|
||||
* where a timeout + cancel does indicate an actual failure.
|
||||
*/
|
||||
if (status && status != HCI_ERROR_UNKNOWN_CONN_ID)
|
||||
mgmt_connect_failed(hdev, &conn->dst, conn->type,
|
||||
conn->dst_type, status);
|
||||
mgmt_connect_failed(hdev, conn, status);
|
||||
|
||||
/* The connection attempt was doing scan for new RPA, and is
|
||||
* in scan phase. If params are not associated with any other
|
||||
@ -778,7 +777,6 @@ static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn *c
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(d, 0, sizeof(*d));
|
||||
d->big = big;
|
||||
d->sync_handle = conn->sync_handle;
|
||||
|
||||
@ -1250,8 +1248,7 @@ void hci_conn_failed(struct hci_conn *conn, u8 status)
|
||||
hci_le_conn_failed(conn, status);
|
||||
break;
|
||||
case ACL_LINK:
|
||||
mgmt_connect_failed(hdev, &conn->dst, conn->type,
|
||||
conn->dst_type, status);
|
||||
mgmt_connect_failed(hdev, conn, status);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -5380,7 +5380,10 @@ int hci_stop_discovery_sync(struct hci_dev *hdev)
|
||||
if (!e)
|
||||
return 0;
|
||||
|
||||
return hci_remote_name_cancel_sync(hdev, &e->data.bdaddr);
|
||||
/* Ignore cancel errors since it should interfere with stopping
|
||||
* of the discovery.
|
||||
*/
|
||||
hci_remote_name_cancel_sync(hdev, &e->data.bdaddr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -48,7 +48,7 @@ static int power_activate(struct led_classdev *led_cdev)
|
||||
htrig = to_hci_basic_led_trigger(led_cdev->trigger);
|
||||
powered = test_bit(HCI_UP, &htrig->hdev->flags);
|
||||
|
||||
led_trigger_event(led_cdev->trigger, powered ? LED_FULL : LED_OFF);
|
||||
led_set_brightness(led_cdev, powered ? LED_FULL : LED_OFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -9779,13 +9779,18 @@ void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
||||
mgmt_pending_remove(cmd);
|
||||
}
|
||||
|
||||
void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
||||
u8 addr_type, u8 status)
|
||||
void mgmt_connect_failed(struct hci_dev *hdev, struct hci_conn *conn, u8 status)
|
||||
{
|
||||
struct mgmt_ev_connect_failed ev;
|
||||
|
||||
bacpy(&ev.addr.bdaddr, bdaddr);
|
||||
ev.addr.type = link_to_bdaddr(link_type, addr_type);
|
||||
if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
|
||||
mgmt_device_disconnected(hdev, &conn->dst, conn->type,
|
||||
conn->dst_type, status, true);
|
||||
return;
|
||||
}
|
||||
|
||||
bacpy(&ev.addr.bdaddr, &conn->dst);
|
||||
ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
|
||||
ev.status = mgmt_status(status);
|
||||
|
||||
mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user