git: 529177b332dc - main - thunderbolt: Get NHI version number from caps

From: Aymeric Wibo <obiwac_at_FreeBSD.org>
Date: Wed, 12 Aug 2026 21:53:28 UTC
The branch main has been updated by obiwac:

URL: https://cgit.FreeBSD.org/src/commit/?id=529177b332dc4ba29d261ab7d2eec796d274b345

commit 529177b332dc4ba29d261ab7d2eec796d274b345
Author:     Aymeric Wibo <obiwac@FreeBSD.org>
AuthorDate: 2026-08-12 17:39:17 +0000
Commit:     Aymeric Wibo <obiwac@FreeBSD.org>
CommitDate: 2026-08-12 21:51:18 +0000

    thunderbolt: Get NHI version number from caps
    
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D49452
---
 sys/dev/thunderbolt/nhi.c     | 29 +++++++++++++++++++++--------
 sys/dev/thunderbolt/nhi_reg.h | 10 +++++++++-
 sys/dev/thunderbolt/nhi_var.h |  5 +++++
 3 files changed, 35 insertions(+), 9 deletions(-)

diff --git a/sys/dev/thunderbolt/nhi.c b/sys/dev/thunderbolt/nhi.c
index a79d604bdf47..4b45560923c3 100644
--- a/sys/dev/thunderbolt/nhi.c
+++ b/sys/dev/thunderbolt/nhi.c
@@ -238,8 +238,9 @@ nhi_outmail_cmd(struct nhi_softc *sc, uint32_t *val)
 int
 nhi_attach(struct nhi_softc *sc)
 {
-	uint32_t val;
-	int error = 0;
+	uint32_t		val;
+	struct nhi_host_caps	caps;
+	int			error = 0;
 
 	if ((error = nhi_setup_sysctl(sc)) != 0)
 		return (error);
@@ -247,13 +248,25 @@ nhi_attach(struct nhi_softc *sc)
 	mtx_init(&sc->nhi_mtx, "nhimtx", "NHI Control Mutex", MTX_DEF);
 
 	/*
-	 * Get the number of TX/RX paths.  This sizes some of the register
-	 * arrays during allocation and initialization.  USB4 spec says that
-	 * the max is 21.
+	 * Get the host interface version and number of TX/RX paths.  This
+	 * sizes some of the register arrays during allocation and
+	 * initialization.  USB4 spec says that the max is 21.
 	 */
-	val = GET_HOST_CAPS_PATHS(nhi_read_reg(sc, NHI_HOST_CAPS));
-	tb_debug(sc, DBG_INIT|DBG_NOISY, "Total Paths= %d\n", val);
-	if (val == 0 || val > 21) {
+	val = nhi_read_reg(sc, NHI_HOST_CAPS);
+	caps = *(struct nhi_host_caps *)&val;
+	if (caps.version_major == 0 && caps.version_minor == 0) {
+		tb_printf(sc, "Host interface is version 1.0\n");
+		sc->ver = NHI_VER_1_0;
+	} else if (caps.version_major == 2 && caps.version_minor == 0) {
+		tb_printf(sc, "Host interface is version 2.0\n");
+		sc->ver = NHI_VER_2_0;
+	} else {
+		tb_printf(sc, "WARN: unexpected host interface version %d.%d -"
+		    " assuming 1.0\n", caps.version_major, caps.version_minor);
+		sc->ver = NHI_VER_1_0;
+	}
+	tb_debug(sc, DBG_INIT|DBG_NOISY, "Total Paths= %d\n", caps.total_paths);
+	if (caps.total_paths == 0 || caps.total_paths > 21) {
 		tb_printf(sc, "WARN: unexpected number of paths: %d\n", val);
 		/* return (ENXIO); */
 	}
diff --git a/sys/dev/thunderbolt/nhi_reg.h b/sys/dev/thunderbolt/nhi_reg.h
index 6e71f4c9646b..6db84aa4a507 100644
--- a/sys/dev/thunderbolt/nhi_reg.h
+++ b/sys/dev/thunderbolt/nhi_reg.h
@@ -176,7 +176,15 @@
 
 /* Native Host Interface Control registers */
 #define NHI_HOST_CAPS			0x39640
-#define	GET_HOST_CAPS_PATHS(val)	((val) & 0x3f)
+
+/* Host Interface Capabilities, 12.6.3.1.1 */
+struct nhi_host_caps {
+	uint32_t	total_paths:11;
+	uint8_t		reserved1:5;
+	uint8_t		version_major:3;
+	uint8_t		version_minor:5;
+	uint8_t		reserved0:8;
+} __packed;
 
 /*
  * This definition comes from the Linux driver.  In the USB4 spec, this
diff --git a/sys/dev/thunderbolt/nhi_var.h b/sys/dev/thunderbolt/nhi_var.h
index e22c0f4a2bae..d4efaa1d46ad 100644
--- a/sys/dev/thunderbolt/nhi_var.h
+++ b/sys/dev/thunderbolt/nhi_var.h
@@ -186,6 +186,11 @@ struct nhi_softc {
 
 	uint8_t			uuid[16];
 	uint8_t			lc_uuid[16];
+
+	enum {
+		NHI_VER_1_0,
+		NHI_VER_2_0,
+	}			ver;
 };
 
 struct nhi_dispatch {