summaryrefslogtreecommitdiff
path: root/drivers/gpu/nova-core/fb/regs.rs
blob: 95adbe124a300d11147ab51b235a16847aad49a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// 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
    }
}