xref: /linux/drivers/gpu/nova-core/fb/hal/gb202.rs (revision 805185b7c7a1069e407b6f7b3bc98e44d415f484)
1 // SPDX-License-Identifier: GPL-2.0
2 // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 
4 //! Blackwell GB20x framebuffer HAL.
5 
6 use kernel::{
7     io::{
8         register::{
9             RegisterBase,
10             WithBase, //
11         },
12         Io, //
13     },
14     num::Bounded,
15     prelude::*,
16     sizes::SizeConstants, //
17 };
18 
19 use crate::{
20     driver::Bar0,
21     fb::hal::FbHal,
22     regs, //
23 };
24 
25 struct Gb202;
26 
27 impl RegisterBase<regs::Fbhub0Base> for Gb202 {
28     const BASE: usize = 0x008a_0000;
29 }
30 
31 fn read_sysmem_flush_page_gb202(bar: Bar0<'_>) -> u64 {
32     let lo = u64::from(
33         bar.read(regs::NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_LO::of::<Gb202>())
34             .adr(),
35     );
36     let hi = u64::from(
37         bar.read(regs::NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_HI::of::<Gb202>())
38             .adr(),
39     );
40 
41     lo | (hi << 32)
42 }
43 
44 /// Write the sysmem flush page address through the GB20x FBHUB0 registers.
45 fn write_sysmem_flush_page_gb202(bar: Bar0<'_>, addr: Bounded<u64, 52>) {
46     // Write HI first. The hardware will trigger the flush on the LO write.
47     bar.write(
48         regs::NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_HI::of::<Gb202>(),
49         regs::NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_HI::zeroed()
50             .with_adr(addr.shr::<32, 20>().cast::<u32>()),
51     );
52     bar.write(
53         regs::NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_LO::of::<Gb202>(),
54         // CAST: lower 32 bits. Hardware ignores bits 7:0.
55         regs::NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_LO::zeroed().with_adr(*addr as u32),
56     );
57 }
58 
59 impl FbHal for Gb202 {
60     fn read_sysmem_flush_page(&self, bar: Bar0<'_>) -> u64 {
61         read_sysmem_flush_page_gb202(bar)
62     }
63 
64     fn write_sysmem_flush_page(&self, bar: Bar0<'_>, addr: u64) -> Result {
65         let addr = Bounded::<u64, 52>::try_new(addr).ok_or(EINVAL)?;
66 
67         write_sysmem_flush_page_gb202(bar, addr);
68 
69         Ok(())
70     }
71 
72     fn supports_display(&self, bar: Bar0<'_>) -> bool {
73         super::ga100::display_enabled_ga100(bar)
74     }
75 
76     fn vidmem_size(&self, bar: Bar0<'_>) -> u64 {
77         super::ga102::vidmem_size_ga102(bar)
78     }
79 
80     fn pmu_reserved_size(&self) -> u32 {
81         super::gb100::pmu_reserved_size_gb100()
82     }
83 
84     fn non_wpr_heap_size(&self) -> u32 {
85         // Non-WPR heap for GB20x (see Open RM: kgspGetNonWprHeapSize, GB202+).
86         u32::SZ_2M + u32::SZ_128K
87     }
88 
89     fn frts_size(&self) -> u64 {
90         super::tu102::frts_size_tu102()
91     }
92 }
93 
94 const GB202: Gb202 = Gb202;
95 pub(super) const GB202_HAL: &dyn FbHal = &GB202;
96