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