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