projects/linux·blob master · refs

101 lines · 3.4 KiB

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