Skip to content

Commit 4a4d4e3

Browse files
Joel FernandesDanilo Krummrich
authored andcommitted
gpu: nova-core: Add code comments related to devinit
Add several code comments to reduce acronym soup and explain how devinit magic and bootflow works before driver loads. These are essential for debug and development of the nova driver. [[email protected]: reformat and reword a couple of sentences] Signed-off-by: Joel Fernandes <[email protected]> Signed-off-by: Alexandre Courbot <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Danilo Krummrich <[email protected]>
1 parent 4092e1b commit 4a4d4e3

File tree

2 files changed

+48
-7
lines changed

2 files changed

+48
-7
lines changed

drivers/gpu/nova-core/gfw.rs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
// SPDX-License-Identifier: GPL-2.0
22

3-
//! GPU Firmware (GFW) support.
3+
//! GPU Firmware (`GFW`) support, a.k.a `devinit`.
44
//!
55
//! Upon reset, the GPU runs some firmware code from the BIOS to setup its core parameters. Most of
66
//! the GPU is considered unusable until this step is completed, so we must wait on it before
77
//! performing driver initialization.
8+
//!
9+
//! A clarification about devinit terminology: devinit is a sequence of register read/writes after
10+
//! reset that performs tasks such as:
11+
//! 1. Programming VRAM memory controller timings.
12+
//! 2. Power sequencing.
13+
//! 3. Clock and PLL configuration.
14+
//! 4. Thermal management.
15+
//!
16+
//! devinit itself is a 'script' which is interpreted by an interpreter program typically running
17+
//! on the PMU microcontroller.
18+
//!
19+
//! Note that the devinit sequence also needs to run during suspend/resume.
820
921
use kernel::bindings;
1022
use kernel::prelude::*;
@@ -14,13 +26,32 @@ use crate::driver::Bar0;
1426
use crate::regs;
1527
use crate::util;
1628

17-
/// Wait until `GFW` (GPU Firmware) completes, or a 4 seconds timeout elapses.
29+
/// Wait for the `GFW` (GPU firmware) boot completion signal (`GFW_BOOT`), or a 4 seconds timeout.
30+
///
31+
/// Upon GPU reset, several microcontrollers (such as PMU, SEC2, GSP etc) run some firmware code to
32+
/// setup its core parameters. Most of the GPU is considered unusable until this step is completed,
33+
/// so it must be waited on very early during driver initialization.
34+
///
35+
/// The `GFW` code includes several components that need to execute before the driver loads. These
36+
/// components are located in the VBIOS ROM and executed in a sequence on these different
37+
/// microcontrollers. The devinit sequence typically runs on the PMU, and the FWSEC runs on the
38+
/// GSP.
39+
///
40+
/// This function waits for a signal indicating that core initialization is complete. Before this
41+
/// signal is received, little can be done with the GPU. This signal is set by the FWSEC running on
42+
/// the GSP in Heavy-secured mode.
1843
pub(crate) fn wait_gfw_boot_completion(bar: &Bar0) -> Result {
44+
// Before accessing the completion status in `NV_PGC6_AON_SECURE_SCRATCH_GROUP_05`, we must
45+
// first check `NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK`. This is because
46+
// `NV_PGC6_AON_SECURE_SCRATCH_GROUP_05` becomes accessible only after the secure firmware
47+
// (FWSEC) lowers the privilege level to allow CPU (LS/Light-secured) access. We can only
48+
// safely read the status register from CPU (LS/Light-secured) once the mask indicates
49+
// that the privilege level has been lowered.
50+
//
1951
// TIMEOUT: arbitrarily large value. GFW starts running immediately after the GPU is put out of
2052
// reset, and should complete in less time than that.
2153
util::wait_on(Delta::from_secs(4), || {
22-
// Check that FWSEC has lowered its protection level before reading the GFW_BOOT
23-
// status.
54+
// Check that FWSEC has lowered its protection level before reading the GFW_BOOT status.
2455
let gfw_booted = regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK::read(bar)
2556
.read_protection_level0()
2657
&& regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT::read(bar).completed();

drivers/gpu/nova-core/regs.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,19 @@ impl NV_PFB_PRI_MMU_WPR2_ADDR_HI {
104104
}
105105
}
106106

107-
/* PGC6 */
108-
109-
register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK @ 0x00118128 {
107+
// PGC6 register space.
108+
//
109+
// `GC6` is a GPU low-power state where VRAM is in self-refresh and the GPU is powered down (except
110+
// for power rails needed to keep self-refresh working and important registers and hardware
111+
// blocks).
112+
//
113+
// These scratch registers remain powered on even in a low-power state and have a designated group
114+
// number.
115+
116+
// Privilege level mask register. It dictates whether the host CPU has privilege to access the
117+
// `PGC6_AON_SECURE_SCRATCH_GROUP_05` register (which it needs to read GFW_BOOT).
118+
register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK @ 0x00118128,
119+
"Privilege level mask register" {
110120
0:0 read_protection_level0 as bool, "Set after FWSEC lowers its protection level";
111121
});
112122

0 commit comments

Comments
 (0)