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