162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Bluetooth support for Intel devices 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2015 Intel Corporation 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/module.h> 1062306a36Sopenharmony_ci#include <linux/firmware.h> 1162306a36Sopenharmony_ci#include <linux/regmap.h> 1262306a36Sopenharmony_ci#include <linux/acpi.h> 1362306a36Sopenharmony_ci#include <acpi/acpi_bus.h> 1462306a36Sopenharmony_ci#include <asm/unaligned.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <net/bluetooth/bluetooth.h> 1762306a36Sopenharmony_ci#include <net/bluetooth/hci_core.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include "btintel.h" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define VERSION "0.1" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define BDADDR_INTEL (&(bdaddr_t){{0x00, 0x8b, 0x9e, 0x19, 0x03, 0x00}}) 2462306a36Sopenharmony_ci#define RSA_HEADER_LEN 644 2562306a36Sopenharmony_ci#define CSS_HEADER_OFFSET 8 2662306a36Sopenharmony_ci#define ECDSA_OFFSET 644 2762306a36Sopenharmony_ci#define ECDSA_HEADER_LEN 320 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#define BTINTEL_PPAG_NAME "PPAG" 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cienum { 3262306a36Sopenharmony_ci DSM_SET_WDISABLE2_DELAY = 1, 3362306a36Sopenharmony_ci DSM_SET_RESET_METHOD = 3, 3462306a36Sopenharmony_ci}; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/* structure to store the PPAG data read from ACPI table */ 3762306a36Sopenharmony_cistruct btintel_ppag { 3862306a36Sopenharmony_ci u32 domain; 3962306a36Sopenharmony_ci u32 mode; 4062306a36Sopenharmony_ci acpi_status status; 4162306a36Sopenharmony_ci struct hci_dev *hdev; 4262306a36Sopenharmony_ci}; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define CMD_WRITE_BOOT_PARAMS 0xfc0e 4562306a36Sopenharmony_cistruct cmd_write_boot_params { 4662306a36Sopenharmony_ci __le32 boot_addr; 4762306a36Sopenharmony_ci u8 fw_build_num; 4862306a36Sopenharmony_ci u8 fw_build_ww; 4962306a36Sopenharmony_ci u8 fw_build_yy; 5062306a36Sopenharmony_ci} __packed; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic struct { 5362306a36Sopenharmony_ci const char *driver_name; 5462306a36Sopenharmony_ci u8 hw_variant; 5562306a36Sopenharmony_ci u32 fw_build_num; 5662306a36Sopenharmony_ci} coredump_info; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic const guid_t btintel_guid_dsm = 5962306a36Sopenharmony_ci GUID_INIT(0xaa10f4e0, 0x81ac, 0x4233, 6062306a36Sopenharmony_ci 0xab, 0xf6, 0x3b, 0x2a, 0xc5, 0x0e, 0x28, 0xd9); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ciint btintel_check_bdaddr(struct hci_dev *hdev) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci struct hci_rp_read_bd_addr *bda; 6562306a36Sopenharmony_ci struct sk_buff *skb; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL, 6862306a36Sopenharmony_ci HCI_INIT_TIMEOUT); 6962306a36Sopenharmony_ci if (IS_ERR(skb)) { 7062306a36Sopenharmony_ci int err = PTR_ERR(skb); 7162306a36Sopenharmony_ci bt_dev_err(hdev, "Reading Intel device address failed (%d)", 7262306a36Sopenharmony_ci err); 7362306a36Sopenharmony_ci return err; 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if (skb->len != sizeof(*bda)) { 7762306a36Sopenharmony_ci bt_dev_err(hdev, "Intel device address length mismatch"); 7862306a36Sopenharmony_ci kfree_skb(skb); 7962306a36Sopenharmony_ci return -EIO; 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci bda = (struct hci_rp_read_bd_addr *)skb->data; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci /* For some Intel based controllers, the default Bluetooth device 8562306a36Sopenharmony_ci * address 00:03:19:9E:8B:00 can be found. These controllers are 8662306a36Sopenharmony_ci * fully operational, but have the danger of duplicate addresses 8762306a36Sopenharmony_ci * and that in turn can cause problems with Bluetooth operation. 8862306a36Sopenharmony_ci */ 8962306a36Sopenharmony_ci if (!bacmp(&bda->bdaddr, BDADDR_INTEL)) { 9062306a36Sopenharmony_ci bt_dev_err(hdev, "Found Intel default device address (%pMR)", 9162306a36Sopenharmony_ci &bda->bdaddr); 9262306a36Sopenharmony_ci set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci kfree_skb(skb); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci return 0; 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_check_bdaddr); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ciint btintel_enter_mfg(struct hci_dev *hdev) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci static const u8 param[] = { 0x01, 0x00 }; 10462306a36Sopenharmony_ci struct sk_buff *skb; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_CMD_TIMEOUT); 10762306a36Sopenharmony_ci if (IS_ERR(skb)) { 10862306a36Sopenharmony_ci bt_dev_err(hdev, "Entering manufacturer mode failed (%ld)", 10962306a36Sopenharmony_ci PTR_ERR(skb)); 11062306a36Sopenharmony_ci return PTR_ERR(skb); 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci kfree_skb(skb); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci return 0; 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_enter_mfg); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ciint btintel_exit_mfg(struct hci_dev *hdev, bool reset, bool patched) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci u8 param[] = { 0x00, 0x00 }; 12162306a36Sopenharmony_ci struct sk_buff *skb; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci /* The 2nd command parameter specifies the manufacturing exit method: 12462306a36Sopenharmony_ci * 0x00: Just disable the manufacturing mode (0x00). 12562306a36Sopenharmony_ci * 0x01: Disable manufacturing mode and reset with patches deactivated. 12662306a36Sopenharmony_ci * 0x02: Disable manufacturing mode and reset with patches activated. 12762306a36Sopenharmony_ci */ 12862306a36Sopenharmony_ci if (reset) 12962306a36Sopenharmony_ci param[1] |= patched ? 0x02 : 0x01; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_CMD_TIMEOUT); 13262306a36Sopenharmony_ci if (IS_ERR(skb)) { 13362306a36Sopenharmony_ci bt_dev_err(hdev, "Exiting manufacturer mode failed (%ld)", 13462306a36Sopenharmony_ci PTR_ERR(skb)); 13562306a36Sopenharmony_ci return PTR_ERR(skb); 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci kfree_skb(skb); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci return 0; 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_exit_mfg); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ciint btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci struct sk_buff *skb; 14662306a36Sopenharmony_ci int err; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc31, 6, bdaddr, HCI_INIT_TIMEOUT); 14962306a36Sopenharmony_ci if (IS_ERR(skb)) { 15062306a36Sopenharmony_ci err = PTR_ERR(skb); 15162306a36Sopenharmony_ci bt_dev_err(hdev, "Changing Intel device address failed (%d)", 15262306a36Sopenharmony_ci err); 15362306a36Sopenharmony_ci return err; 15462306a36Sopenharmony_ci } 15562306a36Sopenharmony_ci kfree_skb(skb); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci return 0; 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_set_bdaddr); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistatic int btintel_set_event_mask(struct hci_dev *hdev, bool debug) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci u8 mask[8] = { 0x87, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 16462306a36Sopenharmony_ci struct sk_buff *skb; 16562306a36Sopenharmony_ci int err; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci if (debug) 16862306a36Sopenharmony_ci mask[1] |= 0x62; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc52, 8, mask, HCI_INIT_TIMEOUT); 17162306a36Sopenharmony_ci if (IS_ERR(skb)) { 17262306a36Sopenharmony_ci err = PTR_ERR(skb); 17362306a36Sopenharmony_ci bt_dev_err(hdev, "Setting Intel event mask failed (%d)", err); 17462306a36Sopenharmony_ci return err; 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci kfree_skb(skb); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci return 0; 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ciint btintel_set_diag(struct hci_dev *hdev, bool enable) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci struct sk_buff *skb; 18462306a36Sopenharmony_ci u8 param[3]; 18562306a36Sopenharmony_ci int err; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci if (enable) { 18862306a36Sopenharmony_ci param[0] = 0x03; 18962306a36Sopenharmony_ci param[1] = 0x03; 19062306a36Sopenharmony_ci param[2] = 0x03; 19162306a36Sopenharmony_ci } else { 19262306a36Sopenharmony_ci param[0] = 0x00; 19362306a36Sopenharmony_ci param[1] = 0x00; 19462306a36Sopenharmony_ci param[2] = 0x00; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc43, 3, param, HCI_INIT_TIMEOUT); 19862306a36Sopenharmony_ci if (IS_ERR(skb)) { 19962306a36Sopenharmony_ci err = PTR_ERR(skb); 20062306a36Sopenharmony_ci if (err == -ENODATA) 20162306a36Sopenharmony_ci goto done; 20262306a36Sopenharmony_ci bt_dev_err(hdev, "Changing Intel diagnostic mode failed (%d)", 20362306a36Sopenharmony_ci err); 20462306a36Sopenharmony_ci return err; 20562306a36Sopenharmony_ci } 20662306a36Sopenharmony_ci kfree_skb(skb); 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cidone: 20962306a36Sopenharmony_ci btintel_set_event_mask(hdev, enable); 21062306a36Sopenharmony_ci return 0; 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_set_diag); 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_cistatic int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable) 21562306a36Sopenharmony_ci{ 21662306a36Sopenharmony_ci int err, ret; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci err = btintel_enter_mfg(hdev); 21962306a36Sopenharmony_ci if (err) 22062306a36Sopenharmony_ci return err; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci ret = btintel_set_diag(hdev, enable); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci err = btintel_exit_mfg(hdev, false, false); 22562306a36Sopenharmony_ci if (err) 22662306a36Sopenharmony_ci return err; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci return ret; 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic int btintel_set_diag_combined(struct hci_dev *hdev, bool enable) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci int ret; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci /* Legacy ROM device needs to be in the manufacturer mode to apply 23662306a36Sopenharmony_ci * diagnostic setting 23762306a36Sopenharmony_ci * 23862306a36Sopenharmony_ci * This flag is set after reading the Intel version. 23962306a36Sopenharmony_ci */ 24062306a36Sopenharmony_ci if (btintel_test_flag(hdev, INTEL_ROM_LEGACY)) 24162306a36Sopenharmony_ci ret = btintel_set_diag_mfg(hdev, enable); 24262306a36Sopenharmony_ci else 24362306a36Sopenharmony_ci ret = btintel_set_diag(hdev, enable); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci return ret; 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic void btintel_hw_error(struct hci_dev *hdev, u8 code) 24962306a36Sopenharmony_ci{ 25062306a36Sopenharmony_ci struct sk_buff *skb; 25162306a36Sopenharmony_ci u8 type = 0x00; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci bt_dev_err(hdev, "Hardware error 0x%2.2x", code); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); 25662306a36Sopenharmony_ci if (IS_ERR(skb)) { 25762306a36Sopenharmony_ci bt_dev_err(hdev, "Reset after hardware error failed (%ld)", 25862306a36Sopenharmony_ci PTR_ERR(skb)); 25962306a36Sopenharmony_ci return; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci kfree_skb(skb); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc22, 1, &type, HCI_INIT_TIMEOUT); 26462306a36Sopenharmony_ci if (IS_ERR(skb)) { 26562306a36Sopenharmony_ci bt_dev_err(hdev, "Retrieving Intel exception info failed (%ld)", 26662306a36Sopenharmony_ci PTR_ERR(skb)); 26762306a36Sopenharmony_ci return; 26862306a36Sopenharmony_ci } 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci if (skb->len != 13) { 27162306a36Sopenharmony_ci bt_dev_err(hdev, "Exception info size mismatch"); 27262306a36Sopenharmony_ci kfree_skb(skb); 27362306a36Sopenharmony_ci return; 27462306a36Sopenharmony_ci } 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci bt_dev_err(hdev, "Exception info %s", (char *)(skb->data + 1)); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci kfree_skb(skb); 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ciint btintel_version_info(struct hci_dev *hdev, struct intel_version *ver) 28262306a36Sopenharmony_ci{ 28362306a36Sopenharmony_ci const char *variant; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci /* The hardware platform number has a fixed value of 0x37 and 28662306a36Sopenharmony_ci * for now only accept this single value. 28762306a36Sopenharmony_ci */ 28862306a36Sopenharmony_ci if (ver->hw_platform != 0x37) { 28962306a36Sopenharmony_ci bt_dev_err(hdev, "Unsupported Intel hardware platform (%u)", 29062306a36Sopenharmony_ci ver->hw_platform); 29162306a36Sopenharmony_ci return -EINVAL; 29262306a36Sopenharmony_ci } 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci /* Check for supported iBT hardware variants of this firmware 29562306a36Sopenharmony_ci * loading method. 29662306a36Sopenharmony_ci * 29762306a36Sopenharmony_ci * This check has been put in place to ensure correct forward 29862306a36Sopenharmony_ci * compatibility options when newer hardware variants come along. 29962306a36Sopenharmony_ci */ 30062306a36Sopenharmony_ci switch (ver->hw_variant) { 30162306a36Sopenharmony_ci case 0x07: /* WP - Legacy ROM */ 30262306a36Sopenharmony_ci case 0x08: /* StP - Legacy ROM */ 30362306a36Sopenharmony_ci case 0x0b: /* SfP */ 30462306a36Sopenharmony_ci case 0x0c: /* WsP */ 30562306a36Sopenharmony_ci case 0x11: /* JfP */ 30662306a36Sopenharmony_ci case 0x12: /* ThP */ 30762306a36Sopenharmony_ci case 0x13: /* HrP */ 30862306a36Sopenharmony_ci case 0x14: /* CcP */ 30962306a36Sopenharmony_ci break; 31062306a36Sopenharmony_ci default: 31162306a36Sopenharmony_ci bt_dev_err(hdev, "Unsupported Intel hardware variant (%u)", 31262306a36Sopenharmony_ci ver->hw_variant); 31362306a36Sopenharmony_ci return -EINVAL; 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci switch (ver->fw_variant) { 31762306a36Sopenharmony_ci case 0x01: 31862306a36Sopenharmony_ci variant = "Legacy ROM 2.5"; 31962306a36Sopenharmony_ci break; 32062306a36Sopenharmony_ci case 0x06: 32162306a36Sopenharmony_ci variant = "Bootloader"; 32262306a36Sopenharmony_ci break; 32362306a36Sopenharmony_ci case 0x22: 32462306a36Sopenharmony_ci variant = "Legacy ROM 2.x"; 32562306a36Sopenharmony_ci break; 32662306a36Sopenharmony_ci case 0x23: 32762306a36Sopenharmony_ci variant = "Firmware"; 32862306a36Sopenharmony_ci break; 32962306a36Sopenharmony_ci default: 33062306a36Sopenharmony_ci bt_dev_err(hdev, "Unsupported firmware variant(%02x)", ver->fw_variant); 33162306a36Sopenharmony_ci return -EINVAL; 33262306a36Sopenharmony_ci } 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci coredump_info.hw_variant = ver->hw_variant; 33562306a36Sopenharmony_ci coredump_info.fw_build_num = ver->fw_build_num; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci bt_dev_info(hdev, "%s revision %u.%u build %u week %u %u", 33862306a36Sopenharmony_ci variant, ver->fw_revision >> 4, ver->fw_revision & 0x0f, 33962306a36Sopenharmony_ci ver->fw_build_num, ver->fw_build_ww, 34062306a36Sopenharmony_ci 2000 + ver->fw_build_yy); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci return 0; 34362306a36Sopenharmony_ci} 34462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_version_info); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_cistatic int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen, 34762306a36Sopenharmony_ci const void *param) 34862306a36Sopenharmony_ci{ 34962306a36Sopenharmony_ci while (plen > 0) { 35062306a36Sopenharmony_ci struct sk_buff *skb; 35162306a36Sopenharmony_ci u8 cmd_param[253], fragment_len = (plen > 252) ? 252 : plen; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci cmd_param[0] = fragment_type; 35462306a36Sopenharmony_ci memcpy(cmd_param + 1, param, fragment_len); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc09, fragment_len + 1, 35762306a36Sopenharmony_ci cmd_param, HCI_INIT_TIMEOUT); 35862306a36Sopenharmony_ci if (IS_ERR(skb)) 35962306a36Sopenharmony_ci return PTR_ERR(skb); 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci kfree_skb(skb); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci plen -= fragment_len; 36462306a36Sopenharmony_ci param += fragment_len; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci return 0; 36862306a36Sopenharmony_ci} 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ciint btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name) 37162306a36Sopenharmony_ci{ 37262306a36Sopenharmony_ci const struct firmware *fw; 37362306a36Sopenharmony_ci struct sk_buff *skb; 37462306a36Sopenharmony_ci const u8 *fw_ptr; 37562306a36Sopenharmony_ci int err; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci err = request_firmware_direct(&fw, ddc_name, &hdev->dev); 37862306a36Sopenharmony_ci if (err < 0) { 37962306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to load Intel DDC file %s (%d)", 38062306a36Sopenharmony_ci ddc_name, err); 38162306a36Sopenharmony_ci return err; 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci bt_dev_info(hdev, "Found Intel DDC parameters: %s", ddc_name); 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci fw_ptr = fw->data; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci /* DDC file contains one or more DDC structure which has 38962306a36Sopenharmony_ci * Length (1 byte), DDC ID (2 bytes), and DDC value (Length - 2). 39062306a36Sopenharmony_ci */ 39162306a36Sopenharmony_ci while (fw->size > fw_ptr - fw->data) { 39262306a36Sopenharmony_ci u8 cmd_plen = fw_ptr[0] + sizeof(u8); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc8b, cmd_plen, fw_ptr, 39562306a36Sopenharmony_ci HCI_INIT_TIMEOUT); 39662306a36Sopenharmony_ci if (IS_ERR(skb)) { 39762306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to send Intel_Write_DDC (%ld)", 39862306a36Sopenharmony_ci PTR_ERR(skb)); 39962306a36Sopenharmony_ci release_firmware(fw); 40062306a36Sopenharmony_ci return PTR_ERR(skb); 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci fw_ptr += cmd_plen; 40462306a36Sopenharmony_ci kfree_skb(skb); 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci release_firmware(fw); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci bt_dev_info(hdev, "Applying Intel DDC parameters completed"); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci return 0; 41262306a36Sopenharmony_ci} 41362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_load_ddc_config); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ciint btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci int err, ret; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci err = btintel_enter_mfg(hdev); 42062306a36Sopenharmony_ci if (err) 42162306a36Sopenharmony_ci return err; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci ret = btintel_set_event_mask(hdev, debug); 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci err = btintel_exit_mfg(hdev, false, false); 42662306a36Sopenharmony_ci if (err) 42762306a36Sopenharmony_ci return err; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci return ret; 43062306a36Sopenharmony_ci} 43162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_set_event_mask_mfg); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ciint btintel_read_version(struct hci_dev *hdev, struct intel_version *ver) 43462306a36Sopenharmony_ci{ 43562306a36Sopenharmony_ci struct sk_buff *skb; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc05, 0, NULL, HCI_CMD_TIMEOUT); 43862306a36Sopenharmony_ci if (IS_ERR(skb)) { 43962306a36Sopenharmony_ci bt_dev_err(hdev, "Reading Intel version information failed (%ld)", 44062306a36Sopenharmony_ci PTR_ERR(skb)); 44162306a36Sopenharmony_ci return PTR_ERR(skb); 44262306a36Sopenharmony_ci } 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci if (skb->len != sizeof(*ver)) { 44562306a36Sopenharmony_ci bt_dev_err(hdev, "Intel version event size mismatch"); 44662306a36Sopenharmony_ci kfree_skb(skb); 44762306a36Sopenharmony_ci return -EILSEQ; 44862306a36Sopenharmony_ci } 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci memcpy(ver, skb->data, sizeof(*ver)); 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci kfree_skb(skb); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci return 0; 45562306a36Sopenharmony_ci} 45662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_read_version); 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_cistatic int btintel_version_info_tlv(struct hci_dev *hdev, 45962306a36Sopenharmony_ci struct intel_version_tlv *version) 46062306a36Sopenharmony_ci{ 46162306a36Sopenharmony_ci const char *variant; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci /* The hardware platform number has a fixed value of 0x37 and 46462306a36Sopenharmony_ci * for now only accept this single value. 46562306a36Sopenharmony_ci */ 46662306a36Sopenharmony_ci if (INTEL_HW_PLATFORM(version->cnvi_bt) != 0x37) { 46762306a36Sopenharmony_ci bt_dev_err(hdev, "Unsupported Intel hardware platform (0x%2x)", 46862306a36Sopenharmony_ci INTEL_HW_PLATFORM(version->cnvi_bt)); 46962306a36Sopenharmony_ci return -EINVAL; 47062306a36Sopenharmony_ci } 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci /* Check for supported iBT hardware variants of this firmware 47362306a36Sopenharmony_ci * loading method. 47462306a36Sopenharmony_ci * 47562306a36Sopenharmony_ci * This check has been put in place to ensure correct forward 47662306a36Sopenharmony_ci * compatibility options when newer hardware variants come along. 47762306a36Sopenharmony_ci */ 47862306a36Sopenharmony_ci switch (INTEL_HW_VARIANT(version->cnvi_bt)) { 47962306a36Sopenharmony_ci case 0x17: /* TyP */ 48062306a36Sopenharmony_ci case 0x18: /* Slr */ 48162306a36Sopenharmony_ci case 0x19: /* Slr-F */ 48262306a36Sopenharmony_ci case 0x1b: /* Mgr */ 48362306a36Sopenharmony_ci case 0x1c: /* Gale Peak (GaP) */ 48462306a36Sopenharmony_ci break; 48562306a36Sopenharmony_ci default: 48662306a36Sopenharmony_ci bt_dev_err(hdev, "Unsupported Intel hardware variant (0x%x)", 48762306a36Sopenharmony_ci INTEL_HW_VARIANT(version->cnvi_bt)); 48862306a36Sopenharmony_ci return -EINVAL; 48962306a36Sopenharmony_ci } 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci switch (version->img_type) { 49262306a36Sopenharmony_ci case 0x01: 49362306a36Sopenharmony_ci variant = "Bootloader"; 49462306a36Sopenharmony_ci /* It is required that every single firmware fragment is acknowledged 49562306a36Sopenharmony_ci * with a command complete event. If the boot parameters indicate 49662306a36Sopenharmony_ci * that this bootloader does not send them, then abort the setup. 49762306a36Sopenharmony_ci */ 49862306a36Sopenharmony_ci if (version->limited_cce != 0x00) { 49962306a36Sopenharmony_ci bt_dev_err(hdev, "Unsupported Intel firmware loading method (0x%x)", 50062306a36Sopenharmony_ci version->limited_cce); 50162306a36Sopenharmony_ci return -EINVAL; 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci /* Secure boot engine type should be either 1 (ECDSA) or 0 (RSA) */ 50562306a36Sopenharmony_ci if (version->sbe_type > 0x01) { 50662306a36Sopenharmony_ci bt_dev_err(hdev, "Unsupported Intel secure boot engine type (0x%x)", 50762306a36Sopenharmony_ci version->sbe_type); 50862306a36Sopenharmony_ci return -EINVAL; 50962306a36Sopenharmony_ci } 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci bt_dev_info(hdev, "Device revision is %u", version->dev_rev_id); 51262306a36Sopenharmony_ci bt_dev_info(hdev, "Secure boot is %s", 51362306a36Sopenharmony_ci version->secure_boot ? "enabled" : "disabled"); 51462306a36Sopenharmony_ci bt_dev_info(hdev, "OTP lock is %s", 51562306a36Sopenharmony_ci version->otp_lock ? "enabled" : "disabled"); 51662306a36Sopenharmony_ci bt_dev_info(hdev, "API lock is %s", 51762306a36Sopenharmony_ci version->api_lock ? "enabled" : "disabled"); 51862306a36Sopenharmony_ci bt_dev_info(hdev, "Debug lock is %s", 51962306a36Sopenharmony_ci version->debug_lock ? "enabled" : "disabled"); 52062306a36Sopenharmony_ci bt_dev_info(hdev, "Minimum firmware build %u week %u %u", 52162306a36Sopenharmony_ci version->min_fw_build_nn, version->min_fw_build_cw, 52262306a36Sopenharmony_ci 2000 + version->min_fw_build_yy); 52362306a36Sopenharmony_ci break; 52462306a36Sopenharmony_ci case 0x03: 52562306a36Sopenharmony_ci variant = "Firmware"; 52662306a36Sopenharmony_ci break; 52762306a36Sopenharmony_ci default: 52862306a36Sopenharmony_ci bt_dev_err(hdev, "Unsupported image type(%02x)", version->img_type); 52962306a36Sopenharmony_ci return -EINVAL; 53062306a36Sopenharmony_ci } 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci coredump_info.hw_variant = INTEL_HW_VARIANT(version->cnvi_bt); 53362306a36Sopenharmony_ci coredump_info.fw_build_num = version->build_num; 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci bt_dev_info(hdev, "%s timestamp %u.%u buildtype %u build %u", variant, 53662306a36Sopenharmony_ci 2000 + (version->timestamp >> 8), version->timestamp & 0xff, 53762306a36Sopenharmony_ci version->build_type, version->build_num); 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci return 0; 54062306a36Sopenharmony_ci} 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_cistatic int btintel_parse_version_tlv(struct hci_dev *hdev, 54362306a36Sopenharmony_ci struct intel_version_tlv *version, 54462306a36Sopenharmony_ci struct sk_buff *skb) 54562306a36Sopenharmony_ci{ 54662306a36Sopenharmony_ci /* Consume Command Complete Status field */ 54762306a36Sopenharmony_ci skb_pull(skb, 1); 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci /* Event parameters contatin multiple TLVs. Read each of them 55062306a36Sopenharmony_ci * and only keep the required data. Also, it use existing legacy 55162306a36Sopenharmony_ci * version field like hw_platform, hw_variant, and fw_variant 55262306a36Sopenharmony_ci * to keep the existing setup flow 55362306a36Sopenharmony_ci */ 55462306a36Sopenharmony_ci while (skb->len) { 55562306a36Sopenharmony_ci struct intel_tlv *tlv; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci /* Make sure skb has a minimum length of the header */ 55862306a36Sopenharmony_ci if (skb->len < sizeof(*tlv)) 55962306a36Sopenharmony_ci return -EINVAL; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci tlv = (struct intel_tlv *)skb->data; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci /* Make sure skb has a enough data */ 56462306a36Sopenharmony_ci if (skb->len < tlv->len + sizeof(*tlv)) 56562306a36Sopenharmony_ci return -EINVAL; 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci switch (tlv->type) { 56862306a36Sopenharmony_ci case INTEL_TLV_CNVI_TOP: 56962306a36Sopenharmony_ci version->cnvi_top = get_unaligned_le32(tlv->val); 57062306a36Sopenharmony_ci break; 57162306a36Sopenharmony_ci case INTEL_TLV_CNVR_TOP: 57262306a36Sopenharmony_ci version->cnvr_top = get_unaligned_le32(tlv->val); 57362306a36Sopenharmony_ci break; 57462306a36Sopenharmony_ci case INTEL_TLV_CNVI_BT: 57562306a36Sopenharmony_ci version->cnvi_bt = get_unaligned_le32(tlv->val); 57662306a36Sopenharmony_ci break; 57762306a36Sopenharmony_ci case INTEL_TLV_CNVR_BT: 57862306a36Sopenharmony_ci version->cnvr_bt = get_unaligned_le32(tlv->val); 57962306a36Sopenharmony_ci break; 58062306a36Sopenharmony_ci case INTEL_TLV_DEV_REV_ID: 58162306a36Sopenharmony_ci version->dev_rev_id = get_unaligned_le16(tlv->val); 58262306a36Sopenharmony_ci break; 58362306a36Sopenharmony_ci case INTEL_TLV_IMAGE_TYPE: 58462306a36Sopenharmony_ci version->img_type = tlv->val[0]; 58562306a36Sopenharmony_ci break; 58662306a36Sopenharmony_ci case INTEL_TLV_TIME_STAMP: 58762306a36Sopenharmony_ci /* If image type is Operational firmware (0x03), then 58862306a36Sopenharmony_ci * running FW Calendar Week and Year information can 58962306a36Sopenharmony_ci * be extracted from Timestamp information 59062306a36Sopenharmony_ci */ 59162306a36Sopenharmony_ci version->min_fw_build_cw = tlv->val[0]; 59262306a36Sopenharmony_ci version->min_fw_build_yy = tlv->val[1]; 59362306a36Sopenharmony_ci version->timestamp = get_unaligned_le16(tlv->val); 59462306a36Sopenharmony_ci break; 59562306a36Sopenharmony_ci case INTEL_TLV_BUILD_TYPE: 59662306a36Sopenharmony_ci version->build_type = tlv->val[0]; 59762306a36Sopenharmony_ci break; 59862306a36Sopenharmony_ci case INTEL_TLV_BUILD_NUM: 59962306a36Sopenharmony_ci /* If image type is Operational firmware (0x03), then 60062306a36Sopenharmony_ci * running FW build number can be extracted from the 60162306a36Sopenharmony_ci * Build information 60262306a36Sopenharmony_ci */ 60362306a36Sopenharmony_ci version->min_fw_build_nn = tlv->val[0]; 60462306a36Sopenharmony_ci version->build_num = get_unaligned_le32(tlv->val); 60562306a36Sopenharmony_ci break; 60662306a36Sopenharmony_ci case INTEL_TLV_SECURE_BOOT: 60762306a36Sopenharmony_ci version->secure_boot = tlv->val[0]; 60862306a36Sopenharmony_ci break; 60962306a36Sopenharmony_ci case INTEL_TLV_OTP_LOCK: 61062306a36Sopenharmony_ci version->otp_lock = tlv->val[0]; 61162306a36Sopenharmony_ci break; 61262306a36Sopenharmony_ci case INTEL_TLV_API_LOCK: 61362306a36Sopenharmony_ci version->api_lock = tlv->val[0]; 61462306a36Sopenharmony_ci break; 61562306a36Sopenharmony_ci case INTEL_TLV_DEBUG_LOCK: 61662306a36Sopenharmony_ci version->debug_lock = tlv->val[0]; 61762306a36Sopenharmony_ci break; 61862306a36Sopenharmony_ci case INTEL_TLV_MIN_FW: 61962306a36Sopenharmony_ci version->min_fw_build_nn = tlv->val[0]; 62062306a36Sopenharmony_ci version->min_fw_build_cw = tlv->val[1]; 62162306a36Sopenharmony_ci version->min_fw_build_yy = tlv->val[2]; 62262306a36Sopenharmony_ci break; 62362306a36Sopenharmony_ci case INTEL_TLV_LIMITED_CCE: 62462306a36Sopenharmony_ci version->limited_cce = tlv->val[0]; 62562306a36Sopenharmony_ci break; 62662306a36Sopenharmony_ci case INTEL_TLV_SBE_TYPE: 62762306a36Sopenharmony_ci version->sbe_type = tlv->val[0]; 62862306a36Sopenharmony_ci break; 62962306a36Sopenharmony_ci case INTEL_TLV_OTP_BDADDR: 63062306a36Sopenharmony_ci memcpy(&version->otp_bd_addr, tlv->val, 63162306a36Sopenharmony_ci sizeof(bdaddr_t)); 63262306a36Sopenharmony_ci break; 63362306a36Sopenharmony_ci default: 63462306a36Sopenharmony_ci /* Ignore rest of information */ 63562306a36Sopenharmony_ci break; 63662306a36Sopenharmony_ci } 63762306a36Sopenharmony_ci /* consume the current tlv and move to next*/ 63862306a36Sopenharmony_ci skb_pull(skb, tlv->len + sizeof(*tlv)); 63962306a36Sopenharmony_ci } 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci return 0; 64262306a36Sopenharmony_ci} 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_cistatic int btintel_read_version_tlv(struct hci_dev *hdev, 64562306a36Sopenharmony_ci struct intel_version_tlv *version) 64662306a36Sopenharmony_ci{ 64762306a36Sopenharmony_ci struct sk_buff *skb; 64862306a36Sopenharmony_ci const u8 param[1] = { 0xFF }; 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci if (!version) 65162306a36Sopenharmony_ci return -EINVAL; 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc05, 1, param, HCI_CMD_TIMEOUT); 65462306a36Sopenharmony_ci if (IS_ERR(skb)) { 65562306a36Sopenharmony_ci bt_dev_err(hdev, "Reading Intel version information failed (%ld)", 65662306a36Sopenharmony_ci PTR_ERR(skb)); 65762306a36Sopenharmony_ci return PTR_ERR(skb); 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci if (skb->data[0]) { 66162306a36Sopenharmony_ci bt_dev_err(hdev, "Intel Read Version command failed (%02x)", 66262306a36Sopenharmony_ci skb->data[0]); 66362306a36Sopenharmony_ci kfree_skb(skb); 66462306a36Sopenharmony_ci return -EIO; 66562306a36Sopenharmony_ci } 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci btintel_parse_version_tlv(hdev, version, skb); 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci kfree_skb(skb); 67062306a36Sopenharmony_ci return 0; 67162306a36Sopenharmony_ci} 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci/* ------- REGMAP IBT SUPPORT ------- */ 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci#define IBT_REG_MODE_8BIT 0x00 67662306a36Sopenharmony_ci#define IBT_REG_MODE_16BIT 0x01 67762306a36Sopenharmony_ci#define IBT_REG_MODE_32BIT 0x02 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_cistruct regmap_ibt_context { 68062306a36Sopenharmony_ci struct hci_dev *hdev; 68162306a36Sopenharmony_ci __u16 op_write; 68262306a36Sopenharmony_ci __u16 op_read; 68362306a36Sopenharmony_ci}; 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_cistruct ibt_cp_reg_access { 68662306a36Sopenharmony_ci __le32 addr; 68762306a36Sopenharmony_ci __u8 mode; 68862306a36Sopenharmony_ci __u8 len; 68962306a36Sopenharmony_ci __u8 data[]; 69062306a36Sopenharmony_ci} __packed; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_cistruct ibt_rp_reg_access { 69362306a36Sopenharmony_ci __u8 status; 69462306a36Sopenharmony_ci __le32 addr; 69562306a36Sopenharmony_ci __u8 data[]; 69662306a36Sopenharmony_ci} __packed; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_cistatic int regmap_ibt_read(void *context, const void *addr, size_t reg_size, 69962306a36Sopenharmony_ci void *val, size_t val_size) 70062306a36Sopenharmony_ci{ 70162306a36Sopenharmony_ci struct regmap_ibt_context *ctx = context; 70262306a36Sopenharmony_ci struct ibt_cp_reg_access cp; 70362306a36Sopenharmony_ci struct ibt_rp_reg_access *rp; 70462306a36Sopenharmony_ci struct sk_buff *skb; 70562306a36Sopenharmony_ci int err = 0; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci if (reg_size != sizeof(__le32)) 70862306a36Sopenharmony_ci return -EINVAL; 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci switch (val_size) { 71162306a36Sopenharmony_ci case 1: 71262306a36Sopenharmony_ci cp.mode = IBT_REG_MODE_8BIT; 71362306a36Sopenharmony_ci break; 71462306a36Sopenharmony_ci case 2: 71562306a36Sopenharmony_ci cp.mode = IBT_REG_MODE_16BIT; 71662306a36Sopenharmony_ci break; 71762306a36Sopenharmony_ci case 4: 71862306a36Sopenharmony_ci cp.mode = IBT_REG_MODE_32BIT; 71962306a36Sopenharmony_ci break; 72062306a36Sopenharmony_ci default: 72162306a36Sopenharmony_ci return -EINVAL; 72262306a36Sopenharmony_ci } 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci /* regmap provides a little-endian formatted addr */ 72562306a36Sopenharmony_ci cp.addr = *(__le32 *)addr; 72662306a36Sopenharmony_ci cp.len = val_size; 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci bt_dev_dbg(ctx->hdev, "Register (0x%x) read", le32_to_cpu(cp.addr)); 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci skb = hci_cmd_sync(ctx->hdev, ctx->op_read, sizeof(cp), &cp, 73162306a36Sopenharmony_ci HCI_CMD_TIMEOUT); 73262306a36Sopenharmony_ci if (IS_ERR(skb)) { 73362306a36Sopenharmony_ci err = PTR_ERR(skb); 73462306a36Sopenharmony_ci bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error (%d)", 73562306a36Sopenharmony_ci le32_to_cpu(cp.addr), err); 73662306a36Sopenharmony_ci return err; 73762306a36Sopenharmony_ci } 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci if (skb->len != sizeof(*rp) + val_size) { 74062306a36Sopenharmony_ci bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error, bad len", 74162306a36Sopenharmony_ci le32_to_cpu(cp.addr)); 74262306a36Sopenharmony_ci err = -EINVAL; 74362306a36Sopenharmony_ci goto done; 74462306a36Sopenharmony_ci } 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci rp = (struct ibt_rp_reg_access *)skb->data; 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci if (rp->addr != cp.addr) { 74962306a36Sopenharmony_ci bt_dev_err(ctx->hdev, "regmap: Register (0x%x) read error, bad addr", 75062306a36Sopenharmony_ci le32_to_cpu(rp->addr)); 75162306a36Sopenharmony_ci err = -EINVAL; 75262306a36Sopenharmony_ci goto done; 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci memcpy(val, rp->data, val_size); 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_cidone: 75862306a36Sopenharmony_ci kfree_skb(skb); 75962306a36Sopenharmony_ci return err; 76062306a36Sopenharmony_ci} 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_cistatic int regmap_ibt_gather_write(void *context, 76362306a36Sopenharmony_ci const void *addr, size_t reg_size, 76462306a36Sopenharmony_ci const void *val, size_t val_size) 76562306a36Sopenharmony_ci{ 76662306a36Sopenharmony_ci struct regmap_ibt_context *ctx = context; 76762306a36Sopenharmony_ci struct ibt_cp_reg_access *cp; 76862306a36Sopenharmony_ci struct sk_buff *skb; 76962306a36Sopenharmony_ci int plen = sizeof(*cp) + val_size; 77062306a36Sopenharmony_ci u8 mode; 77162306a36Sopenharmony_ci int err = 0; 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci if (reg_size != sizeof(__le32)) 77462306a36Sopenharmony_ci return -EINVAL; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci switch (val_size) { 77762306a36Sopenharmony_ci case 1: 77862306a36Sopenharmony_ci mode = IBT_REG_MODE_8BIT; 77962306a36Sopenharmony_ci break; 78062306a36Sopenharmony_ci case 2: 78162306a36Sopenharmony_ci mode = IBT_REG_MODE_16BIT; 78262306a36Sopenharmony_ci break; 78362306a36Sopenharmony_ci case 4: 78462306a36Sopenharmony_ci mode = IBT_REG_MODE_32BIT; 78562306a36Sopenharmony_ci break; 78662306a36Sopenharmony_ci default: 78762306a36Sopenharmony_ci return -EINVAL; 78862306a36Sopenharmony_ci } 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci cp = kmalloc(plen, GFP_KERNEL); 79162306a36Sopenharmony_ci if (!cp) 79262306a36Sopenharmony_ci return -ENOMEM; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci /* regmap provides a little-endian formatted addr/value */ 79562306a36Sopenharmony_ci cp->addr = *(__le32 *)addr; 79662306a36Sopenharmony_ci cp->mode = mode; 79762306a36Sopenharmony_ci cp->len = val_size; 79862306a36Sopenharmony_ci memcpy(&cp->data, val, val_size); 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci bt_dev_dbg(ctx->hdev, "Register (0x%x) write", le32_to_cpu(cp->addr)); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci skb = hci_cmd_sync(ctx->hdev, ctx->op_write, plen, cp, HCI_CMD_TIMEOUT); 80362306a36Sopenharmony_ci if (IS_ERR(skb)) { 80462306a36Sopenharmony_ci err = PTR_ERR(skb); 80562306a36Sopenharmony_ci bt_dev_err(ctx->hdev, "regmap: Register (0x%x) write error (%d)", 80662306a36Sopenharmony_ci le32_to_cpu(cp->addr), err); 80762306a36Sopenharmony_ci goto done; 80862306a36Sopenharmony_ci } 80962306a36Sopenharmony_ci kfree_skb(skb); 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_cidone: 81262306a36Sopenharmony_ci kfree(cp); 81362306a36Sopenharmony_ci return err; 81462306a36Sopenharmony_ci} 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_cistatic int regmap_ibt_write(void *context, const void *data, size_t count) 81762306a36Sopenharmony_ci{ 81862306a36Sopenharmony_ci /* data contains register+value, since we only support 32bit addr, 81962306a36Sopenharmony_ci * minimum data size is 4 bytes. 82062306a36Sopenharmony_ci */ 82162306a36Sopenharmony_ci if (WARN_ONCE(count < 4, "Invalid register access")) 82262306a36Sopenharmony_ci return -EINVAL; 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci return regmap_ibt_gather_write(context, data, 4, data + 4, count - 4); 82562306a36Sopenharmony_ci} 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_cistatic void regmap_ibt_free_context(void *context) 82862306a36Sopenharmony_ci{ 82962306a36Sopenharmony_ci kfree(context); 83062306a36Sopenharmony_ci} 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_cistatic const struct regmap_bus regmap_ibt = { 83362306a36Sopenharmony_ci .read = regmap_ibt_read, 83462306a36Sopenharmony_ci .write = regmap_ibt_write, 83562306a36Sopenharmony_ci .gather_write = regmap_ibt_gather_write, 83662306a36Sopenharmony_ci .free_context = regmap_ibt_free_context, 83762306a36Sopenharmony_ci .reg_format_endian_default = REGMAP_ENDIAN_LITTLE, 83862306a36Sopenharmony_ci .val_format_endian_default = REGMAP_ENDIAN_LITTLE, 83962306a36Sopenharmony_ci}; 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci/* Config is the same for all register regions */ 84262306a36Sopenharmony_cistatic const struct regmap_config regmap_ibt_cfg = { 84362306a36Sopenharmony_ci .name = "btintel_regmap", 84462306a36Sopenharmony_ci .reg_bits = 32, 84562306a36Sopenharmony_ci .val_bits = 32, 84662306a36Sopenharmony_ci}; 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_cistruct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read, 84962306a36Sopenharmony_ci u16 opcode_write) 85062306a36Sopenharmony_ci{ 85162306a36Sopenharmony_ci struct regmap_ibt_context *ctx; 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci bt_dev_info(hdev, "regmap: Init R%x-W%x region", opcode_read, 85462306a36Sopenharmony_ci opcode_write); 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 85762306a36Sopenharmony_ci if (!ctx) 85862306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci ctx->op_read = opcode_read; 86162306a36Sopenharmony_ci ctx->op_write = opcode_write; 86262306a36Sopenharmony_ci ctx->hdev = hdev; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci return regmap_init(&hdev->dev, ®map_ibt, ctx, ®map_ibt_cfg); 86562306a36Sopenharmony_ci} 86662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_regmap_init); 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ciint btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param) 86962306a36Sopenharmony_ci{ 87062306a36Sopenharmony_ci struct intel_reset params = { 0x00, 0x01, 0x00, 0x01, 0x00000000 }; 87162306a36Sopenharmony_ci struct sk_buff *skb; 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci params.boot_param = cpu_to_le32(boot_param); 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(params), ¶ms, 87662306a36Sopenharmony_ci HCI_INIT_TIMEOUT); 87762306a36Sopenharmony_ci if (IS_ERR(skb)) { 87862306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to send Intel Reset command"); 87962306a36Sopenharmony_ci return PTR_ERR(skb); 88062306a36Sopenharmony_ci } 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci kfree_skb(skb); 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci return 0; 88562306a36Sopenharmony_ci} 88662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_send_intel_reset); 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ciint btintel_read_boot_params(struct hci_dev *hdev, 88962306a36Sopenharmony_ci struct intel_boot_params *params) 89062306a36Sopenharmony_ci{ 89162306a36Sopenharmony_ci struct sk_buff *skb; 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc0d, 0, NULL, HCI_INIT_TIMEOUT); 89462306a36Sopenharmony_ci if (IS_ERR(skb)) { 89562306a36Sopenharmony_ci bt_dev_err(hdev, "Reading Intel boot parameters failed (%ld)", 89662306a36Sopenharmony_ci PTR_ERR(skb)); 89762306a36Sopenharmony_ci return PTR_ERR(skb); 89862306a36Sopenharmony_ci } 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci if (skb->len != sizeof(*params)) { 90162306a36Sopenharmony_ci bt_dev_err(hdev, "Intel boot parameters size mismatch"); 90262306a36Sopenharmony_ci kfree_skb(skb); 90362306a36Sopenharmony_ci return -EILSEQ; 90462306a36Sopenharmony_ci } 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci memcpy(params, skb->data, sizeof(*params)); 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci kfree_skb(skb); 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci if (params->status) { 91162306a36Sopenharmony_ci bt_dev_err(hdev, "Intel boot parameters command failed (%02x)", 91262306a36Sopenharmony_ci params->status); 91362306a36Sopenharmony_ci return -bt_to_errno(params->status); 91462306a36Sopenharmony_ci } 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci bt_dev_info(hdev, "Device revision is %u", 91762306a36Sopenharmony_ci le16_to_cpu(params->dev_revid)); 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci bt_dev_info(hdev, "Secure boot is %s", 92062306a36Sopenharmony_ci params->secure_boot ? "enabled" : "disabled"); 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci bt_dev_info(hdev, "OTP lock is %s", 92362306a36Sopenharmony_ci params->otp_lock ? "enabled" : "disabled"); 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci bt_dev_info(hdev, "API lock is %s", 92662306a36Sopenharmony_ci params->api_lock ? "enabled" : "disabled"); 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci bt_dev_info(hdev, "Debug lock is %s", 92962306a36Sopenharmony_ci params->debug_lock ? "enabled" : "disabled"); 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci bt_dev_info(hdev, "Minimum firmware build %u week %u %u", 93262306a36Sopenharmony_ci params->min_fw_build_nn, params->min_fw_build_cw, 93362306a36Sopenharmony_ci 2000 + params->min_fw_build_yy); 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci return 0; 93662306a36Sopenharmony_ci} 93762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_read_boot_params); 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_cistatic int btintel_sfi_rsa_header_secure_send(struct hci_dev *hdev, 94062306a36Sopenharmony_ci const struct firmware *fw) 94162306a36Sopenharmony_ci{ 94262306a36Sopenharmony_ci int err; 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci /* Start the firmware download transaction with the Init fragment 94562306a36Sopenharmony_ci * represented by the 128 bytes of CSS header. 94662306a36Sopenharmony_ci */ 94762306a36Sopenharmony_ci err = btintel_secure_send(hdev, 0x00, 128, fw->data); 94862306a36Sopenharmony_ci if (err < 0) { 94962306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to send firmware header (%d)", err); 95062306a36Sopenharmony_ci goto done; 95162306a36Sopenharmony_ci } 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci /* Send the 256 bytes of public key information from the firmware 95462306a36Sopenharmony_ci * as the PKey fragment. 95562306a36Sopenharmony_ci */ 95662306a36Sopenharmony_ci err = btintel_secure_send(hdev, 0x03, 256, fw->data + 128); 95762306a36Sopenharmony_ci if (err < 0) { 95862306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to send firmware pkey (%d)", err); 95962306a36Sopenharmony_ci goto done; 96062306a36Sopenharmony_ci } 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci /* Send the 256 bytes of signature information from the firmware 96362306a36Sopenharmony_ci * as the Sign fragment. 96462306a36Sopenharmony_ci */ 96562306a36Sopenharmony_ci err = btintel_secure_send(hdev, 0x02, 256, fw->data + 388); 96662306a36Sopenharmony_ci if (err < 0) { 96762306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to send firmware signature (%d)", err); 96862306a36Sopenharmony_ci goto done; 96962306a36Sopenharmony_ci } 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_cidone: 97262306a36Sopenharmony_ci return err; 97362306a36Sopenharmony_ci} 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_cistatic int btintel_sfi_ecdsa_header_secure_send(struct hci_dev *hdev, 97662306a36Sopenharmony_ci const struct firmware *fw) 97762306a36Sopenharmony_ci{ 97862306a36Sopenharmony_ci int err; 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci /* Start the firmware download transaction with the Init fragment 98162306a36Sopenharmony_ci * represented by the 128 bytes of CSS header. 98262306a36Sopenharmony_ci */ 98362306a36Sopenharmony_ci err = btintel_secure_send(hdev, 0x00, 128, fw->data + 644); 98462306a36Sopenharmony_ci if (err < 0) { 98562306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to send firmware header (%d)", err); 98662306a36Sopenharmony_ci return err; 98762306a36Sopenharmony_ci } 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci /* Send the 96 bytes of public key information from the firmware 99062306a36Sopenharmony_ci * as the PKey fragment. 99162306a36Sopenharmony_ci */ 99262306a36Sopenharmony_ci err = btintel_secure_send(hdev, 0x03, 96, fw->data + 644 + 128); 99362306a36Sopenharmony_ci if (err < 0) { 99462306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to send firmware pkey (%d)", err); 99562306a36Sopenharmony_ci return err; 99662306a36Sopenharmony_ci } 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci /* Send the 96 bytes of signature information from the firmware 99962306a36Sopenharmony_ci * as the Sign fragment 100062306a36Sopenharmony_ci */ 100162306a36Sopenharmony_ci err = btintel_secure_send(hdev, 0x02, 96, fw->data + 644 + 224); 100262306a36Sopenharmony_ci if (err < 0) { 100362306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to send firmware signature (%d)", 100462306a36Sopenharmony_ci err); 100562306a36Sopenharmony_ci return err; 100662306a36Sopenharmony_ci } 100762306a36Sopenharmony_ci return 0; 100862306a36Sopenharmony_ci} 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_cistatic int btintel_download_firmware_payload(struct hci_dev *hdev, 101162306a36Sopenharmony_ci const struct firmware *fw, 101262306a36Sopenharmony_ci size_t offset) 101362306a36Sopenharmony_ci{ 101462306a36Sopenharmony_ci int err; 101562306a36Sopenharmony_ci const u8 *fw_ptr; 101662306a36Sopenharmony_ci u32 frag_len; 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci fw_ptr = fw->data + offset; 101962306a36Sopenharmony_ci frag_len = 0; 102062306a36Sopenharmony_ci err = -EINVAL; 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci while (fw_ptr - fw->data < fw->size) { 102362306a36Sopenharmony_ci struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len); 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci frag_len += sizeof(*cmd) + cmd->plen; 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci /* The parameter length of the secure send command requires 102862306a36Sopenharmony_ci * a 4 byte alignment. It happens so that the firmware file 102962306a36Sopenharmony_ci * contains proper Intel_NOP commands to align the fragments 103062306a36Sopenharmony_ci * as needed. 103162306a36Sopenharmony_ci * 103262306a36Sopenharmony_ci * Send set of commands with 4 byte alignment from the 103362306a36Sopenharmony_ci * firmware data buffer as a single Data fragement. 103462306a36Sopenharmony_ci */ 103562306a36Sopenharmony_ci if (!(frag_len % 4)) { 103662306a36Sopenharmony_ci err = btintel_secure_send(hdev, 0x01, frag_len, fw_ptr); 103762306a36Sopenharmony_ci if (err < 0) { 103862306a36Sopenharmony_ci bt_dev_err(hdev, 103962306a36Sopenharmony_ci "Failed to send firmware data (%d)", 104062306a36Sopenharmony_ci err); 104162306a36Sopenharmony_ci goto done; 104262306a36Sopenharmony_ci } 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci fw_ptr += frag_len; 104562306a36Sopenharmony_ci frag_len = 0; 104662306a36Sopenharmony_ci } 104762306a36Sopenharmony_ci } 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_cidone: 105062306a36Sopenharmony_ci return err; 105162306a36Sopenharmony_ci} 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_cistatic bool btintel_firmware_version(struct hci_dev *hdev, 105462306a36Sopenharmony_ci u8 num, u8 ww, u8 yy, 105562306a36Sopenharmony_ci const struct firmware *fw, 105662306a36Sopenharmony_ci u32 *boot_addr) 105762306a36Sopenharmony_ci{ 105862306a36Sopenharmony_ci const u8 *fw_ptr; 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci fw_ptr = fw->data; 106162306a36Sopenharmony_ci 106262306a36Sopenharmony_ci while (fw_ptr - fw->data < fw->size) { 106362306a36Sopenharmony_ci struct hci_command_hdr *cmd = (void *)(fw_ptr); 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci /* Each SKU has a different reset parameter to use in the 106662306a36Sopenharmony_ci * HCI_Intel_Reset command and it is embedded in the firmware 106762306a36Sopenharmony_ci * data. So, instead of using static value per SKU, check 106862306a36Sopenharmony_ci * the firmware data and save it for later use. 106962306a36Sopenharmony_ci */ 107062306a36Sopenharmony_ci if (le16_to_cpu(cmd->opcode) == CMD_WRITE_BOOT_PARAMS) { 107162306a36Sopenharmony_ci struct cmd_write_boot_params *params; 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci params = (void *)(fw_ptr + sizeof(*cmd)); 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci *boot_addr = le32_to_cpu(params->boot_addr); 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci bt_dev_info(hdev, "Boot Address: 0x%x", *boot_addr); 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci bt_dev_info(hdev, "Firmware Version: %u-%u.%u", 108062306a36Sopenharmony_ci params->fw_build_num, params->fw_build_ww, 108162306a36Sopenharmony_ci params->fw_build_yy); 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci return (num == params->fw_build_num && 108462306a36Sopenharmony_ci ww == params->fw_build_ww && 108562306a36Sopenharmony_ci yy == params->fw_build_yy); 108662306a36Sopenharmony_ci } 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci fw_ptr += sizeof(*cmd) + cmd->plen; 108962306a36Sopenharmony_ci } 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ci return false; 109262306a36Sopenharmony_ci} 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ciint btintel_download_firmware(struct hci_dev *hdev, 109562306a36Sopenharmony_ci struct intel_version *ver, 109662306a36Sopenharmony_ci const struct firmware *fw, 109762306a36Sopenharmony_ci u32 *boot_param) 109862306a36Sopenharmony_ci{ 109962306a36Sopenharmony_ci int err; 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci /* SfP and WsP don't seem to update the firmware version on file 110262306a36Sopenharmony_ci * so version checking is currently not possible. 110362306a36Sopenharmony_ci */ 110462306a36Sopenharmony_ci switch (ver->hw_variant) { 110562306a36Sopenharmony_ci case 0x0b: /* SfP */ 110662306a36Sopenharmony_ci case 0x0c: /* WsP */ 110762306a36Sopenharmony_ci /* Skip version checking */ 110862306a36Sopenharmony_ci break; 110962306a36Sopenharmony_ci default: 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci /* Skip download if firmware has the same version */ 111262306a36Sopenharmony_ci if (btintel_firmware_version(hdev, ver->fw_build_num, 111362306a36Sopenharmony_ci ver->fw_build_ww, ver->fw_build_yy, 111462306a36Sopenharmony_ci fw, boot_param)) { 111562306a36Sopenharmony_ci bt_dev_info(hdev, "Firmware already loaded"); 111662306a36Sopenharmony_ci /* Return -EALREADY to indicate that the firmware has 111762306a36Sopenharmony_ci * already been loaded. 111862306a36Sopenharmony_ci */ 111962306a36Sopenharmony_ci return -EALREADY; 112062306a36Sopenharmony_ci } 112162306a36Sopenharmony_ci } 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_ci /* The firmware variant determines if the device is in bootloader 112462306a36Sopenharmony_ci * mode or is running operational firmware. The value 0x06 identifies 112562306a36Sopenharmony_ci * the bootloader and the value 0x23 identifies the operational 112662306a36Sopenharmony_ci * firmware. 112762306a36Sopenharmony_ci * 112862306a36Sopenharmony_ci * If the firmware version has changed that means it needs to be reset 112962306a36Sopenharmony_ci * to bootloader when operational so the new firmware can be loaded. 113062306a36Sopenharmony_ci */ 113162306a36Sopenharmony_ci if (ver->fw_variant == 0x23) 113262306a36Sopenharmony_ci return -EINVAL; 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci err = btintel_sfi_rsa_header_secure_send(hdev, fw); 113562306a36Sopenharmony_ci if (err) 113662306a36Sopenharmony_ci return err; 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci return btintel_download_firmware_payload(hdev, fw, RSA_HEADER_LEN); 113962306a36Sopenharmony_ci} 114062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_download_firmware); 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_cistatic int btintel_download_fw_tlv(struct hci_dev *hdev, 114362306a36Sopenharmony_ci struct intel_version_tlv *ver, 114462306a36Sopenharmony_ci const struct firmware *fw, u32 *boot_param, 114562306a36Sopenharmony_ci u8 hw_variant, u8 sbe_type) 114662306a36Sopenharmony_ci{ 114762306a36Sopenharmony_ci int err; 114862306a36Sopenharmony_ci u32 css_header_ver; 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_ci /* Skip download if firmware has the same version */ 115162306a36Sopenharmony_ci if (btintel_firmware_version(hdev, ver->min_fw_build_nn, 115262306a36Sopenharmony_ci ver->min_fw_build_cw, 115362306a36Sopenharmony_ci ver->min_fw_build_yy, 115462306a36Sopenharmony_ci fw, boot_param)) { 115562306a36Sopenharmony_ci bt_dev_info(hdev, "Firmware already loaded"); 115662306a36Sopenharmony_ci /* Return -EALREADY to indicate that firmware has 115762306a36Sopenharmony_ci * already been loaded. 115862306a36Sopenharmony_ci */ 115962306a36Sopenharmony_ci return -EALREADY; 116062306a36Sopenharmony_ci } 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci /* The firmware variant determines if the device is in bootloader 116362306a36Sopenharmony_ci * mode or is running operational firmware. The value 0x01 identifies 116462306a36Sopenharmony_ci * the bootloader and the value 0x03 identifies the operational 116562306a36Sopenharmony_ci * firmware. 116662306a36Sopenharmony_ci * 116762306a36Sopenharmony_ci * If the firmware version has changed that means it needs to be reset 116862306a36Sopenharmony_ci * to bootloader when operational so the new firmware can be loaded. 116962306a36Sopenharmony_ci */ 117062306a36Sopenharmony_ci if (ver->img_type == 0x03) 117162306a36Sopenharmony_ci return -EINVAL; 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci /* iBT hardware variants 0x0b, 0x0c, 0x11, 0x12, 0x13, 0x14 support 117462306a36Sopenharmony_ci * only RSA secure boot engine. Hence, the corresponding sfi file will 117562306a36Sopenharmony_ci * have RSA header of 644 bytes followed by Command Buffer. 117662306a36Sopenharmony_ci * 117762306a36Sopenharmony_ci * iBT hardware variants 0x17, 0x18 onwards support both RSA and ECDSA 117862306a36Sopenharmony_ci * secure boot engine. As a result, the corresponding sfi file will 117962306a36Sopenharmony_ci * have RSA header of 644, ECDSA header of 320 bytes followed by 118062306a36Sopenharmony_ci * Command Buffer. 118162306a36Sopenharmony_ci * 118262306a36Sopenharmony_ci * CSS Header byte positions 0x08 to 0x0B represent the CSS Header 118362306a36Sopenharmony_ci * version: RSA(0x00010000) , ECDSA (0x00020000) 118462306a36Sopenharmony_ci */ 118562306a36Sopenharmony_ci css_header_ver = get_unaligned_le32(fw->data + CSS_HEADER_OFFSET); 118662306a36Sopenharmony_ci if (css_header_ver != 0x00010000) { 118762306a36Sopenharmony_ci bt_dev_err(hdev, "Invalid CSS Header version"); 118862306a36Sopenharmony_ci return -EINVAL; 118962306a36Sopenharmony_ci } 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci if (hw_variant <= 0x14) { 119262306a36Sopenharmony_ci if (sbe_type != 0x00) { 119362306a36Sopenharmony_ci bt_dev_err(hdev, "Invalid SBE type for hardware variant (%d)", 119462306a36Sopenharmony_ci hw_variant); 119562306a36Sopenharmony_ci return -EINVAL; 119662306a36Sopenharmony_ci } 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci err = btintel_sfi_rsa_header_secure_send(hdev, fw); 119962306a36Sopenharmony_ci if (err) 120062306a36Sopenharmony_ci return err; 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci err = btintel_download_firmware_payload(hdev, fw, RSA_HEADER_LEN); 120362306a36Sopenharmony_ci if (err) 120462306a36Sopenharmony_ci return err; 120562306a36Sopenharmony_ci } else if (hw_variant >= 0x17) { 120662306a36Sopenharmony_ci /* Check if CSS header for ECDSA follows the RSA header */ 120762306a36Sopenharmony_ci if (fw->data[ECDSA_OFFSET] != 0x06) 120862306a36Sopenharmony_ci return -EINVAL; 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci /* Check if the CSS Header version is ECDSA(0x00020000) */ 121162306a36Sopenharmony_ci css_header_ver = get_unaligned_le32(fw->data + ECDSA_OFFSET + CSS_HEADER_OFFSET); 121262306a36Sopenharmony_ci if (css_header_ver != 0x00020000) { 121362306a36Sopenharmony_ci bt_dev_err(hdev, "Invalid CSS Header version"); 121462306a36Sopenharmony_ci return -EINVAL; 121562306a36Sopenharmony_ci } 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_ci if (sbe_type == 0x00) { 121862306a36Sopenharmony_ci err = btintel_sfi_rsa_header_secure_send(hdev, fw); 121962306a36Sopenharmony_ci if (err) 122062306a36Sopenharmony_ci return err; 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci err = btintel_download_firmware_payload(hdev, fw, 122362306a36Sopenharmony_ci RSA_HEADER_LEN + ECDSA_HEADER_LEN); 122462306a36Sopenharmony_ci if (err) 122562306a36Sopenharmony_ci return err; 122662306a36Sopenharmony_ci } else if (sbe_type == 0x01) { 122762306a36Sopenharmony_ci err = btintel_sfi_ecdsa_header_secure_send(hdev, fw); 122862306a36Sopenharmony_ci if (err) 122962306a36Sopenharmony_ci return err; 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci err = btintel_download_firmware_payload(hdev, fw, 123262306a36Sopenharmony_ci RSA_HEADER_LEN + ECDSA_HEADER_LEN); 123362306a36Sopenharmony_ci if (err) 123462306a36Sopenharmony_ci return err; 123562306a36Sopenharmony_ci } 123662306a36Sopenharmony_ci } 123762306a36Sopenharmony_ci return 0; 123862306a36Sopenharmony_ci} 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_cistatic void btintel_reset_to_bootloader(struct hci_dev *hdev) 124162306a36Sopenharmony_ci{ 124262306a36Sopenharmony_ci struct intel_reset params; 124362306a36Sopenharmony_ci struct sk_buff *skb; 124462306a36Sopenharmony_ci 124562306a36Sopenharmony_ci /* Send Intel Reset command. This will result in 124662306a36Sopenharmony_ci * re-enumeration of BT controller. 124762306a36Sopenharmony_ci * 124862306a36Sopenharmony_ci * Intel Reset parameter description: 124962306a36Sopenharmony_ci * reset_type : 0x00 (Soft reset), 125062306a36Sopenharmony_ci * 0x01 (Hard reset) 125162306a36Sopenharmony_ci * patch_enable : 0x00 (Do not enable), 125262306a36Sopenharmony_ci * 0x01 (Enable) 125362306a36Sopenharmony_ci * ddc_reload : 0x00 (Do not reload), 125462306a36Sopenharmony_ci * 0x01 (Reload) 125562306a36Sopenharmony_ci * boot_option: 0x00 (Current image), 125662306a36Sopenharmony_ci * 0x01 (Specified boot address) 125762306a36Sopenharmony_ci * boot_param: Boot address 125862306a36Sopenharmony_ci * 125962306a36Sopenharmony_ci */ 126062306a36Sopenharmony_ci params.reset_type = 0x01; 126162306a36Sopenharmony_ci params.patch_enable = 0x01; 126262306a36Sopenharmony_ci params.ddc_reload = 0x01; 126362306a36Sopenharmony_ci params.boot_option = 0x00; 126462306a36Sopenharmony_ci params.boot_param = cpu_to_le32(0x00000000); 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(params), 126762306a36Sopenharmony_ci ¶ms, HCI_INIT_TIMEOUT); 126862306a36Sopenharmony_ci if (IS_ERR(skb)) { 126962306a36Sopenharmony_ci bt_dev_err(hdev, "FW download error recovery failed (%ld)", 127062306a36Sopenharmony_ci PTR_ERR(skb)); 127162306a36Sopenharmony_ci return; 127262306a36Sopenharmony_ci } 127362306a36Sopenharmony_ci bt_dev_info(hdev, "Intel reset sent to retry FW download"); 127462306a36Sopenharmony_ci kfree_skb(skb); 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci /* Current Intel BT controllers(ThP/JfP) hold the USB reset 127762306a36Sopenharmony_ci * lines for 2ms when it receives Intel Reset in bootloader mode. 127862306a36Sopenharmony_ci * Whereas, the upcoming Intel BT controllers will hold USB reset 127962306a36Sopenharmony_ci * for 150ms. To keep the delay generic, 150ms is chosen here. 128062306a36Sopenharmony_ci */ 128162306a36Sopenharmony_ci msleep(150); 128262306a36Sopenharmony_ci} 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_cistatic int btintel_read_debug_features(struct hci_dev *hdev, 128562306a36Sopenharmony_ci struct intel_debug_features *features) 128662306a36Sopenharmony_ci{ 128762306a36Sopenharmony_ci struct sk_buff *skb; 128862306a36Sopenharmony_ci u8 page_no = 1; 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci /* Intel controller supports two pages, each page is of 128-bit 129162306a36Sopenharmony_ci * feature bit mask. And each bit defines specific feature support 129262306a36Sopenharmony_ci */ 129362306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfca6, sizeof(page_no), &page_no, 129462306a36Sopenharmony_ci HCI_INIT_TIMEOUT); 129562306a36Sopenharmony_ci if (IS_ERR(skb)) { 129662306a36Sopenharmony_ci bt_dev_err(hdev, "Reading supported features failed (%ld)", 129762306a36Sopenharmony_ci PTR_ERR(skb)); 129862306a36Sopenharmony_ci return PTR_ERR(skb); 129962306a36Sopenharmony_ci } 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci if (skb->len != (sizeof(features->page1) + 3)) { 130262306a36Sopenharmony_ci bt_dev_err(hdev, "Supported features event size mismatch"); 130362306a36Sopenharmony_ci kfree_skb(skb); 130462306a36Sopenharmony_ci return -EILSEQ; 130562306a36Sopenharmony_ci } 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci memcpy(features->page1, skb->data + 3, sizeof(features->page1)); 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci /* Read the supported features page2 if required in future. 131062306a36Sopenharmony_ci */ 131162306a36Sopenharmony_ci kfree_skb(skb); 131262306a36Sopenharmony_ci return 0; 131362306a36Sopenharmony_ci} 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_cistatic acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data, 131662306a36Sopenharmony_ci void **ret) 131762306a36Sopenharmony_ci{ 131862306a36Sopenharmony_ci acpi_status status; 131962306a36Sopenharmony_ci size_t len; 132062306a36Sopenharmony_ci struct btintel_ppag *ppag = data; 132162306a36Sopenharmony_ci union acpi_object *p, *elements; 132262306a36Sopenharmony_ci struct acpi_buffer string = {ACPI_ALLOCATE_BUFFER, NULL}; 132362306a36Sopenharmony_ci struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; 132462306a36Sopenharmony_ci struct hci_dev *hdev = ppag->hdev; 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); 132762306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 132862306a36Sopenharmony_ci bt_dev_warn(hdev, "PPAG-BT: ACPI Failure: %s", acpi_format_exception(status)); 132962306a36Sopenharmony_ci return status; 133062306a36Sopenharmony_ci } 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_ci len = strlen(string.pointer); 133362306a36Sopenharmony_ci if (len < strlen(BTINTEL_PPAG_NAME)) { 133462306a36Sopenharmony_ci kfree(string.pointer); 133562306a36Sopenharmony_ci return AE_OK; 133662306a36Sopenharmony_ci } 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_ci if (strncmp((char *)string.pointer + len - 4, BTINTEL_PPAG_NAME, 4)) { 133962306a36Sopenharmony_ci kfree(string.pointer); 134062306a36Sopenharmony_ci return AE_OK; 134162306a36Sopenharmony_ci } 134262306a36Sopenharmony_ci kfree(string.pointer); 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci status = acpi_evaluate_object(handle, NULL, NULL, &buffer); 134562306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 134662306a36Sopenharmony_ci ppag->status = status; 134762306a36Sopenharmony_ci bt_dev_warn(hdev, "PPAG-BT: ACPI Failure: %s", acpi_format_exception(status)); 134862306a36Sopenharmony_ci return status; 134962306a36Sopenharmony_ci } 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ci p = buffer.pointer; 135262306a36Sopenharmony_ci ppag = (struct btintel_ppag *)data; 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_ci if (p->type != ACPI_TYPE_PACKAGE || p->package.count != 2) { 135562306a36Sopenharmony_ci kfree(buffer.pointer); 135662306a36Sopenharmony_ci bt_dev_warn(hdev, "PPAG-BT: Invalid object type: %d or package count: %d", 135762306a36Sopenharmony_ci p->type, p->package.count); 135862306a36Sopenharmony_ci ppag->status = AE_ERROR; 135962306a36Sopenharmony_ci return AE_ERROR; 136062306a36Sopenharmony_ci } 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci elements = p->package.elements; 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci /* PPAG table is located at element[1] */ 136562306a36Sopenharmony_ci p = &elements[1]; 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_ci ppag->domain = (u32)p->package.elements[0].integer.value; 136862306a36Sopenharmony_ci ppag->mode = (u32)p->package.elements[1].integer.value; 136962306a36Sopenharmony_ci ppag->status = AE_OK; 137062306a36Sopenharmony_ci kfree(buffer.pointer); 137162306a36Sopenharmony_ci return AE_CTRL_TERMINATE; 137262306a36Sopenharmony_ci} 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_cistatic int btintel_set_debug_features(struct hci_dev *hdev, 137562306a36Sopenharmony_ci const struct intel_debug_features *features) 137662306a36Sopenharmony_ci{ 137762306a36Sopenharmony_ci u8 mask[11] = { 0x0a, 0x92, 0x02, 0x7f, 0x00, 0x00, 0x00, 0x00, 137862306a36Sopenharmony_ci 0x00, 0x00, 0x00 }; 137962306a36Sopenharmony_ci u8 period[5] = { 0x04, 0x91, 0x02, 0x05, 0x00 }; 138062306a36Sopenharmony_ci u8 trace_enable = 0x02; 138162306a36Sopenharmony_ci struct sk_buff *skb; 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_ci if (!features) { 138462306a36Sopenharmony_ci bt_dev_warn(hdev, "Debug features not read"); 138562306a36Sopenharmony_ci return -EINVAL; 138662306a36Sopenharmony_ci } 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci if (!(features->page1[0] & 0x3f)) { 138962306a36Sopenharmony_ci bt_dev_info(hdev, "Telemetry exception format not supported"); 139062306a36Sopenharmony_ci return 0; 139162306a36Sopenharmony_ci } 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc8b, 11, mask, HCI_INIT_TIMEOUT); 139462306a36Sopenharmony_ci if (IS_ERR(skb)) { 139562306a36Sopenharmony_ci bt_dev_err(hdev, "Setting Intel telemetry ddc write event mask failed (%ld)", 139662306a36Sopenharmony_ci PTR_ERR(skb)); 139762306a36Sopenharmony_ci return PTR_ERR(skb); 139862306a36Sopenharmony_ci } 139962306a36Sopenharmony_ci kfree_skb(skb); 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc8b, 5, period, HCI_INIT_TIMEOUT); 140262306a36Sopenharmony_ci if (IS_ERR(skb)) { 140362306a36Sopenharmony_ci bt_dev_err(hdev, "Setting periodicity for link statistics traces failed (%ld)", 140462306a36Sopenharmony_ci PTR_ERR(skb)); 140562306a36Sopenharmony_ci return PTR_ERR(skb); 140662306a36Sopenharmony_ci } 140762306a36Sopenharmony_ci kfree_skb(skb); 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfca1, 1, &trace_enable, HCI_INIT_TIMEOUT); 141062306a36Sopenharmony_ci if (IS_ERR(skb)) { 141162306a36Sopenharmony_ci bt_dev_err(hdev, "Enable tracing of link statistics events failed (%ld)", 141262306a36Sopenharmony_ci PTR_ERR(skb)); 141362306a36Sopenharmony_ci return PTR_ERR(skb); 141462306a36Sopenharmony_ci } 141562306a36Sopenharmony_ci kfree_skb(skb); 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci bt_dev_info(hdev, "set debug features: trace_enable 0x%02x mask 0x%02x", 141862306a36Sopenharmony_ci trace_enable, mask[3]); 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_ci return 0; 142162306a36Sopenharmony_ci} 142262306a36Sopenharmony_ci 142362306a36Sopenharmony_cistatic int btintel_reset_debug_features(struct hci_dev *hdev, 142462306a36Sopenharmony_ci const struct intel_debug_features *features) 142562306a36Sopenharmony_ci{ 142662306a36Sopenharmony_ci u8 mask[11] = { 0x0a, 0x92, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 142762306a36Sopenharmony_ci 0x00, 0x00, 0x00 }; 142862306a36Sopenharmony_ci u8 trace_enable = 0x00; 142962306a36Sopenharmony_ci struct sk_buff *skb; 143062306a36Sopenharmony_ci 143162306a36Sopenharmony_ci if (!features) { 143262306a36Sopenharmony_ci bt_dev_warn(hdev, "Debug features not read"); 143362306a36Sopenharmony_ci return -EINVAL; 143462306a36Sopenharmony_ci } 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci if (!(features->page1[0] & 0x3f)) { 143762306a36Sopenharmony_ci bt_dev_info(hdev, "Telemetry exception format not supported"); 143862306a36Sopenharmony_ci return 0; 143962306a36Sopenharmony_ci } 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_ci /* Should stop the trace before writing ddc event mask. */ 144262306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfca1, 1, &trace_enable, HCI_INIT_TIMEOUT); 144362306a36Sopenharmony_ci if (IS_ERR(skb)) { 144462306a36Sopenharmony_ci bt_dev_err(hdev, "Stop tracing of link statistics events failed (%ld)", 144562306a36Sopenharmony_ci PTR_ERR(skb)); 144662306a36Sopenharmony_ci return PTR_ERR(skb); 144762306a36Sopenharmony_ci } 144862306a36Sopenharmony_ci kfree_skb(skb); 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc8b, 11, mask, HCI_INIT_TIMEOUT); 145162306a36Sopenharmony_ci if (IS_ERR(skb)) { 145262306a36Sopenharmony_ci bt_dev_err(hdev, "Setting Intel telemetry ddc write event mask failed (%ld)", 145362306a36Sopenharmony_ci PTR_ERR(skb)); 145462306a36Sopenharmony_ci return PTR_ERR(skb); 145562306a36Sopenharmony_ci } 145662306a36Sopenharmony_ci kfree_skb(skb); 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_ci bt_dev_info(hdev, "reset debug features: trace_enable 0x%02x mask 0x%02x", 145962306a36Sopenharmony_ci trace_enable, mask[3]); 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci return 0; 146262306a36Sopenharmony_ci} 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ciint btintel_set_quality_report(struct hci_dev *hdev, bool enable) 146562306a36Sopenharmony_ci{ 146662306a36Sopenharmony_ci struct intel_debug_features features; 146762306a36Sopenharmony_ci int err; 146862306a36Sopenharmony_ci 146962306a36Sopenharmony_ci bt_dev_dbg(hdev, "enable %d", enable); 147062306a36Sopenharmony_ci 147162306a36Sopenharmony_ci /* Read the Intel supported features and if new exception formats 147262306a36Sopenharmony_ci * supported, need to load the additional DDC config to enable. 147362306a36Sopenharmony_ci */ 147462306a36Sopenharmony_ci err = btintel_read_debug_features(hdev, &features); 147562306a36Sopenharmony_ci if (err) 147662306a36Sopenharmony_ci return err; 147762306a36Sopenharmony_ci 147862306a36Sopenharmony_ci /* Set or reset the debug features. */ 147962306a36Sopenharmony_ci if (enable) 148062306a36Sopenharmony_ci err = btintel_set_debug_features(hdev, &features); 148162306a36Sopenharmony_ci else 148262306a36Sopenharmony_ci err = btintel_reset_debug_features(hdev, &features); 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_ci return err; 148562306a36Sopenharmony_ci} 148662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_set_quality_report); 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_cistatic void btintel_coredump(struct hci_dev *hdev) 148962306a36Sopenharmony_ci{ 149062306a36Sopenharmony_ci struct sk_buff *skb; 149162306a36Sopenharmony_ci 149262306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc4e, 0, NULL, HCI_CMD_TIMEOUT); 149362306a36Sopenharmony_ci if (IS_ERR(skb)) { 149462306a36Sopenharmony_ci bt_dev_err(hdev, "Coredump failed (%ld)", PTR_ERR(skb)); 149562306a36Sopenharmony_ci return; 149662306a36Sopenharmony_ci } 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_ci kfree_skb(skb); 149962306a36Sopenharmony_ci} 150062306a36Sopenharmony_ci 150162306a36Sopenharmony_cistatic void btintel_dmp_hdr(struct hci_dev *hdev, struct sk_buff *skb) 150262306a36Sopenharmony_ci{ 150362306a36Sopenharmony_ci char buf[80]; 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "Controller Name: 0x%X\n", 150662306a36Sopenharmony_ci coredump_info.hw_variant); 150762306a36Sopenharmony_ci skb_put_data(skb, buf, strlen(buf)); 150862306a36Sopenharmony_ci 150962306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "Firmware Version: 0x%X\n", 151062306a36Sopenharmony_ci coredump_info.fw_build_num); 151162306a36Sopenharmony_ci skb_put_data(skb, buf, strlen(buf)); 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "Driver: %s\n", coredump_info.driver_name); 151462306a36Sopenharmony_ci skb_put_data(skb, buf, strlen(buf)); 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "Vendor: Intel\n"); 151762306a36Sopenharmony_ci skb_put_data(skb, buf, strlen(buf)); 151862306a36Sopenharmony_ci} 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_cistatic int btintel_register_devcoredump_support(struct hci_dev *hdev) 152162306a36Sopenharmony_ci{ 152262306a36Sopenharmony_ci struct intel_debug_features features; 152362306a36Sopenharmony_ci int err; 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_ci err = btintel_read_debug_features(hdev, &features); 152662306a36Sopenharmony_ci if (err) { 152762306a36Sopenharmony_ci bt_dev_info(hdev, "Error reading debug features"); 152862306a36Sopenharmony_ci return err; 152962306a36Sopenharmony_ci } 153062306a36Sopenharmony_ci 153162306a36Sopenharmony_ci if (!(features.page1[0] & 0x3f)) { 153262306a36Sopenharmony_ci bt_dev_dbg(hdev, "Telemetry exception format not supported"); 153362306a36Sopenharmony_ci return -EOPNOTSUPP; 153462306a36Sopenharmony_ci } 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_ci hci_devcd_register(hdev, btintel_coredump, btintel_dmp_hdr, NULL); 153762306a36Sopenharmony_ci 153862306a36Sopenharmony_ci return err; 153962306a36Sopenharmony_ci} 154062306a36Sopenharmony_ci 154162306a36Sopenharmony_cistatic const struct firmware *btintel_legacy_rom_get_fw(struct hci_dev *hdev, 154262306a36Sopenharmony_ci struct intel_version *ver) 154362306a36Sopenharmony_ci{ 154462306a36Sopenharmony_ci const struct firmware *fw; 154562306a36Sopenharmony_ci char fwname[64]; 154662306a36Sopenharmony_ci int ret; 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_ci snprintf(fwname, sizeof(fwname), 154962306a36Sopenharmony_ci "intel/ibt-hw-%x.%x.%x-fw-%x.%x.%x.%x.%x.bseq", 155062306a36Sopenharmony_ci ver->hw_platform, ver->hw_variant, ver->hw_revision, 155162306a36Sopenharmony_ci ver->fw_variant, ver->fw_revision, ver->fw_build_num, 155262306a36Sopenharmony_ci ver->fw_build_ww, ver->fw_build_yy); 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_ci ret = request_firmware(&fw, fwname, &hdev->dev); 155562306a36Sopenharmony_ci if (ret < 0) { 155662306a36Sopenharmony_ci if (ret == -EINVAL) { 155762306a36Sopenharmony_ci bt_dev_err(hdev, "Intel firmware file request failed (%d)", 155862306a36Sopenharmony_ci ret); 155962306a36Sopenharmony_ci return NULL; 156062306a36Sopenharmony_ci } 156162306a36Sopenharmony_ci 156262306a36Sopenharmony_ci bt_dev_err(hdev, "failed to open Intel firmware file: %s (%d)", 156362306a36Sopenharmony_ci fwname, ret); 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_ci /* If the correct firmware patch file is not found, use the 156662306a36Sopenharmony_ci * default firmware patch file instead 156762306a36Sopenharmony_ci */ 156862306a36Sopenharmony_ci snprintf(fwname, sizeof(fwname), "intel/ibt-hw-%x.%x.bseq", 156962306a36Sopenharmony_ci ver->hw_platform, ver->hw_variant); 157062306a36Sopenharmony_ci if (request_firmware(&fw, fwname, &hdev->dev) < 0) { 157162306a36Sopenharmony_ci bt_dev_err(hdev, "failed to open default fw file: %s", 157262306a36Sopenharmony_ci fwname); 157362306a36Sopenharmony_ci return NULL; 157462306a36Sopenharmony_ci } 157562306a36Sopenharmony_ci } 157662306a36Sopenharmony_ci 157762306a36Sopenharmony_ci bt_dev_info(hdev, "Intel Bluetooth firmware file: %s", fwname); 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_ci return fw; 158062306a36Sopenharmony_ci} 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_cistatic int btintel_legacy_rom_patching(struct hci_dev *hdev, 158362306a36Sopenharmony_ci const struct firmware *fw, 158462306a36Sopenharmony_ci const u8 **fw_ptr, int *disable_patch) 158562306a36Sopenharmony_ci{ 158662306a36Sopenharmony_ci struct sk_buff *skb; 158762306a36Sopenharmony_ci struct hci_command_hdr *cmd; 158862306a36Sopenharmony_ci const u8 *cmd_param; 158962306a36Sopenharmony_ci struct hci_event_hdr *evt = NULL; 159062306a36Sopenharmony_ci const u8 *evt_param = NULL; 159162306a36Sopenharmony_ci int remain = fw->size - (*fw_ptr - fw->data); 159262306a36Sopenharmony_ci 159362306a36Sopenharmony_ci /* The first byte indicates the types of the patch command or event. 159462306a36Sopenharmony_ci * 0x01 means HCI command and 0x02 is HCI event. If the first bytes 159562306a36Sopenharmony_ci * in the current firmware buffer doesn't start with 0x01 or 159662306a36Sopenharmony_ci * the size of remain buffer is smaller than HCI command header, 159762306a36Sopenharmony_ci * the firmware file is corrupted and it should stop the patching 159862306a36Sopenharmony_ci * process. 159962306a36Sopenharmony_ci */ 160062306a36Sopenharmony_ci if (remain > HCI_COMMAND_HDR_SIZE && *fw_ptr[0] != 0x01) { 160162306a36Sopenharmony_ci bt_dev_err(hdev, "Intel fw corrupted: invalid cmd read"); 160262306a36Sopenharmony_ci return -EINVAL; 160362306a36Sopenharmony_ci } 160462306a36Sopenharmony_ci (*fw_ptr)++; 160562306a36Sopenharmony_ci remain--; 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_ci cmd = (struct hci_command_hdr *)(*fw_ptr); 160862306a36Sopenharmony_ci *fw_ptr += sizeof(*cmd); 160962306a36Sopenharmony_ci remain -= sizeof(*cmd); 161062306a36Sopenharmony_ci 161162306a36Sopenharmony_ci /* Ensure that the remain firmware data is long enough than the length 161262306a36Sopenharmony_ci * of command parameter. If not, the firmware file is corrupted. 161362306a36Sopenharmony_ci */ 161462306a36Sopenharmony_ci if (remain < cmd->plen) { 161562306a36Sopenharmony_ci bt_dev_err(hdev, "Intel fw corrupted: invalid cmd len"); 161662306a36Sopenharmony_ci return -EFAULT; 161762306a36Sopenharmony_ci } 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_ci /* If there is a command that loads a patch in the firmware 162062306a36Sopenharmony_ci * file, then enable the patch upon success, otherwise just 162162306a36Sopenharmony_ci * disable the manufacturer mode, for example patch activation 162262306a36Sopenharmony_ci * is not required when the default firmware patch file is used 162362306a36Sopenharmony_ci * because there are no patch data to load. 162462306a36Sopenharmony_ci */ 162562306a36Sopenharmony_ci if (*disable_patch && le16_to_cpu(cmd->opcode) == 0xfc8e) 162662306a36Sopenharmony_ci *disable_patch = 0; 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci cmd_param = *fw_ptr; 162962306a36Sopenharmony_ci *fw_ptr += cmd->plen; 163062306a36Sopenharmony_ci remain -= cmd->plen; 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ci /* This reads the expected events when the above command is sent to the 163362306a36Sopenharmony_ci * device. Some vendor commands expects more than one events, for 163462306a36Sopenharmony_ci * example command status event followed by vendor specific event. 163562306a36Sopenharmony_ci * For this case, it only keeps the last expected event. so the command 163662306a36Sopenharmony_ci * can be sent with __hci_cmd_sync_ev() which returns the sk_buff of 163762306a36Sopenharmony_ci * last expected event. 163862306a36Sopenharmony_ci */ 163962306a36Sopenharmony_ci while (remain > HCI_EVENT_HDR_SIZE && *fw_ptr[0] == 0x02) { 164062306a36Sopenharmony_ci (*fw_ptr)++; 164162306a36Sopenharmony_ci remain--; 164262306a36Sopenharmony_ci 164362306a36Sopenharmony_ci evt = (struct hci_event_hdr *)(*fw_ptr); 164462306a36Sopenharmony_ci *fw_ptr += sizeof(*evt); 164562306a36Sopenharmony_ci remain -= sizeof(*evt); 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_ci if (remain < evt->plen) { 164862306a36Sopenharmony_ci bt_dev_err(hdev, "Intel fw corrupted: invalid evt len"); 164962306a36Sopenharmony_ci return -EFAULT; 165062306a36Sopenharmony_ci } 165162306a36Sopenharmony_ci 165262306a36Sopenharmony_ci evt_param = *fw_ptr; 165362306a36Sopenharmony_ci *fw_ptr += evt->plen; 165462306a36Sopenharmony_ci remain -= evt->plen; 165562306a36Sopenharmony_ci } 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ci /* Every HCI commands in the firmware file has its correspond event. 165862306a36Sopenharmony_ci * If event is not found or remain is smaller than zero, the firmware 165962306a36Sopenharmony_ci * file is corrupted. 166062306a36Sopenharmony_ci */ 166162306a36Sopenharmony_ci if (!evt || !evt_param || remain < 0) { 166262306a36Sopenharmony_ci bt_dev_err(hdev, "Intel fw corrupted: invalid evt read"); 166362306a36Sopenharmony_ci return -EFAULT; 166462306a36Sopenharmony_ci } 166562306a36Sopenharmony_ci 166662306a36Sopenharmony_ci skb = __hci_cmd_sync_ev(hdev, le16_to_cpu(cmd->opcode), cmd->plen, 166762306a36Sopenharmony_ci cmd_param, evt->evt, HCI_INIT_TIMEOUT); 166862306a36Sopenharmony_ci if (IS_ERR(skb)) { 166962306a36Sopenharmony_ci bt_dev_err(hdev, "sending Intel patch command (0x%4.4x) failed (%ld)", 167062306a36Sopenharmony_ci cmd->opcode, PTR_ERR(skb)); 167162306a36Sopenharmony_ci return PTR_ERR(skb); 167262306a36Sopenharmony_ci } 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci /* It ensures that the returned event matches the event data read from 167562306a36Sopenharmony_ci * the firmware file. At fist, it checks the length and then 167662306a36Sopenharmony_ci * the contents of the event. 167762306a36Sopenharmony_ci */ 167862306a36Sopenharmony_ci if (skb->len != evt->plen) { 167962306a36Sopenharmony_ci bt_dev_err(hdev, "mismatch event length (opcode 0x%4.4x)", 168062306a36Sopenharmony_ci le16_to_cpu(cmd->opcode)); 168162306a36Sopenharmony_ci kfree_skb(skb); 168262306a36Sopenharmony_ci return -EFAULT; 168362306a36Sopenharmony_ci } 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci if (memcmp(skb->data, evt_param, evt->plen)) { 168662306a36Sopenharmony_ci bt_dev_err(hdev, "mismatch event parameter (opcode 0x%4.4x)", 168762306a36Sopenharmony_ci le16_to_cpu(cmd->opcode)); 168862306a36Sopenharmony_ci kfree_skb(skb); 168962306a36Sopenharmony_ci return -EFAULT; 169062306a36Sopenharmony_ci } 169162306a36Sopenharmony_ci kfree_skb(skb); 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_ci return 0; 169462306a36Sopenharmony_ci} 169562306a36Sopenharmony_ci 169662306a36Sopenharmony_cistatic int btintel_legacy_rom_setup(struct hci_dev *hdev, 169762306a36Sopenharmony_ci struct intel_version *ver) 169862306a36Sopenharmony_ci{ 169962306a36Sopenharmony_ci const struct firmware *fw; 170062306a36Sopenharmony_ci const u8 *fw_ptr; 170162306a36Sopenharmony_ci int disable_patch, err; 170262306a36Sopenharmony_ci struct intel_version new_ver; 170362306a36Sopenharmony_ci 170462306a36Sopenharmony_ci BT_DBG("%s", hdev->name); 170562306a36Sopenharmony_ci 170662306a36Sopenharmony_ci /* fw_patch_num indicates the version of patch the device currently 170762306a36Sopenharmony_ci * have. If there is no patch data in the device, it is always 0x00. 170862306a36Sopenharmony_ci * So, if it is other than 0x00, no need to patch the device again. 170962306a36Sopenharmony_ci */ 171062306a36Sopenharmony_ci if (ver->fw_patch_num) { 171162306a36Sopenharmony_ci bt_dev_info(hdev, 171262306a36Sopenharmony_ci "Intel device is already patched. patch num: %02x", 171362306a36Sopenharmony_ci ver->fw_patch_num); 171462306a36Sopenharmony_ci goto complete; 171562306a36Sopenharmony_ci } 171662306a36Sopenharmony_ci 171762306a36Sopenharmony_ci /* Opens the firmware patch file based on the firmware version read 171862306a36Sopenharmony_ci * from the controller. If it fails to open the matching firmware 171962306a36Sopenharmony_ci * patch file, it tries to open the default firmware patch file. 172062306a36Sopenharmony_ci * If no patch file is found, allow the device to operate without 172162306a36Sopenharmony_ci * a patch. 172262306a36Sopenharmony_ci */ 172362306a36Sopenharmony_ci fw = btintel_legacy_rom_get_fw(hdev, ver); 172462306a36Sopenharmony_ci if (!fw) 172562306a36Sopenharmony_ci goto complete; 172662306a36Sopenharmony_ci fw_ptr = fw->data; 172762306a36Sopenharmony_ci 172862306a36Sopenharmony_ci /* Enable the manufacturer mode of the controller. 172962306a36Sopenharmony_ci * Only while this mode is enabled, the driver can download the 173062306a36Sopenharmony_ci * firmware patch data and configuration parameters. 173162306a36Sopenharmony_ci */ 173262306a36Sopenharmony_ci err = btintel_enter_mfg(hdev); 173362306a36Sopenharmony_ci if (err) { 173462306a36Sopenharmony_ci release_firmware(fw); 173562306a36Sopenharmony_ci return err; 173662306a36Sopenharmony_ci } 173762306a36Sopenharmony_ci 173862306a36Sopenharmony_ci disable_patch = 1; 173962306a36Sopenharmony_ci 174062306a36Sopenharmony_ci /* The firmware data file consists of list of Intel specific HCI 174162306a36Sopenharmony_ci * commands and its expected events. The first byte indicates the 174262306a36Sopenharmony_ci * type of the message, either HCI command or HCI event. 174362306a36Sopenharmony_ci * 174462306a36Sopenharmony_ci * It reads the command and its expected event from the firmware file, 174562306a36Sopenharmony_ci * and send to the controller. Once __hci_cmd_sync_ev() returns, 174662306a36Sopenharmony_ci * the returned event is compared with the event read from the firmware 174762306a36Sopenharmony_ci * file and it will continue until all the messages are downloaded to 174862306a36Sopenharmony_ci * the controller. 174962306a36Sopenharmony_ci * 175062306a36Sopenharmony_ci * Once the firmware patching is completed successfully, 175162306a36Sopenharmony_ci * the manufacturer mode is disabled with reset and activating the 175262306a36Sopenharmony_ci * downloaded patch. 175362306a36Sopenharmony_ci * 175462306a36Sopenharmony_ci * If the firmware patching fails, the manufacturer mode is 175562306a36Sopenharmony_ci * disabled with reset and deactivating the patch. 175662306a36Sopenharmony_ci * 175762306a36Sopenharmony_ci * If the default patch file is used, no reset is done when disabling 175862306a36Sopenharmony_ci * the manufacturer. 175962306a36Sopenharmony_ci */ 176062306a36Sopenharmony_ci while (fw->size > fw_ptr - fw->data) { 176162306a36Sopenharmony_ci int ret; 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_ci ret = btintel_legacy_rom_patching(hdev, fw, &fw_ptr, 176462306a36Sopenharmony_ci &disable_patch); 176562306a36Sopenharmony_ci if (ret < 0) 176662306a36Sopenharmony_ci goto exit_mfg_deactivate; 176762306a36Sopenharmony_ci } 176862306a36Sopenharmony_ci 176962306a36Sopenharmony_ci release_firmware(fw); 177062306a36Sopenharmony_ci 177162306a36Sopenharmony_ci if (disable_patch) 177262306a36Sopenharmony_ci goto exit_mfg_disable; 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_ci /* Patching completed successfully and disable the manufacturer mode 177562306a36Sopenharmony_ci * with reset and activate the downloaded firmware patches. 177662306a36Sopenharmony_ci */ 177762306a36Sopenharmony_ci err = btintel_exit_mfg(hdev, true, true); 177862306a36Sopenharmony_ci if (err) 177962306a36Sopenharmony_ci return err; 178062306a36Sopenharmony_ci 178162306a36Sopenharmony_ci /* Need build number for downloaded fw patches in 178262306a36Sopenharmony_ci * every power-on boot 178362306a36Sopenharmony_ci */ 178462306a36Sopenharmony_ci err = btintel_read_version(hdev, &new_ver); 178562306a36Sopenharmony_ci if (err) 178662306a36Sopenharmony_ci return err; 178762306a36Sopenharmony_ci 178862306a36Sopenharmony_ci bt_dev_info(hdev, "Intel BT fw patch 0x%02x completed & activated", 178962306a36Sopenharmony_ci new_ver.fw_patch_num); 179062306a36Sopenharmony_ci 179162306a36Sopenharmony_ci goto complete; 179262306a36Sopenharmony_ci 179362306a36Sopenharmony_ciexit_mfg_disable: 179462306a36Sopenharmony_ci /* Disable the manufacturer mode without reset */ 179562306a36Sopenharmony_ci err = btintel_exit_mfg(hdev, false, false); 179662306a36Sopenharmony_ci if (err) 179762306a36Sopenharmony_ci return err; 179862306a36Sopenharmony_ci 179962306a36Sopenharmony_ci bt_dev_info(hdev, "Intel firmware patch completed"); 180062306a36Sopenharmony_ci 180162306a36Sopenharmony_ci goto complete; 180262306a36Sopenharmony_ci 180362306a36Sopenharmony_ciexit_mfg_deactivate: 180462306a36Sopenharmony_ci release_firmware(fw); 180562306a36Sopenharmony_ci 180662306a36Sopenharmony_ci /* Patching failed. Disable the manufacturer mode with reset and 180762306a36Sopenharmony_ci * deactivate the downloaded firmware patches. 180862306a36Sopenharmony_ci */ 180962306a36Sopenharmony_ci err = btintel_exit_mfg(hdev, true, false); 181062306a36Sopenharmony_ci if (err) 181162306a36Sopenharmony_ci return err; 181262306a36Sopenharmony_ci 181362306a36Sopenharmony_ci bt_dev_info(hdev, "Intel firmware patch completed and deactivated"); 181462306a36Sopenharmony_ci 181562306a36Sopenharmony_cicomplete: 181662306a36Sopenharmony_ci /* Set the event mask for Intel specific vendor events. This enables 181762306a36Sopenharmony_ci * a few extra events that are useful during general operation. 181862306a36Sopenharmony_ci */ 181962306a36Sopenharmony_ci btintel_set_event_mask_mfg(hdev, false); 182062306a36Sopenharmony_ci 182162306a36Sopenharmony_ci btintel_check_bdaddr(hdev); 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci return 0; 182462306a36Sopenharmony_ci} 182562306a36Sopenharmony_ci 182662306a36Sopenharmony_cistatic int btintel_download_wait(struct hci_dev *hdev, ktime_t calltime, int msec) 182762306a36Sopenharmony_ci{ 182862306a36Sopenharmony_ci ktime_t delta, rettime; 182962306a36Sopenharmony_ci unsigned long long duration; 183062306a36Sopenharmony_ci int err; 183162306a36Sopenharmony_ci 183262306a36Sopenharmony_ci btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED); 183362306a36Sopenharmony_ci 183462306a36Sopenharmony_ci bt_dev_info(hdev, "Waiting for firmware download to complete"); 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci err = btintel_wait_on_flag_timeout(hdev, INTEL_DOWNLOADING, 183762306a36Sopenharmony_ci TASK_INTERRUPTIBLE, 183862306a36Sopenharmony_ci msecs_to_jiffies(msec)); 183962306a36Sopenharmony_ci if (err == -EINTR) { 184062306a36Sopenharmony_ci bt_dev_err(hdev, "Firmware loading interrupted"); 184162306a36Sopenharmony_ci return err; 184262306a36Sopenharmony_ci } 184362306a36Sopenharmony_ci 184462306a36Sopenharmony_ci if (err) { 184562306a36Sopenharmony_ci bt_dev_err(hdev, "Firmware loading timeout"); 184662306a36Sopenharmony_ci return -ETIMEDOUT; 184762306a36Sopenharmony_ci } 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci if (btintel_test_flag(hdev, INTEL_FIRMWARE_FAILED)) { 185062306a36Sopenharmony_ci bt_dev_err(hdev, "Firmware loading failed"); 185162306a36Sopenharmony_ci return -ENOEXEC; 185262306a36Sopenharmony_ci } 185362306a36Sopenharmony_ci 185462306a36Sopenharmony_ci rettime = ktime_get(); 185562306a36Sopenharmony_ci delta = ktime_sub(rettime, calltime); 185662306a36Sopenharmony_ci duration = (unsigned long long)ktime_to_ns(delta) >> 10; 185762306a36Sopenharmony_ci 185862306a36Sopenharmony_ci bt_dev_info(hdev, "Firmware loaded in %llu usecs", duration); 185962306a36Sopenharmony_ci 186062306a36Sopenharmony_ci return 0; 186162306a36Sopenharmony_ci} 186262306a36Sopenharmony_ci 186362306a36Sopenharmony_cistatic int btintel_boot_wait(struct hci_dev *hdev, ktime_t calltime, int msec) 186462306a36Sopenharmony_ci{ 186562306a36Sopenharmony_ci ktime_t delta, rettime; 186662306a36Sopenharmony_ci unsigned long long duration; 186762306a36Sopenharmony_ci int err; 186862306a36Sopenharmony_ci 186962306a36Sopenharmony_ci bt_dev_info(hdev, "Waiting for device to boot"); 187062306a36Sopenharmony_ci 187162306a36Sopenharmony_ci err = btintel_wait_on_flag_timeout(hdev, INTEL_BOOTING, 187262306a36Sopenharmony_ci TASK_INTERRUPTIBLE, 187362306a36Sopenharmony_ci msecs_to_jiffies(msec)); 187462306a36Sopenharmony_ci if (err == -EINTR) { 187562306a36Sopenharmony_ci bt_dev_err(hdev, "Device boot interrupted"); 187662306a36Sopenharmony_ci return -EINTR; 187762306a36Sopenharmony_ci } 187862306a36Sopenharmony_ci 187962306a36Sopenharmony_ci if (err) { 188062306a36Sopenharmony_ci bt_dev_err(hdev, "Device boot timeout"); 188162306a36Sopenharmony_ci return -ETIMEDOUT; 188262306a36Sopenharmony_ci } 188362306a36Sopenharmony_ci 188462306a36Sopenharmony_ci rettime = ktime_get(); 188562306a36Sopenharmony_ci delta = ktime_sub(rettime, calltime); 188662306a36Sopenharmony_ci duration = (unsigned long long) ktime_to_ns(delta) >> 10; 188762306a36Sopenharmony_ci 188862306a36Sopenharmony_ci bt_dev_info(hdev, "Device booted in %llu usecs", duration); 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_ci return 0; 189162306a36Sopenharmony_ci} 189262306a36Sopenharmony_ci 189362306a36Sopenharmony_cistatic int btintel_boot(struct hci_dev *hdev, u32 boot_addr) 189462306a36Sopenharmony_ci{ 189562306a36Sopenharmony_ci ktime_t calltime; 189662306a36Sopenharmony_ci int err; 189762306a36Sopenharmony_ci 189862306a36Sopenharmony_ci calltime = ktime_get(); 189962306a36Sopenharmony_ci 190062306a36Sopenharmony_ci btintel_set_flag(hdev, INTEL_BOOTING); 190162306a36Sopenharmony_ci 190262306a36Sopenharmony_ci err = btintel_send_intel_reset(hdev, boot_addr); 190362306a36Sopenharmony_ci if (err) { 190462306a36Sopenharmony_ci bt_dev_err(hdev, "Intel Soft Reset failed (%d)", err); 190562306a36Sopenharmony_ci btintel_reset_to_bootloader(hdev); 190662306a36Sopenharmony_ci return err; 190762306a36Sopenharmony_ci } 190862306a36Sopenharmony_ci 190962306a36Sopenharmony_ci /* The bootloader will not indicate when the device is ready. This 191062306a36Sopenharmony_ci * is done by the operational firmware sending bootup notification. 191162306a36Sopenharmony_ci * 191262306a36Sopenharmony_ci * Booting into operational firmware should not take longer than 191362306a36Sopenharmony_ci * 1 second. However if that happens, then just fail the setup 191462306a36Sopenharmony_ci * since something went wrong. 191562306a36Sopenharmony_ci */ 191662306a36Sopenharmony_ci err = btintel_boot_wait(hdev, calltime, 1000); 191762306a36Sopenharmony_ci if (err == -ETIMEDOUT) 191862306a36Sopenharmony_ci btintel_reset_to_bootloader(hdev); 191962306a36Sopenharmony_ci 192062306a36Sopenharmony_ci return err; 192162306a36Sopenharmony_ci} 192262306a36Sopenharmony_ci 192362306a36Sopenharmony_cistatic int btintel_get_fw_name(struct intel_version *ver, 192462306a36Sopenharmony_ci struct intel_boot_params *params, 192562306a36Sopenharmony_ci char *fw_name, size_t len, 192662306a36Sopenharmony_ci const char *suffix) 192762306a36Sopenharmony_ci{ 192862306a36Sopenharmony_ci switch (ver->hw_variant) { 192962306a36Sopenharmony_ci case 0x0b: /* SfP */ 193062306a36Sopenharmony_ci case 0x0c: /* WsP */ 193162306a36Sopenharmony_ci snprintf(fw_name, len, "intel/ibt-%u-%u.%s", 193262306a36Sopenharmony_ci ver->hw_variant, 193362306a36Sopenharmony_ci le16_to_cpu(params->dev_revid), 193462306a36Sopenharmony_ci suffix); 193562306a36Sopenharmony_ci break; 193662306a36Sopenharmony_ci case 0x11: /* JfP */ 193762306a36Sopenharmony_ci case 0x12: /* ThP */ 193862306a36Sopenharmony_ci case 0x13: /* HrP */ 193962306a36Sopenharmony_ci case 0x14: /* CcP */ 194062306a36Sopenharmony_ci snprintf(fw_name, len, "intel/ibt-%u-%u-%u.%s", 194162306a36Sopenharmony_ci ver->hw_variant, 194262306a36Sopenharmony_ci ver->hw_revision, 194362306a36Sopenharmony_ci ver->fw_revision, 194462306a36Sopenharmony_ci suffix); 194562306a36Sopenharmony_ci break; 194662306a36Sopenharmony_ci default: 194762306a36Sopenharmony_ci return -EINVAL; 194862306a36Sopenharmony_ci } 194962306a36Sopenharmony_ci 195062306a36Sopenharmony_ci return 0; 195162306a36Sopenharmony_ci} 195262306a36Sopenharmony_ci 195362306a36Sopenharmony_cistatic int btintel_download_fw(struct hci_dev *hdev, 195462306a36Sopenharmony_ci struct intel_version *ver, 195562306a36Sopenharmony_ci struct intel_boot_params *params, 195662306a36Sopenharmony_ci u32 *boot_param) 195762306a36Sopenharmony_ci{ 195862306a36Sopenharmony_ci const struct firmware *fw; 195962306a36Sopenharmony_ci char fwname[64]; 196062306a36Sopenharmony_ci int err; 196162306a36Sopenharmony_ci ktime_t calltime; 196262306a36Sopenharmony_ci 196362306a36Sopenharmony_ci if (!ver || !params) 196462306a36Sopenharmony_ci return -EINVAL; 196562306a36Sopenharmony_ci 196662306a36Sopenharmony_ci /* The firmware variant determines if the device is in bootloader 196762306a36Sopenharmony_ci * mode or is running operational firmware. The value 0x06 identifies 196862306a36Sopenharmony_ci * the bootloader and the value 0x23 identifies the operational 196962306a36Sopenharmony_ci * firmware. 197062306a36Sopenharmony_ci * 197162306a36Sopenharmony_ci * When the operational firmware is already present, then only 197262306a36Sopenharmony_ci * the check for valid Bluetooth device address is needed. This 197362306a36Sopenharmony_ci * determines if the device will be added as configured or 197462306a36Sopenharmony_ci * unconfigured controller. 197562306a36Sopenharmony_ci * 197662306a36Sopenharmony_ci * It is not possible to use the Secure Boot Parameters in this 197762306a36Sopenharmony_ci * case since that command is only available in bootloader mode. 197862306a36Sopenharmony_ci */ 197962306a36Sopenharmony_ci if (ver->fw_variant == 0x23) { 198062306a36Sopenharmony_ci btintel_clear_flag(hdev, INTEL_BOOTLOADER); 198162306a36Sopenharmony_ci btintel_check_bdaddr(hdev); 198262306a36Sopenharmony_ci 198362306a36Sopenharmony_ci /* SfP and WsP don't seem to update the firmware version on file 198462306a36Sopenharmony_ci * so version checking is currently possible. 198562306a36Sopenharmony_ci */ 198662306a36Sopenharmony_ci switch (ver->hw_variant) { 198762306a36Sopenharmony_ci case 0x0b: /* SfP */ 198862306a36Sopenharmony_ci case 0x0c: /* WsP */ 198962306a36Sopenharmony_ci return 0; 199062306a36Sopenharmony_ci } 199162306a36Sopenharmony_ci 199262306a36Sopenharmony_ci /* Proceed to download to check if the version matches */ 199362306a36Sopenharmony_ci goto download; 199462306a36Sopenharmony_ci } 199562306a36Sopenharmony_ci 199662306a36Sopenharmony_ci /* Read the secure boot parameters to identify the operating 199762306a36Sopenharmony_ci * details of the bootloader. 199862306a36Sopenharmony_ci */ 199962306a36Sopenharmony_ci err = btintel_read_boot_params(hdev, params); 200062306a36Sopenharmony_ci if (err) 200162306a36Sopenharmony_ci return err; 200262306a36Sopenharmony_ci 200362306a36Sopenharmony_ci /* It is required that every single firmware fragment is acknowledged 200462306a36Sopenharmony_ci * with a command complete event. If the boot parameters indicate 200562306a36Sopenharmony_ci * that this bootloader does not send them, then abort the setup. 200662306a36Sopenharmony_ci */ 200762306a36Sopenharmony_ci if (params->limited_cce != 0x00) { 200862306a36Sopenharmony_ci bt_dev_err(hdev, "Unsupported Intel firmware loading method (%u)", 200962306a36Sopenharmony_ci params->limited_cce); 201062306a36Sopenharmony_ci return -EINVAL; 201162306a36Sopenharmony_ci } 201262306a36Sopenharmony_ci 201362306a36Sopenharmony_ci /* If the OTP has no valid Bluetooth device address, then there will 201462306a36Sopenharmony_ci * also be no valid address for the operational firmware. 201562306a36Sopenharmony_ci */ 201662306a36Sopenharmony_ci if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) { 201762306a36Sopenharmony_ci bt_dev_info(hdev, "No device address configured"); 201862306a36Sopenharmony_ci set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); 201962306a36Sopenharmony_ci } 202062306a36Sopenharmony_ci 202162306a36Sopenharmony_cidownload: 202262306a36Sopenharmony_ci /* With this Intel bootloader only the hardware variant and device 202362306a36Sopenharmony_ci * revision information are used to select the right firmware for SfP 202462306a36Sopenharmony_ci * and WsP. 202562306a36Sopenharmony_ci * 202662306a36Sopenharmony_ci * The firmware filename is ibt-<hw_variant>-<dev_revid>.sfi. 202762306a36Sopenharmony_ci * 202862306a36Sopenharmony_ci * Currently the supported hardware variants are: 202962306a36Sopenharmony_ci * 11 (0x0b) for iBT3.0 (LnP/SfP) 203062306a36Sopenharmony_ci * 12 (0x0c) for iBT3.5 (WsP) 203162306a36Sopenharmony_ci * 203262306a36Sopenharmony_ci * For ThP/JfP and for future SKU's, the FW name varies based on HW 203362306a36Sopenharmony_ci * variant, HW revision and FW revision, as these are dependent on CNVi 203462306a36Sopenharmony_ci * and RF Combination. 203562306a36Sopenharmony_ci * 203662306a36Sopenharmony_ci * 17 (0x11) for iBT3.5 (JfP) 203762306a36Sopenharmony_ci * 18 (0x12) for iBT3.5 (ThP) 203862306a36Sopenharmony_ci * 203962306a36Sopenharmony_ci * The firmware file name for these will be 204062306a36Sopenharmony_ci * ibt-<hw_variant>-<hw_revision>-<fw_revision>.sfi. 204162306a36Sopenharmony_ci * 204262306a36Sopenharmony_ci */ 204362306a36Sopenharmony_ci err = btintel_get_fw_name(ver, params, fwname, sizeof(fwname), "sfi"); 204462306a36Sopenharmony_ci if (err < 0) { 204562306a36Sopenharmony_ci if (!btintel_test_flag(hdev, INTEL_BOOTLOADER)) { 204662306a36Sopenharmony_ci /* Firmware has already been loaded */ 204762306a36Sopenharmony_ci btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED); 204862306a36Sopenharmony_ci return 0; 204962306a36Sopenharmony_ci } 205062306a36Sopenharmony_ci 205162306a36Sopenharmony_ci bt_dev_err(hdev, "Unsupported Intel firmware naming"); 205262306a36Sopenharmony_ci return -EINVAL; 205362306a36Sopenharmony_ci } 205462306a36Sopenharmony_ci 205562306a36Sopenharmony_ci err = firmware_request_nowarn(&fw, fwname, &hdev->dev); 205662306a36Sopenharmony_ci if (err < 0) { 205762306a36Sopenharmony_ci if (!btintel_test_flag(hdev, INTEL_BOOTLOADER)) { 205862306a36Sopenharmony_ci /* Firmware has already been loaded */ 205962306a36Sopenharmony_ci btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED); 206062306a36Sopenharmony_ci return 0; 206162306a36Sopenharmony_ci } 206262306a36Sopenharmony_ci 206362306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to load Intel firmware file %s (%d)", 206462306a36Sopenharmony_ci fwname, err); 206562306a36Sopenharmony_ci return err; 206662306a36Sopenharmony_ci } 206762306a36Sopenharmony_ci 206862306a36Sopenharmony_ci bt_dev_info(hdev, "Found device firmware: %s", fwname); 206962306a36Sopenharmony_ci 207062306a36Sopenharmony_ci if (fw->size < 644) { 207162306a36Sopenharmony_ci bt_dev_err(hdev, "Invalid size of firmware file (%zu)", 207262306a36Sopenharmony_ci fw->size); 207362306a36Sopenharmony_ci err = -EBADF; 207462306a36Sopenharmony_ci goto done; 207562306a36Sopenharmony_ci } 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_ci calltime = ktime_get(); 207862306a36Sopenharmony_ci 207962306a36Sopenharmony_ci btintel_set_flag(hdev, INTEL_DOWNLOADING); 208062306a36Sopenharmony_ci 208162306a36Sopenharmony_ci /* Start firmware downloading and get boot parameter */ 208262306a36Sopenharmony_ci err = btintel_download_firmware(hdev, ver, fw, boot_param); 208362306a36Sopenharmony_ci if (err < 0) { 208462306a36Sopenharmony_ci if (err == -EALREADY) { 208562306a36Sopenharmony_ci /* Firmware has already been loaded */ 208662306a36Sopenharmony_ci btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED); 208762306a36Sopenharmony_ci err = 0; 208862306a36Sopenharmony_ci goto done; 208962306a36Sopenharmony_ci } 209062306a36Sopenharmony_ci 209162306a36Sopenharmony_ci /* When FW download fails, send Intel Reset to retry 209262306a36Sopenharmony_ci * FW download. 209362306a36Sopenharmony_ci */ 209462306a36Sopenharmony_ci btintel_reset_to_bootloader(hdev); 209562306a36Sopenharmony_ci goto done; 209662306a36Sopenharmony_ci } 209762306a36Sopenharmony_ci 209862306a36Sopenharmony_ci /* Before switching the device into operational mode and with that 209962306a36Sopenharmony_ci * booting the loaded firmware, wait for the bootloader notification 210062306a36Sopenharmony_ci * that all fragments have been successfully received. 210162306a36Sopenharmony_ci * 210262306a36Sopenharmony_ci * When the event processing receives the notification, then the 210362306a36Sopenharmony_ci * INTEL_DOWNLOADING flag will be cleared. 210462306a36Sopenharmony_ci * 210562306a36Sopenharmony_ci * The firmware loading should not take longer than 5 seconds 210662306a36Sopenharmony_ci * and thus just timeout if that happens and fail the setup 210762306a36Sopenharmony_ci * of this device. 210862306a36Sopenharmony_ci */ 210962306a36Sopenharmony_ci err = btintel_download_wait(hdev, calltime, 5000); 211062306a36Sopenharmony_ci if (err == -ETIMEDOUT) 211162306a36Sopenharmony_ci btintel_reset_to_bootloader(hdev); 211262306a36Sopenharmony_ci 211362306a36Sopenharmony_cidone: 211462306a36Sopenharmony_ci release_firmware(fw); 211562306a36Sopenharmony_ci return err; 211662306a36Sopenharmony_ci} 211762306a36Sopenharmony_ci 211862306a36Sopenharmony_cistatic int btintel_bootloader_setup(struct hci_dev *hdev, 211962306a36Sopenharmony_ci struct intel_version *ver) 212062306a36Sopenharmony_ci{ 212162306a36Sopenharmony_ci struct intel_version new_ver; 212262306a36Sopenharmony_ci struct intel_boot_params params; 212362306a36Sopenharmony_ci u32 boot_param; 212462306a36Sopenharmony_ci char ddcname[64]; 212562306a36Sopenharmony_ci int err; 212662306a36Sopenharmony_ci 212762306a36Sopenharmony_ci BT_DBG("%s", hdev->name); 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci /* Set the default boot parameter to 0x0 and it is updated to 213062306a36Sopenharmony_ci * SKU specific boot parameter after reading Intel_Write_Boot_Params 213162306a36Sopenharmony_ci * command while downloading the firmware. 213262306a36Sopenharmony_ci */ 213362306a36Sopenharmony_ci boot_param = 0x00000000; 213462306a36Sopenharmony_ci 213562306a36Sopenharmony_ci btintel_set_flag(hdev, INTEL_BOOTLOADER); 213662306a36Sopenharmony_ci 213762306a36Sopenharmony_ci err = btintel_download_fw(hdev, ver, ¶ms, &boot_param); 213862306a36Sopenharmony_ci if (err) 213962306a36Sopenharmony_ci return err; 214062306a36Sopenharmony_ci 214162306a36Sopenharmony_ci /* controller is already having an operational firmware */ 214262306a36Sopenharmony_ci if (ver->fw_variant == 0x23) 214362306a36Sopenharmony_ci goto finish; 214462306a36Sopenharmony_ci 214562306a36Sopenharmony_ci err = btintel_boot(hdev, boot_param); 214662306a36Sopenharmony_ci if (err) 214762306a36Sopenharmony_ci return err; 214862306a36Sopenharmony_ci 214962306a36Sopenharmony_ci btintel_clear_flag(hdev, INTEL_BOOTLOADER); 215062306a36Sopenharmony_ci 215162306a36Sopenharmony_ci err = btintel_get_fw_name(ver, ¶ms, ddcname, 215262306a36Sopenharmony_ci sizeof(ddcname), "ddc"); 215362306a36Sopenharmony_ci 215462306a36Sopenharmony_ci if (err < 0) { 215562306a36Sopenharmony_ci bt_dev_err(hdev, "Unsupported Intel firmware naming"); 215662306a36Sopenharmony_ci } else { 215762306a36Sopenharmony_ci /* Once the device is running in operational mode, it needs to 215862306a36Sopenharmony_ci * apply the device configuration (DDC) parameters. 215962306a36Sopenharmony_ci * 216062306a36Sopenharmony_ci * The device can work without DDC parameters, so even if it 216162306a36Sopenharmony_ci * fails to load the file, no need to fail the setup. 216262306a36Sopenharmony_ci */ 216362306a36Sopenharmony_ci btintel_load_ddc_config(hdev, ddcname); 216462306a36Sopenharmony_ci } 216562306a36Sopenharmony_ci 216662306a36Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT); 216762306a36Sopenharmony_ci 216862306a36Sopenharmony_ci /* Read the Intel version information after loading the FW */ 216962306a36Sopenharmony_ci err = btintel_read_version(hdev, &new_ver); 217062306a36Sopenharmony_ci if (err) 217162306a36Sopenharmony_ci return err; 217262306a36Sopenharmony_ci 217362306a36Sopenharmony_ci btintel_version_info(hdev, &new_ver); 217462306a36Sopenharmony_ci 217562306a36Sopenharmony_cifinish: 217662306a36Sopenharmony_ci /* Set the event mask for Intel specific vendor events. This enables 217762306a36Sopenharmony_ci * a few extra events that are useful during general operation. It 217862306a36Sopenharmony_ci * does not enable any debugging related events. 217962306a36Sopenharmony_ci * 218062306a36Sopenharmony_ci * The device will function correctly without these events enabled 218162306a36Sopenharmony_ci * and thus no need to fail the setup. 218262306a36Sopenharmony_ci */ 218362306a36Sopenharmony_ci btintel_set_event_mask(hdev, false); 218462306a36Sopenharmony_ci 218562306a36Sopenharmony_ci return 0; 218662306a36Sopenharmony_ci} 218762306a36Sopenharmony_ci 218862306a36Sopenharmony_cistatic void btintel_get_fw_name_tlv(const struct intel_version_tlv *ver, 218962306a36Sopenharmony_ci char *fw_name, size_t len, 219062306a36Sopenharmony_ci const char *suffix) 219162306a36Sopenharmony_ci{ 219262306a36Sopenharmony_ci /* The firmware file name for new generation controllers will be 219362306a36Sopenharmony_ci * ibt-<cnvi_top type+cnvi_top step>-<cnvr_top type+cnvr_top step> 219462306a36Sopenharmony_ci */ 219562306a36Sopenharmony_ci snprintf(fw_name, len, "intel/ibt-%04x-%04x.%s", 219662306a36Sopenharmony_ci INTEL_CNVX_TOP_PACK_SWAB(INTEL_CNVX_TOP_TYPE(ver->cnvi_top), 219762306a36Sopenharmony_ci INTEL_CNVX_TOP_STEP(ver->cnvi_top)), 219862306a36Sopenharmony_ci INTEL_CNVX_TOP_PACK_SWAB(INTEL_CNVX_TOP_TYPE(ver->cnvr_top), 219962306a36Sopenharmony_ci INTEL_CNVX_TOP_STEP(ver->cnvr_top)), 220062306a36Sopenharmony_ci suffix); 220162306a36Sopenharmony_ci} 220262306a36Sopenharmony_ci 220362306a36Sopenharmony_cistatic int btintel_prepare_fw_download_tlv(struct hci_dev *hdev, 220462306a36Sopenharmony_ci struct intel_version_tlv *ver, 220562306a36Sopenharmony_ci u32 *boot_param) 220662306a36Sopenharmony_ci{ 220762306a36Sopenharmony_ci const struct firmware *fw; 220862306a36Sopenharmony_ci char fwname[64]; 220962306a36Sopenharmony_ci int err; 221062306a36Sopenharmony_ci ktime_t calltime; 221162306a36Sopenharmony_ci 221262306a36Sopenharmony_ci if (!ver || !boot_param) 221362306a36Sopenharmony_ci return -EINVAL; 221462306a36Sopenharmony_ci 221562306a36Sopenharmony_ci /* The firmware variant determines if the device is in bootloader 221662306a36Sopenharmony_ci * mode or is running operational firmware. The value 0x03 identifies 221762306a36Sopenharmony_ci * the bootloader and the value 0x23 identifies the operational 221862306a36Sopenharmony_ci * firmware. 221962306a36Sopenharmony_ci * 222062306a36Sopenharmony_ci * When the operational firmware is already present, then only 222162306a36Sopenharmony_ci * the check for valid Bluetooth device address is needed. This 222262306a36Sopenharmony_ci * determines if the device will be added as configured or 222362306a36Sopenharmony_ci * unconfigured controller. 222462306a36Sopenharmony_ci * 222562306a36Sopenharmony_ci * It is not possible to use the Secure Boot Parameters in this 222662306a36Sopenharmony_ci * case since that command is only available in bootloader mode. 222762306a36Sopenharmony_ci */ 222862306a36Sopenharmony_ci if (ver->img_type == 0x03) { 222962306a36Sopenharmony_ci btintel_clear_flag(hdev, INTEL_BOOTLOADER); 223062306a36Sopenharmony_ci btintel_check_bdaddr(hdev); 223162306a36Sopenharmony_ci } else { 223262306a36Sopenharmony_ci /* 223362306a36Sopenharmony_ci * Check for valid bd address in boot loader mode. Device 223462306a36Sopenharmony_ci * will be marked as unconfigured if empty bd address is 223562306a36Sopenharmony_ci * found. 223662306a36Sopenharmony_ci */ 223762306a36Sopenharmony_ci if (!bacmp(&ver->otp_bd_addr, BDADDR_ANY)) { 223862306a36Sopenharmony_ci bt_dev_info(hdev, "No device address configured"); 223962306a36Sopenharmony_ci set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); 224062306a36Sopenharmony_ci } 224162306a36Sopenharmony_ci } 224262306a36Sopenharmony_ci 224362306a36Sopenharmony_ci btintel_get_fw_name_tlv(ver, fwname, sizeof(fwname), "sfi"); 224462306a36Sopenharmony_ci err = firmware_request_nowarn(&fw, fwname, &hdev->dev); 224562306a36Sopenharmony_ci if (err < 0) { 224662306a36Sopenharmony_ci if (!btintel_test_flag(hdev, INTEL_BOOTLOADER)) { 224762306a36Sopenharmony_ci /* Firmware has already been loaded */ 224862306a36Sopenharmony_ci btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED); 224962306a36Sopenharmony_ci return 0; 225062306a36Sopenharmony_ci } 225162306a36Sopenharmony_ci 225262306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to load Intel firmware file %s (%d)", 225362306a36Sopenharmony_ci fwname, err); 225462306a36Sopenharmony_ci 225562306a36Sopenharmony_ci return err; 225662306a36Sopenharmony_ci } 225762306a36Sopenharmony_ci 225862306a36Sopenharmony_ci bt_dev_info(hdev, "Found device firmware: %s", fwname); 225962306a36Sopenharmony_ci 226062306a36Sopenharmony_ci if (fw->size < 644) { 226162306a36Sopenharmony_ci bt_dev_err(hdev, "Invalid size of firmware file (%zu)", 226262306a36Sopenharmony_ci fw->size); 226362306a36Sopenharmony_ci err = -EBADF; 226462306a36Sopenharmony_ci goto done; 226562306a36Sopenharmony_ci } 226662306a36Sopenharmony_ci 226762306a36Sopenharmony_ci calltime = ktime_get(); 226862306a36Sopenharmony_ci 226962306a36Sopenharmony_ci btintel_set_flag(hdev, INTEL_DOWNLOADING); 227062306a36Sopenharmony_ci 227162306a36Sopenharmony_ci /* Start firmware downloading and get boot parameter */ 227262306a36Sopenharmony_ci err = btintel_download_fw_tlv(hdev, ver, fw, boot_param, 227362306a36Sopenharmony_ci INTEL_HW_VARIANT(ver->cnvi_bt), 227462306a36Sopenharmony_ci ver->sbe_type); 227562306a36Sopenharmony_ci if (err < 0) { 227662306a36Sopenharmony_ci if (err == -EALREADY) { 227762306a36Sopenharmony_ci /* Firmware has already been loaded */ 227862306a36Sopenharmony_ci btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED); 227962306a36Sopenharmony_ci err = 0; 228062306a36Sopenharmony_ci goto done; 228162306a36Sopenharmony_ci } 228262306a36Sopenharmony_ci 228362306a36Sopenharmony_ci /* When FW download fails, send Intel Reset to retry 228462306a36Sopenharmony_ci * FW download. 228562306a36Sopenharmony_ci */ 228662306a36Sopenharmony_ci btintel_reset_to_bootloader(hdev); 228762306a36Sopenharmony_ci goto done; 228862306a36Sopenharmony_ci } 228962306a36Sopenharmony_ci 229062306a36Sopenharmony_ci /* Before switching the device into operational mode and with that 229162306a36Sopenharmony_ci * booting the loaded firmware, wait for the bootloader notification 229262306a36Sopenharmony_ci * that all fragments have been successfully received. 229362306a36Sopenharmony_ci * 229462306a36Sopenharmony_ci * When the event processing receives the notification, then the 229562306a36Sopenharmony_ci * BTUSB_DOWNLOADING flag will be cleared. 229662306a36Sopenharmony_ci * 229762306a36Sopenharmony_ci * The firmware loading should not take longer than 5 seconds 229862306a36Sopenharmony_ci * and thus just timeout if that happens and fail the setup 229962306a36Sopenharmony_ci * of this device. 230062306a36Sopenharmony_ci */ 230162306a36Sopenharmony_ci err = btintel_download_wait(hdev, calltime, 5000); 230262306a36Sopenharmony_ci if (err == -ETIMEDOUT) 230362306a36Sopenharmony_ci btintel_reset_to_bootloader(hdev); 230462306a36Sopenharmony_ci 230562306a36Sopenharmony_cidone: 230662306a36Sopenharmony_ci release_firmware(fw); 230762306a36Sopenharmony_ci return err; 230862306a36Sopenharmony_ci} 230962306a36Sopenharmony_ci 231062306a36Sopenharmony_cistatic int btintel_get_codec_config_data(struct hci_dev *hdev, 231162306a36Sopenharmony_ci __u8 link, struct bt_codec *codec, 231262306a36Sopenharmony_ci __u8 *ven_len, __u8 **ven_data) 231362306a36Sopenharmony_ci{ 231462306a36Sopenharmony_ci int err = 0; 231562306a36Sopenharmony_ci 231662306a36Sopenharmony_ci if (!ven_data || !ven_len) 231762306a36Sopenharmony_ci return -EINVAL; 231862306a36Sopenharmony_ci 231962306a36Sopenharmony_ci *ven_len = 0; 232062306a36Sopenharmony_ci *ven_data = NULL; 232162306a36Sopenharmony_ci 232262306a36Sopenharmony_ci if (link != ESCO_LINK) { 232362306a36Sopenharmony_ci bt_dev_err(hdev, "Invalid link type(%u)", link); 232462306a36Sopenharmony_ci return -EINVAL; 232562306a36Sopenharmony_ci } 232662306a36Sopenharmony_ci 232762306a36Sopenharmony_ci *ven_data = kmalloc(sizeof(__u8), GFP_KERNEL); 232862306a36Sopenharmony_ci if (!*ven_data) { 232962306a36Sopenharmony_ci err = -ENOMEM; 233062306a36Sopenharmony_ci goto error; 233162306a36Sopenharmony_ci } 233262306a36Sopenharmony_ci 233362306a36Sopenharmony_ci /* supports only CVSD and mSBC offload codecs */ 233462306a36Sopenharmony_ci switch (codec->id) { 233562306a36Sopenharmony_ci case 0x02: 233662306a36Sopenharmony_ci **ven_data = 0x00; 233762306a36Sopenharmony_ci break; 233862306a36Sopenharmony_ci case 0x05: 233962306a36Sopenharmony_ci **ven_data = 0x01; 234062306a36Sopenharmony_ci break; 234162306a36Sopenharmony_ci default: 234262306a36Sopenharmony_ci err = -EINVAL; 234362306a36Sopenharmony_ci bt_dev_err(hdev, "Invalid codec id(%u)", codec->id); 234462306a36Sopenharmony_ci goto error; 234562306a36Sopenharmony_ci } 234662306a36Sopenharmony_ci /* codec and its capabilities are pre-defined to ids 234762306a36Sopenharmony_ci * preset id = 0x00 represents CVSD codec with sampling rate 8K 234862306a36Sopenharmony_ci * preset id = 0x01 represents mSBC codec with sampling rate 16K 234962306a36Sopenharmony_ci */ 235062306a36Sopenharmony_ci *ven_len = sizeof(__u8); 235162306a36Sopenharmony_ci return err; 235262306a36Sopenharmony_ci 235362306a36Sopenharmony_cierror: 235462306a36Sopenharmony_ci kfree(*ven_data); 235562306a36Sopenharmony_ci *ven_data = NULL; 235662306a36Sopenharmony_ci return err; 235762306a36Sopenharmony_ci} 235862306a36Sopenharmony_ci 235962306a36Sopenharmony_cistatic int btintel_get_data_path_id(struct hci_dev *hdev, __u8 *data_path_id) 236062306a36Sopenharmony_ci{ 236162306a36Sopenharmony_ci /* Intel uses 1 as data path id for all the usecases */ 236262306a36Sopenharmony_ci *data_path_id = 1; 236362306a36Sopenharmony_ci return 0; 236462306a36Sopenharmony_ci} 236562306a36Sopenharmony_ci 236662306a36Sopenharmony_cistatic int btintel_configure_offload(struct hci_dev *hdev) 236762306a36Sopenharmony_ci{ 236862306a36Sopenharmony_ci struct sk_buff *skb; 236962306a36Sopenharmony_ci int err = 0; 237062306a36Sopenharmony_ci struct intel_offload_use_cases *use_cases; 237162306a36Sopenharmony_ci 237262306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc86, 0, NULL, HCI_INIT_TIMEOUT); 237362306a36Sopenharmony_ci if (IS_ERR(skb)) { 237462306a36Sopenharmony_ci bt_dev_err(hdev, "Reading offload use cases failed (%ld)", 237562306a36Sopenharmony_ci PTR_ERR(skb)); 237662306a36Sopenharmony_ci return PTR_ERR(skb); 237762306a36Sopenharmony_ci } 237862306a36Sopenharmony_ci 237962306a36Sopenharmony_ci if (skb->len < sizeof(*use_cases)) { 238062306a36Sopenharmony_ci err = -EIO; 238162306a36Sopenharmony_ci goto error; 238262306a36Sopenharmony_ci } 238362306a36Sopenharmony_ci 238462306a36Sopenharmony_ci use_cases = (void *)skb->data; 238562306a36Sopenharmony_ci 238662306a36Sopenharmony_ci if (use_cases->status) { 238762306a36Sopenharmony_ci err = -bt_to_errno(skb->data[0]); 238862306a36Sopenharmony_ci goto error; 238962306a36Sopenharmony_ci } 239062306a36Sopenharmony_ci 239162306a36Sopenharmony_ci if (use_cases->preset[0] & 0x03) { 239262306a36Sopenharmony_ci hdev->get_data_path_id = btintel_get_data_path_id; 239362306a36Sopenharmony_ci hdev->get_codec_config_data = btintel_get_codec_config_data; 239462306a36Sopenharmony_ci } 239562306a36Sopenharmony_cierror: 239662306a36Sopenharmony_ci kfree_skb(skb); 239762306a36Sopenharmony_ci return err; 239862306a36Sopenharmony_ci} 239962306a36Sopenharmony_ci 240062306a36Sopenharmony_cistatic void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver) 240162306a36Sopenharmony_ci{ 240262306a36Sopenharmony_ci struct btintel_ppag ppag; 240362306a36Sopenharmony_ci struct sk_buff *skb; 240462306a36Sopenharmony_ci struct hci_ppag_enable_cmd ppag_cmd; 240562306a36Sopenharmony_ci acpi_handle handle; 240662306a36Sopenharmony_ci 240762306a36Sopenharmony_ci /* PPAG is not supported if CRF is HrP2, Jfp2, JfP1 */ 240862306a36Sopenharmony_ci switch (ver->cnvr_top & 0xFFF) { 240962306a36Sopenharmony_ci case 0x504: /* Hrp2 */ 241062306a36Sopenharmony_ci case 0x202: /* Jfp2 */ 241162306a36Sopenharmony_ci case 0x201: /* Jfp1 */ 241262306a36Sopenharmony_ci bt_dev_dbg(hdev, "PPAG not supported for Intel CNVr (0x%3x)", 241362306a36Sopenharmony_ci ver->cnvr_top & 0xFFF); 241462306a36Sopenharmony_ci return; 241562306a36Sopenharmony_ci } 241662306a36Sopenharmony_ci 241762306a36Sopenharmony_ci handle = ACPI_HANDLE(GET_HCIDEV_DEV(hdev)); 241862306a36Sopenharmony_ci if (!handle) { 241962306a36Sopenharmony_ci bt_dev_info(hdev, "No support for BT device in ACPI firmware"); 242062306a36Sopenharmony_ci return; 242162306a36Sopenharmony_ci } 242262306a36Sopenharmony_ci 242362306a36Sopenharmony_ci memset(&ppag, 0, sizeof(ppag)); 242462306a36Sopenharmony_ci 242562306a36Sopenharmony_ci ppag.hdev = hdev; 242662306a36Sopenharmony_ci ppag.status = AE_NOT_FOUND; 242762306a36Sopenharmony_ci acpi_walk_namespace(ACPI_TYPE_PACKAGE, handle, 1, NULL, 242862306a36Sopenharmony_ci btintel_ppag_callback, &ppag, NULL); 242962306a36Sopenharmony_ci 243062306a36Sopenharmony_ci if (ACPI_FAILURE(ppag.status)) { 243162306a36Sopenharmony_ci if (ppag.status == AE_NOT_FOUND) { 243262306a36Sopenharmony_ci bt_dev_dbg(hdev, "PPAG-BT: ACPI entry not found"); 243362306a36Sopenharmony_ci return; 243462306a36Sopenharmony_ci } 243562306a36Sopenharmony_ci return; 243662306a36Sopenharmony_ci } 243762306a36Sopenharmony_ci 243862306a36Sopenharmony_ci if (ppag.domain != 0x12) { 243962306a36Sopenharmony_ci bt_dev_dbg(hdev, "PPAG-BT: Bluetooth domain is disabled in ACPI firmware"); 244062306a36Sopenharmony_ci return; 244162306a36Sopenharmony_ci } 244262306a36Sopenharmony_ci 244362306a36Sopenharmony_ci /* PPAG mode 244462306a36Sopenharmony_ci * BIT 0 : 0 Disabled in EU 244562306a36Sopenharmony_ci * 1 Enabled in EU 244662306a36Sopenharmony_ci * BIT 1 : 0 Disabled in China 244762306a36Sopenharmony_ci * 1 Enabled in China 244862306a36Sopenharmony_ci */ 244962306a36Sopenharmony_ci if ((ppag.mode & 0x01) != BIT(0) && (ppag.mode & 0x02) != BIT(1)) { 245062306a36Sopenharmony_ci bt_dev_dbg(hdev, "PPAG-BT: EU, China mode are disabled in CB/BIOS"); 245162306a36Sopenharmony_ci return; 245262306a36Sopenharmony_ci } 245362306a36Sopenharmony_ci 245462306a36Sopenharmony_ci ppag_cmd.ppag_enable_flags = cpu_to_le32(ppag.mode); 245562306a36Sopenharmony_ci 245662306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, INTEL_OP_PPAG_CMD, sizeof(ppag_cmd), &ppag_cmd, HCI_CMD_TIMEOUT); 245762306a36Sopenharmony_ci if (IS_ERR(skb)) { 245862306a36Sopenharmony_ci bt_dev_warn(hdev, "Failed to send PPAG Enable (%ld)", PTR_ERR(skb)); 245962306a36Sopenharmony_ci return; 246062306a36Sopenharmony_ci } 246162306a36Sopenharmony_ci bt_dev_info(hdev, "PPAG-BT: Enabled (Mode %d)", ppag.mode); 246262306a36Sopenharmony_ci kfree_skb(skb); 246362306a36Sopenharmony_ci} 246462306a36Sopenharmony_ci 246562306a36Sopenharmony_cistatic int btintel_acpi_reset_method(struct hci_dev *hdev) 246662306a36Sopenharmony_ci{ 246762306a36Sopenharmony_ci int ret = 0; 246862306a36Sopenharmony_ci acpi_status status; 246962306a36Sopenharmony_ci union acpi_object *p, *ref; 247062306a36Sopenharmony_ci struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 247162306a36Sopenharmony_ci 247262306a36Sopenharmony_ci status = acpi_evaluate_object(ACPI_HANDLE(GET_HCIDEV_DEV(hdev)), "_PRR", NULL, &buffer); 247362306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 247462306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to run _PRR method"); 247562306a36Sopenharmony_ci ret = -ENODEV; 247662306a36Sopenharmony_ci return ret; 247762306a36Sopenharmony_ci } 247862306a36Sopenharmony_ci p = buffer.pointer; 247962306a36Sopenharmony_ci 248062306a36Sopenharmony_ci if (p->package.count != 1 || p->type != ACPI_TYPE_PACKAGE) { 248162306a36Sopenharmony_ci bt_dev_err(hdev, "Invalid arguments"); 248262306a36Sopenharmony_ci ret = -EINVAL; 248362306a36Sopenharmony_ci goto exit_on_error; 248462306a36Sopenharmony_ci } 248562306a36Sopenharmony_ci 248662306a36Sopenharmony_ci ref = &p->package.elements[0]; 248762306a36Sopenharmony_ci if (ref->type != ACPI_TYPE_LOCAL_REFERENCE) { 248862306a36Sopenharmony_ci bt_dev_err(hdev, "Invalid object type: 0x%x", ref->type); 248962306a36Sopenharmony_ci ret = -EINVAL; 249062306a36Sopenharmony_ci goto exit_on_error; 249162306a36Sopenharmony_ci } 249262306a36Sopenharmony_ci 249362306a36Sopenharmony_ci status = acpi_evaluate_object(ref->reference.handle, "_RST", NULL, NULL); 249462306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 249562306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to run_RST method"); 249662306a36Sopenharmony_ci ret = -ENODEV; 249762306a36Sopenharmony_ci goto exit_on_error; 249862306a36Sopenharmony_ci } 249962306a36Sopenharmony_ci 250062306a36Sopenharmony_ciexit_on_error: 250162306a36Sopenharmony_ci kfree(buffer.pointer); 250262306a36Sopenharmony_ci return ret; 250362306a36Sopenharmony_ci} 250462306a36Sopenharmony_ci 250562306a36Sopenharmony_cistatic void btintel_set_dsm_reset_method(struct hci_dev *hdev, 250662306a36Sopenharmony_ci struct intel_version_tlv *ver_tlv) 250762306a36Sopenharmony_ci{ 250862306a36Sopenharmony_ci struct btintel_data *data = hci_get_priv(hdev); 250962306a36Sopenharmony_ci acpi_handle handle = ACPI_HANDLE(GET_HCIDEV_DEV(hdev)); 251062306a36Sopenharmony_ci u8 reset_payload[4] = {0x01, 0x00, 0x01, 0x00}; 251162306a36Sopenharmony_ci union acpi_object *obj, argv4; 251262306a36Sopenharmony_ci enum { 251362306a36Sopenharmony_ci RESET_TYPE_WDISABLE2, 251462306a36Sopenharmony_ci RESET_TYPE_VSEC 251562306a36Sopenharmony_ci }; 251662306a36Sopenharmony_ci 251762306a36Sopenharmony_ci handle = ACPI_HANDLE(GET_HCIDEV_DEV(hdev)); 251862306a36Sopenharmony_ci 251962306a36Sopenharmony_ci if (!handle) { 252062306a36Sopenharmony_ci bt_dev_dbg(hdev, "No support for bluetooth device in ACPI firmware"); 252162306a36Sopenharmony_ci return; 252262306a36Sopenharmony_ci } 252362306a36Sopenharmony_ci 252462306a36Sopenharmony_ci if (!acpi_has_method(handle, "_PRR")) { 252562306a36Sopenharmony_ci bt_dev_err(hdev, "No support for _PRR ACPI method"); 252662306a36Sopenharmony_ci return; 252762306a36Sopenharmony_ci } 252862306a36Sopenharmony_ci 252962306a36Sopenharmony_ci switch (ver_tlv->cnvi_top & 0xfff) { 253062306a36Sopenharmony_ci case 0x910: /* GalePeak2 */ 253162306a36Sopenharmony_ci reset_payload[2] = RESET_TYPE_VSEC; 253262306a36Sopenharmony_ci break; 253362306a36Sopenharmony_ci default: 253462306a36Sopenharmony_ci /* WDISABLE2 is the default reset method */ 253562306a36Sopenharmony_ci reset_payload[2] = RESET_TYPE_WDISABLE2; 253662306a36Sopenharmony_ci 253762306a36Sopenharmony_ci if (!acpi_check_dsm(handle, &btintel_guid_dsm, 0, 253862306a36Sopenharmony_ci BIT(DSM_SET_WDISABLE2_DELAY))) { 253962306a36Sopenharmony_ci bt_dev_err(hdev, "No dsm support to set reset delay"); 254062306a36Sopenharmony_ci return; 254162306a36Sopenharmony_ci } 254262306a36Sopenharmony_ci argv4.integer.type = ACPI_TYPE_INTEGER; 254362306a36Sopenharmony_ci /* delay required to toggle BT power */ 254462306a36Sopenharmony_ci argv4.integer.value = 160; 254562306a36Sopenharmony_ci obj = acpi_evaluate_dsm(handle, &btintel_guid_dsm, 0, 254662306a36Sopenharmony_ci DSM_SET_WDISABLE2_DELAY, &argv4); 254762306a36Sopenharmony_ci if (!obj) { 254862306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to call dsm to set reset delay"); 254962306a36Sopenharmony_ci return; 255062306a36Sopenharmony_ci } 255162306a36Sopenharmony_ci ACPI_FREE(obj); 255262306a36Sopenharmony_ci } 255362306a36Sopenharmony_ci 255462306a36Sopenharmony_ci bt_dev_info(hdev, "DSM reset method type: 0x%02x", reset_payload[2]); 255562306a36Sopenharmony_ci 255662306a36Sopenharmony_ci if (!acpi_check_dsm(handle, &btintel_guid_dsm, 0, 255762306a36Sopenharmony_ci DSM_SET_RESET_METHOD)) { 255862306a36Sopenharmony_ci bt_dev_warn(hdev, "No support for dsm to set reset method"); 255962306a36Sopenharmony_ci return; 256062306a36Sopenharmony_ci } 256162306a36Sopenharmony_ci argv4.buffer.type = ACPI_TYPE_BUFFER; 256262306a36Sopenharmony_ci argv4.buffer.length = sizeof(reset_payload); 256362306a36Sopenharmony_ci argv4.buffer.pointer = reset_payload; 256462306a36Sopenharmony_ci 256562306a36Sopenharmony_ci obj = acpi_evaluate_dsm(handle, &btintel_guid_dsm, 0, 256662306a36Sopenharmony_ci DSM_SET_RESET_METHOD, &argv4); 256762306a36Sopenharmony_ci if (!obj) { 256862306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to call dsm to set reset method"); 256962306a36Sopenharmony_ci return; 257062306a36Sopenharmony_ci } 257162306a36Sopenharmony_ci ACPI_FREE(obj); 257262306a36Sopenharmony_ci data->acpi_reset_method = btintel_acpi_reset_method; 257362306a36Sopenharmony_ci} 257462306a36Sopenharmony_ci 257562306a36Sopenharmony_cistatic int btintel_bootloader_setup_tlv(struct hci_dev *hdev, 257662306a36Sopenharmony_ci struct intel_version_tlv *ver) 257762306a36Sopenharmony_ci{ 257862306a36Sopenharmony_ci u32 boot_param; 257962306a36Sopenharmony_ci char ddcname[64]; 258062306a36Sopenharmony_ci int err; 258162306a36Sopenharmony_ci struct intel_version_tlv new_ver; 258262306a36Sopenharmony_ci 258362306a36Sopenharmony_ci bt_dev_dbg(hdev, ""); 258462306a36Sopenharmony_ci 258562306a36Sopenharmony_ci /* Set the default boot parameter to 0x0 and it is updated to 258662306a36Sopenharmony_ci * SKU specific boot parameter after reading Intel_Write_Boot_Params 258762306a36Sopenharmony_ci * command while downloading the firmware. 258862306a36Sopenharmony_ci */ 258962306a36Sopenharmony_ci boot_param = 0x00000000; 259062306a36Sopenharmony_ci 259162306a36Sopenharmony_ci btintel_set_flag(hdev, INTEL_BOOTLOADER); 259262306a36Sopenharmony_ci 259362306a36Sopenharmony_ci err = btintel_prepare_fw_download_tlv(hdev, ver, &boot_param); 259462306a36Sopenharmony_ci if (err) 259562306a36Sopenharmony_ci return err; 259662306a36Sopenharmony_ci 259762306a36Sopenharmony_ci /* check if controller is already having an operational firmware */ 259862306a36Sopenharmony_ci if (ver->img_type == 0x03) 259962306a36Sopenharmony_ci goto finish; 260062306a36Sopenharmony_ci 260162306a36Sopenharmony_ci err = btintel_boot(hdev, boot_param); 260262306a36Sopenharmony_ci if (err) 260362306a36Sopenharmony_ci return err; 260462306a36Sopenharmony_ci 260562306a36Sopenharmony_ci btintel_clear_flag(hdev, INTEL_BOOTLOADER); 260662306a36Sopenharmony_ci 260762306a36Sopenharmony_ci btintel_get_fw_name_tlv(ver, ddcname, sizeof(ddcname), "ddc"); 260862306a36Sopenharmony_ci /* Once the device is running in operational mode, it needs to 260962306a36Sopenharmony_ci * apply the device configuration (DDC) parameters. 261062306a36Sopenharmony_ci * 261162306a36Sopenharmony_ci * The device can work without DDC parameters, so even if it 261262306a36Sopenharmony_ci * fails to load the file, no need to fail the setup. 261362306a36Sopenharmony_ci */ 261462306a36Sopenharmony_ci btintel_load_ddc_config(hdev, ddcname); 261562306a36Sopenharmony_ci 261662306a36Sopenharmony_ci /* Read supported use cases and set callbacks to fetch datapath id */ 261762306a36Sopenharmony_ci btintel_configure_offload(hdev); 261862306a36Sopenharmony_ci 261962306a36Sopenharmony_ci hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT); 262062306a36Sopenharmony_ci 262162306a36Sopenharmony_ci /* Set PPAG feature */ 262262306a36Sopenharmony_ci btintel_set_ppag(hdev, ver); 262362306a36Sopenharmony_ci 262462306a36Sopenharmony_ci /* Read the Intel version information after loading the FW */ 262562306a36Sopenharmony_ci err = btintel_read_version_tlv(hdev, &new_ver); 262662306a36Sopenharmony_ci if (err) 262762306a36Sopenharmony_ci return err; 262862306a36Sopenharmony_ci 262962306a36Sopenharmony_ci btintel_version_info_tlv(hdev, &new_ver); 263062306a36Sopenharmony_ci 263162306a36Sopenharmony_cifinish: 263262306a36Sopenharmony_ci /* Set the event mask for Intel specific vendor events. This enables 263362306a36Sopenharmony_ci * a few extra events that are useful during general operation. It 263462306a36Sopenharmony_ci * does not enable any debugging related events. 263562306a36Sopenharmony_ci * 263662306a36Sopenharmony_ci * The device will function correctly without these events enabled 263762306a36Sopenharmony_ci * and thus no need to fail the setup. 263862306a36Sopenharmony_ci */ 263962306a36Sopenharmony_ci btintel_set_event_mask(hdev, false); 264062306a36Sopenharmony_ci 264162306a36Sopenharmony_ci return 0; 264262306a36Sopenharmony_ci} 264362306a36Sopenharmony_ci 264462306a36Sopenharmony_cistatic void btintel_set_msft_opcode(struct hci_dev *hdev, u8 hw_variant) 264562306a36Sopenharmony_ci{ 264662306a36Sopenharmony_ci switch (hw_variant) { 264762306a36Sopenharmony_ci /* Legacy bootloader devices that supports MSFT Extension */ 264862306a36Sopenharmony_ci case 0x11: /* JfP */ 264962306a36Sopenharmony_ci case 0x12: /* ThP */ 265062306a36Sopenharmony_ci case 0x13: /* HrP */ 265162306a36Sopenharmony_ci case 0x14: /* CcP */ 265262306a36Sopenharmony_ci /* All Intel new genration controllers support the Microsoft vendor 265362306a36Sopenharmony_ci * extension are using 0xFC1E for VsMsftOpCode. 265462306a36Sopenharmony_ci */ 265562306a36Sopenharmony_ci case 0x17: 265662306a36Sopenharmony_ci case 0x18: 265762306a36Sopenharmony_ci case 0x19: 265862306a36Sopenharmony_ci case 0x1b: 265962306a36Sopenharmony_ci case 0x1c: 266062306a36Sopenharmony_ci hci_set_msft_opcode(hdev, 0xFC1E); 266162306a36Sopenharmony_ci break; 266262306a36Sopenharmony_ci default: 266362306a36Sopenharmony_ci /* Not supported */ 266462306a36Sopenharmony_ci break; 266562306a36Sopenharmony_ci } 266662306a36Sopenharmony_ci} 266762306a36Sopenharmony_ci 266862306a36Sopenharmony_cistatic int btintel_setup_combined(struct hci_dev *hdev) 266962306a36Sopenharmony_ci{ 267062306a36Sopenharmony_ci const u8 param[1] = { 0xFF }; 267162306a36Sopenharmony_ci struct intel_version ver; 267262306a36Sopenharmony_ci struct intel_version_tlv ver_tlv; 267362306a36Sopenharmony_ci struct sk_buff *skb; 267462306a36Sopenharmony_ci int err; 267562306a36Sopenharmony_ci 267662306a36Sopenharmony_ci BT_DBG("%s", hdev->name); 267762306a36Sopenharmony_ci 267862306a36Sopenharmony_ci /* The some controllers have a bug with the first HCI command sent to it 267962306a36Sopenharmony_ci * returning number of completed commands as zero. This would stall the 268062306a36Sopenharmony_ci * command processing in the Bluetooth core. 268162306a36Sopenharmony_ci * 268262306a36Sopenharmony_ci * As a workaround, send HCI Reset command first which will reset the 268362306a36Sopenharmony_ci * number of completed commands and allow normal command processing 268462306a36Sopenharmony_ci * from now on. 268562306a36Sopenharmony_ci * 268662306a36Sopenharmony_ci * Regarding the INTEL_BROKEN_SHUTDOWN_LED flag, these devices maybe 268762306a36Sopenharmony_ci * in the SW_RFKILL ON state as a workaround of fixing LED issue during 268862306a36Sopenharmony_ci * the shutdown() procedure, and once the device is in SW_RFKILL ON 268962306a36Sopenharmony_ci * state, the only way to exit out of it is sending the HCI_Reset 269062306a36Sopenharmony_ci * command. 269162306a36Sopenharmony_ci */ 269262306a36Sopenharmony_ci if (btintel_test_flag(hdev, INTEL_BROKEN_INITIAL_NCMD) || 269362306a36Sopenharmony_ci btintel_test_flag(hdev, INTEL_BROKEN_SHUTDOWN_LED)) { 269462306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, 269562306a36Sopenharmony_ci HCI_INIT_TIMEOUT); 269662306a36Sopenharmony_ci if (IS_ERR(skb)) { 269762306a36Sopenharmony_ci bt_dev_err(hdev, 269862306a36Sopenharmony_ci "sending initial HCI reset failed (%ld)", 269962306a36Sopenharmony_ci PTR_ERR(skb)); 270062306a36Sopenharmony_ci return PTR_ERR(skb); 270162306a36Sopenharmony_ci } 270262306a36Sopenharmony_ci kfree_skb(skb); 270362306a36Sopenharmony_ci } 270462306a36Sopenharmony_ci 270562306a36Sopenharmony_ci /* Starting from TyP device, the command parameter and response are 270662306a36Sopenharmony_ci * changed even though the OCF for HCI_Intel_Read_Version command 270762306a36Sopenharmony_ci * remains same. The legacy devices can handle even if the 270862306a36Sopenharmony_ci * command has a parameter and returns a correct version information. 270962306a36Sopenharmony_ci * So, it uses new format to support both legacy and new format. 271062306a36Sopenharmony_ci */ 271162306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc05, 1, param, HCI_CMD_TIMEOUT); 271262306a36Sopenharmony_ci if (IS_ERR(skb)) { 271362306a36Sopenharmony_ci bt_dev_err(hdev, "Reading Intel version command failed (%ld)", 271462306a36Sopenharmony_ci PTR_ERR(skb)); 271562306a36Sopenharmony_ci return PTR_ERR(skb); 271662306a36Sopenharmony_ci } 271762306a36Sopenharmony_ci 271862306a36Sopenharmony_ci /* Check the status */ 271962306a36Sopenharmony_ci if (skb->data[0]) { 272062306a36Sopenharmony_ci bt_dev_err(hdev, "Intel Read Version command failed (%02x)", 272162306a36Sopenharmony_ci skb->data[0]); 272262306a36Sopenharmony_ci err = -EIO; 272362306a36Sopenharmony_ci goto exit_error; 272462306a36Sopenharmony_ci } 272562306a36Sopenharmony_ci 272662306a36Sopenharmony_ci /* Apply the common HCI quirks for Intel device */ 272762306a36Sopenharmony_ci set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); 272862306a36Sopenharmony_ci set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); 272962306a36Sopenharmony_ci set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks); 273062306a36Sopenharmony_ci 273162306a36Sopenharmony_ci /* Set up the quality report callback for Intel devices */ 273262306a36Sopenharmony_ci hdev->set_quality_report = btintel_set_quality_report; 273362306a36Sopenharmony_ci 273462306a36Sopenharmony_ci /* For Legacy device, check the HW platform value and size */ 273562306a36Sopenharmony_ci if (skb->len == sizeof(ver) && skb->data[1] == 0x37) { 273662306a36Sopenharmony_ci bt_dev_dbg(hdev, "Read the legacy Intel version information"); 273762306a36Sopenharmony_ci 273862306a36Sopenharmony_ci memcpy(&ver, skb->data, sizeof(ver)); 273962306a36Sopenharmony_ci 274062306a36Sopenharmony_ci /* Display version information */ 274162306a36Sopenharmony_ci btintel_version_info(hdev, &ver); 274262306a36Sopenharmony_ci 274362306a36Sopenharmony_ci /* Check for supported iBT hardware variants of this firmware 274462306a36Sopenharmony_ci * loading method. 274562306a36Sopenharmony_ci * 274662306a36Sopenharmony_ci * This check has been put in place to ensure correct forward 274762306a36Sopenharmony_ci * compatibility options when newer hardware variants come 274862306a36Sopenharmony_ci * along. 274962306a36Sopenharmony_ci */ 275062306a36Sopenharmony_ci switch (ver.hw_variant) { 275162306a36Sopenharmony_ci case 0x07: /* WP */ 275262306a36Sopenharmony_ci case 0x08: /* StP */ 275362306a36Sopenharmony_ci /* Legacy ROM product */ 275462306a36Sopenharmony_ci btintel_set_flag(hdev, INTEL_ROM_LEGACY); 275562306a36Sopenharmony_ci 275662306a36Sopenharmony_ci /* Apply the device specific HCI quirks 275762306a36Sopenharmony_ci * 275862306a36Sopenharmony_ci * WBS for SdP - For the Legacy ROM products, only SdP 275962306a36Sopenharmony_ci * supports the WBS. But the version information is not 276062306a36Sopenharmony_ci * enough to use here because the StP2 and SdP have same 276162306a36Sopenharmony_ci * hw_variant and fw_variant. So, this flag is set by 276262306a36Sopenharmony_ci * the transport driver (btusb) based on the HW info 276362306a36Sopenharmony_ci * (idProduct) 276462306a36Sopenharmony_ci */ 276562306a36Sopenharmony_ci if (!btintel_test_flag(hdev, 276662306a36Sopenharmony_ci INTEL_ROM_LEGACY_NO_WBS_SUPPORT)) 276762306a36Sopenharmony_ci set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, 276862306a36Sopenharmony_ci &hdev->quirks); 276962306a36Sopenharmony_ci if (ver.hw_variant == 0x08 && ver.fw_variant == 0x22) 277062306a36Sopenharmony_ci set_bit(HCI_QUIRK_VALID_LE_STATES, 277162306a36Sopenharmony_ci &hdev->quirks); 277262306a36Sopenharmony_ci 277362306a36Sopenharmony_ci err = btintel_legacy_rom_setup(hdev, &ver); 277462306a36Sopenharmony_ci break; 277562306a36Sopenharmony_ci case 0x0b: /* SfP */ 277662306a36Sopenharmony_ci case 0x11: /* JfP */ 277762306a36Sopenharmony_ci case 0x12: /* ThP */ 277862306a36Sopenharmony_ci case 0x13: /* HrP */ 277962306a36Sopenharmony_ci case 0x14: /* CcP */ 278062306a36Sopenharmony_ci set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); 278162306a36Sopenharmony_ci fallthrough; 278262306a36Sopenharmony_ci case 0x0c: /* WsP */ 278362306a36Sopenharmony_ci /* Apply the device specific HCI quirks 278462306a36Sopenharmony_ci * 278562306a36Sopenharmony_ci * All Legacy bootloader devices support WBS 278662306a36Sopenharmony_ci */ 278762306a36Sopenharmony_ci set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, 278862306a36Sopenharmony_ci &hdev->quirks); 278962306a36Sopenharmony_ci 279062306a36Sopenharmony_ci /* These variants don't seem to support LE Coded PHY */ 279162306a36Sopenharmony_ci set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks); 279262306a36Sopenharmony_ci 279362306a36Sopenharmony_ci /* Setup MSFT Extension support */ 279462306a36Sopenharmony_ci btintel_set_msft_opcode(hdev, ver.hw_variant); 279562306a36Sopenharmony_ci 279662306a36Sopenharmony_ci err = btintel_bootloader_setup(hdev, &ver); 279762306a36Sopenharmony_ci btintel_register_devcoredump_support(hdev); 279862306a36Sopenharmony_ci break; 279962306a36Sopenharmony_ci default: 280062306a36Sopenharmony_ci bt_dev_err(hdev, "Unsupported Intel hw variant (%u)", 280162306a36Sopenharmony_ci ver.hw_variant); 280262306a36Sopenharmony_ci err = -EINVAL; 280362306a36Sopenharmony_ci } 280462306a36Sopenharmony_ci 280562306a36Sopenharmony_ci goto exit_error; 280662306a36Sopenharmony_ci } 280762306a36Sopenharmony_ci 280862306a36Sopenharmony_ci /* memset ver_tlv to start with clean state as few fields are exclusive 280962306a36Sopenharmony_ci * to bootloader mode and are not populated in operational mode 281062306a36Sopenharmony_ci */ 281162306a36Sopenharmony_ci memset(&ver_tlv, 0, sizeof(ver_tlv)); 281262306a36Sopenharmony_ci /* For TLV type device, parse the tlv data */ 281362306a36Sopenharmony_ci err = btintel_parse_version_tlv(hdev, &ver_tlv, skb); 281462306a36Sopenharmony_ci if (err) { 281562306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to parse TLV version information"); 281662306a36Sopenharmony_ci goto exit_error; 281762306a36Sopenharmony_ci } 281862306a36Sopenharmony_ci 281962306a36Sopenharmony_ci if (INTEL_HW_PLATFORM(ver_tlv.cnvi_bt) != 0x37) { 282062306a36Sopenharmony_ci bt_dev_err(hdev, "Unsupported Intel hardware platform (0x%2x)", 282162306a36Sopenharmony_ci INTEL_HW_PLATFORM(ver_tlv.cnvi_bt)); 282262306a36Sopenharmony_ci err = -EINVAL; 282362306a36Sopenharmony_ci goto exit_error; 282462306a36Sopenharmony_ci } 282562306a36Sopenharmony_ci 282662306a36Sopenharmony_ci /* Check for supported iBT hardware variants of this firmware 282762306a36Sopenharmony_ci * loading method. 282862306a36Sopenharmony_ci * 282962306a36Sopenharmony_ci * This check has been put in place to ensure correct forward 283062306a36Sopenharmony_ci * compatibility options when newer hardware variants come 283162306a36Sopenharmony_ci * along. 283262306a36Sopenharmony_ci */ 283362306a36Sopenharmony_ci switch (INTEL_HW_VARIANT(ver_tlv.cnvi_bt)) { 283462306a36Sopenharmony_ci case 0x11: /* JfP */ 283562306a36Sopenharmony_ci case 0x12: /* ThP */ 283662306a36Sopenharmony_ci case 0x13: /* HrP */ 283762306a36Sopenharmony_ci case 0x14: /* CcP */ 283862306a36Sopenharmony_ci /* Some legacy bootloader devices starting from JfP, 283962306a36Sopenharmony_ci * the operational firmware supports both old and TLV based 284062306a36Sopenharmony_ci * HCI_Intel_Read_Version command based on the command 284162306a36Sopenharmony_ci * parameter. 284262306a36Sopenharmony_ci * 284362306a36Sopenharmony_ci * For upgrading firmware case, the TLV based version cannot 284462306a36Sopenharmony_ci * be used because the firmware filename for legacy bootloader 284562306a36Sopenharmony_ci * is based on the old format. 284662306a36Sopenharmony_ci * 284762306a36Sopenharmony_ci * Also, it is not easy to convert TLV based version from the 284862306a36Sopenharmony_ci * legacy version format. 284962306a36Sopenharmony_ci * 285062306a36Sopenharmony_ci * So, as a workaround for those devices, use the legacy 285162306a36Sopenharmony_ci * HCI_Intel_Read_Version to get the version information and 285262306a36Sopenharmony_ci * run the legacy bootloader setup. 285362306a36Sopenharmony_ci */ 285462306a36Sopenharmony_ci err = btintel_read_version(hdev, &ver); 285562306a36Sopenharmony_ci if (err) 285662306a36Sopenharmony_ci break; 285762306a36Sopenharmony_ci 285862306a36Sopenharmony_ci /* Apply the device specific HCI quirks 285962306a36Sopenharmony_ci * 286062306a36Sopenharmony_ci * All Legacy bootloader devices support WBS 286162306a36Sopenharmony_ci */ 286262306a36Sopenharmony_ci set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); 286362306a36Sopenharmony_ci 286462306a36Sopenharmony_ci /* These variants don't seem to support LE Coded PHY */ 286562306a36Sopenharmony_ci set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks); 286662306a36Sopenharmony_ci 286762306a36Sopenharmony_ci /* Set Valid LE States quirk */ 286862306a36Sopenharmony_ci set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); 286962306a36Sopenharmony_ci 287062306a36Sopenharmony_ci /* Setup MSFT Extension support */ 287162306a36Sopenharmony_ci btintel_set_msft_opcode(hdev, ver.hw_variant); 287262306a36Sopenharmony_ci 287362306a36Sopenharmony_ci err = btintel_bootloader_setup(hdev, &ver); 287462306a36Sopenharmony_ci btintel_register_devcoredump_support(hdev); 287562306a36Sopenharmony_ci break; 287662306a36Sopenharmony_ci case 0x17: 287762306a36Sopenharmony_ci case 0x18: 287862306a36Sopenharmony_ci case 0x19: 287962306a36Sopenharmony_ci case 0x1b: 288062306a36Sopenharmony_ci case 0x1c: 288162306a36Sopenharmony_ci /* Display version information of TLV type */ 288262306a36Sopenharmony_ci btintel_version_info_tlv(hdev, &ver_tlv); 288362306a36Sopenharmony_ci 288462306a36Sopenharmony_ci /* Apply the device specific HCI quirks for TLV based devices 288562306a36Sopenharmony_ci * 288662306a36Sopenharmony_ci * All TLV based devices support WBS 288762306a36Sopenharmony_ci */ 288862306a36Sopenharmony_ci set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); 288962306a36Sopenharmony_ci 289062306a36Sopenharmony_ci /* Apply LE States quirk from solar onwards */ 289162306a36Sopenharmony_ci set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); 289262306a36Sopenharmony_ci 289362306a36Sopenharmony_ci /* Setup MSFT Extension support */ 289462306a36Sopenharmony_ci btintel_set_msft_opcode(hdev, 289562306a36Sopenharmony_ci INTEL_HW_VARIANT(ver_tlv.cnvi_bt)); 289662306a36Sopenharmony_ci btintel_set_dsm_reset_method(hdev, &ver_tlv); 289762306a36Sopenharmony_ci 289862306a36Sopenharmony_ci err = btintel_bootloader_setup_tlv(hdev, &ver_tlv); 289962306a36Sopenharmony_ci btintel_register_devcoredump_support(hdev); 290062306a36Sopenharmony_ci break; 290162306a36Sopenharmony_ci default: 290262306a36Sopenharmony_ci bt_dev_err(hdev, "Unsupported Intel hw variant (%u)", 290362306a36Sopenharmony_ci INTEL_HW_VARIANT(ver_tlv.cnvi_bt)); 290462306a36Sopenharmony_ci err = -EINVAL; 290562306a36Sopenharmony_ci break; 290662306a36Sopenharmony_ci } 290762306a36Sopenharmony_ci 290862306a36Sopenharmony_ciexit_error: 290962306a36Sopenharmony_ci kfree_skb(skb); 291062306a36Sopenharmony_ci 291162306a36Sopenharmony_ci return err; 291262306a36Sopenharmony_ci} 291362306a36Sopenharmony_ci 291462306a36Sopenharmony_cistatic int btintel_shutdown_combined(struct hci_dev *hdev) 291562306a36Sopenharmony_ci{ 291662306a36Sopenharmony_ci struct sk_buff *skb; 291762306a36Sopenharmony_ci int ret; 291862306a36Sopenharmony_ci 291962306a36Sopenharmony_ci /* Send HCI Reset to the controller to stop any BT activity which 292062306a36Sopenharmony_ci * were triggered. This will help to save power and maintain the 292162306a36Sopenharmony_ci * sync b/w Host and controller 292262306a36Sopenharmony_ci */ 292362306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); 292462306a36Sopenharmony_ci if (IS_ERR(skb)) { 292562306a36Sopenharmony_ci bt_dev_err(hdev, "HCI reset during shutdown failed"); 292662306a36Sopenharmony_ci return PTR_ERR(skb); 292762306a36Sopenharmony_ci } 292862306a36Sopenharmony_ci kfree_skb(skb); 292962306a36Sopenharmony_ci 293062306a36Sopenharmony_ci 293162306a36Sopenharmony_ci /* Some platforms have an issue with BT LED when the interface is 293262306a36Sopenharmony_ci * down or BT radio is turned off, which takes 5 seconds to BT LED 293362306a36Sopenharmony_ci * goes off. As a workaround, sends HCI_Intel_SW_RFKILL to put the 293462306a36Sopenharmony_ci * device in the RFKILL ON state which turns off the BT LED immediately. 293562306a36Sopenharmony_ci */ 293662306a36Sopenharmony_ci if (btintel_test_flag(hdev, INTEL_BROKEN_SHUTDOWN_LED)) { 293762306a36Sopenharmony_ci skb = __hci_cmd_sync(hdev, 0xfc3f, 0, NULL, HCI_INIT_TIMEOUT); 293862306a36Sopenharmony_ci if (IS_ERR(skb)) { 293962306a36Sopenharmony_ci ret = PTR_ERR(skb); 294062306a36Sopenharmony_ci bt_dev_err(hdev, "turning off Intel device LED failed"); 294162306a36Sopenharmony_ci return ret; 294262306a36Sopenharmony_ci } 294362306a36Sopenharmony_ci kfree_skb(skb); 294462306a36Sopenharmony_ci } 294562306a36Sopenharmony_ci 294662306a36Sopenharmony_ci return 0; 294762306a36Sopenharmony_ci} 294862306a36Sopenharmony_ci 294962306a36Sopenharmony_ciint btintel_configure_setup(struct hci_dev *hdev, const char *driver_name) 295062306a36Sopenharmony_ci{ 295162306a36Sopenharmony_ci hdev->manufacturer = 2; 295262306a36Sopenharmony_ci hdev->setup = btintel_setup_combined; 295362306a36Sopenharmony_ci hdev->shutdown = btintel_shutdown_combined; 295462306a36Sopenharmony_ci hdev->hw_error = btintel_hw_error; 295562306a36Sopenharmony_ci hdev->set_diag = btintel_set_diag_combined; 295662306a36Sopenharmony_ci hdev->set_bdaddr = btintel_set_bdaddr; 295762306a36Sopenharmony_ci 295862306a36Sopenharmony_ci coredump_info.driver_name = driver_name; 295962306a36Sopenharmony_ci 296062306a36Sopenharmony_ci return 0; 296162306a36Sopenharmony_ci} 296262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_configure_setup); 296362306a36Sopenharmony_ci 296462306a36Sopenharmony_cistatic int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb) 296562306a36Sopenharmony_ci{ 296662306a36Sopenharmony_ci struct intel_tlv *tlv = (void *)&skb->data[5]; 296762306a36Sopenharmony_ci 296862306a36Sopenharmony_ci /* The first event is always an event type TLV */ 296962306a36Sopenharmony_ci if (tlv->type != INTEL_TLV_TYPE_ID) 297062306a36Sopenharmony_ci goto recv_frame; 297162306a36Sopenharmony_ci 297262306a36Sopenharmony_ci switch (tlv->val[0]) { 297362306a36Sopenharmony_ci case INTEL_TLV_SYSTEM_EXCEPTION: 297462306a36Sopenharmony_ci case INTEL_TLV_FATAL_EXCEPTION: 297562306a36Sopenharmony_ci case INTEL_TLV_DEBUG_EXCEPTION: 297662306a36Sopenharmony_ci case INTEL_TLV_TEST_EXCEPTION: 297762306a36Sopenharmony_ci /* Generate devcoredump from exception */ 297862306a36Sopenharmony_ci if (!hci_devcd_init(hdev, skb->len)) { 297962306a36Sopenharmony_ci hci_devcd_append(hdev, skb); 298062306a36Sopenharmony_ci hci_devcd_complete(hdev); 298162306a36Sopenharmony_ci } else { 298262306a36Sopenharmony_ci bt_dev_err(hdev, "Failed to generate devcoredump"); 298362306a36Sopenharmony_ci kfree_skb(skb); 298462306a36Sopenharmony_ci } 298562306a36Sopenharmony_ci return 0; 298662306a36Sopenharmony_ci default: 298762306a36Sopenharmony_ci bt_dev_err(hdev, "Invalid exception type %02X", tlv->val[0]); 298862306a36Sopenharmony_ci } 298962306a36Sopenharmony_ci 299062306a36Sopenharmony_cirecv_frame: 299162306a36Sopenharmony_ci return hci_recv_frame(hdev, skb); 299262306a36Sopenharmony_ci} 299362306a36Sopenharmony_ci 299462306a36Sopenharmony_ciint btintel_recv_event(struct hci_dev *hdev, struct sk_buff *skb) 299562306a36Sopenharmony_ci{ 299662306a36Sopenharmony_ci struct hci_event_hdr *hdr = (void *)skb->data; 299762306a36Sopenharmony_ci const char diagnostics_hdr[] = { 0x87, 0x80, 0x03 }; 299862306a36Sopenharmony_ci 299962306a36Sopenharmony_ci if (skb->len > HCI_EVENT_HDR_SIZE && hdr->evt == 0xff && 300062306a36Sopenharmony_ci hdr->plen > 0) { 300162306a36Sopenharmony_ci const void *ptr = skb->data + HCI_EVENT_HDR_SIZE + 1; 300262306a36Sopenharmony_ci unsigned int len = skb->len - HCI_EVENT_HDR_SIZE - 1; 300362306a36Sopenharmony_ci 300462306a36Sopenharmony_ci if (btintel_test_flag(hdev, INTEL_BOOTLOADER)) { 300562306a36Sopenharmony_ci switch (skb->data[2]) { 300662306a36Sopenharmony_ci case 0x02: 300762306a36Sopenharmony_ci /* When switching to the operational firmware 300862306a36Sopenharmony_ci * the device sends a vendor specific event 300962306a36Sopenharmony_ci * indicating that the bootup completed. 301062306a36Sopenharmony_ci */ 301162306a36Sopenharmony_ci btintel_bootup(hdev, ptr, len); 301262306a36Sopenharmony_ci break; 301362306a36Sopenharmony_ci case 0x06: 301462306a36Sopenharmony_ci /* When the firmware loading completes the 301562306a36Sopenharmony_ci * device sends out a vendor specific event 301662306a36Sopenharmony_ci * indicating the result of the firmware 301762306a36Sopenharmony_ci * loading. 301862306a36Sopenharmony_ci */ 301962306a36Sopenharmony_ci btintel_secure_send_result(hdev, ptr, len); 302062306a36Sopenharmony_ci break; 302162306a36Sopenharmony_ci } 302262306a36Sopenharmony_ci } 302362306a36Sopenharmony_ci 302462306a36Sopenharmony_ci /* Handle all diagnostics events separately. May still call 302562306a36Sopenharmony_ci * hci_recv_frame. 302662306a36Sopenharmony_ci */ 302762306a36Sopenharmony_ci if (len >= sizeof(diagnostics_hdr) && 302862306a36Sopenharmony_ci memcmp(&skb->data[2], diagnostics_hdr, 302962306a36Sopenharmony_ci sizeof(diagnostics_hdr)) == 0) { 303062306a36Sopenharmony_ci return btintel_diagnostics(hdev, skb); 303162306a36Sopenharmony_ci } 303262306a36Sopenharmony_ci } 303362306a36Sopenharmony_ci 303462306a36Sopenharmony_ci return hci_recv_frame(hdev, skb); 303562306a36Sopenharmony_ci} 303662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_recv_event); 303762306a36Sopenharmony_ci 303862306a36Sopenharmony_civoid btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len) 303962306a36Sopenharmony_ci{ 304062306a36Sopenharmony_ci const struct intel_bootup *evt = ptr; 304162306a36Sopenharmony_ci 304262306a36Sopenharmony_ci if (len != sizeof(*evt)) 304362306a36Sopenharmony_ci return; 304462306a36Sopenharmony_ci 304562306a36Sopenharmony_ci if (btintel_test_and_clear_flag(hdev, INTEL_BOOTING)) 304662306a36Sopenharmony_ci btintel_wake_up_flag(hdev, INTEL_BOOTING); 304762306a36Sopenharmony_ci} 304862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_bootup); 304962306a36Sopenharmony_ci 305062306a36Sopenharmony_civoid btintel_secure_send_result(struct hci_dev *hdev, 305162306a36Sopenharmony_ci const void *ptr, unsigned int len) 305262306a36Sopenharmony_ci{ 305362306a36Sopenharmony_ci const struct intel_secure_send_result *evt = ptr; 305462306a36Sopenharmony_ci 305562306a36Sopenharmony_ci if (len != sizeof(*evt)) 305662306a36Sopenharmony_ci return; 305762306a36Sopenharmony_ci 305862306a36Sopenharmony_ci if (evt->result) 305962306a36Sopenharmony_ci btintel_set_flag(hdev, INTEL_FIRMWARE_FAILED); 306062306a36Sopenharmony_ci 306162306a36Sopenharmony_ci if (btintel_test_and_clear_flag(hdev, INTEL_DOWNLOADING) && 306262306a36Sopenharmony_ci btintel_test_flag(hdev, INTEL_FIRMWARE_LOADED)) 306362306a36Sopenharmony_ci btintel_wake_up_flag(hdev, INTEL_DOWNLOADING); 306462306a36Sopenharmony_ci} 306562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(btintel_secure_send_result); 306662306a36Sopenharmony_ci 306762306a36Sopenharmony_ciMODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); 306862306a36Sopenharmony_ciMODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION); 306962306a36Sopenharmony_ciMODULE_VERSION(VERSION); 307062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 307162306a36Sopenharmony_ciMODULE_FIRMWARE("intel/ibt-11-5.sfi"); 307262306a36Sopenharmony_ciMODULE_FIRMWARE("intel/ibt-11-5.ddc"); 307362306a36Sopenharmony_ciMODULE_FIRMWARE("intel/ibt-12-16.sfi"); 307462306a36Sopenharmony_ciMODULE_FIRMWARE("intel/ibt-12-16.ddc"); 3075