mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-22 12:14:01 +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 2018-12-19 Here's the main bluetooth-next pull request for 4.21: - Multiple fixes & improvements for Broadcom-based controllers - New USB ID for an Intel controller - Support for new Broadcom controller variants - Use DEFINE_SHOW_ATTRIBUTE to simplify debugfs code - Eliminate confusing "last event is not cmd complete" warning message - Added vendor suspend/resume support for H:5 (3-Wire UART) controllers - Various other smaller improvements & fixes 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
29d3c047b7
@ -10,6 +10,8 @@ device the slave device is attached to.
|
||||
Required properties:
|
||||
|
||||
- compatible: should contain one of the following:
|
||||
* "brcm,bcm20702a1"
|
||||
* "brcm,bcm4330-bt"
|
||||
* "brcm,bcm43438-bt"
|
||||
|
||||
Optional properties:
|
||||
@ -18,8 +20,13 @@ Optional properties:
|
||||
- shutdown-gpios: GPIO specifier, used to enable the BT module
|
||||
- device-wakeup-gpios: GPIO specifier, used to wakeup the controller
|
||||
- host-wakeup-gpios: GPIO specifier, used to wakeup the host processor
|
||||
- clocks: clock specifier if external clock provided to the controller
|
||||
- clock-names: should be "extclk"
|
||||
- clocks: 1 or 2 clocks as defined in clock-names below, in that order
|
||||
- clock-names: names for clock inputs, matching the clocks given
|
||||
- "extclk": deprecated, replaced by "txco"
|
||||
- "txco": external reference clock (not a standalone crystal)
|
||||
- "lpo": external low power 32.768 kHz clock
|
||||
- vbat-supply: phandle to regulator supply for VBAT
|
||||
- vddio-supply: phandle to regulator supply for VDDIO
|
||||
|
||||
|
||||
Example:
|
||||
|
@ -33,6 +33,8 @@
|
||||
#define VERSION "0.1"
|
||||
|
||||
#define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}})
|
||||
#define BDADDR_BCM20702A1 (&(bdaddr_t) {{0x00, 0x00, 0xa0, 0x02, 0x70, 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}})
|
||||
|
||||
@ -64,15 +66,23 @@ int btbcm_check_bdaddr(struct hci_dev *hdev)
|
||||
* The address 00:20:70:02:A0:00 indicates a BCM20702A0 controller
|
||||
* with no configured address.
|
||||
*
|
||||
* The address 20:70:02:A0:00:00 indicates a BCM20702A1 controller
|
||||
* with no configured address.
|
||||
*
|
||||
* The address 43:24:B3:00:00:00 indicates a BCM4324B3 controller
|
||||
* with waiting for configuration state.
|
||||
*
|
||||
* The address 43:30:B1:00:00:00 indicates a BCM4330B1 controller
|
||||
* with waiting for configuration state.
|
||||
*
|
||||
* The address 43:43:A0:12:1F:AC indicates a BCM43430A0 controller
|
||||
* with no configured address.
|
||||
*/
|
||||
if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0) ||
|
||||
!bacmp(&bda->bdaddr, BDADDR_BCM20702A1) ||
|
||||
!bacmp(&bda->bdaddr, BDADDR_BCM4324B3) ||
|
||||
!bacmp(&bda->bdaddr, BDADDR_BCM4330B1)) {
|
||||
!bacmp(&bda->bdaddr, BDADDR_BCM4330B1) ||
|
||||
!bacmp(&bda->bdaddr, BDADDR_BCM43430A0)) {
|
||||
bt_dev_info(hdev, "BCM: Using default device address (%pMR)",
|
||||
&bda->bdaddr);
|
||||
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
|
||||
@ -330,6 +340,8 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = {
|
||||
{ 0x2209, "BCM43430A1" }, /* 001.002.009 */
|
||||
{ 0x6119, "BCM4345C0" }, /* 003.001.025 */
|
||||
{ 0x230f, "BCM4356A2" }, /* 001.003.015 */
|
||||
{ 0x220e, "BCM20702A1" }, /* 001.002.014 */
|
||||
{ 0x4217, "BCM4329B1" }, /* 002.002.023 */
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -344,6 +344,7 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
/* Intel Bluetooth devices */
|
||||
{ USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_NEW },
|
||||
{ USB_DEVICE(0x8087, 0x0026), .driver_info = BTUSB_INTEL_NEW },
|
||||
{ USB_DEVICE(0x8087, 0x0029), .driver_info = BTUSB_INTEL_NEW },
|
||||
{ USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },
|
||||
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
|
||||
{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },
|
||||
@ -1935,10 +1936,8 @@ static void btusb_intel_bootup(struct btusb_data *data, const void *ptr,
|
||||
if (len != sizeof(*evt))
|
||||
return;
|
||||
|
||||
if (test_and_clear_bit(BTUSB_BOOTING, &data->flags)) {
|
||||
smp_mb__after_atomic();
|
||||
if (test_and_clear_bit(BTUSB_BOOTING, &data->flags))
|
||||
wake_up_bit(&data->flags, BTUSB_BOOTING);
|
||||
}
|
||||
}
|
||||
|
||||
static void btusb_intel_secure_send_result(struct btusb_data *data,
|
||||
@ -1953,10 +1952,8 @@ static void btusb_intel_secure_send_result(struct btusb_data *data,
|
||||
set_bit(BTUSB_FIRMWARE_FAILED, &data->flags);
|
||||
|
||||
if (test_and_clear_bit(BTUSB_DOWNLOADING, &data->flags) &&
|
||||
test_bit(BTUSB_FIRMWARE_LOADED, &data->flags)) {
|
||||
smp_mb__after_atomic();
|
||||
test_bit(BTUSB_FIRMWARE_LOADED, &data->flags))
|
||||
wake_up_bit(&data->flags, BTUSB_DOWNLOADING);
|
||||
}
|
||||
}
|
||||
|
||||
static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
@ -2055,6 +2052,35 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
return -EILSEQ;
|
||||
}
|
||||
|
||||
static bool btusb_setup_intel_new_get_fw_name(struct intel_version *ver,
|
||||
struct intel_boot_params *params,
|
||||
char *fw_name, size_t len,
|
||||
const char *suffix)
|
||||
{
|
||||
switch (ver->hw_variant) {
|
||||
case 0x0b: /* SfP */
|
||||
case 0x0c: /* WsP */
|
||||
snprintf(fw_name, len, "intel/ibt-%u-%u.%s",
|
||||
le16_to_cpu(ver->hw_variant),
|
||||
le16_to_cpu(params->dev_revid),
|
||||
suffix);
|
||||
break;
|
||||
case 0x11: /* JfP */
|
||||
case 0x12: /* ThP */
|
||||
case 0x13: /* HrP */
|
||||
case 0x14: /* CcP */
|
||||
snprintf(fw_name, len, "intel/ibt-%u-%u-%u.%s",
|
||||
le16_to_cpu(ver->hw_variant),
|
||||
le16_to_cpu(ver->hw_revision),
|
||||
le16_to_cpu(ver->fw_revision),
|
||||
suffix);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
{
|
||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
||||
@ -2106,7 +2132,7 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
case 0x11: /* JfP */
|
||||
case 0x12: /* ThP */
|
||||
case 0x13: /* HrP */
|
||||
case 0x14: /* QnJ, IcP */
|
||||
case 0x14: /* CcP */
|
||||
break;
|
||||
default:
|
||||
bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)",
|
||||
@ -2190,23 +2216,9 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
* ibt-<hw_variant>-<hw_revision>-<fw_revision>.sfi.
|
||||
*
|
||||
*/
|
||||
switch (ver.hw_variant) {
|
||||
case 0x0b: /* SfP */
|
||||
case 0x0c: /* WsP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params.dev_revid));
|
||||
break;
|
||||
case 0x11: /* JfP */
|
||||
case 0x12: /* ThP */
|
||||
case 0x13: /* HrP */
|
||||
case 0x14: /* QnJ, IcP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.sfi",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(ver.hw_revision),
|
||||
le16_to_cpu(ver.fw_revision));
|
||||
break;
|
||||
default:
|
||||
err = btusb_setup_intel_new_get_fw_name(&ver, ¶ms, fwname,
|
||||
sizeof(fwname), "sfi");
|
||||
if (!err) {
|
||||
bt_dev_err(hdev, "Unsupported Intel firmware naming");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -2222,23 +2234,9 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
||||
/* Save the DDC file name for later use to apply once the firmware
|
||||
* downloading is done.
|
||||
*/
|
||||
switch (ver.hw_variant) {
|
||||
case 0x0b: /* SfP */
|
||||
case 0x0c: /* WsP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params.dev_revid));
|
||||
break;
|
||||
case 0x11: /* JfP */
|
||||
case 0x12: /* ThP */
|
||||
case 0x13: /* HrP */
|
||||
case 0x14: /* QnJ, IcP */
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u-%u.ddc",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(ver.hw_revision),
|
||||
le16_to_cpu(ver.fw_revision));
|
||||
break;
|
||||
default:
|
||||
err = btusb_setup_intel_new_get_fw_name(&ver, ¶ms, fwname,
|
||||
sizeof(fwname), "ddc");
|
||||
if (!err) {
|
||||
bt_dev_err(hdev, "Unsupported Intel firmware naming");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <linux/property.h>
|
||||
#include <linux/platform_data/x86/apple.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/tty.h>
|
||||
@ -51,8 +52,16 @@
|
||||
#define BCM_LM_DIAG_PKT 0x07
|
||||
#define BCM_LM_DIAG_SIZE 63
|
||||
|
||||
#define BCM_TYPE49_PKT 0x31
|
||||
#define BCM_TYPE49_SIZE 0
|
||||
|
||||
#define BCM_TYPE52_PKT 0x34
|
||||
#define BCM_TYPE52_SIZE 0
|
||||
|
||||
#define BCM_AUTOSUSPEND_DELAY 5000 /* default autosleep delay */
|
||||
|
||||
#define BCM_NUM_SUPPLIES 2
|
||||
|
||||
/**
|
||||
* struct bcm_device - device driver resources
|
||||
* @serdev_hu: HCI UART controller struct
|
||||
@ -71,8 +80,10 @@
|
||||
* @btlp: Apple ACPI method to toggle BT_WAKE pin ("Bluetooth Low Power")
|
||||
* @btpu: Apple ACPI method to drive BT_REG_ON pin high ("Bluetooth Power Up")
|
||||
* @btpd: Apple ACPI method to drive BT_REG_ON pin low ("Bluetooth Power Down")
|
||||
* @clk: clock used by Bluetooth device
|
||||
* @clk_enabled: whether @clk is prepared and enabled
|
||||
* @txco_clk: external reference frequency clock used by Bluetooth device
|
||||
* @lpo_clk: external LPO clock used by Bluetooth device
|
||||
* @supplies: VBAT and VDDIO supplies used by Bluetooth device
|
||||
* @res_enabled: whether clocks and supplies are prepared and enabled
|
||||
* @init_speed: default baudrate of Bluetooth device;
|
||||
* the host UART is initially set to this baudrate so that
|
||||
* it can configure the Bluetooth device for @oper_speed
|
||||
@ -102,8 +113,10 @@ struct bcm_device {
|
||||
int gpio_int_idx;
|
||||
#endif
|
||||
|
||||
struct clk *clk;
|
||||
bool clk_enabled;
|
||||
struct clk *txco_clk;
|
||||
struct clk *lpo_clk;
|
||||
struct regulator_bulk_data supplies[BCM_NUM_SUPPLIES];
|
||||
bool res_enabled;
|
||||
|
||||
u32 init_speed;
|
||||
u32 oper_speed;
|
||||
@ -214,32 +227,59 @@ static int bcm_gpio_set_power(struct bcm_device *dev, bool powered)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (powered && !IS_ERR(dev->clk) && !dev->clk_enabled) {
|
||||
err = clk_prepare_enable(dev->clk);
|
||||
if (powered && !dev->res_enabled) {
|
||||
err = regulator_bulk_enable(BCM_NUM_SUPPLIES, dev->supplies);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* LPO clock needs to be 32.768 kHz */
|
||||
err = clk_set_rate(dev->lpo_clk, 32768);
|
||||
if (err) {
|
||||
dev_err(dev->dev, "Could not set LPO clock rate\n");
|
||||
goto err_regulator_disable;
|
||||
}
|
||||
|
||||
err = clk_prepare_enable(dev->lpo_clk);
|
||||
if (err)
|
||||
goto err_regulator_disable;
|
||||
|
||||
err = clk_prepare_enable(dev->txco_clk);
|
||||
if (err)
|
||||
goto err_lpo_clk_disable;
|
||||
}
|
||||
|
||||
err = dev->set_shutdown(dev, powered);
|
||||
if (err)
|
||||
goto err_clk_disable;
|
||||
goto err_txco_clk_disable;
|
||||
|
||||
err = dev->set_device_wakeup(dev, powered);
|
||||
if (err)
|
||||
goto err_revert_shutdown;
|
||||
|
||||
if (!powered && !IS_ERR(dev->clk) && dev->clk_enabled)
|
||||
clk_disable_unprepare(dev->clk);
|
||||
if (!powered && dev->res_enabled) {
|
||||
clk_disable_unprepare(dev->txco_clk);
|
||||
clk_disable_unprepare(dev->lpo_clk);
|
||||
regulator_bulk_disable(BCM_NUM_SUPPLIES, dev->supplies);
|
||||
}
|
||||
|
||||
dev->clk_enabled = powered;
|
||||
/* wait for device to power on and come out of reset */
|
||||
usleep_range(10000, 20000);
|
||||
|
||||
dev->res_enabled = powered;
|
||||
|
||||
return 0;
|
||||
|
||||
err_revert_shutdown:
|
||||
dev->set_shutdown(dev, !powered);
|
||||
err_clk_disable:
|
||||
if (powered && !IS_ERR(dev->clk) && !dev->clk_enabled)
|
||||
clk_disable_unprepare(dev->clk);
|
||||
err_txco_clk_disable:
|
||||
if (powered && !dev->res_enabled)
|
||||
clk_disable_unprepare(dev->txco_clk);
|
||||
err_lpo_clk_disable:
|
||||
if (powered && !dev->res_enabled)
|
||||
clk_disable_unprepare(dev->lpo_clk);
|
||||
err_regulator_disable:
|
||||
if (powered && !dev->res_enabled)
|
||||
regulator_bulk_disable(BCM_NUM_SUPPLIES, dev->supplies);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -561,12 +601,28 @@ finalize:
|
||||
.lsize = 0, \
|
||||
.maxlen = BCM_NULL_SIZE
|
||||
|
||||
#define BCM_RECV_TYPE49 \
|
||||
.type = BCM_TYPE49_PKT, \
|
||||
.hlen = BCM_TYPE49_SIZE, \
|
||||
.loff = 0, \
|
||||
.lsize = 0, \
|
||||
.maxlen = BCM_TYPE49_SIZE
|
||||
|
||||
#define BCM_RECV_TYPE52 \
|
||||
.type = BCM_TYPE52_PKT, \
|
||||
.hlen = BCM_TYPE52_SIZE, \
|
||||
.loff = 0, \
|
||||
.lsize = 0, \
|
||||
.maxlen = BCM_TYPE52_SIZE
|
||||
|
||||
static const struct h4_recv_pkt bcm_recv_pkts[] = {
|
||||
{ H4_RECV_ACL, .recv = hci_recv_frame },
|
||||
{ H4_RECV_SCO, .recv = hci_recv_frame },
|
||||
{ H4_RECV_EVENT, .recv = hci_recv_frame },
|
||||
{ BCM_RECV_LM_DIAG, .recv = hci_recv_diag },
|
||||
{ BCM_RECV_NULL, .recv = hci_recv_diag },
|
||||
{ BCM_RECV_TYPE49, .recv = hci_recv_diag },
|
||||
{ BCM_RECV_TYPE52, .recv = hci_recv_diag },
|
||||
};
|
||||
|
||||
static int bcm_recv(struct hci_uart *hu, const void *data, int count)
|
||||
@ -896,16 +952,57 @@ static int bcm_gpio_set_shutdown(struct bcm_device *dev, bool powered)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Try a bunch of names for TXCO */
|
||||
static struct clk *bcm_get_txco(struct device *dev)
|
||||
{
|
||||
struct clk *clk;
|
||||
|
||||
/* New explicit name */
|
||||
clk = devm_clk_get(dev, "txco");
|
||||
if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
|
||||
return clk;
|
||||
|
||||
/* Deprecated name */
|
||||
clk = devm_clk_get(dev, "extclk");
|
||||
if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
|
||||
return clk;
|
||||
|
||||
/* Original code used no name at all */
|
||||
return devm_clk_get(dev, NULL);
|
||||
}
|
||||
|
||||
static int bcm_get_resources(struct bcm_device *dev)
|
||||
{
|
||||
const struct dmi_system_id *dmi_id;
|
||||
int err;
|
||||
|
||||
dev->name = dev_name(dev->dev);
|
||||
|
||||
if (x86_apple_machine && !bcm_apple_get_resources(dev))
|
||||
return 0;
|
||||
|
||||
dev->clk = devm_clk_get(dev->dev, NULL);
|
||||
dev->txco_clk = bcm_get_txco(dev->dev);
|
||||
|
||||
/* Handle deferred probing */
|
||||
if (dev->txco_clk == ERR_PTR(-EPROBE_DEFER))
|
||||
return PTR_ERR(dev->txco_clk);
|
||||
|
||||
/* Ignore all other errors as before */
|
||||
if (IS_ERR(dev->txco_clk))
|
||||
dev->txco_clk = NULL;
|
||||
|
||||
dev->lpo_clk = devm_clk_get(dev->dev, "lpo");
|
||||
if (dev->lpo_clk == ERR_PTR(-EPROBE_DEFER))
|
||||
return PTR_ERR(dev->lpo_clk);
|
||||
|
||||
if (IS_ERR(dev->lpo_clk))
|
||||
dev->lpo_clk = NULL;
|
||||
|
||||
/* Check if we accidentally fetched the lpo clock twice */
|
||||
if (dev->lpo_clk && clk_is_match(dev->lpo_clk, dev->txco_clk)) {
|
||||
devm_clk_put(dev->dev, dev->txco_clk);
|
||||
dev->txco_clk = NULL;
|
||||
}
|
||||
|
||||
dev->device_wakeup = devm_gpiod_get_optional(dev->dev, "device-wakeup",
|
||||
GPIOD_OUT_LOW);
|
||||
@ -920,6 +1017,13 @@ static int bcm_get_resources(struct bcm_device *dev)
|
||||
dev->set_device_wakeup = bcm_gpio_set_device_wakeup;
|
||||
dev->set_shutdown = bcm_gpio_set_shutdown;
|
||||
|
||||
dev->supplies[0].supply = "vbat";
|
||||
dev->supplies[1].supply = "vddio";
|
||||
err = devm_regulator_bulk_get(dev->dev, BCM_NUM_SUPPLIES,
|
||||
dev->supplies);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* IRQ can be declared in ACPI table as Interrupt or GpioInt */
|
||||
if (dev->irq <= 0) {
|
||||
struct gpio_desc *gpio;
|
||||
@ -1314,6 +1418,8 @@ static void bcm_serdev_remove(struct serdev_device *serdev)
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id bcm_bluetooth_of_match[] = {
|
||||
{ .compatible = "brcm,bcm20702a1" },
|
||||
{ .compatible = "brcm,bcm4330-bt" },
|
||||
{ .compatible = "brcm,bcm43438-bt" },
|
||||
{ },
|
||||
};
|
||||
|
@ -115,6 +115,8 @@ struct h5_vnd {
|
||||
int (*setup)(struct h5 *h5);
|
||||
void (*open)(struct h5 *h5);
|
||||
void (*close)(struct h5 *h5);
|
||||
int (*suspend)(struct h5 *h5);
|
||||
int (*resume)(struct h5 *h5);
|
||||
const struct acpi_gpio_mapping *acpi_gpio_map;
|
||||
};
|
||||
|
||||
@ -841,6 +843,28 @@ static void h5_serdev_remove(struct serdev_device *serdev)
|
||||
hci_uart_unregister_device(&h5->serdev_hu);
|
||||
}
|
||||
|
||||
static int __maybe_unused h5_serdev_suspend(struct device *dev)
|
||||
{
|
||||
struct h5 *h5 = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (h5->vnd && h5->vnd->suspend)
|
||||
ret = h5->vnd->suspend(h5);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused h5_serdev_resume(struct device *dev)
|
||||
{
|
||||
struct h5 *h5 = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (h5->vnd && h5->vnd->resume)
|
||||
ret = h5->vnd->resume(h5);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_RTL
|
||||
static int h5_btrtl_setup(struct h5 *h5)
|
||||
{
|
||||
@ -907,6 +931,56 @@ static void h5_btrtl_close(struct h5 *h5)
|
||||
gpiod_set_value_cansleep(h5->enable_gpio, 0);
|
||||
}
|
||||
|
||||
/* Suspend/resume support. On many devices the RTL BT device loses power during
|
||||
* suspend/resume, causing it to lose its firmware and all state. So we simply
|
||||
* turn it off on suspend and reprobe on resume. This mirrors how RTL devices
|
||||
* are handled in the USB driver, where the USB_QUIRK_RESET_RESUME is used which
|
||||
* also causes a reprobe on resume.
|
||||
*/
|
||||
static int h5_btrtl_suspend(struct h5 *h5)
|
||||
{
|
||||
serdev_device_set_flow_control(h5->hu->serdev, false);
|
||||
gpiod_set_value_cansleep(h5->device_wake_gpio, 0);
|
||||
gpiod_set_value_cansleep(h5->enable_gpio, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct h5_btrtl_reprobe {
|
||||
struct device *dev;
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
static void h5_btrtl_reprobe_worker(struct work_struct *work)
|
||||
{
|
||||
struct h5_btrtl_reprobe *reprobe =
|
||||
container_of(work, struct h5_btrtl_reprobe, work);
|
||||
int ret;
|
||||
|
||||
ret = device_reprobe(reprobe->dev);
|
||||
if (ret && ret != -EPROBE_DEFER)
|
||||
dev_err(reprobe->dev, "Reprobe error %d\n", ret);
|
||||
|
||||
put_device(reprobe->dev);
|
||||
kfree(reprobe);
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
static int h5_btrtl_resume(struct h5 *h5)
|
||||
{
|
||||
struct h5_btrtl_reprobe *reprobe;
|
||||
|
||||
reprobe = kzalloc(sizeof(*reprobe), GFP_KERNEL);
|
||||
if (!reprobe)
|
||||
return -ENOMEM;
|
||||
|
||||
__module_get(THIS_MODULE);
|
||||
|
||||
INIT_WORK(&reprobe->work, h5_btrtl_reprobe_worker);
|
||||
reprobe->dev = get_device(&h5->hu->serdev->dev);
|
||||
queue_work(system_long_wq, &reprobe->work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct acpi_gpio_params btrtl_device_wake_gpios = { 0, 0, false };
|
||||
static const struct acpi_gpio_params btrtl_enable_gpios = { 1, 0, false };
|
||||
static const struct acpi_gpio_params btrtl_host_wake_gpios = { 2, 0, false };
|
||||
@ -921,6 +995,8 @@ static struct h5_vnd rtl_vnd = {
|
||||
.setup = h5_btrtl_setup,
|
||||
.open = h5_btrtl_open,
|
||||
.close = h5_btrtl_close,
|
||||
.suspend = h5_btrtl_suspend,
|
||||
.resume = h5_btrtl_resume,
|
||||
.acpi_gpio_map = acpi_btrtl_gpios,
|
||||
};
|
||||
#endif
|
||||
@ -935,12 +1011,17 @@ static const struct acpi_device_id h5_acpi_match[] = {
|
||||
MODULE_DEVICE_TABLE(acpi, h5_acpi_match);
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops h5_serdev_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(h5_serdev_suspend, h5_serdev_resume)
|
||||
};
|
||||
|
||||
static struct serdev_device_driver h5_serdev_driver = {
|
||||
.probe = h5_serdev_probe,
|
||||
.remove = h5_serdev_remove,
|
||||
.driver = {
|
||||
.name = "hci_uart_h5",
|
||||
.acpi_match_table = ACPI_PTR(h5_acpi_match),
|
||||
.pm = &h5_serdev_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -596,8 +596,8 @@ static int intel_setup(struct hci_uart *hu)
|
||||
* is in bootloader mode or if it already has operational firmware
|
||||
* loaded.
|
||||
*/
|
||||
err = btintel_read_version(hdev, &ver);
|
||||
if (err)
|
||||
err = btintel_read_version(hdev, &ver);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* The hardware platform number has a fixed value of 0x37 and
|
||||
@ -909,10 +909,8 @@ static int intel_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
set_bit(STATE_FIRMWARE_FAILED, &intel->flags);
|
||||
|
||||
if (test_and_clear_bit(STATE_DOWNLOADING, &intel->flags) &&
|
||||
test_bit(STATE_FIRMWARE_LOADED, &intel->flags)) {
|
||||
smp_mb__after_atomic();
|
||||
test_bit(STATE_FIRMWARE_LOADED, &intel->flags))
|
||||
wake_up_bit(&intel->flags, STATE_DOWNLOADING);
|
||||
}
|
||||
|
||||
/* When switching to the operational firmware the device
|
||||
* sends a vendor specific event indicating that the bootup
|
||||
@ -920,10 +918,8 @@ static int intel_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
*/
|
||||
} else if (skb->len == 9 && hdr->evt == 0xff && hdr->plen == 0x07 &&
|
||||
skb->data[2] == 0x02) {
|
||||
if (test_and_clear_bit(STATE_BOOTING, &intel->flags)) {
|
||||
smp_mb__after_atomic();
|
||||
if (test_and_clear_bit(STATE_BOOTING, &intel->flags))
|
||||
wake_up_bit(&intel->flags, STATE_BOOTING);
|
||||
}
|
||||
}
|
||||
recv:
|
||||
return hci_recv_frame(hdev, skb);
|
||||
@ -960,17 +956,13 @@ static int intel_recv_lpm(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
break;
|
||||
case LPM_OP_SUSPEND_ACK:
|
||||
set_bit(STATE_SUSPENDED, &intel->flags);
|
||||
if (test_and_clear_bit(STATE_LPM_TRANSACTION, &intel->flags)) {
|
||||
smp_mb__after_atomic();
|
||||
if (test_and_clear_bit(STATE_LPM_TRANSACTION, &intel->flags))
|
||||
wake_up_bit(&intel->flags, STATE_LPM_TRANSACTION);
|
||||
}
|
||||
break;
|
||||
case LPM_OP_RESUME_ACK:
|
||||
clear_bit(STATE_SUSPENDED, &intel->flags);
|
||||
if (test_and_clear_bit(STATE_LPM_TRANSACTION, &intel->flags)) {
|
||||
smp_mb__after_atomic();
|
||||
if (test_and_clear_bit(STATE_LPM_TRANSACTION, &intel->flags))
|
||||
wake_up_bit(&intel->flags, STATE_LPM_TRANSACTION);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
bt_dev_err(hdev, "Unknown LPM opcode (%02x)", lpm->opcode);
|
||||
|
@ -333,9 +333,6 @@ int hci_uart_register_device(struct hci_uart *hu,
|
||||
if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags))
|
||||
set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks);
|
||||
|
||||
if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags))
|
||||
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
||||
|
||||
if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags))
|
||||
hdev->dev_type = HCI_AMP;
|
||||
else
|
||||
|
@ -232,18 +232,7 @@ static int lowpan_context_show(struct seq_file *file, void *offset)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lowpan_context_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, lowpan_context_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations lowpan_context_fops = {
|
||||
.open = lowpan_context_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
DEFINE_SHOW_ATTRIBUTE(lowpan_context);
|
||||
|
||||
static int lowpan_short_addr_get(void *data, u64 *val)
|
||||
{
|
||||
|
@ -5711,6 +5711,12 @@ static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode,
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Check if request ended in Command Status - no way to retreive
|
||||
* any extra parameters in this case.
|
||||
*/
|
||||
if (hdr->evt == HCI_EV_CMD_STATUS)
|
||||
return false;
|
||||
|
||||
if (hdr->evt != HCI_EV_CMD_COMPLETE) {
|
||||
bt_dev_err(hdev, "last event is not cmd complete (0x%2.2x)",
|
||||
hdr->evt);
|
||||
|
@ -1556,7 +1556,7 @@ int __hci_req_setup_ext_adv_instance(struct hci_request *req, u8 instance)
|
||||
connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
|
||||
mgmt_get_connectable(hdev);
|
||||
|
||||
if (!is_advertising_allowed(hdev, connectable))
|
||||
if (!is_advertising_allowed(hdev, connectable))
|
||||
return -EPERM;
|
||||
|
||||
/* Set require_privacy to true only when non-connectable
|
||||
|
@ -7650,17 +7650,7 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l2cap_debugfs_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, l2cap_debugfs_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations l2cap_debugfs_fops = {
|
||||
.open = l2cap_debugfs_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
DEFINE_SHOW_ATTRIBUTE(l2cap_debugfs);
|
||||
|
||||
static struct dentry *l2cap_debugfs;
|
||||
|
||||
|
@ -2166,17 +2166,7 @@ static int rfcomm_dlc_debugfs_show(struct seq_file *f, void *x)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rfcomm_dlc_debugfs_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, rfcomm_dlc_debugfs_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations rfcomm_dlc_debugfs_fops = {
|
||||
.open = rfcomm_dlc_debugfs_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
DEFINE_SHOW_ATTRIBUTE(rfcomm_dlc_debugfs);
|
||||
|
||||
static struct dentry *rfcomm_dlc_debugfs;
|
||||
|
||||
|
@ -1020,17 +1020,7 @@ static int rfcomm_sock_debugfs_show(struct seq_file *f, void *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rfcomm_sock_debugfs_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, rfcomm_sock_debugfs_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations rfcomm_sock_debugfs_fops = {
|
||||
.open = rfcomm_sock_debugfs_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
DEFINE_SHOW_ATTRIBUTE(rfcomm_sock_debugfs);
|
||||
|
||||
static struct dentry *rfcomm_sock_debugfs;
|
||||
|
||||
|
@ -1173,17 +1173,7 @@ static int sco_debugfs_show(struct seq_file *f, void *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sco_debugfs_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, sco_debugfs_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations sco_debugfs_fops = {
|
||||
.open = sco_debugfs_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
DEFINE_SHOW_ATTRIBUTE(sco_debugfs);
|
||||
|
||||
static struct dentry *sco_debugfs;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user