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