Skip to content

Commit bbe5db7

Browse files
GnurouDanilo Krummrich
authored andcommitted
gpu: nova-core: wait for GFW_BOOT completion
Upon reset, the GPU executes the GFW (GPU Firmware) in order to initialize its base parameters such as clocks. The driver must ensure that this step is completed before using the hardware. Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> Link: https://lore.kernel.org/r/20250619-nova-frts-v6-12-ecf41ef99252@nvidia.com [ Slightly adjust comments in wait_gfw_boot_completion(). - Danilo ] Signed-off-by: Danilo Krummrich <dakr@kernel.org>
1 parent a03c9bd commit bbe5db7

5 files changed

Lines changed: 72 additions & 1 deletion

File tree

drivers/gpu/nova-core/gfw.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! GPU Firmware (GFW) support.
4+
//!
5+
//! Upon reset, the GPU runs some firmware code from the BIOS to setup its core parameters. Most of
6+
//! the GPU is considered unusable until this step is completed, so we must wait on it before
7+
//! performing driver initialization.
8+
9+
use core::time::Duration;
10+
11+
use kernel::bindings;
12+
use kernel::prelude::*;
13+
14+
use crate::driver::Bar0;
15+
use crate::regs;
16+
use crate::util;
17+
18+
/// Wait until `GFW` (GPU Firmware) completes, or a 4 seconds timeout elapses.
19+
pub(crate) fn wait_gfw_boot_completion(bar: &Bar0) -> Result {
20+
// TIMEOUT: arbitrarily large value. GFW starts running immediately after the GPU is put out of
21+
// reset, and should complete in less time than that.
22+
util::wait_on(Duration::from_secs(4), || {
23+
// Check that FWSEC has lowered its protection level before reading the GFW_BOOT
24+
// status.
25+
let gfw_booted = regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK::read(bar)
26+
.read_protection_level0()
27+
&& regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT::read(bar).completed();
28+
29+
if gfw_booted {
30+
Some(())
31+
} else {
32+
// TODO: replace with [1] once merged.
33+
// [1] https://lore.kernel.org/rust-for-linux/20250423192857.199712-6-fujita.tomonori@gmail.com/
34+
//
35+
// SAFETY: `msleep()` is safe to call with any parameter.
36+
unsafe { bindings::msleep(1) };
37+
38+
None
39+
}
40+
})
41+
}

drivers/gpu/nova-core/gpu.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use kernel::{device, devres::Devres, error::code::*, pci, prelude::*};
44

55
use crate::driver::Bar0;
66
use crate::firmware::{Firmware, FIRMWARE_VERSION};
7+
use crate::gfw;
78
use crate::regs;
89
use crate::util;
910
use core::fmt;
@@ -182,6 +183,10 @@ impl Gpu {
182183
spec.revision
183184
);
184185

186+
// We must wait for GFW_BOOT completion before doing any significant setup on the GPU.
187+
gfw::wait_gfw_boot_completion(bar)
188+
.inspect_err(|_| dev_err!(pdev.as_ref(), "GFW boot did not complete"))?;
189+
185190
Ok(pin_init!(Self {
186191
spec,
187192
bar: devres_bar,

drivers/gpu/nova-core/nova_core.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
55
mod driver;
66
mod firmware;
7+
mod gfw;
78
mod gpu;
89
mod regs;
910
mod util;

drivers/gpu/nova-core/regs.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,28 @@ impl NV_PMC_BOOT_0 {
3737
.and_then(Chipset::try_from)
3838
}
3939
}
40+
41+
/* PGC6 */
42+
43+
register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK @ 0x00118128 {
44+
0:0 read_protection_level0 as bool, "Set after FWSEC lowers its protection level";
45+
});
46+
47+
// TODO: This is an array of registers.
48+
register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_05 @ 0x00118234 {
49+
31:0 value as u32;
50+
});
51+
52+
register!(
53+
NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT => NV_PGC6_AON_SECURE_SCRATCH_GROUP_05,
54+
"Scratch group 05 register 0 used as GFW boot progress indicator" {
55+
7:0 progress as u8, "Progress of GFW boot (0xff means completed)";
56+
}
57+
);
58+
59+
impl NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT {
60+
/// Returns `true` if GFW boot is completed.
61+
pub(crate) fn completed(self) -> bool {
62+
self.progress() == 0xff
63+
}
64+
}

drivers/gpu/nova-core/util.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ pub(crate) const fn const_bytes_to_str(bytes: &[u8]) -> &str {
3434
///
3535
/// TODO: replace with `read_poll_timeout` once it is available.
3636
/// (https://lore.kernel.org/lkml/20250220070611.214262-8-fujita.tomonori@gmail.com/)
37-
#[expect(dead_code)]
3837
pub(crate) fn wait_on<R, F: Fn() -> Option<R>>(timeout: Duration, cond: F) -> Result<R> {
3938
let start_time = Instant::now();
4039

0 commit comments

Comments
 (0)