// SPDX-License-Identifier: GPL-2.0 use core::marker::PhantomData; use kernel::{ device, io::poll::read_poll_timeout, prelude::*, time::Delta, // }; use crate::{ driver::Bar0, falcon::{ Falcon, FalconBromParams, FalconEngine, FalconModSelAlgo, PeregrineCoreSelect, // }, regs, }; use super::FalconHal; fn select_core_ga102(bar: &Bar0) -> Result { let bcr_ctrl = regs::NV_PRISCV_RISCV_BCR_CTRL::read(bar, &E::ID); if bcr_ctrl.core_select() != PeregrineCoreSelect::Falcon { regs::NV_PRISCV_RISCV_BCR_CTRL::default() .set_core_select(PeregrineCoreSelect::Falcon) .write(bar, &E::ID); // TIMEOUT: falcon core should take less than 10ms to report being enabled. read_poll_timeout( || Ok(regs::NV_PRISCV_RISCV_BCR_CTRL::read(bar, &E::ID)), |r| r.valid(), Delta::ZERO, Delta::from_millis(10), )?; } Ok(()) } fn signature_reg_fuse_version_ga102( dev: &device::Device, bar: &Bar0, engine_id_mask: u16, ucode_id: u8, ) -> Result { // Each engine has 16 ucode version registers numbered from 1 to 16. let ucode_idx = match usize::from(ucode_id) { ucode_id @ 1..=regs::NV_FUSE_OPT_FPF_SIZE => ucode_id - 1, _ => { dev_err!(dev, "invalid ucode id {:#x}", ucode_id); return Err(EINVAL); } }; // `ucode_idx` is guaranteed to be in the range [0..15], making the `read` calls provable valid // at build-time. let reg_fuse_version = if engine_id_mask & 0x0001 != 0 { regs::NV_FUSE_OPT_FPF_SEC2_UCODE1_VERSION::read(bar, ucode_idx).data() } else if engine_id_mask & 0x0004 != 0 { regs::NV_FUSE_OPT_FPF_NVDEC_UCODE1_VERSION::read(bar, ucode_idx).data() } else if engine_id_mask & 0x0400 != 0 { regs::NV_FUSE_OPT_FPF_GSP_UCODE1_VERSION::read(bar, ucode_idx).data() } else { dev_err!(dev, "unexpected engine_id_mask {:#x}", engine_id_mask); return Err(EINVAL); }; // TODO[NUMM]: replace with `last_set_bit` once it lands. Ok(u16::BITS - reg_fuse_version.leading_zeros()) } fn program_brom_ga102(bar: &Bar0, params: &FalconBromParams) -> Result { regs::NV_PFALCON2_FALCON_BROM_PARAADDR::default() .set_value(params.pkc_data_offset) .write(bar, &E::ID, 0); regs::NV_PFALCON2_FALCON_BROM_ENGIDMASK::default() .set_value(u32::from(params.engine_id_mask)) .write(bar, &E::ID); regs::NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID::default() .set_ucode_id(params.ucode_id) .write(bar, &E::ID); regs::NV_PFALCON2_FALCON_MOD_SEL::default() .set_algo(FalconModSelAlgo::Rsa3k) .write(bar, &E::ID); Ok(()) } pub(super) struct Ga102(PhantomData); impl Ga102 { pub(super) fn new() -> Self { Self(PhantomData) } } impl FalconHal for Ga102 { fn select_core(&self, _falcon: &Falcon, bar: &Bar0) -> Result { select_core_ga102::(bar) } fn signature_reg_fuse_version( &self, falcon: &Falcon, bar: &Bar0, engine_id_mask: u16, ucode_id: u8, ) -> Result { signature_reg_fuse_version_ga102(&falcon.dev, bar, engine_id_mask, ucode_id) } fn program_brom(&self, _falcon: &Falcon, bar: &Bar0, params: &FalconBromParams) -> Result { program_brom_ga102::(bar, params) } }