xref: /linux/drivers/gpu/nova-core/falcon/gsp.rs (revision 570f7e331f5febb30f1384817463c7e42b65ca7d)
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     falcon::{
18         Falcon,
19         FalconEngine,
20         PFalcon2Base,
21         PFalconBase, //
22     },
23     regs,
24 };
25 
26 /// Type specifying the `Gsp` falcon engine. Cannot be instantiated.
27 pub(crate) struct Gsp(());
28 
29 impl RegisterBase<PFalconBase> for Gsp {
30     const BASE: usize = 0x00110000;
31 }
32 
33 impl RegisterBase<PFalcon2Base> for Gsp {
34     const BASE: usize = 0x00111000;
35 }
36 
37 impl FalconEngine for Gsp {}
38 
39 impl<'a> Falcon<'a, Gsp> {
40     /// Clears the SWGEN0 bit in the Falcon's IRQ status clear register to
41     /// allow GSP to signal CPU for processing new messages in message queue.
42     pub(crate) fn clear_swgen0_intr(&self) {
43         self.bar.write(
44             WithBase::of::<Gsp>(),
45             regs::NV_PFALCON_FALCON_IRQSCLR::zeroed().with_swgen0(true),
46         );
47     }
48 
49     /// Checks if GSP reload/resume has completed during the boot process.
50     pub(crate) fn check_reload_completed(&self, timeout: Delta) -> Result<bool> {
51         read_poll_timeout(
52             || Ok(self.bar.read(regs::NV_PGC6_BSI_SECURE_SCRATCH_14)),
53             |val| val.boot_stage_3_handoff(),
54             Delta::ZERO,
55             timeout,
56         )
57         .map(|_| true)
58     }
59 
60     /// Returns whether the RISC-V branch privilege lockdown bit is set.
61     pub(crate) fn riscv_branch_privilege_lockdown(&self) -> bool {
62         self.bar
63             .read(regs::NV_PFALCON_FALCON_HWCFG2::of::<Gsp>())
64             .riscv_br_priv_lockdown()
65     }
66 
67     /// Returns whether GSP registers can be read by the CPU.
68     pub(crate) fn priv_target_mask_released(&self) -> bool {
69         /// Pattern returned by GSP register reads while the PRIV target mask still blocks CPU
70         /// access. The low byte varies; the upper 24 bits are fixed.
71         const LOCKED_PATTERN: u32 = 0xbadf_4100;
72         const LOCKED_MASK: u32 = 0xffff_ff00;
73 
74         let hwcfg2 = self
75             .bar
76             .read(regs::NV_PFALCON_FALCON_HWCFG2::of::<Gsp>())
77             .into_raw();
78 
79         hwcfg2 != 0 && (hwcfg2 & LOCKED_MASK) != LOCKED_PATTERN
80     }
81 }
82