// SPDX-License-Identifier: GPL-2.0use kernel::prelude::*;use crate::{ falcon::{ Falcon, FalconBromParams, FalconEngine, // }, gpu::{ Architecture, Chipset, // },};mod ga102;mod tu102;/// Method used to load data into falcon memory. Some GPU architectures need/// PIO and others can use DMA.pub(crate) enum LoadMethod { /// Programmed I/O Pio, /// Direct Memory Access Dma,}/// Hardware Abstraction Layer for Falcon cores.////// Implements chipset-specific low-level operations. The trait is generic against [`FalconEngine`]/// so its `BASE` parameter can be used in order to avoid runtime bound checks when accessing/// registers.pub(crate) trait FalconHal<E: FalconEngine>: Send + Sync { /// Activates the Falcon core if the engine is a risvc/falcon dual engine. fn select_core(&self, _falcon: &Falcon<'_, E>) -> Result { Ok(()) } /// Returns the fused version of the signature to use in order to run a HS firmware on this /// falcon instance. `engine_id_mask` and `ucode_id` are obtained from the firmware header. fn signature_reg_fuse_version( &self, falcon: &Falcon<'_, E>, engine_id_mask: u16, ucode_id: u8, ) -> Result<u32>; /// Program the boot ROM registers prior to starting a secure firmware. fn program_brom(&self, falcon: &Falcon<'_, E>, params: &FalconBromParams); /// Check if the RISC-V core is active. /// Returns `true` if the RISC-V core is active, `false` otherwise. fn is_riscv_active(&self, falcon: &Falcon<'_, E>) -> bool; /// Checks whether the RISC-V core is halted. /// /// Returns [`ENOTSUPP`] if the chipset does not expose RISC-V halt status. fn is_riscv_halted(&self, falcon: &Falcon<'_, E>) -> Result<bool>; /// Wait for memory scrubbing to complete. fn reset_wait_mem_scrubbing(&self, falcon: &Falcon<'_, E>) -> Result; /// Reset the falcon engine. fn reset_eng(&self, falcon: &Falcon<'_, E>) -> Result; /// Returns the method used to load data into the falcon's memory. /// /// The only chipsets supporting PIO are those < GA102, and PIO is the preferred method for /// these. For anything above, the PIO registers appear to be masked to the CPU, so DMA is the /// only usable method. fn load_method(&self) -> LoadMethod;}/// Returns a boxed falcon HAL adequate for `chipset`.////// We use a heap-allocated trait object instead of a statically defined one because the/// generic `FalconEngine` argument makes it difficult to define all the combinations/// statically.pub(super) fn falcon_hal<E: FalconEngine + 'static>( chipset: Chipset,) -> Result<KBox<dyn FalconHal<E>>> { let hal = match chipset.arch() { Architecture::Turing => { KBox::new(tu102::Tu102::<E>::new(), GFP_KERNEL)? as KBox<dyn FalconHal<E>> } // GA100 boots like Turing so use Turing HAL Architecture::Ampere if chipset == Chipset::GA100 => { KBox::new(tu102::Tu102::<E>::new(), GFP_KERNEL)? as KBox<dyn FalconHal<E>> } Architecture::Ampere | Architecture::Ada | Architecture::Hopper | Architecture::BlackwellGB10x | Architecture::BlackwellGB20x => { KBox::new(ga102::Ga102::<E>::new(), GFP_KERNEL)? as KBox<dyn FalconHal<E>> } }; Ok(hal)}
// SPDX-License-Identifier: GPL-2.0
use kernel::prelude::*;
use crate::{
falcon::{
Falcon,
FalconBromParams,
FalconEngine, //
},
gpu::{
Architecture,
Chipset, //
},
};
mod ga102;
mod tu102;
/// Method used to load data into falcon memory. Some GPU architectures need
/// PIO and others can use DMA.
pub(crate) enum LoadMethod {
/// Programmed I/O
Pio,
/// Direct Memory Access
Dma,
}
/// Hardware Abstraction Layer for Falcon cores.
///
/// Implements chipset-specific low-level operations. The trait is generic against [`FalconEngine`]
/// so its `BASE` parameter can be used in order to avoid runtime bound checks when accessing
/// registers.
pub(crate) trait FalconHal<E: FalconEngine>: Send + Sync {
/// Activates the Falcon core if the engine is a risvc/falcon dual engine.
fn select_core(&self, _falcon: &Falcon<'_, E>) -> Result {
Ok(())
}
/// Returns the fused version of the signature to use in order to run a HS firmware on this
/// falcon instance. `engine_id_mask` and `ucode_id` are obtained from the firmware header.
fn signature_reg_fuse_version(
&self,
falcon: &Falcon<'_, E>,
engine_id_mask: u16,
ucode_id: u8,
) -> Result<u32>;
/// Program the boot ROM registers prior to starting a secure firmware.
fn program_brom(&self, falcon: &Falcon<'_, E>, params: &FalconBromParams);
/// Check if the RISC-V core is active.
/// Returns `true` if the RISC-V core is active, `false` otherwise.
fn is_riscv_active(&self, falcon: &Falcon<'_, E>) -> bool;
/// Checks whether the RISC-V core is halted.
///
/// Returns [`ENOTSUPP`] if the chipset does not expose RISC-V halt status.
fn is_riscv_halted(&self, falcon: &Falcon<'_, E>) -> Result<bool>;
/// Wait for memory scrubbing to complete.
fn reset_wait_mem_scrubbing(&self, falcon: &Falcon<'_, E>) -> Result;
/// Reset the falcon engine.
fn reset_eng(&self, falcon: &Falcon<'_, E>) -> Result;
/// Returns the method used to load data into the falcon's memory.
///
/// The only chipsets supporting PIO are those < GA102, and PIO is the preferred method for
/// these. For anything above, the PIO registers appear to be masked to the CPU, so DMA is the
/// only usable method.
fn load_method(&self) -> LoadMethod;
}
/// Returns a boxed falcon HAL adequate for `chipset`.
///
/// We use a heap-allocated trait object instead of a statically defined one because the
/// generic `FalconEngine` argument makes it difficult to define all the combinations
/// statically.
pub(super) fn falcon_hal<E: FalconEngine + 'static>(
chipset: Chipset,
) -> Result<KBox<dyn FalconHal<E>>> {
let hal = match chipset.arch() {
Architecture::Turing => {
KBox::new(tu102::Tu102::<E>::new(), GFP_KERNEL)? as KBox<dyn FalconHal<E>>
}
// GA100 boots like Turing so use Turing HAL
Architecture::Ampere if chipset == Chipset::GA100 => {
KBox::new(tu102::Tu102::<E>::new(), GFP_KERNEL)? as KBox<dyn FalconHal<E>>
}
Architecture::Ampere
| Architecture::Ada
| Architecture::Hopper
| Architecture::BlackwellGB10x
| Architecture::BlackwellGB20x => {
KBox::new(ga102::Ga102::<E>::new(), GFP_KERNEL)? as KBox<dyn FalconHal<E>>
}
};
Ok(hal)
}