1 // SPDX-License-Identifier: GPL-2.0 2 3 use core::marker::PhantomData; 4 5 use kernel::{ 6 device, 7 io::poll::read_poll_timeout, 8 prelude::*, 9 time::Delta, // 10 }; 11 12 use crate::{ 13 driver::Bar0, 14 falcon::{ 15 Falcon, 16 FalconBromParams, 17 FalconEngine, 18 FalconModSelAlgo, 19 PeregrineCoreSelect, // 20 }, 21 regs, 22 }; 23 24 use super::FalconHal; 25 26 fn select_core_ga102<E: FalconEngine>(bar: &Bar0) -> Result { 27 let bcr_ctrl = regs::NV_PRISCV_RISCV_BCR_CTRL::read(bar, &E::ID); 28 if bcr_ctrl.core_select() != PeregrineCoreSelect::Falcon { 29 regs::NV_PRISCV_RISCV_BCR_CTRL::default() 30 .set_core_select(PeregrineCoreSelect::Falcon) 31 .write(bar, &E::ID); 32 33 // TIMEOUT: falcon core should take less than 10ms to report being enabled. 34 read_poll_timeout( 35 || Ok(regs::NV_PRISCV_RISCV_BCR_CTRL::read(bar, &E::ID)), 36 |r| r.valid(), 37 Delta::ZERO, 38 Delta::from_millis(10), 39 )?; 40 } 41 42 Ok(()) 43 } 44 45 fn signature_reg_fuse_version_ga102( 46 dev: &device::Device, 47 bar: &Bar0, 48 engine_id_mask: u16, 49 ucode_id: u8, 50 ) -> Result<u32> { 51 // Each engine has 16 ucode version registers numbered from 1 to 16. 52 let ucode_idx = match usize::from(ucode_id) { 53 ucode_id @ 1..=regs::NV_FUSE_OPT_FPF_SIZE => ucode_id - 1, 54 _ => { 55 dev_err!(dev, "invalid ucode id {:#x}", ucode_id); 56 return Err(EINVAL); 57 } 58 }; 59 60 // `ucode_idx` is guaranteed to be in the range [0..15], making the `read` calls provable valid 61 // at build-time. 62 let reg_fuse_version = if engine_id_mask & 0x0001 != 0 { 63 regs::NV_FUSE_OPT_FPF_SEC2_UCODE1_VERSION::read(bar, ucode_idx).data() 64 } else if engine_id_mask & 0x0004 != 0 { 65 regs::NV_FUSE_OPT_FPF_NVDEC_UCODE1_VERSION::read(bar, ucode_idx).data() 66 } else if engine_id_mask & 0x0400 != 0 { 67 regs::NV_FUSE_OPT_FPF_GSP_UCODE1_VERSION::read(bar, ucode_idx).data() 68 } else { 69 dev_err!(dev, "unexpected engine_id_mask {:#x}", engine_id_mask); 70 return Err(EINVAL); 71 }; 72 73 // TODO[NUMM]: replace with `last_set_bit` once it lands. 74 Ok(u16::BITS - reg_fuse_version.leading_zeros()) 75 } 76 77 fn program_brom_ga102<E: FalconEngine>(bar: &Bar0, params: &FalconBromParams) -> Result { 78 regs::NV_PFALCON2_FALCON_BROM_PARAADDR::default() 79 .set_value(params.pkc_data_offset) 80 .write(bar, &E::ID, 0); 81 regs::NV_PFALCON2_FALCON_BROM_ENGIDMASK::default() 82 .set_value(u32::from(params.engine_id_mask)) 83 .write(bar, &E::ID); 84 regs::NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID::default() 85 .set_ucode_id(params.ucode_id) 86 .write(bar, &E::ID); 87 regs::NV_PFALCON2_FALCON_MOD_SEL::default() 88 .set_algo(FalconModSelAlgo::Rsa3k) 89 .write(bar, &E::ID); 90 91 Ok(()) 92 } 93 94 pub(super) struct Ga102<E: FalconEngine>(PhantomData<E>); 95 96 impl<E: FalconEngine> Ga102<E> { 97 pub(super) fn new() -> Self { 98 Self(PhantomData) 99 } 100 } 101 102 impl<E: FalconEngine> FalconHal<E> for Ga102<E> { 103 fn select_core(&self, _falcon: &Falcon<E>, bar: &Bar0) -> Result { 104 select_core_ga102::<E>(bar) 105 } 106 107 fn signature_reg_fuse_version( 108 &self, 109 falcon: &Falcon<E>, 110 bar: &Bar0, 111 engine_id_mask: u16, 112 ucode_id: u8, 113 ) -> Result<u32> { 114 signature_reg_fuse_version_ga102(&falcon.dev, bar, engine_id_mask, ucode_id) 115 } 116 117 fn program_brom(&self, _falcon: &Falcon<E>, bar: &Bar0, params: &FalconBromParams) -> Result { 118 program_brom_ga102::<E>(bar, params) 119 } 120 } 121