xref: /linux/drivers/gpu/nova-core/fb/regs.rs (revision 4e69c1856bfd9ffb7e9d335a25842fa211628929)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 use kernel::{
4     io::register,
5     sizes::SizeConstants, //
6 };
7 
8 // PDISP
9 
10 register! {
11     pub(super) NV_PDISP_VGA_WORKSPACE_BASE(u32) @ 0x00625f04 {
12         /// VGA workspace base address divided by 0x10000.
13         31:8    addr;
14         /// Set if the `addr` field is valid.
15         3:3     status_valid => bool;
16     }
17 }
18 
19 impl NV_PDISP_VGA_WORKSPACE_BASE {
20     /// Returns the base address of the VGA workspace, or `None` if none exists.
21     pub(super) fn vga_workspace_addr(self) -> Option<u64> {
22         if self.status_valid() {
23             Some(u64::from(self.addr()) << 16)
24         } else {
25             None
26         }
27     }
28 }
29 
30 // PFB
31 
32 register! {
33     /// Low bits of the physical system memory address used by the GPU to perform sysmembar
34     /// operations (see [`crate::fb::SysmemFlush`]).
35     pub(super) NV_PFB_NISO_FLUSH_SYSMEM_ADDR(u32) @ 0x00100c10 {
36         31:0    adr_39_08;
37     }
38 
39     /// High bits of the physical system memory address used by the GPU to perform sysmembar
40     /// operations.
41     pub(super) NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI(u32) @ 0x00100c40 {
42         23:0    adr_63_40;
43     }
44 
45     pub(super) NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE(u32) @ 0x00100ce0 {
46         30:30   ecc_mode_enabled => bool;
47         9:4     lower_mag;
48         3:0     lower_scale;
49     }
50 
51     pub(super) NV_PFB_PRI_MMU_WPR2_ADDR_LO(u32) @ 0x001fa824 {
52         /// Bits 12..40 of the lower (inclusive) bound of the WPR2 region.
53         31:4    lo_val;
54     }
55 
56     pub(super) NV_PFB_PRI_MMU_WPR2_ADDR_HI(u32) @ 0x001fa828 {
57         /// Bits 12..40 of the higher (exclusive) bound of the WPR2 region.
58         31:4    hi_val;
59     }
60 }
61 
62 /// Base of the GB10x HSHUB0 register window (`NV_HSHUB0_PRIV_BASE` in Open RM).
63 ///
64 /// The base is provided by the GB10x framebuffer HAL.
65 pub(super) struct Hshub0Base(());
66 
67 register! {
68     // GB10x sysmem flush registers, relative to the HSHUB0 base. GB10x routes sysmembar
69     // through a primary and an EG (egress) pair that must both be programmed to the same
70     // address. Hardware ignores bits 7:0 of each LO register. The boot path uses a fixed
71     // HSHUB0 base, so the multiple runtime-discovered HSHUB bases are not needed here.
72     pub(super) NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ Hshub0Base + 0x00000e50 {
73         31:0    adr => u32;
74     }
75 
76     pub(super) NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ Hshub0Base + 0x00000e54 {
77         19:0    adr;
78     }
79 
80     pub(super) NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ Hshub0Base + 0x000006c0 {
81         31:0    adr => u32;
82     }
83 
84     pub(super) NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ Hshub0Base + 0x000006c4 {
85         19:0    adr;
86     }
87 }
88 
89 register! {
90     // GB20x FBHUB0 sysmem flush registers. Unlike the older
91     // NV_PFB_NISO_FLUSH_SYSMEM_ADDR registers, which encode the address with an
92     // 8-bit right-shift, these take the raw address split into lower and upper
93     // halves. Hardware ignores bits 7:0 of the LO register.
94     pub(super) NV_PFB_FBHUB0_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ 0x008a1d58 {
95         31:0    adr => u32;
96     }
97 
98     pub(super) NV_PFB_FBHUB0_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ 0x008a1d5c {
99         19:0    adr;
100     }
101 }
102 
103 register! {
104     /// Low bits of the physical system memory address used by the GPU to perform
105     /// sysmembar operations on Hopper.
106     ///
107     /// Like the GB20x FBHUB0 registers, and unlike the Ampere
108     /// `NV_PFB_NISO_FLUSH_SYSMEM_ADDR` registers (which encode the address with an
109     /// 8-bit right-shift), these take the raw address split into lower and upper
110     /// halves. Hardware ignores bits 7:0 of the LO register.
111     pub(super) NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ 0x00100a34 {
112         31:0    adr => u32;
113     }
114 
115     /// High bits of the physical system memory address used by the GPU to perform
116     /// sysmembar operations on Hopper.
117     pub(super) NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ 0x00100a38 {
118         19:0    adr;
119     }
120 }
121 
122 impl NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE {
123     /// Returns the usable framebuffer size, in bytes.
124     pub(super) fn usable_fb_size(self) -> u64 {
125         let size = (u64::from(self.lower_mag()) << u64::from(self.lower_scale())) * u64::SZ_1M;
126 
127         if self.ecc_mode_enabled() {
128             // Remove the amount of memory reserved for ECC (one per 16 units).
129             size / 16 * 15
130         } else {
131             size
132         }
133     }
134 }
135 
136 impl NV_PFB_PRI_MMU_WPR2_ADDR_LO {
137     /// Returns the lower (inclusive) bound of the WPR2 region.
138     pub(super) fn lower_bound(self) -> u64 {
139         u64::from(self.lo_val()) << 12
140     }
141 }
142 
143 impl NV_PFB_PRI_MMU_WPR2_ADDR_HI {
144     /// Returns the higher (exclusive) bound of the WPR2 region.
145     ///
146     /// A value of zero means the WPR2 region is not set.
147     pub(super) fn higher_bound(self) -> u64 {
148         u64::from(self.hi_val()) << 12
149     }
150 
151     /// Returns whether the WPR2 region is currently set.
152     pub(super) fn is_wpr2_set(self) -> bool {
153         self.hi_val() != 0
154     }
155 }
156