xref: /linux/drivers/gpu/nova-core/falcon/hal/ga102.rs (revision 220994d61cebfc04f071d69049127657c7e8191b)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 use core::marker::PhantomData;
4 
5 use kernel::device;
6 use kernel::prelude::*;
7 use kernel::time::Delta;
8 
9 use crate::driver::Bar0;
10 use crate::falcon::{
11     Falcon, FalconBromParams, FalconEngine, FalconModSelAlgo, PeregrineCoreSelect,
12 };
13 use crate::regs;
14 use crate::util;
15 
16 use super::FalconHal;
17 
select_core_ga102<E: FalconEngine>(bar: &Bar0) -> Result18 fn select_core_ga102<E: FalconEngine>(bar: &Bar0) -> Result {
19     let bcr_ctrl = regs::NV_PRISCV_RISCV_BCR_CTRL::read(bar, E::BASE);
20     if bcr_ctrl.core_select() != PeregrineCoreSelect::Falcon {
21         regs::NV_PRISCV_RISCV_BCR_CTRL::default()
22             .set_core_select(PeregrineCoreSelect::Falcon)
23             .write(bar, E::BASE);
24 
25         // TIMEOUT: falcon core should take less than 10ms to report being enabled.
26         util::wait_on(Delta::from_millis(10), || {
27             let r = regs::NV_PRISCV_RISCV_BCR_CTRL::read(bar, E::BASE);
28             if r.valid() {
29                 Some(())
30             } else {
31                 None
32             }
33         })?;
34     }
35 
36     Ok(())
37 }
38 
signature_reg_fuse_version_ga102( dev: &device::Device, bar: &Bar0, engine_id_mask: u16, ucode_id: u8, ) -> Result<u32>39 fn signature_reg_fuse_version_ga102(
40     dev: &device::Device,
41     bar: &Bar0,
42     engine_id_mask: u16,
43     ucode_id: u8,
44 ) -> Result<u32> {
45     // TODO[REGA]: The ucode fuse versions are contained in the
46     // FUSE_OPT_FPF_<ENGINE>_UCODE<X>_VERSION registers, which are an array. Our register
47     // definition macros do not allow us to manage them properly, so we need to hardcode their
48     // addresses for now. Clean this up once we support register arrays.
49 
50     // Each engine has 16 ucode version registers numbered from 1 to 16.
51     if ucode_id == 0 || ucode_id > 16 {
52         dev_err!(dev, "invalid ucode id {:#x}", ucode_id);
53         return Err(EINVAL);
54     }
55 
56     // Base address of the FUSE registers array corresponding to the engine.
57     let reg_fuse_base = if engine_id_mask & 0x0001 != 0 {
58         regs::NV_FUSE_OPT_FPF_SEC2_UCODE1_VERSION::OFFSET
59     } else if engine_id_mask & 0x0004 != 0 {
60         regs::NV_FUSE_OPT_FPF_NVDEC_UCODE1_VERSION::OFFSET
61     } else if engine_id_mask & 0x0400 != 0 {
62         regs::NV_FUSE_OPT_FPF_GSP_UCODE1_VERSION::OFFSET
63     } else {
64         dev_err!(dev, "unexpected engine_id_mask {:#x}", engine_id_mask);
65         return Err(EINVAL);
66     };
67 
68     // Read `reg_fuse_base[ucode_id - 1]`.
69     let reg_fuse_version =
70         bar.read32(reg_fuse_base + ((ucode_id - 1) as usize * core::mem::size_of::<u32>()));
71 
72     // TODO[NUMM]: replace with `last_set_bit` once it lands.
73     Ok(u32::BITS - reg_fuse_version.leading_zeros())
74 }
75 
program_brom_ga102<E: FalconEngine>(bar: &Bar0, params: &FalconBromParams) -> Result76 fn program_brom_ga102<E: FalconEngine>(bar: &Bar0, params: &FalconBromParams) -> Result {
77     regs::NV_PFALCON2_FALCON_BROM_PARAADDR::default()
78         .set_value(params.pkc_data_offset)
79         .write(bar, E::BASE);
80     regs::NV_PFALCON2_FALCON_BROM_ENGIDMASK::default()
81         .set_value(u32::from(params.engine_id_mask))
82         .write(bar, E::BASE);
83     regs::NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID::default()
84         .set_ucode_id(params.ucode_id)
85         .write(bar, E::BASE);
86     regs::NV_PFALCON2_FALCON_MOD_SEL::default()
87         .set_algo(FalconModSelAlgo::Rsa3k)
88         .write(bar, E::BASE);
89 
90     Ok(())
91 }
92 
93 pub(super) struct Ga102<E: FalconEngine>(PhantomData<E>);
94 
95 impl<E: FalconEngine> Ga102<E> {
new() -> Self96     pub(super) fn new() -> Self {
97         Self(PhantomData)
98     }
99 }
100 
101 impl<E: FalconEngine> FalconHal<E> for Ga102<E> {
select_core(&self, _falcon: &Falcon<E>, bar: &Bar0) -> Result102     fn select_core(&self, _falcon: &Falcon<E>, bar: &Bar0) -> Result {
103         select_core_ga102::<E>(bar)
104     }
105 
signature_reg_fuse_version( &self, falcon: &Falcon<E>, bar: &Bar0, engine_id_mask: u16, ucode_id: u8, ) -> Result<u32>106     fn signature_reg_fuse_version(
107         &self,
108         falcon: &Falcon<E>,
109         bar: &Bar0,
110         engine_id_mask: u16,
111         ucode_id: u8,
112     ) -> Result<u32> {
113         signature_reg_fuse_version_ga102(&falcon.dev, bar, engine_id_mask, ucode_id)
114     }
115 
program_brom(&self, _falcon: &Falcon<E>, bar: &Bar0, params: &FalconBromParams) -> Result116     fn program_brom(&self, _falcon: &Falcon<E>, bar: &Bar0, params: &FalconBromParams) -> Result {
117         program_brom_ga102::<E>(bar, params)
118     }
119 }
120