diff --git a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_intel.c b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_intel.c
--- a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_intel.c
+++ b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt_intel.c
@@ -59,6 +59,7 @@
 enum {
 	UBT_INTEL_DEVICE_7260,
 	UBT_INTEL_DEVICE_8260,
+	UBT_INTEL_DEVICE_TLV,
 };
 
 struct ubt_intel_version_rp {
@@ -74,6 +75,11 @@
 	uint8_t fw_patch_num;
 } __attribute__ ((packed));
 
+struct ubt_intel_tlv_field {
+	uint8_t type;
+	uint8_t len;
+	uint8_t val[];
+} __attribute__ ((packed));
 static device_probe_t	ubt_intel_probe;
 
 /*
@@ -93,6 +99,8 @@
 	{ USB_VPI(USB_VENDOR_INTEL2, 0x0025, UBT_INTEL_DEVICE_8260) },
 	{ USB_VPI(USB_VENDOR_INTEL2, 0x0026, UBT_INTEL_DEVICE_8260) },
 	{ USB_VPI(USB_VENDOR_INTEL2, 0x0029, UBT_INTEL_DEVICE_8260) },
+	/* Intel AX210 */
+	{ USB_VPI(USB_VENDOR_INTEL2, 0x0032, UBT_INTEL_DEVICE_TLV) },
 };
 
 /*
@@ -128,6 +136,50 @@
 	return (error);
 }
 
+static bool
+ubt_intel_tlv_is_firmware_running(struct usb_device *dev)
+{
+#define TLV_BUFFER_SIZE 252
+	uint8_t evtbuf[offsetof(struct ubt_hci_event_command_compl, data) + TLV_BUFFER_SIZE] = {0};
+	struct ubt_hci_event_command_compl *evt = (struct ubt_hci_event_command_compl *)evtbuf;
+	uint8_t cmdbuf[offsetof(struct ubt_hci_cmd, data) + 1];
+	struct ubt_hci_cmd *cmd = (struct ubt_hci_cmd *)cmdbuf;
+	usb_error_t error;
+	struct ubt_intel_tlv_field *f;
+	size_t pos;
+
+	cmd->opcode = htole16(0xfc05),
+	cmd->length = 1,
+	cmd->data[0] = 0xff;
+
+	evt->header.length = TLV_BUFFER_SIZE + UBT_HCI_EVENT_COMPL_HEAD_SIZE;
+
+	error = ubt_do_hci_request(dev, cmd, evt, UBT_INTEL_HCICMD_TIMEOUT);
+	if (error != USB_ERR_NORMAL_COMPLETION)
+		return false;
+
+	if (evt->header.event != NG_HCI_EVENT_COMMAND_COMPL)
+		return false;
+
+	pos = offsetof(struct ubt_hci_event_command_compl, data);
+
+	while ((pos + 2) < evt->header.length) {
+		f = (struct ubt_intel_tlv_field *) &evt->data[pos];
+		if (pos + f->len >= evt->header.length)
+			break;
+
+		if (f->type == 0x1c && f->len == 1) {
+			if (f->val[0] == 0x03)
+				return true;
+			return false;
+		}
+
+		pos += offsetof(struct ubt_intel_tlv_field, val);
+		pos += f->len;
+	}
+	return false;
+}
+
 /*
  * Probe for a Intel Wireless Bluetooth device.
  */
@@ -193,6 +245,14 @@
 			return (ENXIO);
 		break;
 
+	case UBT_INTEL_DEVICE_TLV:
+		/*
+		 * Find if the device is in bootloader mode or is running
+		 * operational firmware.
+		 */
+		if (!ubt_intel_tlv_is_firmware_running(uaa->device))
+			return ENXIO;
+		break;
 	default:
 		KASSERT(0 == 1, ("Unknown DRIVER_INFO"));
 	}
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.h b/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.h
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.h
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.h
@@ -42,6 +42,34 @@
 	uint8_t fw_patch_num;
 } __attribute__ ((packed));
 
+struct iwmbt_tlv {
+	uint8_t status;
+#define IWMBT_TLV_MAX 4096
+	uint8_t tlv_data[IWMBT_TLV_MAX];
+	/* Must be at end (not part of transferred data) */
+	uint16_t tlv_len;
+} __attribute__ ((packed));
+
+struct iwmbt_tlv_field {
+	uint8_t type;
+	uint8_t len;
+	uint8_t val[];
+} __attribute__ ((packed));
+
+enum types {
+	IWMBT_TLV_TYPE_STATE = 0x2c,	// 1 == Bootloader
+	IWMBT_TLV_TYPE_ECDSA = 0x2f,
+};
+
+struct iwmbt_parsed_tlv {
+	uint32_t parse_state;
+	uint32_t fn_first;
+	uint32_t fn_second;
+	uint32_t hw_version;
+	uint8_t  running;
+	uint8_t  sigtype;
+};
+
 struct iwmbt_boot_params {
 	uint8_t status;
 	uint8_t otp_format;
@@ -73,5 +101,8 @@
 extern	char *iwmbt_get_fwname(struct iwmbt_version *ver,
 	struct iwmbt_boot_params *params, const char *prefix,
 	const char *suffix);
+extern	char *iwmbt_get_fwname_tlv(const char *prefix,
+	struct iwmbt_parsed_tlv *ptlv,
+	const char *suffix);
 
 #endif
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c b/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbt_fw.c
@@ -170,3 +170,23 @@
 
 	return (fwname);
 }
+
+static uint16_t
+iwmbt_mangle_tlv_value(uint32_t val)
+{
+	uint16_t ret = ((val & 0xfff) << 4) | ((val & 0x0f000000) >> 24);
+	return bswap16(ret);
+}
+
+char *
+iwmbt_get_fwname_tlv(const char *prefix, struct iwmbt_parsed_tlv *ptlv, const char *suffix)
+{
+	char *fwname;
+
+	asprintf(&fwname, "%s/ibt-%04x-%04x.%s",
+	    prefix,
+	    iwmbt_mangle_tlv_value(ptlv->fn_first),
+	    iwmbt_mangle_tlv_value(ptlv->fn_second),
+	    suffix);
+	return fwname;
+}
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.h
@@ -27,6 +27,8 @@
 #ifndef	__IWMBT_HW_H__
 #define	__IWMBT_HW_H__
 
+#include <stdbool.h>
+
 /* USB control request (HCI command) structure */
 struct iwmbt_hci_cmd {
 	uint16_t	opcode;
@@ -74,16 +76,18 @@
 extern	int iwmbt_patch_fwfile(struct libusb_device_handle *hdl,
 	    const struct iwmbt_firmware *fw);
 extern	int iwmbt_load_fwfile(struct libusb_device_handle *hdl,
-	    const struct iwmbt_firmware *fw, uint32_t *boot_param);
+	    const struct iwmbt_firmware *fw, uint32_t *boot_param, bool is_tlv, uint8_t sigtype);
 extern	int iwmbt_enter_manufacturer(struct libusb_device_handle *hdl);
 extern	int iwmbt_exit_manufacturer(struct libusb_device_handle *hdl,
 	    int mode);
 extern	int iwmbt_get_version(struct libusb_device_handle *hdl,
 	    struct iwmbt_version *version);
+extern	int iwmbt_get_tlv(struct libusb_device_handle *hdl,
+	    struct iwmbt_tlv *tlv);
 extern	int iwmbt_get_boot_params(struct libusb_device_handle *hdl,
 	    struct iwmbt_boot_params *params);
 extern	int iwmbt_intel_reset(struct libusb_device_handle *hdl,
-	    uint32_t boot_param);
+	    uint32_t boot_param, bool hard);
 extern	int iwmbt_load_ddc(struct libusb_device_handle *hdl,
 	    const struct iwmbt_firmware *ddc);
 extern	int iwmbt_set_event_mask(struct libusb_device_handle *hdl);
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbt_hw.c
@@ -269,7 +269,7 @@
 
 int
 iwmbt_load_fwfile(struct libusb_device_handle *hdl,
-    const struct iwmbt_firmware *fw, uint32_t *boot_param)
+    const struct iwmbt_firmware *fw, uint32_t *boot_param, bool is_tlv, uint8_t sigtype)
 {
 	int ready = 0, sent = 0;
 	int ret, transferred;
@@ -300,15 +300,26 @@
 
 	iwmbt_debug("file=%s, size=%d", fw->fwname, fw->len);
 
-	IWMBT_SEND_FRAGMENT(0x00, 0x80, "CCS segment");
-	IWMBT_SEND_FRAGMENT(0x03, 0x80, "public key / part 1");
-	IWMBT_SEND_FRAGMENT(0x03, 0x80, "public key / part 2");
+	if (sigtype == 0 || !is_tlv) {
+		IWMBT_SEND_FRAGMENT(0x00, 0x80, "CCS segment");
+		IWMBT_SEND_FRAGMENT(0x03, 0x80, "public key / part 1");
+		IWMBT_SEND_FRAGMENT(0x03, 0x80, "public key / part 2");
 
-	/* skip 4 bytes */
-	sent += 4;
+		/* skip 4 bytes */
+		sent += 4;
 
-	IWMBT_SEND_FRAGMENT(0x02, 0x80, "signature / part 1");
-	IWMBT_SEND_FRAGMENT(0x02, 0x80, "signature / part 2");
+		IWMBT_SEND_FRAGMENT(0x02, 0x80, "signature / part 1");
+		IWMBT_SEND_FRAGMENT(0x02, 0x80, "signature / part 2");
+
+		if (is_tlv)
+			sent += 320;
+	} else {
+		sent += 644;
+
+		IWMBT_SEND_FRAGMENT(0x00, 128, "CSS segment");
+		IWMBT_SEND_FRAGMENT(0x03, 96, "public key?");
+		IWMBT_SEND_FRAGMENT(0x02, 96, "signature?");
+	}
 
 	/*
 	 * Send firmware chunks. Chunk len must be 4 byte aligned.
@@ -460,6 +471,46 @@
 	return (0);
 }
 
+int
+iwmbt_get_tlv(struct libusb_device_handle *hdl,
+    struct iwmbt_tlv *tlv)
+{
+	int ret, transferred;
+	struct iwmbt_hci_event_cmd_compl*event;
+	uint8_t buf[IWMBT_HCI_EVT_COMPL_SIZE(struct iwmbt_tlv) - sizeof(tlv->tlv_len)];
+	uint8_t cmdbuf[offsetof(struct iwmbt_hci_cmd, data) + 1];
+	struct iwmbt_hci_cmd *cmd = (struct iwmbt_hci_cmd *) cmdbuf;
+	cmd->opcode = htole16(0xfc05),
+	cmd->length = 1,
+	cmd->data[0] = 0xff;
+
+	memset(buf, 0, sizeof(buf));
+
+	ret = iwmbt_hci_command(hdl,
+	    cmd,
+	    buf,
+	    sizeof(buf),
+	    &transferred,
+	    IWMBT_HCI_CMD_TIMEOUT);
+
+	if (ret < 0 || transferred < 1) {
+		iwmbt_debug("Can't get TLV: : code=%d, size=%d",
+		     ret,
+		    transferred);
+		return (-1);
+	}
+	tlv->tlv_len = transferred - offsetof(struct iwmbt_tlv, tlv_data) - offsetof(struct iwmbt_hci_event_cmd_compl, data);
+
+	event = (struct iwmbt_hci_event_cmd_compl *)buf;
+	if (event->data[0]) {
+		iwmbt_debug("Bad status: : status=%02x", event->data[0]);
+		return -1;
+	}
+	memcpy(tlv, event->data, transferred);
+
+	return (0);
+}
+
 int
 iwmbt_get_boot_params(struct libusb_device_handle *hdl,
     struct iwmbt_boot_params *params)
@@ -495,7 +546,7 @@
 }
 
 int
-iwmbt_intel_reset(struct libusb_device_handle *hdl, uint32_t boot_param)
+iwmbt_intel_reset(struct libusb_device_handle *hdl, uint32_t boot_param, bool hard)
 {
 	int ret, transferred = 0;
 	struct iwmbt_hci_event *event;
@@ -504,6 +555,17 @@
 		.length = 8,
 		.data = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 },
 	};
+	if (hard) {
+		cmd.data[0] = 0x01;
+		cmd.data[1] = 0x01;
+		cmd.data[2] = 0x01;
+		cmd.data[3] = 0x00;
+	} else {
+		cmd.data[0] = 0x00;
+		cmd.data[1] = 0x00;
+		cmd.data[2] = 0x00;
+		cmd.data[3] = 0x01;
+	}
 	uint8_t buf[IWMBT_HCI_MAX_EVENT_SIZE];
 
 	le32enc(cmd.data + 4, boot_param);
@@ -514,20 +576,30 @@
 	    buf,
 	    sizeof(buf),
 	    &transferred,
-	    IWMBT_HCI_CMD_TIMEOUT);
+	    IWMBT_LOADCMPL_TIMEOUT);
 
-	if (ret < 0 || transferred < (int)sizeof(struct iwmbt_hci_event) + 1) {
-		 iwmbt_debug("Intel Reset command failed: code=%d, size=%d",
-		    ret,
-		    transferred);
-		 return (ret);
-	}
+	if (hard) {
+		if (ret < 0) {
+			iwmbt_debug("Intel Hard Reset command failed: code=%d, size=%d",
+			    ret,
+			    transferred);
+			return (ret);
+		}
+		usleep(150000);
+	} else {
+		if (ret < 0 || transferred < (int)sizeof(struct iwmbt_hci_event) + 1) {
+			 iwmbt_debug("Intel Reset command failed: code=%d, size=%d",
+			    ret,
+			    transferred);
+			 return (ret);
+		}
 
-	/* expect Vendor Specific Event 0x02 */
-	event = (struct iwmbt_hci_event *)buf;
-	if (event->header.event != 0xFF || event->data[0] != 0x02) {
-		iwmbt_err("Intel Reset completion event missed");
-		return (-1);
+		/* expect Vendor Specific Event 0x02 */
+		event = (struct iwmbt_hci_event *)buf;
+		if (event->header.event != 0xFF || event->data[0] != 0x02) {
+			iwmbt_err("Intel Reset completion event missed.  event: %02x, data[0]: %02x", event->header.event, event->data[0]);
+			return (-1);
+		}
 	}
 
 	return (0);
diff --git a/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf b/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf
--- a/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf
+++ b/usr.sbin/bluetooth/iwmbtfw/iwmbtfw.conf
@@ -6,6 +6,6 @@
 	match "subsystem"	"DEVICE";
 	match "type"		"ATTACH";
 	match "vendor"		"0x8087";
-	match "product"		"(0x07dc|0x0a2a|0x0aa7|0x0a2b|0x0aaa|0x0025|0x0026|0x0029)";
+	match "product"		"(0x07dc|0x0a2a|0x0aa7|0x0a2b|0x0aaa|0x0025|0x0026|0x0029|0x0032)";
 	action "/usr/sbin/iwmbtfw -d $cdev -f /usr/local/share/iwmbt-firmware";
 };
diff --git a/usr.sbin/bluetooth/iwmbtfw/main.c b/usr.sbin/bluetooth/iwmbtfw/main.c
--- a/usr.sbin/bluetooth/iwmbtfw/main.c
+++ b/usr.sbin/bluetooth/iwmbtfw/main.c
@@ -34,6 +34,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <libgen.h>
+#include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -73,6 +74,12 @@
 	{ .vendor_id = 0x8087, .product_id = 0x0029 },
 };
 
+static struct iwmbt_devid iwmbt_list_tlv[] = {
+
+	{ .vendor_id = 0x8087, .product_id = 0x0032 },
+
+};
+
 static int
 iwmbt_is_7260(struct libusb_device_descriptor *d)
 {
@@ -109,9 +116,33 @@
 	return (0);
 }
 
+static int
+iwmbt_is_tlv(struct libusb_device_descriptor *d)
+{
+	int i;
+
+	/* Search looking for whether it's a TLV device (ie: AX210) */
+	for (i = 0; i < (int) nitems(iwmbt_list_tlv); i++) {
+		if ((iwmbt_list_tlv[i].product_id == d->idProduct) &&
+		    (iwmbt_list_tlv[i].vendor_id == d->idVendor)) {
+			iwmbt_info("found TLV");
+			return (1);
+		}
+	}
+
+	/* Not found */
+	return (0);
+}
+
+enum use_method {
+	IWMBT_METHOD_OLD,
+	IWMBT_METHOD_8260,
+	IWMBT_METHOD_TLV,
+};
+
 static libusb_device *
 iwmbt_find_device(libusb_context *ctx, int bus_id, int dev_id,
-    int *iwmbt_use_old_method)
+    enum use_method *iwmbt_use_method)
 {
 	libusb_device **list, *dev = NULL, *found = NULL;
 	struct libusb_device_descriptor d;
@@ -146,7 +177,7 @@
 				 * Take a reference so it's not freed later on.
 				 */
 				found = libusb_ref_device(dev);
-				*iwmbt_use_old_method = 1;
+				*iwmbt_use_method = IWMBT_METHOD_OLD;
 				break;
 			} else
 			if (iwmbt_is_8260(&d)) {
@@ -154,7 +185,15 @@
 				 * Take a reference so it's not freed later on.
 				 */
 				found = libusb_ref_device(dev);
-				*iwmbt_use_old_method = 0;
+				*iwmbt_use_method = IWMBT_METHOD_8260;
+				break;
+			} else
+			if (iwmbt_is_tlv(&d)) {
+				/*
+				 * Take a reference so it's not freed later on.
+				 */
+				found = libusb_ref_device(dev);
+				*iwmbt_use_method = IWMBT_METHOD_TLV;
 				break;
 			}
 		}
@@ -200,6 +239,117 @@
 	    params->otp_bdaddr[0]);
 }
 
+static int
+iwmbt_tlv_foreach(struct iwmbt_tlv *tlv, int (*cb)(struct iwmbt_tlv_field *, void *), void *cbdata)
+{
+	struct iwmbt_tlv_field *f;
+	size_t pos = 0;
+	int rc;
+
+	while ((pos + 2) < tlv->tlv_len) {
+		f = (struct iwmbt_tlv_field *) &tlv->tlv_data[pos];
+		if (pos + f->len >= tlv->tlv_len)
+			break;
+		rc = cb(f, cbdata);
+		if (rc)
+			return rc;
+		pos += offsetof(struct iwmbt_tlv_field, val);
+		pos += f->len;
+	}
+	return 0;
+}
+
+static int
+iwmbt_dump_one_tlv(struct iwmbt_tlv_field *f, void *cbdata __unused)
+{
+	uint32_t tmp;
+
+	switch (f->len) {
+		case 1:
+			iwmbt_info("TLV: 0x%02x = 0x%02x", f->type, f->val[0]);
+			break;
+		case 2:
+			memcpy(&tmp, f->val, f->len);
+			iwmbt_info("TLV: 0x%02x = 0x%04x", f->type, le16toh(*(uint16_t *)&tmp));
+			break;
+		case 4:
+			memcpy(&tmp, f->val, f->len);
+			iwmbt_info("TLV: 0x%02x = 0x%08x", f->type, le32toh(*(uint16_t *)&tmp));
+			break;
+		default:
+			iwmbt_info("TLV: 0x%02x has unhandled length of %d", f->type, f->len);
+			break;
+	}
+	return 0;
+}
+
+static void
+iwmbt_dump_tlv(struct iwmbt_tlv *tlv)
+{
+	iwmbt_tlv_foreach(tlv, iwmbt_dump_one_tlv, NULL);
+}
+
+static int
+iwmbt_parse_one_tlv(struct iwmbt_tlv_field *f, void *cbdata)
+{
+	struct iwmbt_parsed_tlv *parsed = cbdata;
+
+	switch (f->type) {
+		case 0x10:
+			if (f->len != sizeof(parsed->fn_first)) {
+				iwmbt_err("Invalid fn_first length %d (expected %zu)", f->len, sizeof(parsed->fn_first));
+				return -1;
+			}
+			memcpy(&parsed->fn_first, f->val, f->len);
+			parsed->parse_state |= 1;
+			break;
+		case 0x11:
+			if (f->len != sizeof(parsed->fn_second)) {
+				iwmbt_err("Invalid fn_second length %d (expected %zu)", f->len, sizeof(parsed->fn_second));
+				return -1;
+			}
+			memcpy(&parsed->fn_second, f->val, f->len);
+			parsed->parse_state |= 2;
+			break;
+		case 0x12:
+			if (f->len != sizeof(parsed->hw_version)) {
+				iwmbt_err("Invalid hw_version length %d (expected %zu)", f->len, sizeof(parsed->fn_second));
+				return -1;
+			}
+			memcpy(&parsed->hw_version, f->val, f->len);
+			parsed->parse_state |= 4;
+			break;
+		case 0x1e:
+			if (f->len != sizeof(parsed->running)) {
+				iwmbt_err("Invalid running length %d (expected %zu)", f->len, sizeof(parsed->fn_second));
+				return -1;
+			}
+			memcpy(&parsed->running, f->val, f->len);
+			parsed->parse_state |= 8;
+			break;
+		case 0x2f:
+			if (f->len != sizeof(parsed->sigtype)) {
+				iwmbt_err("Invalid sigtype length %d (expected %zu)", f->len, sizeof(parsed->fn_second));
+				return -1;
+			}
+			memcpy(&parsed->sigtype, f->val, f->len);
+			parsed->parse_state |= 16;
+			break;
+	}
+	return 0;
+}
+
+static int
+iwmbt_parse_tlv(struct iwmbt_tlv *tlv, struct iwmbt_parsed_tlv *parsed)
+{
+	parsed->parse_state = 0;
+	if (iwmbt_tlv_foreach(tlv, iwmbt_parse_one_tlv, parsed))
+		return -1;
+	if (parsed->parse_state != 31)
+		return -1;
+	return 0;
+}
+
 static int
 iwmbt_patch_firmware(libusb_device_handle *hdl, const char *firmware_path)
 {
@@ -227,7 +377,7 @@
 
 static int
 iwmbt_init_firmware(libusb_device_handle *hdl, const char *firmware_path,
-    uint32_t *boot_param)
+    uint32_t *boot_param, bool is_tlv, uint8_t sigtype)
 {
 	struct iwmbt_firmware fw;
 	int ret;
@@ -241,7 +391,7 @@
 	}
 
 	/* Load in the firmware */
-	ret = iwmbt_load_fwfile(hdl, &fw, boot_param);
+	ret = iwmbt_load_fwfile(hdl, &fw, boot_param, is_tlv, sigtype);
 	if (ret < 0)
 		iwmbt_debug("Loading firmware file failed");
 
@@ -317,6 +467,8 @@
 	libusb_context *ctx = NULL;
 	libusb_device *dev = NULL;
 	libusb_device_handle *hdl = NULL;
+	struct iwmbt_tlv tlv;
+	struct iwmbt_parsed_tlv ptlv;
 	static struct iwmbt_version ver;
 	static struct iwmbt_boot_params params;
 	uint32_t boot_param;
@@ -327,7 +479,7 @@
 	char *firmware_dir = NULL;
 	char *firmware_path = NULL;
 	int retcode = 1;
-	int iwmbt_use_old_method = 0;
+	enum use_method iwmbt_use_method = IWMBT_METHOD_8260;
 
 	/* Parse command line arguments */
 	while ((n = getopt(argc, argv, "Dd:f:hIm:p:v:")) != -1) {
@@ -372,7 +524,7 @@
 	iwmbt_debug("opening dev %d.%d", (int) bus_id, (int) dev_id);
 
 	/* Find a device based on the bus/dev id */
-	dev = iwmbt_find_device(ctx, bus_id, dev_id, &iwmbt_use_old_method);
+	dev = iwmbt_find_device(ctx, bus_id, dev_id, &iwmbt_use_method);
 	if (dev == NULL) {
 		iwmbt_err("device not found");
 		goto shutdown;
@@ -402,15 +554,29 @@
 	}
 
 	/* Get Intel version */
-	r = iwmbt_get_version(hdl, &ver);
+	if (iwmbt_use_method == IWMBT_METHOD_TLV)
+		r = iwmbt_get_tlv(hdl, &tlv);
+	else
+		r = iwmbt_get_version(hdl, &ver);
 	if (r < 0) {
 		iwmbt_debug("iwmbt_get_version() failed code %d", r);
 		goto shutdown;
 	}
+
+	/* Parse TLV and extract ver stuff from it */
+	if (iwmbt_use_method == IWMBT_METHOD_TLV) {
+		/* TODO: Parse in get? */
+		iwmbt_dump_tlv(&tlv);
+		if (iwmbt_parse_tlv(&tlv, &ptlv))
+			goto shutdown;
+		ver.hw_platform = (ptlv.hw_version & 0x0000ff00) >> 8;
+		ver.hw_variant = (ptlv.hw_version & 0x003f0000) >> 16;
+	}
+
 	iwmbt_dump_version(&ver);
 	iwmbt_debug("fw_variant=0x%02x", (int) ver.fw_variant);
 
-	if (iwmbt_use_old_method) {
+	if (iwmbt_use_method == IWMBT_METHOD_OLD) {
 
 		/* fw_patch_num = >0 operational mode */
 		if (ver.fw_patch_num > 0x00) {
@@ -469,7 +635,8 @@
 			iwmbt_info("Intel Event Mask is set");
 		(void)iwmbt_exit_manufacturer(hdl, 0x00);
 
-	} else {
+	} else
+	if (iwmbt_use_method == IWMBT_METHOD_8260) {
 
 		/* fw_variant = 0x06 bootloader mode / 0x23 operational mode */
 		if (ver.fw_variant == 0x23) {
@@ -509,14 +676,14 @@
 		iwmbt_debug("firmware_path = %s", firmware_path);
 
 		/* Download firmware and parse it for magic Intel Reset parameter */
-		r = iwmbt_init_firmware(hdl, firmware_path, &boot_param);
+		r = iwmbt_init_firmware(hdl, firmware_path, &boot_param, false, 0);
 		free(firmware_path);
 		if (r < 0)
 			goto shutdown;
 
 		iwmbt_info("Firmware download complete");
 
-		r = iwmbt_intel_reset(hdl, boot_param);
+		r = iwmbt_intel_reset(hdl, boot_param, false);
 		if (r < 0) {
 			iwmbt_debug("iwmbt_intel_reset() failed!");
 			goto shutdown;
@@ -542,6 +709,67 @@
 			free(firmware_path);
 		}
 
+		/* Set Intel Event mask */
+		r = iwmbt_set_event_mask(hdl);
+		if (r == 0)
+			iwmbt_info("Intel Event Mask is set");
+	} else {
+
+		switch (ver.hw_variant) {
+			case 0x17:
+				break;
+			default:
+				iwmbt_err("unknown hw_variant 0x%02x", (int) ver.hw_variant);
+				goto shutdown;
+		}
+
+		if (ptlv.running != 0x01) {
+			/* Reset to bootloader */
+			// TODO: Possibly always exit here... to reset:
+			r = iwmbt_intel_reset(hdl, 0, true);
+			if (r < 0) {
+				iwmbt_debug("iwmbt_intel_reset() failed!");
+				goto shutdown;
+			}
+		}
+
+		firmware_path = iwmbt_get_fwname_tlv(firmware_dir, &ptlv, "sfi");
+		iwmbt_debug("firmware_path = %s", firmware_path);
+
+		/* Download firmware and parse it for magic Intel Reset parameter */
+		r = iwmbt_init_firmware(hdl, firmware_path, &boot_param, true, ptlv.sigtype);
+		free(firmware_path);
+		if (r < 0)
+			goto shutdown;
+
+		iwmbt_info("Firmware download complete");
+
+		r = iwmbt_intel_reset(hdl, boot_param, false);
+		if (r < 0) {
+			iwmbt_debug("iwmbt_intel_reset() failed!");
+			goto shutdown;
+		}
+
+		iwmbt_info("Firmware operational");
+
+		/* Once device is running in operational mode we can ignore failures */
+		retcode = 0;
+
+		/* Execute Read Intel Version one more time */
+		r = iwmbt_get_version(hdl, &ver);
+		if (r == 0)
+			iwmbt_dump_version(&ver);
+
+		/* Apply the device configuration (DDC) parameters */
+		firmware_path = iwmbt_get_fwname_tlv(firmware_dir, &ptlv, "ddc");
+		iwmbt_debug("ddc_path = %s", firmware_path);
+		if (firmware_path != NULL) {
+			r = iwmbt_init_ddc(hdl, firmware_path);
+			if (r == 0)
+				iwmbt_info("DDC download complete");
+			free(firmware_path);
+		}
+
 		/* Set Intel Event mask */
 		r = iwmbt_set_event_mask(hdl);
 		if (r == 0)