xref: /linux/drivers/gpu/nova-core/regs.rs (revision af10924fc471d1c693b8689249f53ea10b0519b7)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 // Required to retain the original register names used by OpenRM, which are all capital snake case
4 // but are mapped to types.
5 #![allow(non_camel_case_types)]
6 
7 #[macro_use]
8 pub(crate) mod macros;
9 
10 use crate::falcon::{
11     DmaTrfCmdSize, FalconCoreRev, FalconCoreRevSubversion, FalconFbifMemType, FalconFbifTarget,
12     FalconModSelAlgo, FalconSecurityModel, PFalconBase, PeregrineCoreSelect,
13 };
14 use crate::gpu::{Architecture, Chipset};
15 use kernel::prelude::*;
16 
17 // PMC
18 
19 register!(NV_PMC_BOOT_0 @ 0x00000000, "Basic revision information about the GPU" {
20     3:0     minor_revision as u8, "Minor revision of the chip";
21     7:4     major_revision as u8, "Major revision of the chip";
22     8:8     architecture_1 as u8, "MSB of the architecture";
23     23:20   implementation as u8, "Implementation version of the architecture";
24     28:24   architecture_0 as u8, "Lower bits of the architecture";
25 });
26 
27 impl NV_PMC_BOOT_0 {
28     /// Combines `architecture_0` and `architecture_1` to obtain the architecture of the chip.
29     pub(crate) fn architecture(self) -> Result<Architecture> {
30         Architecture::try_from(
31             self.architecture_0() | (self.architecture_1() << Self::ARCHITECTURE_0_RANGE.len()),
32         )
33     }
34 
35     /// Combines `architecture` and `implementation` to obtain a code unique to the chipset.
36     pub(crate) fn chipset(self) -> Result<Chipset> {
37         self.architecture()
38             .map(|arch| {
39                 ((arch as u32) << Self::IMPLEMENTATION_RANGE.len())
40                     | u32::from(self.implementation())
41             })
42             .and_then(Chipset::try_from)
43     }
44 }
45 
46 // PBUS
47 
48 // TODO[REGA]: this is an array of registers.
49 register!(NV_PBUS_SW_SCRATCH_0E@0x00001438  {
50     31:16   frts_err_code as u16;
51 });
52 
53 // PFB
54 
55 // The following two registers together hold the physical system memory address that is used by the
56 // GPU to perform sysmembar operations (see `fb::SysmemFlush`).
57 
58 register!(NV_PFB_NISO_FLUSH_SYSMEM_ADDR @ 0x00100c10 {
59     31:0    adr_39_08 as u32;
60 });
61 
62 register!(NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI @ 0x00100c40 {
63     23:0    adr_63_40 as u32;
64 });
65 
66 register!(NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE @ 0x00100ce0 {
67     3:0     lower_scale as u8;
68     9:4     lower_mag as u8;
69     30:30   ecc_mode_enabled as bool;
70 });
71 
72 impl NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE {
73     /// Returns the usable framebuffer size, in bytes.
74     pub(crate) fn usable_fb_size(self) -> u64 {
75         let size = (u64::from(self.lower_mag()) << u64::from(self.lower_scale()))
76             * kernel::sizes::SZ_1M as u64;
77 
78         if self.ecc_mode_enabled() {
79             // Remove the amount of memory reserved for ECC (one per 16 units).
80             size / 16 * 15
81         } else {
82             size
83         }
84     }
85 }
86 
87 register!(NV_PFB_PRI_MMU_WPR2_ADDR_LO@0x001fa824  {
88     31:4    lo_val as u32, "Bits 12..40 of the lower (inclusive) bound of the WPR2 region";
89 });
90 
91 impl NV_PFB_PRI_MMU_WPR2_ADDR_LO {
92     /// Returns the lower (inclusive) bound of the WPR2 region.
93     pub(crate) fn lower_bound(self) -> u64 {
94         u64::from(self.lo_val()) << 12
95     }
96 }
97 
98 register!(NV_PFB_PRI_MMU_WPR2_ADDR_HI@0x001fa828  {
99     31:4    hi_val as u32, "Bits 12..40 of the higher (exclusive) bound of the WPR2 region";
100 });
101 
102 impl NV_PFB_PRI_MMU_WPR2_ADDR_HI {
103     /// Returns the higher (exclusive) bound of the WPR2 region.
104     ///
105     /// A value of zero means the WPR2 region is not set.
106     pub(crate) fn higher_bound(self) -> u64 {
107         u64::from(self.hi_val()) << 12
108     }
109 }
110 
111 // PGC6 register space.
112 //
113 // `GC6` is a GPU low-power state where VRAM is in self-refresh and the GPU is powered down (except
114 // for power rails needed to keep self-refresh working and important registers and hardware
115 // blocks).
116 //
117 // These scratch registers remain powered on even in a low-power state and have a designated group
118 // number.
119 
120 // Privilege level mask register. It dictates whether the host CPU has privilege to access the
121 // `PGC6_AON_SECURE_SCRATCH_GROUP_05` register (which it needs to read GFW_BOOT).
122 register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK @ 0x00118128,
123           "Privilege level mask register" {
124     0:0     read_protection_level0 as bool, "Set after FWSEC lowers its protection level";
125 });
126 
127 // TODO[REGA]: This is an array of registers.
128 register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_05 @ 0x00118234 {
129     31:0    value as u32;
130 });
131 
132 register!(
133     NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT => NV_PGC6_AON_SECURE_SCRATCH_GROUP_05,
134     "Scratch group 05 register 0 used as GFW boot progress indicator" {
135         7:0    progress as u8, "Progress of GFW boot (0xff means completed)";
136     }
137 );
138 
139 impl NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT {
140     /// Returns `true` if GFW boot is completed.
141     pub(crate) fn completed(self) -> bool {
142         self.progress() == 0xff
143     }
144 }
145 
146 register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_42 @ 0x001183a4 {
147     31:0    value as u32;
148 });
149 
150 register!(
151     NV_USABLE_FB_SIZE_IN_MB => NV_PGC6_AON_SECURE_SCRATCH_GROUP_42,
152     "Scratch group 42 register used as framebuffer size" {
153         31:0    value as u32, "Usable framebuffer size, in megabytes";
154     }
155 );
156 
157 impl NV_USABLE_FB_SIZE_IN_MB {
158     /// Returns the usable framebuffer size, in bytes.
159     pub(crate) fn usable_fb_size(self) -> u64 {
160         u64::from(self.value()) * kernel::sizes::SZ_1M as u64
161     }
162 }
163 
164 // PDISP
165 
166 register!(NV_PDISP_VGA_WORKSPACE_BASE @ 0x00625f04 {
167     3:3     status_valid as bool, "Set if the `addr` field is valid";
168     31:8    addr as u32, "VGA workspace base address divided by 0x10000";
169 });
170 
171 impl NV_PDISP_VGA_WORKSPACE_BASE {
172     /// Returns the base address of the VGA workspace, or `None` if none exists.
173     pub(crate) fn vga_workspace_addr(self) -> Option<u64> {
174         if self.status_valid() {
175             Some(u64::from(self.addr()) << 16)
176         } else {
177             None
178         }
179     }
180 }
181 
182 // FUSE
183 
184 register!(NV_FUSE_OPT_FPF_NVDEC_UCODE1_VERSION @ 0x00824100 {
185     15:0    data as u16;
186 });
187 
188 register!(NV_FUSE_OPT_FPF_SEC2_UCODE1_VERSION @ 0x00824140 {
189     15:0    data as u16;
190 });
191 
192 register!(NV_FUSE_OPT_FPF_GSP_UCODE1_VERSION @ 0x008241c0 {
193     15:0    data as u16;
194 });
195 
196 // PFALCON
197 
198 register!(NV_PFALCON_FALCON_IRQSCLR @ PFalconBase[0x00000004] {
199     4:4     halt as bool;
200     6:6     swgen0 as bool;
201 });
202 
203 register!(NV_PFALCON_FALCON_MAILBOX0 @ PFalconBase[0x00000040] {
204     31:0    value as u32;
205 });
206 
207 register!(NV_PFALCON_FALCON_MAILBOX1 @ PFalconBase[0x00000044] {
208     31:0    value as u32;
209 });
210 
211 register!(NV_PFALCON_FALCON_RM @ PFalconBase[0x00000084] {
212     31:0    value as u32;
213 });
214 
215 register!(NV_PFALCON_FALCON_HWCFG2 @ PFalconBase[0x000000f4] {
216     10:10   riscv as bool;
217     12:12   mem_scrubbing as bool, "Set to 0 after memory scrubbing is completed";
218     31:31   reset_ready as bool, "Signal indicating that reset is completed (GA102+)";
219 });
220 
221 impl NV_PFALCON_FALCON_HWCFG2 {
222     /// Returns `true` if memory scrubbing is completed.
223     pub(crate) fn mem_scrubbing_done(self) -> bool {
224         !self.mem_scrubbing()
225     }
226 }
227 
228 register!(NV_PFALCON_FALCON_CPUCTL @ PFalconBase[0x00000100] {
229     1:1     startcpu as bool;
230     4:4     halted as bool;
231     6:6     alias_en as bool;
232 });
233 
234 register!(NV_PFALCON_FALCON_BOOTVEC @ PFalconBase[0x00000104] {
235     31:0    value as u32;
236 });
237 
238 register!(NV_PFALCON_FALCON_DMACTL @ PFalconBase[0x0000010c] {
239     0:0     require_ctx as bool;
240     1:1     dmem_scrubbing as bool;
241     2:2     imem_scrubbing as bool;
242     6:3     dmaq_num as u8;
243     7:7     secure_stat as bool;
244 });
245 
246 register!(NV_PFALCON_FALCON_DMATRFBASE @ PFalconBase[0x00000110] {
247     31:0    base as u32;
248 });
249 
250 register!(NV_PFALCON_FALCON_DMATRFMOFFS @ PFalconBase[0x00000114] {
251     23:0    offs as u32;
252 });
253 
254 register!(NV_PFALCON_FALCON_DMATRFCMD @ PFalconBase[0x00000118] {
255     0:0     full as bool;
256     1:1     idle as bool;
257     3:2     sec as u8;
258     4:4     imem as bool;
259     5:5     is_write as bool;
260     10:8    size as u8 ?=> DmaTrfCmdSize;
261     14:12   ctxdma as u8;
262     16:16   set_dmtag as u8;
263 });
264 
265 register!(NV_PFALCON_FALCON_DMATRFFBOFFS @ PFalconBase[0x0000011c] {
266     31:0    offs as u32;
267 });
268 
269 register!(NV_PFALCON_FALCON_DMATRFBASE1 @ PFalconBase[0x00000128] {
270     8:0     base as u16;
271 });
272 
273 register!(NV_PFALCON_FALCON_HWCFG1 @ PFalconBase[0x0000012c] {
274     3:0     core_rev as u8 ?=> FalconCoreRev, "Core revision";
275     5:4     security_model as u8 ?=> FalconSecurityModel, "Security model";
276     7:6     core_rev_subversion as u8 ?=> FalconCoreRevSubversion, "Core revision subversion";
277 });
278 
279 register!(NV_PFALCON_FALCON_CPUCTL_ALIAS @ PFalconBase[0x00000130] {
280     1:1     startcpu as bool;
281 });
282 
283 // Actually known as `NV_PSEC_FALCON_ENGINE` and `NV_PGSP_FALCON_ENGINE` depending on the falcon
284 // instance.
285 register!(NV_PFALCON_FALCON_ENGINE @ PFalconBase[0x000003c0] {
286     0:0     reset as bool;
287 });
288 
289 // TODO[REGA]: this is an array of registers.
290 register!(NV_PFALCON_FBIF_TRANSCFG @ PFalconBase[0x00000600] {
291     1:0     target as u8 ?=> FalconFbifTarget;
292     2:2     mem_type as bool => FalconFbifMemType;
293 });
294 
295 register!(NV_PFALCON_FBIF_CTL @ PFalconBase[0x00000624] {
296     7:7     allow_phys_no_ctx as bool;
297 });
298 
299 register!(NV_PFALCON2_FALCON_MOD_SEL @ PFalconBase[0x00001180] {
300     7:0     algo as u8 ?=> FalconModSelAlgo;
301 });
302 
303 register!(NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID @ PFalconBase[0x00001198] {
304     7:0    ucode_id as u8;
305 });
306 
307 register!(NV_PFALCON2_FALCON_BROM_ENGIDMASK @ PFalconBase[0x0000119c] {
308     31:0    value as u32;
309 });
310 
311 // TODO[REGA]: this is an array of registers.
312 register!(NV_PFALCON2_FALCON_BROM_PARAADDR @ PFalconBase[0x00001210] {
313     31:0    value as u32;
314 });
315 
316 // PRISCV
317 
318 register!(NV_PRISCV_RISCV_BCR_CTRL @ PFalconBase[0x00001668] {
319     0:0     valid as bool;
320     4:4     core_select as bool => PeregrineCoreSelect;
321     8:8     br_fetch as bool;
322 });
323 
324 // The modules below provide registers that are not identical on all supported chips. They should
325 // only be used in HAL modules.
326 
327 pub(crate) mod gm107 {
328     // FUSE
329 
330     register!(NV_FUSE_STATUS_OPT_DISPLAY @ 0x00021c04 {
331         0:0     display_disabled as bool;
332     });
333 }
334 
335 pub(crate) mod ga100 {
336     // FUSE
337 
338     register!(NV_FUSE_STATUS_OPT_DISPLAY @ 0x00820c04 {
339         0:0     display_disabled as bool;
340     });
341 }
342