xref: /linux/drivers/gpu/nova-core/falcon/hal.rs (revision d639d9fa162aadec1ae9980c4dcf6e50bd2f8290)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 use kernel::prelude::*;
4 
5 use crate::{
6     driver::Bar0,
7     falcon::{
8         Falcon,
9         FalconBromParams,
10         FalconEngine, //
11     },
12     gpu::{
13         Architecture,
14         Chipset, //
15     },
16 };
17 
18 mod ga102;
19 mod tu102;
20 
21 /// Method used to load data into falcon memory. Some GPU architectures need
22 /// PIO and others can use DMA.
23 pub(crate) enum LoadMethod {
24     /// Programmed I/O
25     Pio,
26     /// Direct Memory Access
27     Dma,
28 }
29 
30 /// Hardware Abstraction Layer for Falcon cores.
31 ///
32 /// Implements chipset-specific low-level operations. The trait is generic against [`FalconEngine`]
33 /// so its `BASE` parameter can be used in order to avoid runtime bound checks when accessing
34 /// registers.
35 pub(crate) trait FalconHal<E: FalconEngine>: Send + Sync {
36     /// Activates the Falcon core if the engine is a risvc/falcon dual engine.
37     fn select_core(&self, _falcon: &Falcon<E>, _bar: Bar0<'_>) -> Result {
38         Ok(())
39     }
40 
41     /// Returns the fused version of the signature to use in order to run a HS firmware on this
42     /// falcon instance. `engine_id_mask` and `ucode_id` are obtained from the firmware header.
43     fn signature_reg_fuse_version(
44         &self,
45         falcon: &Falcon<E>,
46         bar: Bar0<'_>,
47         engine_id_mask: u16,
48         ucode_id: u8,
49     ) -> Result<u32>;
50 
51     /// Program the boot ROM registers prior to starting a secure firmware.
52     fn program_brom(&self, falcon: &Falcon<E>, bar: Bar0<'_>, params: &FalconBromParams);
53 
54     /// Check if the RISC-V core is active.
55     /// Returns `true` if the RISC-V core is active, `false` otherwise.
56     fn is_riscv_active(&self, bar: Bar0<'_>) -> bool;
57 
58     /// Wait for memory scrubbing to complete.
59     fn reset_wait_mem_scrubbing(&self, bar: Bar0<'_>) -> Result;
60 
61     /// Reset the falcon engine.
62     fn reset_eng(&self, bar: Bar0<'_>) -> Result;
63 
64     /// Returns the method used to load data into the falcon's memory.
65     ///
66     /// The only chipsets supporting PIO are those < GA102, and PIO is the preferred method for
67     /// these. For anything above, the PIO registers appear to be masked to the CPU, so DMA is the
68     /// only usable method.
69     fn load_method(&self) -> LoadMethod;
70 }
71 
72 /// Returns a boxed falcon HAL adequate for `chipset`.
73 ///
74 /// We use a heap-allocated trait object instead of a statically defined one because the
75 /// generic `FalconEngine` argument makes it difficult to define all the combinations
76 /// statically.
77 pub(super) fn falcon_hal<E: FalconEngine + 'static>(
78     chipset: Chipset,
79 ) -> Result<KBox<dyn FalconHal<E>>> {
80     let hal = match chipset.arch() {
81         Architecture::Turing => {
82             KBox::new(tu102::Tu102::<E>::new(), GFP_KERNEL)? as KBox<dyn FalconHal<E>>
83         }
84         // GA100 boots like Turing so use Turing HAL
85         Architecture::Ampere if chipset == Chipset::GA100 => {
86             KBox::new(tu102::Tu102::<E>::new(), GFP_KERNEL)? as KBox<dyn FalconHal<E>>
87         }
88         Architecture::Ampere
89         | Architecture::Ada
90         | Architecture::Hopper
91         | Architecture::BlackwellGB10x
92         | Architecture::BlackwellGB20x => {
93             KBox::new(ga102::Ga102::<E>::new(), GFP_KERNEL)? as KBox<dyn FalconHal<E>>
94         }
95     };
96 
97     Ok(hal)
98 }
99