xref: /linux/drivers/gpu/nova-core/gfw.rs (revision 3606620b316c29e3de8ff87b40828c722086a9c9)
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[DLAY]: replace with [1] once it merges.
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 }
42