xref: /linux/drivers/gpu/nova-core/falcon/hal/ga102.rs (revision 220994d61cebfc04f071d69049127657c7e8191b)
169f5cd67SAlexandre Courbot // SPDX-License-Identifier: GPL-2.0
269f5cd67SAlexandre Courbot 
369f5cd67SAlexandre Courbot use core::marker::PhantomData;
469f5cd67SAlexandre Courbot 
569f5cd67SAlexandre Courbot use kernel::device;
669f5cd67SAlexandre Courbot use kernel::prelude::*;
7*4092e1b4SAlexandre Courbot use kernel::time::Delta;
869f5cd67SAlexandre Courbot 
969f5cd67SAlexandre Courbot use crate::driver::Bar0;
1069f5cd67SAlexandre Courbot use crate::falcon::{
1169f5cd67SAlexandre Courbot     Falcon, FalconBromParams, FalconEngine, FalconModSelAlgo, PeregrineCoreSelect,
1269f5cd67SAlexandre Courbot };
1369f5cd67SAlexandre Courbot use crate::regs;
1469f5cd67SAlexandre Courbot use crate::util;
1569f5cd67SAlexandre Courbot 
1669f5cd67SAlexandre Courbot use super::FalconHal;
1769f5cd67SAlexandre Courbot 
select_core_ga102<E: FalconEngine>(bar: &Bar0) -> Result1869f5cd67SAlexandre Courbot fn select_core_ga102<E: FalconEngine>(bar: &Bar0) -> Result {
1969f5cd67SAlexandre Courbot     let bcr_ctrl = regs::NV_PRISCV_RISCV_BCR_CTRL::read(bar, E::BASE);
2069f5cd67SAlexandre Courbot     if bcr_ctrl.core_select() != PeregrineCoreSelect::Falcon {
2169f5cd67SAlexandre Courbot         regs::NV_PRISCV_RISCV_BCR_CTRL::default()
2269f5cd67SAlexandre Courbot             .set_core_select(PeregrineCoreSelect::Falcon)
2369f5cd67SAlexandre Courbot             .write(bar, E::BASE);
2469f5cd67SAlexandre Courbot 
2569f5cd67SAlexandre Courbot         // TIMEOUT: falcon core should take less than 10ms to report being enabled.
26*4092e1b4SAlexandre Courbot         util::wait_on(Delta::from_millis(10), || {
2769f5cd67SAlexandre Courbot             let r = regs::NV_PRISCV_RISCV_BCR_CTRL::read(bar, E::BASE);
2869f5cd67SAlexandre Courbot             if r.valid() {
2969f5cd67SAlexandre Courbot                 Some(())
3069f5cd67SAlexandre Courbot             } else {
3169f5cd67SAlexandre Courbot                 None
3269f5cd67SAlexandre Courbot             }
3369f5cd67SAlexandre Courbot         })?;
3469f5cd67SAlexandre Courbot     }
3569f5cd67SAlexandre Courbot 
3669f5cd67SAlexandre Courbot     Ok(())
3769f5cd67SAlexandre Courbot }
3869f5cd67SAlexandre Courbot 
signature_reg_fuse_version_ga102( dev: &device::Device, bar: &Bar0, engine_id_mask: u16, ucode_id: u8, ) -> Result<u32>3969f5cd67SAlexandre Courbot fn signature_reg_fuse_version_ga102(
4069f5cd67SAlexandre Courbot     dev: &device::Device,
4169f5cd67SAlexandre Courbot     bar: &Bar0,
4269f5cd67SAlexandre Courbot     engine_id_mask: u16,
4369f5cd67SAlexandre Courbot     ucode_id: u8,
4469f5cd67SAlexandre Courbot ) -> Result<u32> {
453606620bSAlexandre Courbot     // TODO[REGA]: The ucode fuse versions are contained in the
463606620bSAlexandre Courbot     // FUSE_OPT_FPF_<ENGINE>_UCODE<X>_VERSION registers, which are an array. Our register
473606620bSAlexandre Courbot     // definition macros do not allow us to manage them properly, so we need to hardcode their
483606620bSAlexandre Courbot     // addresses for now. Clean this up once we support register arrays.
4969f5cd67SAlexandre Courbot 
5069f5cd67SAlexandre Courbot     // Each engine has 16 ucode version registers numbered from 1 to 16.
5169f5cd67SAlexandre Courbot     if ucode_id == 0 || ucode_id > 16 {
5269f5cd67SAlexandre Courbot         dev_err!(dev, "invalid ucode id {:#x}", ucode_id);
5369f5cd67SAlexandre Courbot         return Err(EINVAL);
5469f5cd67SAlexandre Courbot     }
5569f5cd67SAlexandre Courbot 
5669f5cd67SAlexandre Courbot     // Base address of the FUSE registers array corresponding to the engine.
5769f5cd67SAlexandre Courbot     let reg_fuse_base = if engine_id_mask & 0x0001 != 0 {
5869f5cd67SAlexandre Courbot         regs::NV_FUSE_OPT_FPF_SEC2_UCODE1_VERSION::OFFSET
5969f5cd67SAlexandre Courbot     } else if engine_id_mask & 0x0004 != 0 {
6069f5cd67SAlexandre Courbot         regs::NV_FUSE_OPT_FPF_NVDEC_UCODE1_VERSION::OFFSET
6169f5cd67SAlexandre Courbot     } else if engine_id_mask & 0x0400 != 0 {
6269f5cd67SAlexandre Courbot         regs::NV_FUSE_OPT_FPF_GSP_UCODE1_VERSION::OFFSET
6369f5cd67SAlexandre Courbot     } else {
6469f5cd67SAlexandre Courbot         dev_err!(dev, "unexpected engine_id_mask {:#x}", engine_id_mask);
6569f5cd67SAlexandre Courbot         return Err(EINVAL);
6669f5cd67SAlexandre Courbot     };
6769f5cd67SAlexandre Courbot 
6869f5cd67SAlexandre Courbot     // Read `reg_fuse_base[ucode_id - 1]`.
6969f5cd67SAlexandre Courbot     let reg_fuse_version =
7069f5cd67SAlexandre Courbot         bar.read32(reg_fuse_base + ((ucode_id - 1) as usize * core::mem::size_of::<u32>()));
7169f5cd67SAlexandre Courbot 
723606620bSAlexandre Courbot     // TODO[NUMM]: replace with `last_set_bit` once it lands.
7369f5cd67SAlexandre Courbot     Ok(u32::BITS - reg_fuse_version.leading_zeros())
7469f5cd67SAlexandre Courbot }
7569f5cd67SAlexandre Courbot 
program_brom_ga102<E: FalconEngine>(bar: &Bar0, params: &FalconBromParams) -> Result7669f5cd67SAlexandre Courbot fn program_brom_ga102<E: FalconEngine>(bar: &Bar0, params: &FalconBromParams) -> Result {
7769f5cd67SAlexandre Courbot     regs::NV_PFALCON2_FALCON_BROM_PARAADDR::default()
7869f5cd67SAlexandre Courbot         .set_value(params.pkc_data_offset)
7969f5cd67SAlexandre Courbot         .write(bar, E::BASE);
8069f5cd67SAlexandre Courbot     regs::NV_PFALCON2_FALCON_BROM_ENGIDMASK::default()
8143ad65ecSDanilo Krummrich         .set_value(u32::from(params.engine_id_mask))
8269f5cd67SAlexandre Courbot         .write(bar, E::BASE);
8369f5cd67SAlexandre Courbot     regs::NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID::default()
8469f5cd67SAlexandre Courbot         .set_ucode_id(params.ucode_id)
8569f5cd67SAlexandre Courbot         .write(bar, E::BASE);
8669f5cd67SAlexandre Courbot     regs::NV_PFALCON2_FALCON_MOD_SEL::default()
8769f5cd67SAlexandre Courbot         .set_algo(FalconModSelAlgo::Rsa3k)
8869f5cd67SAlexandre Courbot         .write(bar, E::BASE);
8969f5cd67SAlexandre Courbot 
9069f5cd67SAlexandre Courbot     Ok(())
9169f5cd67SAlexandre Courbot }
9269f5cd67SAlexandre Courbot 
9369f5cd67SAlexandre Courbot pub(super) struct Ga102<E: FalconEngine>(PhantomData<E>);
9469f5cd67SAlexandre Courbot 
9569f5cd67SAlexandre Courbot impl<E: FalconEngine> Ga102<E> {
new() -> Self9669f5cd67SAlexandre Courbot     pub(super) fn new() -> Self {
9769f5cd67SAlexandre Courbot         Self(PhantomData)
9869f5cd67SAlexandre Courbot     }
9969f5cd67SAlexandre Courbot }
10069f5cd67SAlexandre Courbot 
10169f5cd67SAlexandre Courbot impl<E: FalconEngine> FalconHal<E> for Ga102<E> {
select_core(&self, _falcon: &Falcon<E>, bar: &Bar0) -> Result10269f5cd67SAlexandre Courbot     fn select_core(&self, _falcon: &Falcon<E>, bar: &Bar0) -> Result {
10369f5cd67SAlexandre Courbot         select_core_ga102::<E>(bar)
10469f5cd67SAlexandre Courbot     }
10569f5cd67SAlexandre Courbot 
signature_reg_fuse_version( &self, falcon: &Falcon<E>, bar: &Bar0, engine_id_mask: u16, ucode_id: u8, ) -> Result<u32>10669f5cd67SAlexandre Courbot     fn signature_reg_fuse_version(
10769f5cd67SAlexandre Courbot         &self,
10869f5cd67SAlexandre Courbot         falcon: &Falcon<E>,
10969f5cd67SAlexandre Courbot         bar: &Bar0,
11069f5cd67SAlexandre Courbot         engine_id_mask: u16,
11169f5cd67SAlexandre Courbot         ucode_id: u8,
11269f5cd67SAlexandre Courbot     ) -> Result<u32> {
11369f5cd67SAlexandre Courbot         signature_reg_fuse_version_ga102(&falcon.dev, bar, engine_id_mask, ucode_id)
11469f5cd67SAlexandre Courbot     }
11569f5cd67SAlexandre Courbot 
program_brom(&self, _falcon: &Falcon<E>, bar: &Bar0, params: &FalconBromParams) -> Result11669f5cd67SAlexandre Courbot     fn program_brom(&self, _falcon: &Falcon<E>, bar: &Bar0, params: &FalconBromParams) -> Result {
11769f5cd67SAlexandre Courbot         program_brom_ga102::<E>(bar, params)
11869f5cd67SAlexandre Courbot     }
11969f5cd67SAlexandre Courbot }
120