Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/gpu/nova-core/regs.rs
49600 views
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 kernel::prelude::*;
11
12
use crate::{
13
falcon::{
14
DmaTrfCmdSize,
15
FalconCoreRev,
16
FalconCoreRevSubversion,
17
FalconFbifMemType,
18
FalconFbifTarget,
19
FalconModSelAlgo,
20
FalconSecurityModel,
21
PFalcon2Base,
22
PFalconBase,
23
PeregrineCoreSelect, //
24
},
25
gpu::{
26
Architecture,
27
Chipset, //
28
},
29
num::FromSafeCast,
30
};
31
32
// PMC
33
34
register!(NV_PMC_BOOT_0 @ 0x00000000, "Basic revision information about the GPU" {
35
3:0 minor_revision as u8, "Minor revision of the chip";
36
7:4 major_revision as u8, "Major revision of the chip";
37
8:8 architecture_1 as u8, "MSB of the architecture";
38
23:20 implementation as u8, "Implementation version of the architecture";
39
28:24 architecture_0 as u8, "Lower bits of the architecture";
40
});
41
42
impl NV_PMC_BOOT_0 {
43
pub(crate) fn is_older_than_fermi(self) -> bool {
44
// From https://github.com/NVIDIA/open-gpu-doc/tree/master/manuals :
45
const NV_PMC_BOOT_0_ARCHITECTURE_GF100: u8 = 0xc;
46
47
// Older chips left arch1 zeroed out. That, combined with an arch0 value that is less than
48
// GF100, means "older than Fermi".
49
self.architecture_1() == 0 && self.architecture_0() < NV_PMC_BOOT_0_ARCHITECTURE_GF100
50
}
51
}
52
53
register!(NV_PMC_BOOT_42 @ 0x00000a00, "Extended architecture information" {
54
15:12 minor_revision as u8, "Minor revision of the chip";
55
19:16 major_revision as u8, "Major revision of the chip";
56
23:20 implementation as u8, "Implementation version of the architecture";
57
29:24 architecture as u8 ?=> Architecture, "Architecture value";
58
});
59
60
impl NV_PMC_BOOT_42 {
61
/// Combines `architecture` and `implementation` to obtain a code unique to the chipset.
62
pub(crate) fn chipset(self) -> Result<Chipset> {
63
self.architecture()
64
.map(|arch| {
65
((arch as u32) << Self::IMPLEMENTATION_RANGE.len())
66
| u32::from(self.implementation())
67
})
68
.and_then(Chipset::try_from)
69
}
70
71
/// Returns the raw architecture value from the register.
72
fn architecture_raw(self) -> u8 {
73
((self.0 >> Self::ARCHITECTURE_RANGE.start()) & ((1 << Self::ARCHITECTURE_RANGE.len()) - 1))
74
as u8
75
}
76
}
77
78
impl kernel::fmt::Display for NV_PMC_BOOT_42 {
79
fn fmt(&self, f: &mut kernel::fmt::Formatter<'_>) -> kernel::fmt::Result {
80
write!(
81
f,
82
"boot42 = 0x{:08x} (architecture 0x{:x}, implementation 0x{:x})",
83
self.0,
84
self.architecture_raw(),
85
self.implementation()
86
)
87
}
88
}
89
90
// PBUS
91
92
register!(NV_PBUS_SW_SCRATCH @ 0x00001400[64] {});
93
94
register!(NV_PBUS_SW_SCRATCH_0E_FRTS_ERR => NV_PBUS_SW_SCRATCH[0xe],
95
"scratch register 0xe used as FRTS firmware error code" {
96
31:16 frts_err_code as u16;
97
});
98
99
// PFB
100
101
// The following two registers together hold the physical system memory address that is used by the
102
// GPU to perform sysmembar operations (see `fb::SysmemFlush`).
103
104
register!(NV_PFB_NISO_FLUSH_SYSMEM_ADDR @ 0x00100c10 {
105
31:0 adr_39_08 as u32;
106
});
107
108
register!(NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI @ 0x00100c40 {
109
23:0 adr_63_40 as u32;
110
});
111
112
register!(NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE @ 0x00100ce0 {
113
3:0 lower_scale as u8;
114
9:4 lower_mag as u8;
115
30:30 ecc_mode_enabled as bool;
116
});
117
118
register!(NV_PGSP_QUEUE_HEAD @ 0x00110c00 {
119
31:0 address as u32;
120
});
121
122
impl NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE {
123
/// Returns the usable framebuffer size, in bytes.
124
pub(crate) fn usable_fb_size(self) -> u64 {
125
let size = (u64::from(self.lower_mag()) << u64::from(self.lower_scale()))
126
* u64::from_safe_cast(kernel::sizes::SZ_1M);
127
128
if self.ecc_mode_enabled() {
129
// Remove the amount of memory reserved for ECC (one per 16 units).
130
size / 16 * 15
131
} else {
132
size
133
}
134
}
135
}
136
137
register!(NV_PFB_PRI_MMU_WPR2_ADDR_LO@0x001fa824 {
138
31:4 lo_val as u32, "Bits 12..40 of the lower (inclusive) bound of the WPR2 region";
139
});
140
141
impl NV_PFB_PRI_MMU_WPR2_ADDR_LO {
142
/// Returns the lower (inclusive) bound of the WPR2 region.
143
pub(crate) fn lower_bound(self) -> u64 {
144
u64::from(self.lo_val()) << 12
145
}
146
}
147
148
register!(NV_PFB_PRI_MMU_WPR2_ADDR_HI@0x001fa828 {
149
31:4 hi_val as u32, "Bits 12..40 of the higher (exclusive) bound of the WPR2 region";
150
});
151
152
impl NV_PFB_PRI_MMU_WPR2_ADDR_HI {
153
/// Returns the higher (exclusive) bound of the WPR2 region.
154
///
155
/// A value of zero means the WPR2 region is not set.
156
pub(crate) fn higher_bound(self) -> u64 {
157
u64::from(self.hi_val()) << 12
158
}
159
}
160
161
// PGC6 register space.
162
//
163
// `GC6` is a GPU low-power state where VRAM is in self-refresh and the GPU is powered down (except
164
// for power rails needed to keep self-refresh working and important registers and hardware
165
// blocks).
166
//
167
// These scratch registers remain powered on even in a low-power state and have a designated group
168
// number.
169
170
// Boot Sequence Interface (BSI) register used to determine
171
// if GSP reload/resume has completed during the boot process.
172
register!(NV_PGC6_BSI_SECURE_SCRATCH_14 @ 0x001180f8 {
173
26:26 boot_stage_3_handoff as bool;
174
});
175
176
// Privilege level mask register. It dictates whether the host CPU has privilege to access the
177
// `PGC6_AON_SECURE_SCRATCH_GROUP_05` register (which it needs to read GFW_BOOT).
178
register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK @ 0x00118128,
179
"Privilege level mask register" {
180
0:0 read_protection_level0 as bool, "Set after FWSEC lowers its protection level";
181
});
182
183
// OpenRM defines this as a register array, but doesn't specify its size and only uses its first
184
// element. Be conservative until we know the actual size or need to use more registers.
185
register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_05 @ 0x00118234[1] {});
186
187
register!(
188
NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT => NV_PGC6_AON_SECURE_SCRATCH_GROUP_05[0],
189
"Scratch group 05 register 0 used as GFW boot progress indicator" {
190
7:0 progress as u8, "Progress of GFW boot (0xff means completed)";
191
}
192
);
193
194
impl NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT {
195
/// Returns `true` if GFW boot is completed.
196
pub(crate) fn completed(self) -> bool {
197
self.progress() == 0xff
198
}
199
}
200
201
register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_42 @ 0x001183a4 {
202
31:0 value as u32;
203
});
204
205
register!(
206
NV_USABLE_FB_SIZE_IN_MB => NV_PGC6_AON_SECURE_SCRATCH_GROUP_42,
207
"Scratch group 42 register used as framebuffer size" {
208
31:0 value as u32, "Usable framebuffer size, in megabytes";
209
}
210
);
211
212
impl NV_USABLE_FB_SIZE_IN_MB {
213
/// Returns the usable framebuffer size, in bytes.
214
pub(crate) fn usable_fb_size(self) -> u64 {
215
u64::from(self.value()) * u64::from_safe_cast(kernel::sizes::SZ_1M)
216
}
217
}
218
219
// PDISP
220
221
register!(NV_PDISP_VGA_WORKSPACE_BASE @ 0x00625f04 {
222
3:3 status_valid as bool, "Set if the `addr` field is valid";
223
31:8 addr as u32, "VGA workspace base address divided by 0x10000";
224
});
225
226
impl NV_PDISP_VGA_WORKSPACE_BASE {
227
/// Returns the base address of the VGA workspace, or `None` if none exists.
228
pub(crate) fn vga_workspace_addr(self) -> Option<u64> {
229
if self.status_valid() {
230
Some(u64::from(self.addr()) << 16)
231
} else {
232
None
233
}
234
}
235
}
236
237
// FUSE
238
239
pub(crate) const NV_FUSE_OPT_FPF_SIZE: usize = 16;
240
241
register!(NV_FUSE_OPT_FPF_NVDEC_UCODE1_VERSION @ 0x00824100[NV_FUSE_OPT_FPF_SIZE] {
242
15:0 data as u16;
243
});
244
245
register!(NV_FUSE_OPT_FPF_SEC2_UCODE1_VERSION @ 0x00824140[NV_FUSE_OPT_FPF_SIZE] {
246
15:0 data as u16;
247
});
248
249
register!(NV_FUSE_OPT_FPF_GSP_UCODE1_VERSION @ 0x008241c0[NV_FUSE_OPT_FPF_SIZE] {
250
15:0 data as u16;
251
});
252
253
// PFALCON
254
255
register!(NV_PFALCON_FALCON_IRQSCLR @ PFalconBase[0x00000004] {
256
4:4 halt as bool;
257
6:6 swgen0 as bool;
258
});
259
260
register!(NV_PFALCON_FALCON_MAILBOX0 @ PFalconBase[0x00000040] {
261
31:0 value as u32;
262
});
263
264
register!(NV_PFALCON_FALCON_MAILBOX1 @ PFalconBase[0x00000044] {
265
31:0 value as u32;
266
});
267
268
// Used to store version information about the firmware running
269
// on the Falcon processor.
270
register!(NV_PFALCON_FALCON_OS @ PFalconBase[0x00000080] {
271
31:0 value as u32;
272
});
273
274
register!(NV_PFALCON_FALCON_RM @ PFalconBase[0x00000084] {
275
31:0 value as u32;
276
});
277
278
register!(NV_PFALCON_FALCON_HWCFG2 @ PFalconBase[0x000000f4] {
279
10:10 riscv as bool;
280
12:12 mem_scrubbing as bool, "Set to 0 after memory scrubbing is completed";
281
31:31 reset_ready as bool, "Signal indicating that reset is completed (GA102+)";
282
});
283
284
impl NV_PFALCON_FALCON_HWCFG2 {
285
/// Returns `true` if memory scrubbing is completed.
286
pub(crate) fn mem_scrubbing_done(self) -> bool {
287
!self.mem_scrubbing()
288
}
289
}
290
291
register!(NV_PFALCON_FALCON_CPUCTL @ PFalconBase[0x00000100] {
292
1:1 startcpu as bool;
293
4:4 halted as bool;
294
6:6 alias_en as bool;
295
});
296
297
register!(NV_PFALCON_FALCON_BOOTVEC @ PFalconBase[0x00000104] {
298
31:0 value as u32;
299
});
300
301
register!(NV_PFALCON_FALCON_DMACTL @ PFalconBase[0x0000010c] {
302
0:0 require_ctx as bool;
303
1:1 dmem_scrubbing as bool;
304
2:2 imem_scrubbing as bool;
305
6:3 dmaq_num as u8;
306
7:7 secure_stat as bool;
307
});
308
309
register!(NV_PFALCON_FALCON_DMATRFBASE @ PFalconBase[0x00000110] {
310
31:0 base as u32;
311
});
312
313
register!(NV_PFALCON_FALCON_DMATRFMOFFS @ PFalconBase[0x00000114] {
314
23:0 offs as u32;
315
});
316
317
register!(NV_PFALCON_FALCON_DMATRFCMD @ PFalconBase[0x00000118] {
318
0:0 full as bool;
319
1:1 idle as bool;
320
3:2 sec as u8;
321
4:4 imem as bool;
322
5:5 is_write as bool;
323
10:8 size as u8 ?=> DmaTrfCmdSize;
324
14:12 ctxdma as u8;
325
16:16 set_dmtag as u8;
326
});
327
328
register!(NV_PFALCON_FALCON_DMATRFFBOFFS @ PFalconBase[0x0000011c] {
329
31:0 offs as u32;
330
});
331
332
register!(NV_PFALCON_FALCON_DMATRFBASE1 @ PFalconBase[0x00000128] {
333
8:0 base as u16;
334
});
335
336
register!(NV_PFALCON_FALCON_HWCFG1 @ PFalconBase[0x0000012c] {
337
3:0 core_rev as u8 ?=> FalconCoreRev, "Core revision";
338
5:4 security_model as u8 ?=> FalconSecurityModel, "Security model";
339
7:6 core_rev_subversion as u8 ?=> FalconCoreRevSubversion, "Core revision subversion";
340
});
341
342
register!(NV_PFALCON_FALCON_CPUCTL_ALIAS @ PFalconBase[0x00000130] {
343
1:1 startcpu as bool;
344
});
345
346
// Actually known as `NV_PSEC_FALCON_ENGINE` and `NV_PGSP_FALCON_ENGINE` depending on the falcon
347
// instance.
348
register!(NV_PFALCON_FALCON_ENGINE @ PFalconBase[0x000003c0] {
349
0:0 reset as bool;
350
});
351
352
register!(NV_PFALCON_FBIF_TRANSCFG @ PFalconBase[0x00000600[8]] {
353
1:0 target as u8 ?=> FalconFbifTarget;
354
2:2 mem_type as bool => FalconFbifMemType;
355
});
356
357
register!(NV_PFALCON_FBIF_CTL @ PFalconBase[0x00000624] {
358
7:7 allow_phys_no_ctx as bool;
359
});
360
361
/* PFALCON2 */
362
363
register!(NV_PFALCON2_FALCON_MOD_SEL @ PFalcon2Base[0x00000180] {
364
7:0 algo as u8 ?=> FalconModSelAlgo;
365
});
366
367
register!(NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID @ PFalcon2Base[0x00000198] {
368
7:0 ucode_id as u8;
369
});
370
371
register!(NV_PFALCON2_FALCON_BROM_ENGIDMASK @ PFalcon2Base[0x0000019c] {
372
31:0 value as u32;
373
});
374
375
// OpenRM defines this as a register array, but doesn't specify its size and only uses its first
376
// element. Be conservative until we know the actual size or need to use more registers.
377
register!(NV_PFALCON2_FALCON_BROM_PARAADDR @ PFalcon2Base[0x00000210[1]] {
378
31:0 value as u32;
379
});
380
381
// PRISCV
382
383
register!(NV_PRISCV_RISCV_CPUCTL @ PFalcon2Base[0x00000388] {
384
0:0 halted as bool;
385
7:7 active_stat as bool;
386
});
387
388
register!(NV_PRISCV_RISCV_BCR_CTRL @ PFalcon2Base[0x00000668] {
389
0:0 valid as bool;
390
4:4 core_select as bool => PeregrineCoreSelect;
391
8:8 br_fetch as bool;
392
});
393
394
// The modules below provide registers that are not identical on all supported chips. They should
395
// only be used in HAL modules.
396
397
pub(crate) mod gm107 {
398
// FUSE
399
400
register!(NV_FUSE_STATUS_OPT_DISPLAY @ 0x00021c04 {
401
0:0 display_disabled as bool;
402
});
403
}
404
405
pub(crate) mod ga100 {
406
// FUSE
407
408
register!(NV_FUSE_STATUS_OPT_DISPLAY @ 0x00820c04 {
409
0:0 display_disabled as bool;
410
});
411
}
412
413