xref: /linux/drivers/gpu/nova-core/regs.rs (revision 71d4e7233f235871b13553e504e591ace6b54373)
1 // SPDX-License-Identifier: GPL-2.0
2 // SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 
4 use kernel::{
5     io::{
6         register,
7         register::WithBase,
8         Io, //
9     },
10     prelude::*,
11     sizes::SizeConstants,
12     time, //
13 };
14 
15 use crate::{
16     driver::Bar0,
17     falcon::{
18         DmaTrfCmdSize,
19         FalconCoreRev,
20         FalconCoreRevSubversion,
21         FalconEngine,
22         FalconFbifMemType,
23         FalconFbifTarget,
24         FalconMem,
25         FalconModSelAlgo,
26         FalconSecurityModel,
27         PFalcon2Base,
28         PFalconBase,
29         PeregrineCoreSelect, //
30     },
31     gpu::{
32         Architecture,
33         Chipset, //
34     },
35 };
36 
37 // PMC
38 
39 register! {
40     /// Basic revision information about the GPU.
41     pub(crate) NV_PMC_BOOT_0(u32) @ 0x00000000 {
42         /// Lower bits of the architecture.
43         28:24   architecture_0;
44         /// Implementation version of the architecture.
45         23:20   implementation;
46         /// MSB of the architecture.
47         8:8     architecture_1;
48         /// Major revision of the chip.
49         7:4     major_revision;
50         /// Minor revision of the chip.
51         3:0     minor_revision;
52     }
53 
54     /// Extended architecture information.
55     pub(crate) NV_PMC_BOOT_42(u32) @ 0x00000a00 {
56         /// Architecture value.
57         29:24   architecture ?=> Architecture;
58         /// Implementation version of the architecture.
59         23:20   implementation;
60         /// Major revision of the chip.
61         19:16   major_revision;
62         /// Minor revision of the chip.
63         15:12   minor_revision;
64     }
65 }
66 
67 impl NV_PMC_BOOT_0 {
68     pub(crate) fn is_older_than_fermi(self) -> bool {
69         // From https://github.com/NVIDIA/open-gpu-doc/tree/master/manuals :
70         const NV_PMC_BOOT_0_ARCHITECTURE_GF100: u32 = 0xc;
71 
72         // Older chips left arch1 zeroed out. That, combined with an arch0 value that is less than
73         // GF100, means "older than Fermi".
74         self.architecture_1() == 0 && self.architecture_0() < NV_PMC_BOOT_0_ARCHITECTURE_GF100
75     }
76 }
77 
78 impl NV_PMC_BOOT_42 {
79     /// Combines `architecture` and `implementation` to obtain a code unique to the chipset.
80     pub(crate) fn chipset(self) -> Result<Chipset> {
81         self.architecture()
82             .map(|arch| {
83                 ((arch as u32) << Self::IMPLEMENTATION_RANGE.len())
84                     | u32::from(self.implementation())
85             })
86             .and_then(Chipset::try_from)
87     }
88 
89     /// Returns the raw architecture value from the register.
90     fn architecture_raw(self) -> u8 {
91         ((self.into_raw() >> Self::ARCHITECTURE_RANGE.start())
92             & ((1 << Self::ARCHITECTURE_RANGE.len()) - 1)) as u8
93     }
94 }
95 
96 impl kernel::fmt::Display for NV_PMC_BOOT_42 {
97     fn fmt(&self, f: &mut kernel::fmt::Formatter<'_>) -> kernel::fmt::Result {
98         write!(
99             f,
100             "boot42 = 0x{:08x} (architecture 0x{:x}, implementation 0x{:x})",
101             self.inner,
102             self.architecture_raw(),
103             self.implementation()
104         )
105     }
106 }
107 
108 // PBUS
109 
110 register! {
111     pub(crate) NV_PBUS_SW_SCRATCH(u32)[64] @ 0x00001400 {}
112 
113     /// Scratch register 0xe used as FRTS firmware error code.
114     pub(crate) NV_PBUS_SW_SCRATCH_0E_FRTS_ERR(u32) => NV_PBUS_SW_SCRATCH[0xe] {
115         31:16   frts_err_code;
116     }
117 }
118 
119 // PFB
120 
121 register! {
122     /// Low bits of the physical system memory address used by the GPU to perform sysmembar
123     /// operations (see [`crate::fb::SysmemFlush`]).
124     pub(crate) NV_PFB_NISO_FLUSH_SYSMEM_ADDR(u32) @ 0x00100c10 {
125         31:0    adr_39_08;
126     }
127 
128     /// High bits of the physical system memory address used by the GPU to perform sysmembar
129     /// operations.
130     pub(crate) NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI(u32) @ 0x00100c40 {
131         23:0    adr_63_40;
132     }
133 
134     pub(crate) NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE(u32) @ 0x00100ce0 {
135         30:30   ecc_mode_enabled => bool;
136         9:4     lower_mag;
137         3:0     lower_scale;
138     }
139 
140     pub(crate) NV_PFB_PRI_MMU_WPR2_ADDR_LO(u32) @ 0x001fa824 {
141         /// Bits 12..40 of the lower (inclusive) bound of the WPR2 region.
142         31:4    lo_val;
143     }
144 
145     pub(crate) NV_PFB_PRI_MMU_WPR2_ADDR_HI(u32) @ 0x001fa828 {
146         /// Bits 12..40 of the higher (exclusive) bound of the WPR2 region.
147         31:4    hi_val;
148     }
149 }
150 
151 /// Base of the GB10x HSHUB0 register window (`NV_HSHUB0_PRIV_BASE` in Open RM).
152 ///
153 /// The base is provided by the GB10x framebuffer HAL.
154 pub(crate) struct Hshub0Base(());
155 
156 register! {
157     // GB10x sysmem flush registers, relative to the HSHUB0 base. GB10x routes sysmembar
158     // through a primary and an EG (egress) pair that must both be programmed to the same
159     // address. Hardware ignores bits 7:0 of each LO register. The boot path uses a fixed
160     // HSHUB0 base, so the multiple runtime-discovered HSHUB bases are not needed here.
161     pub(crate) NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ Hshub0Base + 0x00000e50 {
162         31:0    adr => u32;
163     }
164 
165     pub(crate) NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ Hshub0Base + 0x00000e54 {
166         19:0    adr;
167     }
168 
169     pub(crate) NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ Hshub0Base + 0x000006c0 {
170         31:0    adr => u32;
171     }
172 
173     pub(crate) NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ Hshub0Base + 0x000006c4 {
174         19:0    adr;
175     }
176 }
177 
178 register! {
179     // GB20x FBHUB0 sysmem flush registers. Unlike the older
180     // NV_PFB_NISO_FLUSH_SYSMEM_ADDR registers, which encode the address with an
181     // 8-bit right-shift, these take the raw address split into lower and upper
182     // halves. Hardware ignores bits 7:0 of the LO register.
183     pub(crate) NV_PFB_FBHUB0_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ 0x008a1d58 {
184         31:0    adr => u32;
185     }
186 
187     pub(crate) NV_PFB_FBHUB0_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ 0x008a1d5c {
188         19:0    adr;
189     }
190 }
191 
192 register! {
193     /// Low bits of the physical system memory address used by the GPU to perform
194     /// sysmembar operations on Hopper.
195     ///
196     /// Like the GB20x FBHUB0 registers, and unlike the Ampere
197     /// `NV_PFB_NISO_FLUSH_SYSMEM_ADDR` registers (which encode the address with an
198     /// 8-bit right-shift), these take the raw address split into lower and upper
199     /// halves. Hardware ignores bits 7:0 of the LO register.
200     pub(crate) NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ 0x00100a34 {
201         31:0    adr => u32;
202     }
203 
204     /// High bits of the physical system memory address used by the GPU to perform
205     /// sysmembar operations on Hopper.
206     pub(crate) NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ 0x00100a38 {
207         19:0    adr;
208     }
209 }
210 
211 impl NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE {
212     /// Returns the usable framebuffer size, in bytes.
213     pub(crate) fn usable_fb_size(self) -> u64 {
214         let size = (u64::from(self.lower_mag()) << u64::from(self.lower_scale())) * u64::SZ_1M;
215 
216         if self.ecc_mode_enabled() {
217             // Remove the amount of memory reserved for ECC (one per 16 units).
218             size / 16 * 15
219         } else {
220             size
221         }
222     }
223 }
224 
225 impl NV_PFB_PRI_MMU_WPR2_ADDR_LO {
226     /// Returns the lower (inclusive) bound of the WPR2 region.
227     pub(crate) fn lower_bound(self) -> u64 {
228         u64::from(self.lo_val()) << 12
229     }
230 }
231 
232 impl NV_PFB_PRI_MMU_WPR2_ADDR_HI {
233     /// Returns the higher (exclusive) bound of the WPR2 region.
234     ///
235     /// A value of zero means the WPR2 region is not set.
236     pub(crate) fn higher_bound(self) -> u64 {
237         u64::from(self.hi_val()) << 12
238     }
239 
240     /// Returns whether the WPR2 region is currently set.
241     pub(crate) fn is_wpr2_set(self) -> bool {
242         self.hi_val() != 0
243     }
244 }
245 
246 // PGC6 register space.
247 //
248 // `GC6` is a GPU low-power state where VRAM is in self-refresh and the GPU is powered down (except
249 // for power rails needed to keep self-refresh working and important registers and hardware
250 // blocks).
251 //
252 // These scratch registers remain powered on even in a low-power state and have a designated group
253 // number.
254 
255 register! {
256     /// Boot Sequence Interface (BSI) register used to determine
257     /// if GSP reload/resume has completed during the boot process.
258     pub(crate) NV_PGC6_BSI_SECURE_SCRATCH_14(u32) @ 0x001180f8 {
259         26:26   boot_stage_3_handoff => bool;
260     }
261 
262     /// Privilege level mask register. It dictates whether the host CPU has privilege to access the
263     /// `PGC6_AON_SECURE_SCRATCH_GROUP_05` register (which it needs to read GFW_BOOT).
264     pub(crate) NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK(u32) @ 0x00118128 {
265         /// Set after FWSEC lowers its protection level.
266         0:0     read_protection_level0 => bool;
267     }
268 
269     /// OpenRM defines this as a register array, but doesn't specify its size and only uses its
270     /// first element. Be conservative until we know the actual size or need to use more registers.
271     pub(crate) NV_PGC6_AON_SECURE_SCRATCH_GROUP_05(u32)[1] @ 0x00118234 {}
272 
273     /// Scratch group 05 register 0 used as GFW boot progress indicator.
274     pub(crate) NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT(u32)
275         => NV_PGC6_AON_SECURE_SCRATCH_GROUP_05[0] {
276         /// Progress of GFW boot (0xff means completed).
277         7:0    progress;
278     }
279 
280     pub(crate) NV_PGC6_AON_SECURE_SCRATCH_GROUP_42(u32) @ 0x001183a4 {
281         31:0    value;
282     }
283 
284     /// Scratch group 42 register used as framebuffer size.
285     pub(crate) NV_USABLE_FB_SIZE_IN_MB(u32) => NV_PGC6_AON_SECURE_SCRATCH_GROUP_42 {
286         /// Usable framebuffer size, in megabytes.
287         31:0    value;
288     }
289 }
290 
291 impl NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT {
292     /// Returns `true` if GFW boot is completed.
293     pub(crate) fn completed(self) -> bool {
294         self.progress() == 0xff
295     }
296 }
297 
298 impl NV_USABLE_FB_SIZE_IN_MB {
299     /// Returns the usable framebuffer size, in bytes.
300     pub(crate) fn usable_fb_size(self) -> u64 {
301         u64::from(self.value()) * u64::SZ_1M
302     }
303 }
304 
305 // FUSE
306 
307 pub(crate) const NV_FUSE_OPT_FPF_SIZE: usize = 16;
308 
309 register! {
310     pub(crate) NV_FUSE_OPT_FPF_NVDEC_UCODE1_VERSION(u32)[NV_FUSE_OPT_FPF_SIZE] @ 0x00824100 {
311         15:0    data => u16;
312     }
313 
314     pub(crate) NV_FUSE_OPT_FPF_SEC2_UCODE1_VERSION(u32)[NV_FUSE_OPT_FPF_SIZE] @ 0x00824140 {
315         15:0    data => u16;
316     }
317 
318     pub(crate) NV_FUSE_OPT_FPF_GSP_UCODE1_VERSION(u32)[NV_FUSE_OPT_FPF_SIZE] @ 0x008241c0 {
319         15:0    data => u16;
320     }
321 }
322 
323 // PFALCON
324 
325 register! {
326     pub(crate) NV_PFALCON_FALCON_IRQSCLR(u32) @ PFalconBase + 0x00000004 {
327         6:6     swgen0 => bool;
328         4:4     halt => bool;
329     }
330 
331     pub(crate) NV_PFALCON_FALCON_MAILBOX0(u32) @ PFalconBase + 0x00000040 {
332         31:0    value => u32;
333     }
334 
335     pub(crate) NV_PFALCON_FALCON_MAILBOX1(u32) @ PFalconBase + 0x00000044 {
336         31:0    value => u32;
337     }
338 
339     /// Used to store version information about the firmware running
340     /// on the Falcon processor.
341     pub(crate) NV_PFALCON_FALCON_OS(u32) @ PFalconBase + 0x00000080 {
342         31:0    value => u32;
343     }
344 
345     pub(crate) NV_PFALCON_FALCON_RM(u32) @ PFalconBase + 0x00000084 {
346         31:0    value => u32;
347     }
348 
349     pub(crate) NV_PFALCON_FALCON_HWCFG2(u32) @ PFalconBase + 0x000000f4 {
350         /// Signal indicating that reset is completed (GA102+).
351         31:31   reset_ready => bool;
352         /// RISC-V branch privilege lockdown bit.
353         13:13   riscv_br_priv_lockdown => bool;
354         /// Set to 0 after memory scrubbing is completed.
355         12:12   mem_scrubbing => bool;
356         10:10   riscv => bool;
357     }
358 
359     pub(crate) NV_PFALCON_FALCON_CPUCTL(u32) @ PFalconBase + 0x00000100 {
360         6:6     alias_en => bool;
361         4:4     halted => bool;
362         1:1     startcpu => bool;
363     }
364 
365     pub(crate) NV_PFALCON_FALCON_BOOTVEC(u32) @ PFalconBase + 0x00000104 {
366         31:0    value => u32;
367     }
368 
369     pub(crate) NV_PFALCON_FALCON_DMACTL(u32) @ PFalconBase + 0x0000010c {
370         7:7     secure_stat => bool;
371         6:3     dmaq_num;
372         2:2     imem_scrubbing => bool;
373         1:1     dmem_scrubbing => bool;
374         0:0     require_ctx => bool;
375     }
376 
377     pub(crate) NV_PFALCON_FALCON_DMATRFBASE(u32) @ PFalconBase + 0x00000110 {
378         31:0    base => u32;
379     }
380 
381     pub(crate) NV_PFALCON_FALCON_DMATRFMOFFS(u32) @ PFalconBase + 0x00000114 {
382         23:0    offs;
383     }
384 
385     pub(crate) NV_PFALCON_FALCON_DMATRFCMD(u32) @ PFalconBase + 0x00000118 {
386         16:16   set_dmtag;
387         14:12   ctxdma;
388         10:8    size ?=> DmaTrfCmdSize;
389         5:5     is_write => bool;
390         4:4     imem => bool;
391         3:2     sec;
392         1:1     idle => bool;
393         0:0     full => bool;
394     }
395 
396     pub(crate) NV_PFALCON_FALCON_DMATRFFBOFFS(u32) @ PFalconBase + 0x0000011c {
397         31:0    offs => u32;
398     }
399 
400     pub(crate) NV_PFALCON_FALCON_DMATRFBASE1(u32) @ PFalconBase + 0x00000128 {
401         8:0     base;
402     }
403 
404     pub(crate) NV_PFALCON_FALCON_HWCFG1(u32) @ PFalconBase + 0x0000012c {
405         /// Core revision subversion.
406         7:6     core_rev_subversion => FalconCoreRevSubversion;
407         /// Security model.
408         5:4     security_model ?=> FalconSecurityModel;
409         /// Core revision.
410         3:0     core_rev ?=> FalconCoreRev;
411     }
412 
413     pub(crate) NV_PFALCON_FALCON_CPUCTL_ALIAS(u32) @ PFalconBase + 0x00000130 {
414         1:1     startcpu => bool;
415     }
416 
417     /// IMEM access control register. Up to 4 ports are available for IMEM access.
418     pub(crate) NV_PFALCON_FALCON_IMEMC(u32)[4, stride = 16] @ PFalconBase + 0x00000180 {
419         /// Access secure IMEM.
420         28:28     secure => bool;
421         /// Auto-increment on write.
422         24:24     aincw => bool;
423         /// IMEM block and word offset.
424         15:0      offs;
425     }
426 
427     /// IMEM data register. Reading/writing this register accesses IMEM at the address
428     /// specified by the corresponding IMEMC register.
429     pub(crate) NV_PFALCON_FALCON_IMEMD(u32)[4, stride = 16] @ PFalconBase + 0x00000184 {
430         31:0      data;
431     }
432 
433     /// IMEM tag register. Used to set the tag for the current IMEM block.
434     pub(crate) NV_PFALCON_FALCON_IMEMT(u32)[4, stride = 16] @ PFalconBase + 0x00000188 {
435         15:0      tag;
436     }
437 
438     /// DMEM access control register. Up to 8 ports are available for DMEM access.
439     pub(crate) NV_PFALCON_FALCON_DMEMC(u32)[8, stride = 8] @ PFalconBase + 0x000001c0 {
440         /// Auto-increment on write.
441         24:24     aincw => bool;
442         /// DMEM block and word offset.
443         15:0      offs;
444     }
445 
446     /// DMEM data register. Reading/writing this register accesses DMEM at the address
447     /// specified by the corresponding DMEMC register.
448     pub(crate) NV_PFALCON_FALCON_DMEMD(u32)[8, stride = 8] @ PFalconBase + 0x000001c4 {
449         31:0      data;
450     }
451 
452     /// Actually known as `NV_PSEC_FALCON_ENGINE` and `NV_PGSP_FALCON_ENGINE` depending on the
453     /// falcon instance.
454     pub(crate) NV_PFALCON_FALCON_ENGINE(u32) @ PFalconBase + 0x000003c0 {
455         0:0     reset => bool;
456     }
457 
458     pub(crate) NV_PFALCON_FBIF_TRANSCFG(u32)[8] @ PFalconBase + 0x00000600 {
459         2:2     mem_type => FalconFbifMemType;
460         1:0     target ?=> FalconFbifTarget;
461     }
462 
463     pub(crate) NV_PFALCON_FBIF_CTL(u32) @ PFalconBase + 0x00000624 {
464         7:7     allow_phys_no_ctx => bool;
465     }
466 
467     // Falcon EMEM PIO registers (used by FSP on Hopper/Blackwell).
468     // These provide the falcon external memory communication interface.
469 
470     pub(crate) NV_PFALCON_FALCON_EMEMC(u32) @ PFalconBase + 0x00000ac0 {
471         /// EMEM byte offset (4-byte aligned) within the block.
472         7:2     offs;
473         /// EMEM block to access.
474         15:8    blk;
475         /// Auto-increment the offset after each write.
476         24:24   aincw => bool;
477         /// Auto-increment the offset after each read.
478         25:25   aincr => bool;
479     }
480 
481     pub(crate) NV_PFALCON_FALCON_EMEMD(u32) @ PFalconBase + 0x00000ac4 {
482         31:0    data => u32;
483     }
484 }
485 
486 impl NV_PFALCON_FALCON_DMACTL {
487     /// Returns `true` if memory scrubbing is completed.
488     pub(crate) fn mem_scrubbing_done(self) -> bool {
489         !self.dmem_scrubbing() && !self.imem_scrubbing()
490     }
491 }
492 
493 impl NV_PFALCON_FALCON_DMATRFCMD {
494     /// Programs the `imem` and `sec` fields for the given FalconMem
495     pub(crate) fn with_falcon_mem(self, mem: FalconMem) -> Self {
496         let this = self.with_imem(mem != FalconMem::Dmem);
497 
498         match mem {
499             FalconMem::ImemSecure => this.with_const_sec::<1>(),
500             _ => this.with_const_sec::<0>(),
501         }
502     }
503 }
504 
505 impl NV_PFALCON_FALCON_ENGINE {
506     /// Resets the falcon
507     pub(crate) fn reset_engine<E: FalconEngine>(bar: Bar0<'_>) {
508         bar.update(Self::of::<E>(), |r| r.with_reset(true));
509 
510         // TIMEOUT: falcon engine should not take more than 10us to reset.
511         time::delay::fsleep(time::Delta::from_micros(10));
512 
513         bar.update(Self::of::<E>(), |r| r.with_reset(false));
514     }
515 }
516 
517 impl NV_PFALCON_FALCON_HWCFG2 {
518     /// Returns `true` if memory scrubbing is completed.
519     pub(crate) fn mem_scrubbing_done(self) -> bool {
520         !self.mem_scrubbing()
521     }
522 }
523 
524 /* PFALCON2 */
525 
526 register! {
527     pub(crate) NV_PFALCON2_FALCON_MOD_SEL(u32) @ PFalcon2Base + 0x00000180 {
528         7:0     algo ?=> FalconModSelAlgo;
529     }
530 
531     pub(crate) NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID(u32) @ PFalcon2Base + 0x00000198 {
532         7:0    ucode_id => u8;
533     }
534 
535     pub(crate) NV_PFALCON2_FALCON_BROM_ENGIDMASK(u32) @ PFalcon2Base + 0x0000019c {
536         31:0    value => u32;
537     }
538 
539     /// OpenRM defines this as a register array, but doesn't specify its size and only uses its
540     /// first element. Be conservative until we know the actual size or need to use more registers.
541     pub(crate) NV_PFALCON2_FALCON_BROM_PARAADDR(u32)[1] @ PFalcon2Base + 0x00000210 {
542         31:0    value => u32;
543     }
544 }
545 
546 // PRISCV
547 
548 register! {
549     /// RISC-V status register for debug (Turing and GA100 only).
550     /// Reflects current RISC-V core status.
551     pub(crate) NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS(u32) @ PFalcon2Base + 0x00000240 {
552         /// RISC-V core active/inactive status.
553         0:0     active_stat => bool;
554     }
555 
556     /// GA102 and later.
557     pub(crate) NV_PRISCV_RISCV_CPUCTL(u32) @ PFalcon2Base + 0x00000388 {
558         7:7     active_stat => bool;
559         4:4     halted => bool;
560     }
561 
562     /// GA102 and later.
563     pub(crate) NV_PRISCV_RISCV_BCR_CTRL(u32) @ PFalcon2Base + 0x00000668 {
564         8:8     br_fetch => bool;
565         4:4     core_select => PeregrineCoreSelect;
566         0:0     valid => bool;
567     }
568 }
569 
570 // FSP (Foundation Security Processor) queue registers for Hopper/Blackwell Chain of Trust.
571 // These registers manage falcon EMEM communication queues.
572 
573 register! {
574     pub(crate) NV_PFSP_QUEUE_HEAD(u32)[8] @ 0x008f2c00 {
575         31:0    address => u32;
576     }
577 
578     pub(crate) NV_PFSP_QUEUE_TAIL(u32)[8] @ 0x008f2c04 {
579         31:0    address => u32;
580     }
581 
582     pub(crate) NV_PFSP_MSGQ_HEAD(u32)[8] @ 0x008f2c80 {
583         31:0    val => u32;
584     }
585 
586     pub(crate) NV_PFSP_MSGQ_TAIL(u32)[8] @ 0x008f2c84 {
587         31:0    val => u32;
588     }
589 }
590 
591 // The modules below provide registers that are not identical on all supported chips. They should
592 // only be used in HAL modules.
593 
594 pub(crate) mod gm107 {
595     use kernel::io::register;
596 
597     // FUSE
598 
599     register! {
600         pub(crate) NV_FUSE_STATUS_OPT_DISPLAY(u32) @ 0x00021c04 {
601             0:0     display_disabled => bool;
602         }
603     }
604 }
605 
606 pub(crate) mod ga100 {
607     use kernel::io::register;
608 
609     // FUSE
610 
611     register! {
612         pub(crate) NV_FUSE_STATUS_OPT_DISPLAY(u32) @ 0x00820c04 {
613             0:0     display_disabled => bool;
614         }
615     }
616 }
617 
618 pub(crate) const NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE_STATUS_SUCCESS: u32 = 0xff;
619 
620 pub(crate) mod gh100 {
621     use kernel::io::register;
622 
623     // PTHERM
624 
625     register! {
626         pub(crate) NV_THERM_I2CS_SCRATCH(u32) @ 0x000200bc {
627             31:0    data;
628         }
629 
630         // Alias to `NV_THERM_I2CS_SCRATCH` when used to check for FSP boot completion.
631         pub(crate) NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE(u32) => NV_THERM_I2CS_SCRATCH {
632             31:0    fsp_boot_complete;
633         }
634     }
635 }
636 
637 pub(crate) mod gb202 {
638     use kernel::io::register;
639 
640     // PTHERM
641 
642     register! {
643         pub(crate) NV_THERM_I2CS_SCRATCH(u32) @ 0x00ad00bc {
644             31:0    data;
645         }
646 
647         // Alias to `NV_THERM_I2CS_SCRATCH` when used to check for FSP boot completion.
648         pub(crate) NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE(u32) => NV_THERM_I2CS_SCRATCH {
649             31:0    fsp_boot_complete;
650         }
651     }
652 }
653