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