| // SPDX-License-Identifier: GPL-2.0 | |
| use kernel::{ | |
| io::register, | |
| sizes::SizeConstants, // | |
| }; | |
| // PDISP | |
| register! { | |
| pub(super) NV_PDISP_VGA_WORKSPACE_BASE(u32) @ 0x00625f04 { | |
| /// VGA workspace base address divided by 0x10000. | |
| 31:8 addr; | |
| /// Set if the `addr` field is valid. | |
| 3:3 status_valid => bool; | |
| } | |
| } | |
| impl NV_PDISP_VGA_WORKSPACE_BASE { | |
| /// Returns the base address of the VGA workspace, or `None` if none exists. | |
| pub(super) fn vga_workspace_addr(self) -> Option<u64> { | |
| if self.status_valid() { | |
| Some(u64::from(self.addr()) << 16) | |
| } else { | |
| None | |
| } | |
| } | |
| } | |
| // PFB | |
| register! { | |
| /// Low bits of the physical system memory address used by the GPU to perform sysmembar | |
| /// operations (see [`crate::fb::SysmemFlush`]). | |
| pub(super) NV_PFB_NISO_FLUSH_SYSMEM_ADDR(u32) @ 0x00100c10 { | |
| 31:0 adr_39_08; | |
| } | |
| /// High bits of the physical system memory address used by the GPU to perform sysmembar | |
| /// operations. | |
| pub(super) NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI(u32) @ 0x00100c40 { | |
| 23:0 adr_63_40; | |
| } | |
| pub(super) NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE(u32) @ 0x00100ce0 { | |
| 30:30 ecc_mode_enabled => bool; | |
| 9:4 lower_mag; | |
| 3:0 lower_scale; | |
| } | |
| pub(super) NV_PFB_PRI_MMU_WPR2_ADDR_LO(u32) @ 0x001fa824 { | |
| /// Bits 12..40 of the lower (inclusive) bound of the WPR2 region. | |
| 31:4 lo_val; | |
| } | |
| pub(super) NV_PFB_PRI_MMU_WPR2_ADDR_HI(u32) @ 0x001fa828 { | |
| /// Bits 12..40 of the higher (exclusive) bound of the WPR2 region. | |
| 31:4 hi_val; | |
| } | |
| } | |
| /// Base of the GB10x HSHUB0 register window (`NV_HSHUB0_PRIV_BASE` in Open RM). | |
| /// | |
| /// The base is provided by the GB10x framebuffer HAL. | |
| pub(super) struct Hshub0Base(()); | |
| register! { | |
| // GB10x sysmem flush registers, relative to the HSHUB0 base. GB10x routes sysmembar | |
| // through a primary and an EG (egress) pair that must both be programmed to the same | |
| // address. Hardware ignores bits 7:0 of each LO register. The boot path uses a fixed | |
| // HSHUB0 base, so the multiple runtime-discovered HSHUB bases are not needed here. | |
| pub(super) NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ Hshub0Base + 0x00000e50 { | |
| 31:0 adr => u32; | |
| } | |
| pub(super) NV_PFB_HSHUB_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ Hshub0Base + 0x00000e54 { | |
| 19:0 adr; | |
| } | |
| pub(super) NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ Hshub0Base + 0x000006c0 { | |
| 31:0 adr => u32; | |
| } | |
| pub(super) NV_PFB_HSHUB_EG_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ Hshub0Base + 0x000006c4 { | |
| 19:0 adr; | |
| } | |
| } | |
| register! { | |
| // GB20x FBHUB0 sysmem flush registers. Unlike the older | |
| // NV_PFB_NISO_FLUSH_SYSMEM_ADDR registers, which encode the address with an | |
| // 8-bit right-shift, these take the raw address split into lower and upper | |
| // halves. Hardware ignores bits 7:0 of the LO register. | |
| pub(super) NV_PFB_FBHUB0_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ 0x008a1d58 { | |
| 31:0 adr => u32; | |
| } | |
| pub(super) NV_PFB_FBHUB0_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ 0x008a1d5c { | |
| 19:0 adr; | |
| } | |
| } | |
| register! { | |
| /// Low bits of the physical system memory address used by the GPU to perform | |
| /// sysmembar operations on Hopper. | |
| /// | |
| /// Like the GB20x FBHUB0 registers, and unlike the Ampere | |
| /// `NV_PFB_NISO_FLUSH_SYSMEM_ADDR` registers (which encode the address with an | |
| /// 8-bit right-shift), these take the raw address split into lower and upper | |
| /// halves. Hardware ignores bits 7:0 of the LO register. | |
| pub(super) NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_LO(u32) @ 0x00100a34 { | |
| 31:0 adr => u32; | |
| } | |
| /// High bits of the physical system memory address used by the GPU to perform | |
| /// sysmembar operations on Hopper. | |
| pub(super) NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_HI(u32) @ 0x00100a38 { | |
| 19:0 adr; | |
| } | |
| } | |
| impl NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE { | |
| /// Returns the usable framebuffer size, in bytes. | |
| pub(super) fn usable_fb_size(self) -> u64 { | |
| let size = (u64::from(self.lower_mag()) << u64::from(self.lower_scale())) * u64::SZ_1M; | |
| if self.ecc_mode_enabled() { | |
| // Remove the amount of memory reserved for ECC (one per 16 units). | |
| size / 16 * 15 | |
| } else { | |
| size | |
| } | |
| } | |
| } | |
| impl NV_PFB_PRI_MMU_WPR2_ADDR_LO { | |
| /// Returns the lower (inclusive) bound of the WPR2 region. | |
| pub(super) fn lower_bound(self) -> u64 { | |
| u64::from(self.lo_val()) << 12 | |
| } | |
| } | |
| impl NV_PFB_PRI_MMU_WPR2_ADDR_HI { | |
| /// Returns the higher (exclusive) bound of the WPR2 region. | |
| /// | |
| /// A value of zero means the WPR2 region is not set. | |
| pub(super) fn higher_bound(self) -> u64 { | |
| u64::from(self.hi_val()) << 12 | |
| } | |
| /// Returns whether the WPR2 region is currently set. | |
| pub(super) fn is_wpr2_set(self) -> bool { | |
| self.hi_val() != 0 | |
| } | |
| } |