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