xref: /linux/drivers/gpu/nova-core/falcon/gsp.rs (revision bba2c3615bd6cfee7456d1130f2e6b01b3f4e9ba)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 use kernel::{
4     io::{
5         poll::read_poll_timeout,
6         register::{
7             RegisterBase,
8             WithBase, //
9         },
10         Io,
11     },
12     prelude::*,
13     time::Delta, //
14 };
15 
16 use crate::{
17     driver::Bar0,
18     falcon::{
19         Falcon,
20         FalconEngine,
21         PFalcon2Base,
22         PFalconBase, //
23     },
24     regs,
25 };
26 
27 /// Pattern returned by GSP register reads while the PRIV target mask still blocks CPU access.
28 const GSP_TARGET_MASK_LOCKED_PATTERN: u32 = 0xbadf_4100;
29 const GSP_TARGET_MASK_LOCKED_MASK: u32 = 0xffff_ff00;
30 
31 /// Type specifying the `Gsp` falcon engine. Cannot be instantiated.
32 pub(crate) struct Gsp(());
33 
34 impl RegisterBase<PFalconBase> for Gsp {
35     const BASE: usize = 0x00110000;
36 }
37 
38 impl RegisterBase<PFalcon2Base> for Gsp {
39     const BASE: usize = 0x00111000;
40 }
41 
42 impl FalconEngine for Gsp {}
43 
44 impl Falcon<Gsp> {
45     /// Clears the SWGEN0 bit in the Falcon's IRQ status clear register to
46     /// allow GSP to signal CPU for processing new messages in message queue.
47     pub(crate) fn clear_swgen0_intr(&self, bar: Bar0<'_>) {
48         bar.write(
49             WithBase::of::<Gsp>(),
50             regs::NV_PFALCON_FALCON_IRQSCLR::zeroed().with_swgen0(true),
51         );
52     }
53 
54     /// Checks if GSP reload/resume has completed during the boot process.
55     pub(crate) fn check_reload_completed(&self, bar: Bar0<'_>, timeout: Delta) -> Result<bool> {
56         read_poll_timeout(
57             || Ok(bar.read(regs::NV_PGC6_BSI_SECURE_SCRATCH_14)),
58             |val| val.boot_stage_3_handoff(),
59             Delta::ZERO,
60             timeout,
61         )
62         .map(|_| true)
63     }
64 
65     /// Returns whether the RISC-V branch privilege lockdown bit is set.
66     pub(crate) fn riscv_branch_privilege_lockdown(&self, bar: Bar0<'_>) -> bool {
67         bar.read(regs::NV_PFALCON_FALCON_HWCFG2::of::<Gsp>())
68             .riscv_br_priv_lockdown()
69     }
70 
71     /// Returns whether GSP registers can be read by the CPU.
72     pub(crate) fn priv_target_mask_released(&self, bar: Bar0<'_>) -> bool {
73         let hwcfg2 = bar
74             .read(regs::NV_PFALCON_FALCON_HWCFG2::of::<Gsp>())
75             .into_raw();
76 
77         hwcfg2 != 0 && (hwcfg2 & GSP_TARGET_MASK_LOCKED_MASK) != GSP_TARGET_MASK_LOCKED_PATTERN
78     }
79 }
80