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