Skip to content

Commit eb9e749

Browse files
kirankrishnappa-intelVudentz
authored andcommitted
Bluetooth: btintel: Allow configuring drive strength of BRI
BRI (Bluetooth Radio Interface) traffic from CNVr to CNVi was found causing cross talk step errors to WiFi. To avoid this potential issue OEM platforms can replace BRI resistor to adjust the BRI response line drive strength. During the *setup*, driver reads the drive strength value from uefi variable and passes it to the controller via vendor specific command with opcode 0xfc0a. dmesg: .. [21.982720] Bluetooth: hci0: Bootloader timestamp 2023.33 buildtype 1 build 45995 [21.984250] Bluetooth: hci0: Found device firmware: intel/ibt-0190-0291-iml.sfi [21.984255] Bluetooth: hci0: Boot Address: 0x30099000 [21.984256] Bluetooth: hci0: Firmware Version: 160-24.24 [22.011501] Bluetooth: hci0: Waiting for firmware download to complete [22.011518] Bluetooth: hci0: Firmware loaded in 26624 usecs [22.011584] Bluetooth: hci0: Waiting for device to boot [22.013546] Bluetooth: hci0: Malformed MSFT vendor event: 0x02 [22.013552] Bluetooth: hci0: Device booted in 1967 usecs ... [22.013792] Bluetooth: hci0: dsbr: enable: 0x01 value: 0x0b ... [22.015027] Bluetooth: hci0: Found device firmware: intel/ibt-0190-0291.sfi [22.015041] Bluetooth: hci0: Boot Address: 0x10000800 [22.015043] Bluetooth: hci0: Firmware Version: 160-24.24 [22.395821] Bluetooth: BNEP (Ethernet Emulation) ver 1.3 [22.395828] Bluetooth: BNEP filters: protocol multicast ... Signed-off-by: Kiran K <kiran.k@intel.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
1 parent 8af174e commit eb9e749

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed

drivers/bluetooth/btintel.c

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/acpi.h>
1313
#include <acpi/acpi_bus.h>
1414
#include <asm/unaligned.h>
15+
#include <linux/efi.h>
1516

1617
#include <net/bluetooth/bluetooth.h>
1718
#include <net/bluetooth/hci_core.h>
@@ -26,6 +27,8 @@
2627
#define ECDSA_OFFSET 644
2728
#define ECDSA_HEADER_LEN 320
2829

30+
#define BTINTEL_EFI_DSBR L"UefiCnvCommonDSBR"
31+
2932
enum {
3033
DSM_SET_WDISABLE2_DELAY = 1,
3134
DSM_SET_RESET_METHOD = 3,
@@ -2616,6 +2619,120 @@ static u8 btintel_classify_pkt_type(struct hci_dev *hdev, struct sk_buff *skb)
26162619
return hci_skb_pkt_type(skb);
26172620
}
26182621

2622+
/*
2623+
* UefiCnvCommonDSBR UEFI variable provides information from the OEM platforms
2624+
* if they have replaced the BRI (Bluetooth Radio Interface) resistor to
2625+
* overcome the potential STEP errors on their designs. Based on the
2626+
* configauration, bluetooth firmware shall adjust the BRI response line drive
2627+
* strength. The below structure represents DSBR data.
2628+
* struct {
2629+
* u8 header;
2630+
* u32 dsbr;
2631+
* } __packed;
2632+
*
2633+
* header - defines revision number of the structure
2634+
* dsbr - defines drive strength BRI response
2635+
* bit0
2636+
* 0 - instructs bluetooth firmware to use default values
2637+
* 1 - instructs bluetooth firmware to override default values
2638+
* bit3:1
2639+
* Reserved
2640+
* bit7:4
2641+
* DSBR override values (only if bit0 is set. Default value is 0xF
2642+
* bit31:7
2643+
* Reserved
2644+
* Expected values for dsbr field:
2645+
* 1. 0xF1 - indicates that the resistor on board is 33 Ohm
2646+
* 2. 0x00 or 0xB1 - indicates that the resistor on board is 10 Ohm
2647+
* 3. Non existing UEFI variable or invalid (none of the above) - indicates
2648+
* that the resistor on board is 10 Ohm
2649+
* Even if uefi variable is not present, driver shall send 0xfc0a command to
2650+
* firmware to use default values.
2651+
*
2652+
*/
2653+
static int btintel_uefi_get_dsbr(u32 *dsbr_var)
2654+
{
2655+
struct btintel_dsbr {
2656+
u8 header;
2657+
u32 dsbr;
2658+
} __packed data;
2659+
2660+
efi_status_t status;
2661+
unsigned long data_size = 0;
2662+
efi_guid_t guid = EFI_GUID(0xe65d8884, 0xd4af, 0x4b20, 0x8d, 0x03,
2663+
0x77, 0x2e, 0xcc, 0x3d, 0xa5, 0x31);
2664+
2665+
if (!IS_ENABLED(CONFIG_EFI))
2666+
return -EOPNOTSUPP;
2667+
2668+
if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
2669+
return -EOPNOTSUPP;
2670+
2671+
status = efi.get_variable(BTINTEL_EFI_DSBR, &guid, NULL, &data_size,
2672+
NULL);
2673+
2674+
if (status != EFI_BUFFER_TOO_SMALL || !data_size)
2675+
return -EIO;
2676+
2677+
status = efi.get_variable(BTINTEL_EFI_DSBR, &guid, NULL, &data_size,
2678+
&data);
2679+
2680+
if (status != EFI_SUCCESS)
2681+
return -ENXIO;
2682+
2683+
*dsbr_var = data.dsbr;
2684+
return 0;
2685+
}
2686+
2687+
static int btintel_set_dsbr(struct hci_dev *hdev, struct intel_version_tlv *ver)
2688+
{
2689+
struct btintel_dsbr_cmd {
2690+
u8 enable;
2691+
u8 dsbr;
2692+
} __packed;
2693+
2694+
struct btintel_dsbr_cmd cmd;
2695+
struct sk_buff *skb;
2696+
u8 status;
2697+
u32 dsbr;
2698+
bool apply_dsbr;
2699+
int err;
2700+
2701+
/* DSBR command needs to be sent for BlazarI + B0 step product after
2702+
* downloading IML image.
2703+
*/
2704+
apply_dsbr = (ver->img_type == BTINTEL_IMG_IML &&
2705+
((ver->cnvi_top & 0xfff) == BTINTEL_CNVI_BLAZARI) &&
2706+
INTEL_CNVX_TOP_STEP(ver->cnvi_top) == 0x01);
2707+
2708+
if (!apply_dsbr)
2709+
return 0;
2710+
2711+
dsbr = 0;
2712+
err = btintel_uefi_get_dsbr(&dsbr);
2713+
if (err < 0)
2714+
bt_dev_dbg(hdev, "Error reading efi: %ls (%d)",
2715+
BTINTEL_EFI_DSBR, err);
2716+
2717+
cmd.enable = dsbr & BIT(0);
2718+
cmd.dsbr = dsbr >> 4 & 0xF;
2719+
2720+
bt_dev_info(hdev, "dsbr: enable: 0x%2.2x value: 0x%2.2x", cmd.enable,
2721+
cmd.dsbr);
2722+
2723+
skb = __hci_cmd_sync(hdev, 0xfc0a, sizeof(cmd), &cmd, HCI_CMD_TIMEOUT);
2724+
if (IS_ERR(skb))
2725+
return -bt_to_errno(PTR_ERR(skb));
2726+
2727+
status = skb->data[0];
2728+
kfree_skb(skb);
2729+
2730+
if (status)
2731+
return -bt_to_errno(status);
2732+
2733+
return 0;
2734+
}
2735+
26192736
int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
26202737
struct intel_version_tlv *ver)
26212738
{
@@ -2650,6 +2767,13 @@ int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
26502767
if (err)
26512768
return err;
26522769

2770+
/* set drive strength of BRI response */
2771+
err = btintel_set_dsbr(hdev, ver);
2772+
if (err) {
2773+
bt_dev_err(hdev, "Failed to send dsbr command (%d)", err);
2774+
return err;
2775+
}
2776+
26532777
/* If image type returned is BTINTEL_IMG_IML, then controller supports
26542778
* intermediate loader image
26552779
*/

0 commit comments

Comments
 (0)