return -EIO;
}
- /* Consume Command Complete Status field */
- skb_pull(skb, 1);
-
- /* Event parameters contatin multiple TLVs. Read each of them
- * and only keep the required data. Also, it use existing legacy
- * version field like hw_platform, hw_variant, and fw_variant
- * to keep the existing setup flow
- */
- while (skb->len) {
- struct intel_tlv *tlv;
-
- tlv = (struct intel_tlv *)skb->data;
- switch (tlv->type) {
- case INTEL_TLV_CNVI_TOP:
- version->cnvi_top = get_unaligned_le32(tlv->val);
- break;
- case INTEL_TLV_CNVR_TOP:
- version->cnvr_top = get_unaligned_le32(tlv->val);
- break;
- case INTEL_TLV_CNVI_BT:
- version->cnvi_bt = get_unaligned_le32(tlv->val);
- break;
- case INTEL_TLV_CNVR_BT:
- version->cnvr_bt = get_unaligned_le32(tlv->val);
- break;
- case INTEL_TLV_DEV_REV_ID:
- version->dev_rev_id = get_unaligned_le16(tlv->val);
- break;
- case INTEL_TLV_IMAGE_TYPE:
- version->img_type = tlv->val[0];
- break;
- case INTEL_TLV_TIME_STAMP:
- /* If image type is Operational firmware (0x03), then
- * running FW Calendar Week and Year information can
- * be extracted from Timestamp information
- */
- version->min_fw_build_cw = tlv->val[0];
- version->min_fw_build_yy = tlv->val[1];
- version->timestamp = get_unaligned_le16(tlv->val);
- break;
- case INTEL_TLV_BUILD_TYPE:
- version->build_type = tlv->val[0];
- break;
- case INTEL_TLV_BUILD_NUM:
- /* If image type is Operational firmware (0x03), then
- * running FW build number can be extracted from the
- * Build information
- */
- version->min_fw_build_nn = tlv->val[0];
- version->build_num = get_unaligned_le32(tlv->val);
- break;
- case INTEL_TLV_SECURE_BOOT:
- version->secure_boot = tlv->val[0];
- break;
- case INTEL_TLV_OTP_LOCK:
- version->otp_lock = tlv->val[0];
- break;
- case INTEL_TLV_API_LOCK:
- version->api_lock = tlv->val[0];
- break;
- case INTEL_TLV_DEBUG_LOCK:
- version->debug_lock = tlv->val[0];
- break;
- case INTEL_TLV_MIN_FW:
- version->min_fw_build_nn = tlv->val[0];
- version->min_fw_build_cw = tlv->val[1];
- version->min_fw_build_yy = tlv->val[2];
- break;
- case INTEL_TLV_LIMITED_CCE:
- version->limited_cce = tlv->val[0];
- break;
- case INTEL_TLV_SBE_TYPE:
- version->sbe_type = tlv->val[0];
- break;
- case INTEL_TLV_OTP_BDADDR:
- memcpy(&version->otp_bd_addr, tlv->val, tlv->len);
- break;
- default:
- /* Ignore rest of information */
- break;
- }
- /* consume the current tlv and move to next*/
- skb_pull(skb, tlv->len + sizeof(*tlv));
- }
+ btintel_parse_version_tlv(hdev, version, skb);
kfree_skb(skb);
return 0;
}
EXPORT_SYMBOL_GPL(btintel_download_firmware);
-int btintel_download_firmware_newgen(struct hci_dev *hdev,
- struct intel_version_tlv *ver,
- const struct firmware *fw, u32 *boot_param,
- u8 hw_variant, u8 sbe_type)
+static int btintel_download_fw_tlv(struct hci_dev *hdev,
+ struct intel_version_tlv *ver,
+ const struct firmware *fw, u32 *boot_param,
+ u8 hw_variant, u8 sbe_type)
{
int err;
u32 css_header_ver;
}
return 0;
}
-EXPORT_SYMBOL_GPL(btintel_download_firmware_newgen);
void btintel_reset_to_bootloader(struct hci_dev *hdev)
{
return 0;
}
+static int btintel_download_wait(struct hci_dev *hdev, ktime_t calltime, int msec)
+{
+ ktime_t delta, rettime;
+ unsigned long long duration;
+ int err;
+
+ btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED);
+
+ bt_dev_info(hdev, "Waiting for firmware download to complete");
+
+ err = btintel_wait_on_flag_timeout(hdev, INTEL_DOWNLOADING,
+ TASK_INTERRUPTIBLE,
+ msecs_to_jiffies(msec));
+ if (err == -EINTR) {
+ bt_dev_err(hdev, "Firmware loading interrupted");
+ return err;
+ }
+
+ if (err) {
+ bt_dev_err(hdev, "Firmware loading timeout");
+ return -ETIMEDOUT;
+ }
+
+ if (btintel_test_flag(hdev, INTEL_FIRMWARE_FAILED)) {
+ bt_dev_err(hdev, "Firmware loading failed");
+ return -ENOEXEC;
+ }
+
+ rettime = ktime_get();
+ delta = ktime_sub(rettime, calltime);
+ duration = (unsigned long long)ktime_to_ns(delta) >> 10;
+
+ bt_dev_info(hdev, "Firmware loaded in %llu usecs", duration);
+
+ return 0;
+}
+
+static int btintel_boot_wait(struct hci_dev *hdev, ktime_t calltime, int msec)
+{
+ ktime_t delta, rettime;
+ unsigned long long duration;
+ int err;
+
+ bt_dev_info(hdev, "Waiting for device to boot");
+
+ err = btintel_wait_on_flag_timeout(hdev, INTEL_BOOTING,
+ TASK_INTERRUPTIBLE,
+ msecs_to_jiffies(msec));
+ if (err == -EINTR) {
+ bt_dev_err(hdev, "Device boot interrupted");
+ return -EINTR;
+ }
+
+ if (err) {
+ bt_dev_err(hdev, "Device boot timeout");
+ return -ETIMEDOUT;
+ }
+
+ rettime = ktime_get();
+ delta = ktime_sub(rettime, calltime);
+ duration = (unsigned long long) ktime_to_ns(delta) >> 10;
+
+ bt_dev_info(hdev, "Device booted in %llu usecs", duration);
+
+ return 0;
+}
+
+static int btintel_boot(struct hci_dev *hdev, u32 boot_addr)
+{
+ ktime_t calltime;
+ int err;
+
+ calltime = ktime_get();
+
+ btintel_set_flag(hdev, INTEL_BOOTING);
+
+ err = btintel_send_intel_reset(hdev, boot_addr);
+ if (err) {
+ bt_dev_err(hdev, "Intel Soft Reset failed (%d)", err);
+ btintel_reset_to_bootloader(hdev);
+ return err;
+ }
+
+ /* The bootloader will not indicate when the device is ready. This
+ * is done by the operational firmware sending bootup notification.
+ *
+ * Booting into operational firmware should not take longer than
+ * 1 second. However if that happens, then just fail the setup
+ * since something went wrong.
+ */
+ err = btintel_boot_wait(hdev, calltime, 1000);
+ if (err == -ETIMEDOUT)
+ btintel_reset_to_bootloader(hdev);
+
+ return err;
+}
+
+static int btintel_get_fw_name(struct intel_version *ver,
+ struct intel_boot_params *params,
+ char *fw_name, size_t len,
+ const char *suffix)
+{
+ switch (ver->hw_variant) {
+ case 0x0b: /* SfP */
+ case 0x0c: /* WsP */
+ snprintf(fw_name, len, "intel/ibt-%u-%u.%s",
+ le16_to_cpu(ver->hw_variant),
+ le16_to_cpu(params->dev_revid),
+ suffix);
+ break;
+ case 0x11: /* JfP */
+ case 0x12: /* ThP */
+ case 0x13: /* HrP */
+ case 0x14: /* CcP */
+ snprintf(fw_name, len, "intel/ibt-%u-%u-%u.%s",
+ le16_to_cpu(ver->hw_variant),
+ le16_to_cpu(ver->hw_revision),
+ le16_to_cpu(ver->fw_revision),
+ suffix);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int btintel_download_fw(struct hci_dev *hdev,
+ struct intel_version *ver,
+ struct intel_boot_params *params,
+ u32 *boot_param)
+{
+ const struct firmware *fw;
+ char fwname[64];
+ int err;
+ ktime_t calltime;
+
+ if (!ver || !params)
+ return -EINVAL;
+
+ /* The firmware variant determines if the device is in bootloader
+ * mode or is running operational firmware. The value 0x06 identifies
+ * the bootloader and the value 0x23 identifies the operational
+ * firmware.
+ *
+ * When the operational firmware is already present, then only
+ * the check for valid Bluetooth device address is needed. This
+ * determines if the device will be added as configured or
+ * unconfigured controller.
+ *
+ * It is not possible to use the Secure Boot Parameters in this
+ * case since that command is only available in bootloader mode.
+ */
+ if (ver->fw_variant == 0x23) {
+ btintel_clear_flag(hdev, INTEL_BOOTLOADER);
+ btintel_check_bdaddr(hdev);
+
+ /* SfP and WsP don't seem to update the firmware version on file
+ * so version checking is currently possible.
+ */
+ switch (ver->hw_variant) {
+ case 0x0b: /* SfP */
+ case 0x0c: /* WsP */
+ return 0;
+ }
+
+ /* Proceed to download to check if the version matches */
+ goto download;
+ }
+
+ /* Read the secure boot parameters to identify the operating
+ * details of the bootloader.
+ */
+ err = btintel_read_boot_params(hdev, params);
+ if (err)
+ return err;
+
+ /* It is required that every single firmware fragment is acknowledged
+ * with a command complete event. If the boot parameters indicate
+ * that this bootloader does not send them, then abort the setup.
+ */
+ if (params->limited_cce != 0x00) {
+ bt_dev_err(hdev, "Unsupported Intel firmware loading method (%u)",
+ params->limited_cce);
+ return -EINVAL;
+ }
+
+ /* If the OTP has no valid Bluetooth device address, then there will
+ * also be no valid address for the operational firmware.
+ */
+ if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) {
+ bt_dev_info(hdev, "No device address configured");
+ set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
+ }
+
+download:
+ /* With this Intel bootloader only the hardware variant and device
+ * revision information are used to select the right firmware for SfP
+ * and WsP.
+ *
+ * The firmware filename is ibt-<hw_variant>-<dev_revid>.sfi.
+ *
+ * Currently the supported hardware variants are:
+ * 11 (0x0b) for iBT3.0 (LnP/SfP)
+ * 12 (0x0c) for iBT3.5 (WsP)
+ *
+ * For ThP/JfP and for future SKU's, the FW name varies based on HW
+ * variant, HW revision and FW revision, as these are dependent on CNVi
+ * and RF Combination.
+ *
+ * 17 (0x11) for iBT3.5 (JfP)
+ * 18 (0x12) for iBT3.5 (ThP)
+ *
+ * The firmware file name for these will be
+ * ibt-<hw_variant>-<hw_revision>-<fw_revision>.sfi.
+ *
+ */
+ err = btintel_get_fw_name(ver, params, fwname, sizeof(fwname), "sfi");
+ if (err < 0) {
+ if (!btintel_test_flag(hdev, INTEL_BOOTLOADER)) {
+ /* Firmware has already been loaded */
+ btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED);
+ return 0;
+ }
+
+ bt_dev_err(hdev, "Unsupported Intel firmware naming");
+ return -EINVAL;
+ }
+
+ err = firmware_request_nowarn(&fw, fwname, &hdev->dev);
+ if (err < 0) {
+ if (!btintel_test_flag(hdev, INTEL_BOOTLOADER)) {
+ /* Firmware has already been loaded */
+ btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED);
+ return 0;
+ }
+
+ bt_dev_err(hdev, "Failed to load Intel firmware file %s (%d)",
+ fwname, err);
+ return err;
+ }
+
+ bt_dev_info(hdev, "Found device firmware: %s", fwname);
+
+ if (fw->size < 644) {
+ bt_dev_err(hdev, "Invalid size of firmware file (%zu)",
+ fw->size);
+ err = -EBADF;
+ goto done;
+ }
+
+ calltime = ktime_get();
+
+ btintel_set_flag(hdev, INTEL_DOWNLOADING);
+
+ /* Start firmware downloading and get boot parameter */
+ err = btintel_download_firmware(hdev, ver, fw, boot_param);
+ if (err < 0) {
+ if (err == -EALREADY) {
+ /* Firmware has already been loaded */
+ btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED);
+ err = 0;
+ goto done;
+ }
+
+ /* When FW download fails, send Intel Reset to retry
+ * FW download.
+ */
+ btintel_reset_to_bootloader(hdev);
+ goto done;
+ }
+
+ /* Before switching the device into operational mode and with that
+ * booting the loaded firmware, wait for the bootloader notification
+ * that all fragments have been successfully received.
+ *
+ * When the event processing receives the notification, then the
+ * INTEL_DOWNLOADING flag will be cleared.
+ *
+ * The firmware loading should not take longer than 5 seconds
+ * and thus just timeout if that happens and fail the setup
+ * of this device.
+ */
+ err = btintel_download_wait(hdev, calltime, 5000);
+ if (err == -ETIMEDOUT)
+ btintel_reset_to_bootloader(hdev);
+
+done:
+ release_firmware(fw);
+ return err;
+}
+
+static int btintel_bootloader_setup(struct hci_dev *hdev,
+ struct intel_version *ver)
+{
+ struct intel_version new_ver;
+ struct intel_boot_params params;
+ u32 boot_param;
+ char ddcname[64];
+ int err;
+ struct intel_debug_features features;
+
+ BT_DBG("%s", hdev->name);
+
+ /* Set the default boot parameter to 0x0 and it is updated to
+ * SKU specific boot parameter after reading Intel_Write_Boot_Params
+ * command while downloading the firmware.
+ */
+ boot_param = 0x00000000;
+
+ btintel_set_flag(hdev, INTEL_BOOTLOADER);
+
+ err = btintel_download_fw(hdev, ver, ¶ms, &boot_param);
+ if (err)
+ return err;
+
+ /* controller is already having an operational firmware */
+ if (ver->fw_variant == 0x23)
+ goto finish;
+
+ err = btintel_boot(hdev, boot_param);
+ if (err)
+ return err;
+
+ btintel_clear_flag(hdev, INTEL_BOOTLOADER);
+
+ err = btintel_get_fw_name(ver, ¶ms, ddcname,
+ sizeof(ddcname), "ddc");
+
+ if (err < 0) {
+ bt_dev_err(hdev, "Unsupported Intel firmware naming");
+ } else {
+ /* Once the device is running in operational mode, it needs to
+ * apply the device configuration (DDC) parameters.
+ *
+ * The device can work without DDC parameters, so even if it
+ * fails to load the file, no need to fail the setup.
+ */
+ btintel_load_ddc_config(hdev, ddcname);
+ }
+
+ /* Read the Intel supported features and if new exception formats
+ * supported, need to load the additional DDC config to enable.
+ */
+ err = btintel_read_debug_features(hdev, &features);
+ if (!err) {
+ /* Set DDC mask for available debug features */
+ btintel_set_debug_features(hdev, &features);
+ }
+
+ /* Read the Intel version information after loading the FW */
+ err = btintel_read_version(hdev, &new_ver);
+ if (err)
+ return err;
+
+ btintel_version_info(hdev, &new_ver);
+
+finish:
+ /* All Intel controllers that support the Microsoft vendor
+ * extension are using 0xFC1E for VsMsftOpCode.
+ */
+ switch (ver->hw_variant) {
+ case 0x11: /* JfP */
+ case 0x12: /* ThP */
+ case 0x13: /* HrP */
+ case 0x14: /* CcP */
+ hci_set_msft_opcode(hdev, 0xFC1E);
+ break;
+ }
+
+ /* Set the event mask for Intel specific vendor events. This enables
+ * a few extra events that are useful during general operation. It
+ * does not enable any debugging related events.
+ *
+ * The device will function correctly without these events enabled
+ * and thus no need to fail the setup.
+ */
+ btintel_set_event_mask(hdev, false);
+
+ return 0;
+}
+
+static void btintel_get_fw_name_tlv(const struct intel_version_tlv *ver,
+ char *fw_name, size_t len,
+ const char *suffix)
+{
+ /* The firmware file name for new generation controllers will be
+ * ibt-<cnvi_top type+cnvi_top step>-<cnvr_top type+cnvr_top step>
+ */
+ snprintf(fw_name, len, "intel/ibt-%04x-%04x.%s",
+ INTEL_CNVX_TOP_PACK_SWAB(INTEL_CNVX_TOP_TYPE(ver->cnvi_top),
+ INTEL_CNVX_TOP_STEP(ver->cnvi_top)),
+ INTEL_CNVX_TOP_PACK_SWAB(INTEL_CNVX_TOP_TYPE(ver->cnvr_top),
+ INTEL_CNVX_TOP_STEP(ver->cnvr_top)),
+ suffix);
+}
+
+static int btintel_prepare_fw_download_tlv(struct hci_dev *hdev,
+ struct intel_version_tlv *ver,
+ u32 *boot_param)
+{
+ const struct firmware *fw;
+ char fwname[64];
+ int err;
+ ktime_t calltime;
+
+ if (!ver || !boot_param)
+ return -EINVAL;
+
+ /* The firmware variant determines if the device is in bootloader
+ * mode or is running operational firmware. The value 0x03 identifies
+ * the bootloader and the value 0x23 identifies the operational
+ * firmware.
+ *
+ * When the operational firmware is already present, then only
+ * the check for valid Bluetooth device address is needed. This
+ * determines if the device will be added as configured or
+ * unconfigured controller.
+ *
+ * It is not possible to use the Secure Boot Parameters in this
+ * case since that command is only available in bootloader mode.
+ */
+ if (ver->img_type == 0x03) {
+ btintel_clear_flag(hdev, INTEL_BOOTLOADER);
+ btintel_check_bdaddr(hdev);
+ }
+
+ /* If the OTP has no valid Bluetooth device address, then there will
+ * also be no valid address for the operational firmware.
+ */
+ if (!bacmp(&ver->otp_bd_addr, BDADDR_ANY)) {
+ bt_dev_info(hdev, "No device address configured");
+ set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
+ }
+
+ btintel_get_fw_name_tlv(ver, fwname, sizeof(fwname), "sfi");
+ err = firmware_request_nowarn(&fw, fwname, &hdev->dev);
+ if (err < 0) {
+ if (!btintel_test_flag(hdev, INTEL_BOOTLOADER)) {
+ /* Firmware has already been loaded */
+ btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED);
+ return 0;
+ }
+
+ bt_dev_err(hdev, "Failed to load Intel firmware file %s (%d)",
+ fwname, err);
+
+ return err;
+ }
+
+ bt_dev_info(hdev, "Found device firmware: %s", fwname);
+
+ if (fw->size < 644) {
+ bt_dev_err(hdev, "Invalid size of firmware file (%zu)",
+ fw->size);
+ err = -EBADF;
+ goto done;
+ }
+
+ calltime = ktime_get();
+
+ btintel_set_flag(hdev, INTEL_DOWNLOADING);
+
+ /* Start firmware downloading and get boot parameter */
+ err = btintel_download_fw_tlv(hdev, ver, fw, boot_param,
+ INTEL_HW_VARIANT(ver->cnvi_bt),
+ ver->sbe_type);
+ if (err < 0) {
+ if (err == -EALREADY) {
+ /* Firmware has already been loaded */
+ btintel_set_flag(hdev, INTEL_FIRMWARE_LOADED);
+ err = 0;
+ goto done;
+ }
+
+ /* When FW download fails, send Intel Reset to retry
+ * FW download.
+ */
+ btintel_reset_to_bootloader(hdev);
+ goto done;
+ }
+
+ /* Before switching the device into operational mode and with that
+ * booting the loaded firmware, wait for the bootloader notification
+ * that all fragments have been successfully received.
+ *
+ * When the event processing receives the notification, then the
+ * BTUSB_DOWNLOADING flag will be cleared.
+ *
+ * The firmware loading should not take longer than 5 seconds
+ * and thus just timeout if that happens and fail the setup
+ * of this device.
+ */
+ err = btintel_download_wait(hdev, calltime, 5000);
+ if (err == -ETIMEDOUT)
+ btintel_reset_to_bootloader(hdev);
+
+done:
+ release_firmware(fw);
+ return err;
+}
+
+static int btintel_bootloader_setup_tlv(struct hci_dev *hdev,
+ struct intel_version_tlv *ver)
+{
+ u32 boot_param;
+ char ddcname[64];
+ int err;
+ struct intel_debug_features features;
+ struct intel_version_tlv new_ver;
+
+ bt_dev_dbg(hdev, "");
+
+ /* Set the default boot parameter to 0x0 and it is updated to
+ * SKU specific boot parameter after reading Intel_Write_Boot_Params
+ * command while downloading the firmware.
+ */
+ boot_param = 0x00000000;
+
+ btintel_set_flag(hdev, INTEL_BOOTLOADER);
+
+ err = btintel_prepare_fw_download_tlv(hdev, ver, &boot_param);
+ if (err)
+ return err;
+
+ /* check if controller is already having an operational firmware */
+ if (ver->img_type == 0x03)
+ goto finish;
+
+ err = btintel_boot(hdev, boot_param);
+ if (err)
+ return err;
+
+ btintel_clear_flag(hdev, INTEL_BOOTLOADER);
+
+ btintel_get_fw_name_tlv(ver, ddcname, sizeof(ddcname), "ddc");
+ /* Once the device is running in operational mode, it needs to
+ * apply the device configuration (DDC) parameters.
+ *
+ * The device can work without DDC parameters, so even if it
+ * fails to load the file, no need to fail the setup.
+ */
+ btintel_load_ddc_config(hdev, ddcname);
+
+ /* Read the Intel supported features and if new exception formats
+ * supported, need to load the additional DDC config to enable.
+ */
+ err = btintel_read_debug_features(hdev, &features);
+ if (!err) {
+ /* Set DDC mask for available debug features */
+ btintel_set_debug_features(hdev, &features);
+ }
+
+ /* Read the Intel version information after loading the FW */
+ err = btintel_read_version_tlv(hdev, &new_ver);
+ if (err)
+ return err;
+
+ btintel_version_info_tlv(hdev, &new_ver);
+
+finish:
+ /* Set the event mask for Intel specific vendor events. This enables
+ * a few extra events that are useful during general operation. It
+ * does not enable any debugging related events.
+ *
+ * The device will function correctly without these events enabled
+ * and thus no need to fail the setup.
+ */
+ btintel_set_event_mask(hdev, false);
+
+ return 0;
+}
+
static int btintel_setup_combined(struct hci_dev *hdev)
{
const u8 param[1] = { 0xFF };
case 0x12: /* ThP */
case 0x13: /* HrP */
case 0x14: /* CcP */
- /* TODO: call setup routine for bootloader product */
+ err = btintel_bootloader_setup(hdev, &ver);
break;
default:
bt_dev_err(hdev, "Unsupported Intel hw variant (%u)",
goto exit_error;
}
- /* Display version information of TLV type */
- btintel_version_info_tlv(hdev, &ver_tlv);
-
- /* TODO: Need to filter the device for new generation */
- /* TODO: call setup routine for tlv based bootloader product */
+ /* Check for supported iBT hardware variants of this firmware
+ * loading method.
+ *
+ * This check has been put in place to ensure correct forward
+ * compatibility options when newer hardware variants come
+ * along.
+ */
+ switch (INTEL_HW_VARIANT(ver_tlv.cnvi_bt)) {
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ /* Display version information of TLV type */
+ btintel_version_info_tlv(hdev, &ver_tlv);
+
+ err = btintel_bootloader_setup_tlv(hdev, &ver_tlv);
+ break;
+ default:
+ bt_dev_err(hdev, "Unsupported Intel hw variant (%u)",
+ INTEL_HW_VARIANT(ver_tlv.cnvi_bt));
+ return -EINVAL;
+ }
exit_error:
kfree_skb(skb);
hdev->manufacturer = 2;
hdev->setup = btintel_setup_combined;
hdev->shutdown = btintel_shutdown_combined;
+ hdev->hw_error = btintel_hw_error;
hdev->set_diag = btintel_set_diag_combined;
hdev->set_bdaddr = btintel_set_bdaddr;
}
EXPORT_SYMBOL_GPL(btintel_configure_setup);
+void btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len)
+{
+ const struct intel_bootup *evt = ptr;
+
+ if (len != sizeof(*evt))
+ return;
+
+ if (btintel_test_and_clear_flag(hdev, INTEL_BOOTING))
+ btintel_wake_up_flag(hdev, INTEL_BOOTING);
+}
+EXPORT_SYMBOL_GPL(btintel_bootup);
+
+void btintel_secure_send_result(struct hci_dev *hdev,
+ const void *ptr, unsigned int len)
+{
+ const struct intel_secure_send_result *evt = ptr;
+
+ if (len != sizeof(*evt))
+ return;
+
+ if (evt->result)
+ btintel_set_flag(hdev, INTEL_FIRMWARE_FAILED);
+
+ if (btintel_test_and_clear_flag(hdev, INTEL_DOWNLOADING) &&
+ btintel_test_flag(hdev, INTEL_FIRMWARE_LOADED))
+ btintel_wake_up_flag(hdev, INTEL_DOWNLOADING);
+}
+EXPORT_SYMBOL_GPL(btintel_secure_send_result);
+
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION);
MODULE_VERSION(VERSION);
#define BTUSB_BCM_PATCHRAM 0x400
#define BTUSB_MARVELL 0x800
#define BTUSB_SWAVE 0x1000
-#define BTUSB_INTEL_NEW 0x2000
#define BTUSB_AMP 0x4000
#define BTUSB_QCA_ROME 0x8000
#define BTUSB_BCM_APPLE 0x10000
#define BTUSB_WIDEBAND_SPEECH 0x400000
#define BTUSB_VALID_LE_STATES 0x800000
#define BTUSB_QCA_WCN6855 0x1000000
-#define BTUSB_INTEL_NEWGEN 0x2000000
#define BTUSB_INTEL_BROKEN_INITIAL_NCMD 0x4000000
static const struct usb_device_id btusb_table[] = {
{ USB_DEVICE(0x1286, 0x204e), .driver_info = BTUSB_MARVELL },
/* Intel Bluetooth devices */
- { USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_NEW |
+ { USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_COMBINED |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
- { USB_DEVICE(0x8087, 0x0026), .driver_info = BTUSB_INTEL_NEW |
+ { USB_DEVICE(0x8087, 0x0026), .driver_info = BTUSB_INTEL_COMBINED |
BTUSB_WIDEBAND_SPEECH },
- { USB_DEVICE(0x8087, 0x0029), .driver_info = BTUSB_INTEL_NEW |
+ { USB_DEVICE(0x8087, 0x0029), .driver_info = BTUSB_INTEL_COMBINED |
BTUSB_WIDEBAND_SPEECH },
- { USB_DEVICE(0x8087, 0x0032), .driver_info = BTUSB_INTEL_NEWGEN |
+ { USB_DEVICE(0x8087, 0x0032), .driver_info = BTUSB_INTEL_COMBINED |
BTUSB_WIDEBAND_SPEECH},
- { USB_DEVICE(0x8087, 0x0033), .driver_info = BTUSB_INTEL_NEWGEN |
+ { USB_DEVICE(0x8087, 0x0033), .driver_info = BTUSB_INTEL_COMBINED |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
{ USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED |
BTUSB_INTEL_BROKEN_INITIAL_NCMD },
{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED },
- { USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_NEW |
+ { USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_COMBINED |
BTUSB_WIDEBAND_SPEECH },
{ USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL_COMBINED |
BTUSB_WIDEBAND_SPEECH },
- { USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_NEW |
+ { USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_COMBINED |
BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES },
static int btusb_recv_bulk_intel(struct btusb_data *data, void *buffer,
int count)
{
+ struct hci_dev *hdev = data->hdev;
+
/* When the device is in bootloader mode, then it can send
* events via the bulk endpoint. These events are treated the
* same way as the ones received from the interrupt endpoint.
*/
- if (test_bit(BTUSB_BOOTLOADER, &data->flags))
+ if (btintel_test_flag(hdev, INTEL_BOOTLOADER))
return btusb_recv_intr(data, buffer, count);
return btusb_recv_bulk(data, buffer, count);
}
-static void btusb_intel_bootup(struct btusb_data *data, const void *ptr,
- unsigned int len)
-{
- const struct intel_bootup *evt = ptr;
-
- if (len != sizeof(*evt))
- return;
-
- if (test_and_clear_bit(BTUSB_BOOTING, &data->flags))
- wake_up_bit(&data->flags, BTUSB_BOOTING);
-}
-
-static void btusb_intel_secure_send_result(struct btusb_data *data,
- const void *ptr, unsigned int len)
-{
- const struct intel_secure_send_result *evt = ptr;
-
- if (len != sizeof(*evt))
- return;
-
- if (evt->result)
- set_bit(BTUSB_FIRMWARE_FAILED, &data->flags);
-
- if (test_and_clear_bit(BTUSB_DOWNLOADING, &data->flags) &&
- test_bit(BTUSB_FIRMWARE_LOADED, &data->flags))
- wake_up_bit(&data->flags, BTUSB_DOWNLOADING);
-}
-
static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct btusb_data *data = hci_get_drvdata(hdev);
-
- if (test_bit(BTUSB_BOOTLOADER, &data->flags)) {
+ if (btintel_test_flag(hdev, INTEL_BOOTLOADER)) {
struct hci_event_hdr *hdr = (void *)skb->data;
if (skb->len > HCI_EVENT_HDR_SIZE && hdr->evt == 0xff &&
* the device sends a vendor specific event
* indicating that the bootup completed.
*/
- btusb_intel_bootup(data, ptr, len);
+ btintel_bootup(hdev, ptr, len);
break;
case 0x06:
/* When the firmware loading completes the
* indicating the result of the firmware
* loading.
*/
- btusb_intel_secure_send_result(data, ptr, len);
+ btintel_secure_send_result(hdev, ptr, len);
break;
}
}
static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct btusb_data *data = hci_get_drvdata(hdev);
struct urb *urb;
BT_DBG("%s", hdev->name);
switch (hci_skb_pkt_type(skb)) {
case HCI_COMMAND_PKT:
- if (test_bit(BTUSB_BOOTLOADER, &data->flags)) {
+ if (btintel_test_flag(hdev, INTEL_BOOTLOADER)) {
struct hci_command_hdr *cmd = (void *)skb->data;
__u16 opcode = le16_to_cpu(cmd->opcode);
return -EILSEQ;
}
-static int btusb_setup_intel_new_get_fw_name(struct intel_version *ver,
- struct intel_boot_params *params,
- char *fw_name, size_t len,
- const char *suffix)
-{
- switch (ver->hw_variant) {
- case 0x0b: /* SfP */
- case 0x0c: /* WsP */
- snprintf(fw_name, len, "intel/ibt-%u-%u.%s",
- le16_to_cpu(ver->hw_variant),
- le16_to_cpu(params->dev_revid),
- suffix);
- break;
- case 0x11: /* JfP */
- case 0x12: /* ThP */
- case 0x13: /* HrP */
- case 0x14: /* CcP */
- snprintf(fw_name, len, "intel/ibt-%u-%u-%u.%s",
- le16_to_cpu(ver->hw_variant),
- le16_to_cpu(ver->hw_revision),
- le16_to_cpu(ver->fw_revision),
- suffix);
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void btusb_setup_intel_newgen_get_fw_name(const struct intel_version_tlv *ver_tlv,
- char *fw_name, size_t len,
- const char *suffix)
-{
- /* The firmware file name for new generation controllers will be
- * ibt-<cnvi_top type+cnvi_top step>-<cnvr_top type+cnvr_top step>
- */
- snprintf(fw_name, len, "intel/ibt-%04x-%04x.%s",
- INTEL_CNVX_TOP_PACK_SWAB(INTEL_CNVX_TOP_TYPE(ver_tlv->cnvi_top),
- INTEL_CNVX_TOP_STEP(ver_tlv->cnvi_top)),
- INTEL_CNVX_TOP_PACK_SWAB(INTEL_CNVX_TOP_TYPE(ver_tlv->cnvr_top),
- INTEL_CNVX_TOP_STEP(ver_tlv->cnvr_top)),
- suffix);
-}
-
-static int btusb_download_wait(struct hci_dev *hdev, ktime_t calltime, int msec)
-{
- struct btusb_data *data = hci_get_drvdata(hdev);
- ktime_t delta, rettime;
- unsigned long long duration;
- int err;
-
- set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
-
- bt_dev_info(hdev, "Waiting for firmware download to complete");
-
- err = wait_on_bit_timeout(&data->flags, BTUSB_DOWNLOADING,
- TASK_INTERRUPTIBLE,
- msecs_to_jiffies(msec));
- if (err == -EINTR) {
- bt_dev_err(hdev, "Firmware loading interrupted");
- return err;
- }
-
- if (err) {
- bt_dev_err(hdev, "Firmware loading timeout");
- return -ETIMEDOUT;
- }
-
- if (test_bit(BTUSB_FIRMWARE_FAILED, &data->flags)) {
- bt_dev_err(hdev, "Firmware loading failed");
- return -ENOEXEC;
- }
-
- rettime = ktime_get();
- delta = ktime_sub(rettime, calltime);
- duration = (unsigned long long)ktime_to_ns(delta) >> 10;
-
- bt_dev_info(hdev, "Firmware loaded in %llu usecs", duration);
-
- return 0;
-}
-
-static int btusb_intel_download_firmware_newgen(struct hci_dev *hdev,
- struct intel_version_tlv *ver,
- u32 *boot_param)
-{
- const struct firmware *fw;
- char fwname[64];
- int err;
- struct btusb_data *data = hci_get_drvdata(hdev);
- ktime_t calltime;
-
- if (!ver || !boot_param)
- return -EINVAL;
-
- /* The firmware variant determines if the device is in bootloader
- * mode or is running operational firmware. The value 0x03 identifies
- * the bootloader and the value 0x23 identifies the operational
- * firmware.
- *
- * When the operational firmware is already present, then only
- * the check for valid Bluetooth device address is needed. This
- * determines if the device will be added as configured or
- * unconfigured controller.
- *
- * It is not possible to use the Secure Boot Parameters in this
- * case since that command is only available in bootloader mode.
- */
- if (ver->img_type == 0x03) {
- clear_bit(BTUSB_BOOTLOADER, &data->flags);
- btintel_check_bdaddr(hdev);
- }
-
- /* If the OTP has no valid Bluetooth device address, then there will
- * also be no valid address for the operational firmware.
- */
- if (!bacmp(&ver->otp_bd_addr, BDADDR_ANY)) {
- bt_dev_info(hdev, "No device address configured");
- set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
- }
-
- btusb_setup_intel_newgen_get_fw_name(ver, fwname, sizeof(fwname), "sfi");
- err = firmware_request_nowarn(&fw, fwname, &hdev->dev);
- if (err < 0) {
- if (!test_bit(BTUSB_BOOTLOADER, &data->flags)) {
- /* Firmware has already been loaded */
- set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
- return 0;
- }
-
- bt_dev_err(hdev, "Failed to load Intel firmware file %s (%d)",
- fwname, err);
-
- return err;
- }
-
- bt_dev_info(hdev, "Found device firmware: %s", fwname);
-
- if (fw->size < 644) {
- bt_dev_err(hdev, "Invalid size of firmware file (%zu)",
- fw->size);
- err = -EBADF;
- goto done;
- }
-
- calltime = ktime_get();
-
- set_bit(BTUSB_DOWNLOADING, &data->flags);
-
- /* Start firmware downloading and get boot parameter */
- err = btintel_download_firmware_newgen(hdev, ver, fw, boot_param,
- INTEL_HW_VARIANT(ver->cnvi_bt),
- ver->sbe_type);
- if (err < 0) {
- if (err == -EALREADY) {
- /* Firmware has already been loaded */
- set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
- err = 0;
- goto done;
- }
-
- /* When FW download fails, send Intel Reset to retry
- * FW download.
- */
- btintel_reset_to_bootloader(hdev);
- goto done;
- }
-
- /* Before switching the device into operational mode and with that
- * booting the loaded firmware, wait for the bootloader notification
- * that all fragments have been successfully received.
- *
- * When the event processing receives the notification, then the
- * BTUSB_DOWNLOADING flag will be cleared.
- *
- * The firmware loading should not take longer than 5 seconds
- * and thus just timeout if that happens and fail the setup
- * of this device.
- */
- err = btusb_download_wait(hdev, calltime, 5000);
- if (err == -ETIMEDOUT)
- btintel_reset_to_bootloader(hdev);
-
-done:
- release_firmware(fw);
- return err;
-}
-
-static int btusb_intel_download_firmware(struct hci_dev *hdev,
- struct intel_version *ver,
- struct intel_boot_params *params,
- u32 *boot_param)
-{
- const struct firmware *fw;
- char fwname[64];
- int err;
- struct btusb_data *data = hci_get_drvdata(hdev);
- ktime_t calltime;
-
- if (!ver || !params)
- return -EINVAL;
-
- /* The firmware variant determines if the device is in bootloader
- * mode or is running operational firmware. The value 0x06 identifies
- * the bootloader and the value 0x23 identifies the operational
- * firmware.
- *
- * When the operational firmware is already present, then only
- * the check for valid Bluetooth device address is needed. This
- * determines if the device will be added as configured or
- * unconfigured controller.
- *
- * It is not possible to use the Secure Boot Parameters in this
- * case since that command is only available in bootloader mode.
- */
- if (ver->fw_variant == 0x23) {
- clear_bit(BTUSB_BOOTLOADER, &data->flags);
- btintel_check_bdaddr(hdev);
-
- /* SfP and WsP don't seem to update the firmware version on file
- * so version checking is currently possible.
- */
- switch (ver->hw_variant) {
- case 0x0b: /* SfP */
- case 0x0c: /* WsP */
- return 0;
- }
-
- /* Proceed to download to check if the version matches */
- goto download;
- }
-
- /* Read the secure boot parameters to identify the operating
- * details of the bootloader.
- */
- err = btintel_read_boot_params(hdev, params);
- if (err)
- return err;
-
- /* It is required that every single firmware fragment is acknowledged
- * with a command complete event. If the boot parameters indicate
- * that this bootloader does not send them, then abort the setup.
- */
- if (params->limited_cce != 0x00) {
- bt_dev_err(hdev, "Unsupported Intel firmware loading method (%u)",
- params->limited_cce);
- return -EINVAL;
- }
-
- /* If the OTP has no valid Bluetooth device address, then there will
- * also be no valid address for the operational firmware.
- */
- if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) {
- bt_dev_info(hdev, "No device address configured");
- set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
- }
-
-download:
- /* With this Intel bootloader only the hardware variant and device
- * revision information are used to select the right firmware for SfP
- * and WsP.
- *
- * The firmware filename is ibt-<hw_variant>-<dev_revid>.sfi.
- *
- * Currently the supported hardware variants are:
- * 11 (0x0b) for iBT3.0 (LnP/SfP)
- * 12 (0x0c) for iBT3.5 (WsP)
- *
- * For ThP/JfP and for future SKU's, the FW name varies based on HW
- * variant, HW revision and FW revision, as these are dependent on CNVi
- * and RF Combination.
- *
- * 17 (0x11) for iBT3.5 (JfP)
- * 18 (0x12) for iBT3.5 (ThP)
- *
- * The firmware file name for these will be
- * ibt-<hw_variant>-<hw_revision>-<fw_revision>.sfi.
- *
- */
- err = btusb_setup_intel_new_get_fw_name(ver, params, fwname,
- sizeof(fwname), "sfi");
- if (err < 0) {
- if (!test_bit(BTUSB_BOOTLOADER, &data->flags)) {
- /* Firmware has already been loaded */
- set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
- return 0;
- }
-
- bt_dev_err(hdev, "Unsupported Intel firmware naming");
- return -EINVAL;
- }
-
- err = firmware_request_nowarn(&fw, fwname, &hdev->dev);
- if (err < 0) {
- if (!test_bit(BTUSB_BOOTLOADER, &data->flags)) {
- /* Firmware has already been loaded */
- set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
- return 0;
- }
-
- bt_dev_err(hdev, "Failed to load Intel firmware file %s (%d)",
- fwname, err);
- return err;
- }
-
- bt_dev_info(hdev, "Found device firmware: %s", fwname);
-
- if (fw->size < 644) {
- bt_dev_err(hdev, "Invalid size of firmware file (%zu)",
- fw->size);
- err = -EBADF;
- goto done;
- }
-
- calltime = ktime_get();
-
- set_bit(BTUSB_DOWNLOADING, &data->flags);
-
- /* Start firmware downloading and get boot parameter */
- err = btintel_download_firmware(hdev, ver, fw, boot_param);
- if (err < 0) {
- if (err == -EALREADY) {
- /* Firmware has already been loaded */
- set_bit(BTUSB_FIRMWARE_LOADED, &data->flags);
- err = 0;
- goto done;
- }
-
- /* When FW download fails, send Intel Reset to retry
- * FW download.
- */
- btintel_reset_to_bootloader(hdev);
- goto done;
- }
-
- /* Before switching the device into operational mode and with that
- * booting the loaded firmware, wait for the bootloader notification
- * that all fragments have been successfully received.
- *
- * When the event processing receives the notification, then the
- * BTUSB_DOWNLOADING flag will be cleared.
- *
- * The firmware loading should not take longer than 5 seconds
- * and thus just timeout if that happens and fail the setup
- * of this device.
- */
- err = btusb_download_wait(hdev, calltime, 5000);
- if (err == -ETIMEDOUT)
- btintel_reset_to_bootloader(hdev);
-
-done:
- release_firmware(fw);
- return err;
-}
-
-static int btusb_boot_wait(struct hci_dev *hdev, ktime_t calltime, int msec)
-{
- struct btusb_data *data = hci_get_drvdata(hdev);
- ktime_t delta, rettime;
- unsigned long long duration;
- int err;
-
- bt_dev_info(hdev, "Waiting for device to boot");
-
- err = wait_on_bit_timeout(&data->flags, BTUSB_BOOTING,
- TASK_INTERRUPTIBLE,
- msecs_to_jiffies(msec));
- if (err == -EINTR) {
- bt_dev_err(hdev, "Device boot interrupted");
- return -EINTR;
- }
-
- if (err) {
- bt_dev_err(hdev, "Device boot timeout");
- return -ETIMEDOUT;
- }
-
- rettime = ktime_get();
- delta = ktime_sub(rettime, calltime);
- duration = (unsigned long long) ktime_to_ns(delta) >> 10;
-
- bt_dev_info(hdev, "Device booted in %llu usecs", duration);
-
- return 0;
-}
-
-static int btusb_intel_boot(struct hci_dev *hdev, u32 boot_addr)
-{
- struct btusb_data *data = hci_get_drvdata(hdev);
- ktime_t calltime;
- int err;
-
- calltime = ktime_get();
-
- set_bit(BTUSB_BOOTING, &data->flags);
-
- err = btintel_send_intel_reset(hdev, boot_addr);
- if (err) {
- bt_dev_err(hdev, "Intel Soft Reset failed (%d)", err);
- btintel_reset_to_bootloader(hdev);
- return err;
- }
-
- /* The bootloader will not indicate when the device is ready. This
- * is done by the operational firmware sending bootup notification.
- *
- * Booting into operational firmware should not take longer than
- * 1 second. However if that happens, then just fail the setup
- * since something went wrong.
- */
- err = btusb_boot_wait(hdev, calltime, 1000);
- if (err == -ETIMEDOUT)
- btintel_reset_to_bootloader(hdev);
-
- return err;
-}
-
-static int btusb_setup_intel_new(struct hci_dev *hdev)
-{
- struct btusb_data *data = hci_get_drvdata(hdev);
- struct intel_version ver;
- struct intel_boot_params params;
- u32 boot_param;
- char ddcname[64];
- int err;
- struct intel_debug_features features;
-
- BT_DBG("%s", hdev->name);
-
- /* Set the default boot parameter to 0x0 and it is updated to
- * SKU specific boot parameter after reading Intel_Write_Boot_Params
- * command while downloading the firmware.
- */
- boot_param = 0x00000000;
-
- /* Read the Intel version information to determine if the device
- * is in bootloader mode or if it already has operational firmware
- * loaded.
- */
- err = btintel_read_version(hdev, &ver);
- if (err) {
- bt_dev_err(hdev, "Intel Read version failed (%d)", err);
- btintel_reset_to_bootloader(hdev);
- return err;
- }
-
- err = btintel_version_info(hdev, &ver);
- if (err)
- return err;
-
- err = btusb_intel_download_firmware(hdev, &ver, ¶ms, &boot_param);
- if (err)
- return err;
-
- /* controller is already having an operational firmware */
- if (ver.fw_variant == 0x23)
- goto finish;
-
- err = btusb_intel_boot(hdev, boot_param);
- if (err)
- return err;
-
- clear_bit(BTUSB_BOOTLOADER, &data->flags);
-
- err = btusb_setup_intel_new_get_fw_name(&ver, ¶ms, ddcname,
- sizeof(ddcname), "ddc");
-
- if (err < 0) {
- bt_dev_err(hdev, "Unsupported Intel firmware naming");
- } else {
- /* Once the device is running in operational mode, it needs to
- * apply the device configuration (DDC) parameters.
- *
- * The device can work without DDC parameters, so even if it
- * fails to load the file, no need to fail the setup.
- */
- btintel_load_ddc_config(hdev, ddcname);
- }
-
- /* Read the Intel supported features and if new exception formats
- * supported, need to load the additional DDC config to enable.
- */
- err = btintel_read_debug_features(hdev, &features);
- if (!err) {
- /* Set DDC mask for available debug features */
- btintel_set_debug_features(hdev, &features);
- }
-
- /* Read the Intel version information after loading the FW */
- err = btintel_read_version(hdev, &ver);
- if (err)
- return err;
-
- btintel_version_info(hdev, &ver);
-
-finish:
- /* All Intel controllers that support the Microsoft vendor
- * extension are using 0xFC1E for VsMsftOpCode.
- */
- switch (ver.hw_variant) {
- case 0x11: /* JfP */
- case 0x12: /* ThP */
- case 0x13: /* HrP */
- case 0x14: /* CcP */
- hci_set_msft_opcode(hdev, 0xFC1E);
- break;
- }
-
- /* Set the event mask for Intel specific vendor events. This enables
- * a few extra events that are useful during general operation. It
- * does not enable any debugging related events.
- *
- * The device will function correctly without these events enabled
- * and thus no need to fail the setup.
- */
- btintel_set_event_mask(hdev, false);
-
- return 0;
-}
-
-static int btusb_setup_intel_newgen(struct hci_dev *hdev)
-{
- struct btusb_data *data = hci_get_drvdata(hdev);
- u32 boot_param;
- char ddcname[64];
- int err;
- struct intel_debug_features features;
- struct intel_version_tlv version;
-
- bt_dev_dbg(hdev, "");
-
- /* Set the default boot parameter to 0x0 and it is updated to
- * SKU specific boot parameter after reading Intel_Write_Boot_Params
- * command while downloading the firmware.
- */
- boot_param = 0x00000000;
-
- /* Read the Intel version information to determine if the device
- * is in bootloader mode or if it already has operational firmware
- * loaded.
- */
- err = btintel_read_version_tlv(hdev, &version);
- if (err) {
- bt_dev_err(hdev, "Intel Read version failed (%d)", err);
- btintel_reset_to_bootloader(hdev);
- return err;
- }
-
- err = btintel_version_info_tlv(hdev, &version);
- if (err)
- return err;
-
- err = btusb_intel_download_firmware_newgen(hdev, &version, &boot_param);
- if (err)
- return err;
-
- /* check if controller is already having an operational firmware */
- if (version.img_type == 0x03)
- goto finish;
-
- err = btusb_intel_boot(hdev, boot_param);
- if (err)
- return err;
-
- clear_bit(BTUSB_BOOTLOADER, &data->flags);
-
- btusb_setup_intel_newgen_get_fw_name(&version, ddcname, sizeof(ddcname),
- "ddc");
- /* Once the device is running in operational mode, it needs to
- * apply the device configuration (DDC) parameters.
- *
- * The device can work without DDC parameters, so even if it
- * fails to load the file, no need to fail the setup.
- */
- btintel_load_ddc_config(hdev, ddcname);
-
- /* Read the Intel supported features and if new exception formats
- * supported, need to load the additional DDC config to enable.
- */
- err = btintel_read_debug_features(hdev, &features);
- if (!err) {
- /* Set DDC mask for available debug features */
- btintel_set_debug_features(hdev, &features);
- }
-
- /* Read the Intel version information after loading the FW */
- err = btintel_read_version_tlv(hdev, &version);
- if (err)
- return err;
-
- btintel_version_info_tlv(hdev, &version);
-
-finish:
- /* All Intel new genration controllers support the Microsoft vendor
- * extension are using 0xFC1E for VsMsftOpCode.
- */
- switch (INTEL_HW_VARIANT(version.cnvi_bt)) {
- case 0x17:
- case 0x18:
- case 0x19:
- hci_set_msft_opcode(hdev, 0xFC1E);
- break;
- }
-
- /* Set the event mask for Intel specific vendor events. This enables
- * a few extra events that are useful during general operation. It
- * does not enable any debugging related events.
- *
- * The device will function correctly without these events enabled
- * and thus no need to fail the setup.
- */
- btintel_set_event_mask(hdev, false);
-
- return 0;
-}
-
-static int btusb_shutdown_intel_new(struct hci_dev *hdev)
-{
- struct sk_buff *skb;
-
- /* Send HCI Reset to the controller to stop any BT activity which
- * were triggered. This will help to save power and maintain the
- * sync b/w Host and controller
- */
- skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
- if (IS_ERR(skb)) {
- bt_dev_err(hdev, "HCI reset during shutdown failed");
- return PTR_ERR(skb);
- }
- kfree_skb(skb);
-
- return 0;
-}
-
/* UHW CR mapping */
#define MTK_BT_MISC 0x70002510
#define MTK_BT_SUBSYS_RST 0x70002610
priv_size = 0;
+ data->recv_event = hci_recv_frame;
+ data->recv_bulk = btusb_recv_bulk;
+
if (id->driver_info & BTUSB_INTEL_COMBINED) {
/* Allocate extra space for Intel device */
priv_size += sizeof(struct btintel_data);
- }
- if (id->driver_info & BTUSB_INTEL_NEW) {
+ /* Override the rx handlers */
data->recv_event = btusb_recv_event_intel;
data->recv_bulk = btusb_recv_bulk_intel;
- set_bit(BTUSB_BOOTLOADER, &data->flags);
- } else {
- data->recv_event = hci_recv_frame;
- data->recv_bulk = btusb_recv_bulk;
}
data->recv_acl = hci_recv_frame;
goto out_free_dev;
/* Transport specific configuration */
+ hdev->send = btusb_send_frame_intel;
hdev->cmd_timeout = btusb_intel_cmd_timeout;
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
btintel_set_flag(hdev, INTEL_BROKEN_INITIAL_NCMD);
}
- if (id->driver_info & BTUSB_INTEL_NEW) {
- hdev->manufacturer = 2;
- hdev->send = btusb_send_frame_intel;
- hdev->setup = btusb_setup_intel_new;
- hdev->shutdown = btusb_shutdown_intel_new;
- hdev->hw_error = btintel_hw_error;
- hdev->set_diag = btintel_set_diag;
- hdev->set_bdaddr = btintel_set_bdaddr;
- hdev->cmd_timeout = btusb_intel_cmd_timeout;
- set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
- set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
- set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks);
- }
-
- if (id->driver_info & BTUSB_INTEL_NEWGEN) {
- hdev->manufacturer = 2;
- hdev->send = btusb_send_frame_intel;
- hdev->setup = btusb_setup_intel_newgen;
- hdev->shutdown = btusb_shutdown_intel_new;
- hdev->hw_error = btintel_hw_error;
- hdev->set_diag = btintel_set_diag;
- hdev->set_bdaddr = btintel_set_bdaddr;
- hdev->cmd_timeout = btusb_intel_cmd_timeout;
- set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
- set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
- set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks);
-
- data->recv_event = btusb_recv_event_intel;
- data->recv_bulk = btusb_recv_bulk_intel;
- set_bit(BTUSB_BOOTLOADER, &data->flags);
- }
-
if (id->driver_info & BTUSB_MARVELL)
hdev->set_bdaddr = btusb_set_bdaddr_marvell;