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