[PATCH v11 12/22] gpu: nova-core: Hopper/Blackwell: add FSP secure boot completion waiting
From: John Hubbard
Date: Fri May 29 2026 - 23:15:37 EST
Hopper and Blackwell use FSP instead of SEC2 for secure boot. The
driver must wait for FSP secure boot to complete before continuing
with GSP bring-up. Poll for boot success with a 5-second timeout.
Co-developed-by: Alexandre Courbot <acourbot@xxxxxxxxxx>
Signed-off-by: Alexandre Courbot <acourbot@xxxxxxxxxx>
Signed-off-by: John Hubbard <jhubbard@xxxxxxxxxx>
---
drivers/gpu/nova-core/fsp.rs | 51 ++++++++++++++++++++++++++
drivers/gpu/nova-core/fsp/hal.rs | 27 ++++++++++++++
drivers/gpu/nova-core/fsp/hal/gb202.rs | 23 ++++++++++++
drivers/gpu/nova-core/fsp/hal/gh100.rs | 23 ++++++++++++
drivers/gpu/nova-core/gsp/hal/gh100.rs | 5 ++-
drivers/gpu/nova-core/nova_core.rs | 1 +
drivers/gpu/nova-core/regs.rs | 36 ++++++++++++++++++
7 files changed, 165 insertions(+), 1 deletion(-)
create mode 100644 drivers/gpu/nova-core/fsp.rs
create mode 100644 drivers/gpu/nova-core/fsp/hal.rs
create mode 100644 drivers/gpu/nova-core/fsp/hal/gb202.rs
create mode 100644 drivers/gpu/nova-core/fsp/hal/gh100.rs
diff --git a/drivers/gpu/nova-core/fsp.rs b/drivers/gpu/nova-core/fsp.rs
new file mode 100644
index 000000000000..ee8fc384fe38
--- /dev/null
+++ b/drivers/gpu/nova-core/fsp.rs
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+//! FSP (Firmware System Processor) interface for Hopper/Blackwell GPUs.
+//!
+//! Hopper/Blackwell use a simplified firmware boot sequence: FMC, then FSP, then GSP.
+//! Unlike Turing/Ampere/Ada, there is no SEC2 (Security Engine 2) usage.
+//! FSP handles secure boot directly using FMC firmware and Chain of Trust.
+
+use kernel::{
+ device,
+ io::poll::read_poll_timeout,
+ prelude::*,
+ time::Delta, //
+};
+
+use crate::{
+ driver::Bar0,
+ gpu::Chipset,
+ regs, //
+};
+
+mod hal;
+
+/// FSP interface for Hopper/Blackwell GPUs.
+pub(crate) struct Fsp;
+
+impl Fsp {
+ /// Wait for FSP secure boot completion.
+ ///
+ /// Polls the thermal scratch register until FSP signals boot completion
+ /// or timeout occurs.
+ pub(crate) fn wait_secure_boot(dev: &device::Device, bar: &Bar0, chipset: Chipset) -> Result {
+ /// FSP secure boot completion timeout in milliseconds.
+ const FSP_SECURE_BOOT_TIMEOUT_MS: i64 = 5000;
+
+ let hal = hal::fsp_hal(chipset).ok_or(ENOTSUPP)?;
+
+ read_poll_timeout(
+ || Ok(hal.fsp_boot_status(bar)),
+ |&status| status == regs::NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE_STATUS_SUCCESS,
+ Delta::from_millis(10),
+ Delta::from_millis(FSP_SECURE_BOOT_TIMEOUT_MS),
+ )
+ .map_err(|_| {
+ dev_err!(dev, "FSP secure boot completion timeout\n");
+ ETIMEDOUT
+ })
+ .map(|_| ())
+ }
+}
diff --git a/drivers/gpu/nova-core/fsp/hal.rs b/drivers/gpu/nova-core/fsp/hal.rs
new file mode 100644
index 000000000000..83d1e7daa998
--- /dev/null
+++ b/drivers/gpu/nova-core/fsp/hal.rs
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+use crate::{
+ driver::Bar0,
+ gpu::{
+ Architecture,
+ Chipset, //
+ },
+};
+
+mod gb202;
+mod gh100;
+
+pub(super) trait FspHal {
+ /// Returns the secure boot status from the architecture-specific `NV_THERM_I2CS_SCRATCH` register.
+ fn fsp_boot_status(&self, bar: &Bar0) -> u32;
+}
+
+/// Returns the FSP HAL, or `None` if the architecture doesn't support FSP.
+pub(crate) fn fsp_hal(chipset: Chipset) -> Option<&'static dyn FspHal> {
+ match chipset.arch() {
+ Architecture::Turing | Architecture::Ampere | Architecture::Ada => None,
+ Architecture::Hopper | Architecture::BlackwellGB10x => Some(gh100::GH100_HAL),
+ Architecture::BlackwellGB20x => Some(gb202::GB202_HAL),
+ }
+}
diff --git a/drivers/gpu/nova-core/fsp/hal/gb202.rs b/drivers/gpu/nova-core/fsp/hal/gb202.rs
new file mode 100644
index 000000000000..2f08b6c9f308
--- /dev/null
+++ b/drivers/gpu/nova-core/fsp/hal/gb202.rs
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+use kernel::io::Io;
+
+use crate::{
+ driver::Bar0,
+ fsp::hal::FspHal,
+ regs, //
+};
+
+struct Gb202;
+
+impl FspHal for Gb202 {
+ fn fsp_boot_status(&self, bar: &Bar0) -> u32 {
+ bar.read(regs::gb202::NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE)
+ .fsp_boot_complete()
+ .into()
+ }
+}
+
+const GB202: Gb202 = Gb202;
+pub(super) const GB202_HAL: &dyn FspHal = &GB202;
diff --git a/drivers/gpu/nova-core/fsp/hal/gh100.rs b/drivers/gpu/nova-core/fsp/hal/gh100.rs
new file mode 100644
index 000000000000..290fb55a81da
--- /dev/null
+++ b/drivers/gpu/nova-core/fsp/hal/gh100.rs
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+use kernel::io::Io;
+
+use crate::{
+ driver::Bar0,
+ fsp::hal::FspHal,
+ regs, //
+};
+
+struct Gh100;
+
+impl FspHal for Gh100 {
+ fn fsp_boot_status(&self, bar: &Bar0) -> u32 {
+ bar.read(regs::gh100::NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE)
+ .fsp_boot_complete()
+ .into()
+ }
+}
+
+const GH100: Gh100 = Gh100;
+pub(super) const GH100_HAL: &dyn FspHal = &GH100;
diff --git a/drivers/gpu/nova-core/gsp/hal/gh100.rs b/drivers/gpu/nova-core/gsp/hal/gh100.rs
index c38d88bc42b0..151df05e303b 100644
--- a/drivers/gpu/nova-core/gsp/hal/gh100.rs
+++ b/drivers/gpu/nova-core/gsp/hal/gh100.rs
@@ -21,6 +21,7 @@
fsp::FspFirmware,
FIRMWARE_VERSION, //
},
+ fsp::Fsp,
gpu::Chipset,
gsp::{
boot::BootUnloadGuard,
@@ -41,7 +42,7 @@ fn boot<'a>(
&self,
_gsp: &'a Gsp,
dev: &'a device::Device<device::Bound>,
- _bar: &'a Bar0,
+ bar: &'a Bar0,
chipset: Chipset,
_fb_layout: &FbLayout,
_wpr_meta: &Coherent<GspFwWprMeta>,
@@ -51,6 +52,8 @@ fn boot<'a>(
let _fsp_falcon = Falcon::<FspEngine>::new(dev, chipset)?;
let _fsp_fw = FspFirmware::new(dev, chipset, FIRMWARE_VERSION)?;
+ Fsp::wait_secure_boot(dev, bar, chipset)?;
+
Err(ENOTSUPP)
}
}
diff --git a/drivers/gpu/nova-core/nova_core.rs b/drivers/gpu/nova-core/nova_core.rs
index 5a260062295f..7b6c331da10e 100644
--- a/drivers/gpu/nova-core/nova_core.rs
+++ b/drivers/gpu/nova-core/nova_core.rs
@@ -17,6 +17,7 @@
mod falcon;
mod fb;
mod firmware;
+mod fsp;
mod gpu;
mod gsp;
#[macro_use]
diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs
index 65be6ec71ed4..270779d31ab3 100644
--- a/drivers/gpu/nova-core/regs.rs
+++ b/drivers/gpu/nova-core/regs.rs
@@ -579,3 +579,39 @@ pub(crate) mod ga100 {
}
}
}
+
+pub(crate) const NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE_STATUS_SUCCESS: u32 = 0xff;
+
+pub(crate) mod gh100 {
+ use kernel::io::register;
+
+ // PTHERM
+
+ register! {
+ pub(crate) NV_THERM_I2CS_SCRATCH(u32) @ 0x000200bc {
+ 31:0 data;
+ }
+
+ // Alias to `NV_THERM_I2CS_SCRATCH` when used to check for FSP boot completion.
+ pub(crate) NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE(u32) => NV_THERM_I2CS_SCRATCH {
+ 31:0 fsp_boot_complete;
+ }
+ }
+}
+
+pub(crate) mod gb202 {
+ use kernel::io::register;
+
+ // PTHERM
+
+ register! {
+ pub(crate) NV_THERM_I2CS_SCRATCH(u32) @ 0x00ad00bc {
+ 31:0 data;
+ }
+
+ // Alias to `NV_THERM_I2CS_SCRATCH` when used to check for FSP boot completion.
+ pub(crate) NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE(u32) => NV_THERM_I2CS_SCRATCH {
+ 31:0 fsp_boot_complete;
+ }
+ }
+}
--
2.54.0