Commit 38f7e545 authored by Alexandre Courbot's avatar Alexandre Courbot
Browse files

gpu: nova-core: convert falcon registers to kernel register macro



Convert all PFALCON, PFALCON2 and PRISCV registers to use the kernel's
register macro and update the code accordingly.

Because they rely on the same types to implement relative registers,
they need to be updated in lockstep.

nova-core's local register macro is now unused, so remove it.

Reviewed-by: default avatarGary Guo <gary@garyguo.net>
Acked-by: default avatarDanilo Krummrich <dakr@kernel.org>
Link: https://patch.msgid.link/20260325-b4-nova-register-v4-8-bdf172f0f6ca@nvidia.com


[acourbot@nvidia.com: remove unused import.]
Signed-off-by: default avatarAlexandre Courbot <acourbot@nvidia.com>
parent 02ade255
Loading
Loading
Loading
Loading
+211 −329
Original line number Diff line number Diff line
@@ -15,7 +15,11 @@
    },
    io::{
        poll::read_poll_timeout,
        Io, //
        register::{
            RegisterBase,
            WithBase, //
        },
        Io,
    },
    prelude::*,
    sync::aref::ARef,
@@ -23,6 +27,7 @@
};

use crate::{
    bounded_enum,
    dma::DmaObject,
    driver::Bar0,
    falcon::hal::LoadMethod,
@@ -32,7 +37,6 @@
        FromSafeCast, //
    },
    regs,
    regs::macros::RegisterBase, //
};

pub(crate) mod gsp;
@@ -42,23 +46,11 @@
/// Alignment (in bytes) of falcon memory blocks.
pub(crate) const MEM_BLOCK_ALIGNMENT: usize = 256;

// TODO[FPRI]: Replace with `ToPrimitive`.
macro_rules! impl_from_enum_to_u8 {
    ($enum_type:ty) => {
        impl From<$enum_type> for u8 {
            fn from(value: $enum_type) -> Self {
                value as u8
            }
        }
    };
}

bounded_enum! {
    /// Revision number of a falcon core, used in the [`crate::regs::NV_PFALCON_FALCON_HWCFG1`]
    /// register.
#[repr(u8)]
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) enum FalconCoreRev {
    #[default]
    #[derive(Debug, Copy, Clone)]
    pub(crate) enum FalconCoreRev with TryFrom<Bounded<u32, 4>> {
        Rev1 = 1,
        Rev2 = 2,
        Rev3 = 3,
@@ -67,76 +59,31 @@ pub(crate) enum FalconCoreRev {
        Rev6 = 6,
        Rev7 = 7,
    }
impl_from_enum_to_u8!(FalconCoreRev);

// TODO[FPRI]: replace with `FromPrimitive`.
impl TryFrom<u8> for FalconCoreRev {
    type Error = Error;

    fn try_from(value: u8) -> Result<Self> {
        use FalconCoreRev::*;

        let rev = match value {
            1 => Rev1,
            2 => Rev2,
            3 => Rev3,
            4 => Rev4,
            5 => Rev5,
            6 => Rev6,
            7 => Rev7,
            _ => return Err(EINVAL),
        };

        Ok(rev)
    }
}

bounded_enum! {
    /// Revision subversion number of a falcon core, used in the
    /// [`crate::regs::NV_PFALCON_FALCON_HWCFG1`] register.
#[repr(u8)]
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) enum FalconCoreRevSubversion {
    #[default]
    #[derive(Debug, Copy, Clone)]
    pub(crate) enum FalconCoreRevSubversion with From<Bounded<u32, 2>> {
        Subversion0 = 0,
        Subversion1 = 1,
        Subversion2 = 2,
        Subversion3 = 3,
    }
impl_from_enum_to_u8!(FalconCoreRevSubversion);

// TODO[FPRI]: replace with `FromPrimitive`.
impl TryFrom<u8> for FalconCoreRevSubversion {
    type Error = Error;

    fn try_from(value: u8) -> Result<Self> {
        use FalconCoreRevSubversion::*;

        let sub_version = match value & 0b11 {
            0 => Subversion0,
            1 => Subversion1,
            2 => Subversion2,
            3 => Subversion3,
            _ => return Err(EINVAL),
        };

        Ok(sub_version)
    }
}

/// Security model of a falcon core, used in the [`crate::regs::NV_PFALCON_FALCON_HWCFG1`]
/// register.
#[repr(u8)]
#[derive(Debug, Default, Copy, Clone)]
bounded_enum! {
    /// Security mode of the Falcon microprocessor.
    ///
    /// See `falcon.rst` for more details.
pub(crate) enum FalconSecurityModel {
    #[derive(Debug, Copy, Clone)]
    pub(crate) enum FalconSecurityModel with TryFrom<Bounded<u32, 2>> {
        /// Non-Secure: runs unsigned code without privileges.
    #[default]
        None = 0,
        /// Light-Secured (LS): Runs signed code with some privileges.
    /// Entry into this mode is only possible from 'Heavy-secure' mode, which verifies the code's
    /// signature.
        /// Entry into this mode is only possible from 'Heavy-secure' mode, which verifies the
        /// code's signature.
        ///
        /// Also known as Low-Secure, Privilege Level 2 or PL2.
        Light = 2,
@@ -146,104 +93,44 @@ pub(crate) enum FalconSecurityModel {
        /// Also known as High-Secure, Privilege Level 3 or PL3.
        Heavy = 3,
    }
impl_from_enum_to_u8!(FalconSecurityModel);

// TODO[FPRI]: replace with `FromPrimitive`.
impl TryFrom<u8> for FalconSecurityModel {
    type Error = Error;

    fn try_from(value: u8) -> Result<Self> {
        use FalconSecurityModel::*;

        let sec_model = match value {
            0 => None,
            2 => Light,
            3 => Heavy,
            _ => return Err(EINVAL),
        };

        Ok(sec_model)
    }
}

/// Signing algorithm for a given firmware, used in the [`crate::regs::NV_PFALCON2_FALCON_MOD_SEL`]
/// register. It is passed to the Falcon Boot ROM (BROM) as a parameter.
#[repr(u8)]
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
pub(crate) enum FalconModSelAlgo {
bounded_enum! {
    /// Signing algorithm for a given firmware, used in the
    /// [`crate::regs::NV_PFALCON2_FALCON_MOD_SEL`] register. It is passed to the Falcon Boot ROM
    /// (BROM) as a parameter.
    #[derive(Debug, Copy, Clone)]
    pub(crate) enum FalconModSelAlgo with TryFrom<Bounded<u32, 8>> {
        /// AES.
    #[expect(dead_code)]
        Aes = 0,
        /// RSA3K.
    #[default]
        Rsa3k = 1,
    }
impl_from_enum_to_u8!(FalconModSelAlgo);

// TODO[FPRI]: replace with `FromPrimitive`.
impl TryFrom<u8> for FalconModSelAlgo {
    type Error = Error;

    fn try_from(value: u8) -> Result<Self> {
        match value {
            1 => Ok(FalconModSelAlgo::Rsa3k),
            _ => Err(EINVAL),
        }
    }
}

/// Valid values for the `size` field of the [`crate::regs::NV_PFALCON_FALCON_DMATRFCMD`] register.
#[repr(u8)]
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
pub(crate) enum DmaTrfCmdSize {
bounded_enum! {
    /// Valid values for the `size` field of the [`crate::regs::NV_PFALCON_FALCON_DMATRFCMD`]
    /// register.
    #[derive(Debug, Copy, Clone)]
    pub(crate) enum DmaTrfCmdSize with TryFrom<Bounded<u32, 3>> {
        /// 256 bytes transfer.
    #[default]
        Size256B = 0x6,
    }
impl_from_enum_to_u8!(DmaTrfCmdSize);

// TODO[FPRI]: replace with `FromPrimitive`.
impl TryFrom<u8> for DmaTrfCmdSize {
    type Error = Error;

    fn try_from(value: u8) -> Result<Self> {
        match value {
            0x6 => Ok(Self::Size256B),
            _ => Err(EINVAL),
        }
    }
}

bounded_enum! {
    /// Currently active core on a dual falcon/riscv (Peregrine) controller.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub(crate) enum PeregrineCoreSelect {
    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
    pub(crate) enum PeregrineCoreSelect with From<Bounded<u32, 1>> {
        /// Falcon core is active.
    #[default]
        Falcon = 0,
        /// RISC-V core is active.
        Riscv = 1,
    }

impl From<bool> for PeregrineCoreSelect {
    fn from(value: bool) -> Self {
        match value {
            false => PeregrineCoreSelect::Falcon,
            true => PeregrineCoreSelect::Riscv,
        }
    }
}

impl From<PeregrineCoreSelect> for bool {
    fn from(value: PeregrineCoreSelect) -> Self {
        match value {
            PeregrineCoreSelect::Falcon => false,
            PeregrineCoreSelect::Riscv => true,
        }
    }
}

/// Different types of memory present in a falcon core.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(crate) enum FalconMem {
    /// Secure Instruction Memory.
    ImemSecure,
@@ -254,13 +141,12 @@ pub(crate) enum FalconMem {
    Dmem,
}

bounded_enum! {
    /// Defines the Framebuffer Interface (FBIF) aperture type.
    /// This determines the memory type for external memory access during a DMA transfer, which is
    /// performed by the Falcon's Framebuffer DMA (FBDMA) engine. See falcon.rst for more details.
#[derive(Debug, Clone, Default)]
pub(crate) enum FalconFbifTarget {
    /// VRAM.
    #[default]
    #[derive(Debug, Copy, Clone)]
    pub(crate) enum FalconFbifTarget with TryFrom<Bounded<u32, 2>> {
        /// Local Framebuffer (GPU's VRAM memory).
        LocalFb = 0,
        /// Coherent system memory (System DRAM).
@@ -268,51 +154,17 @@ pub(crate) enum FalconFbifTarget {
        /// Non-coherent system memory (System DRAM).
        NoncoherentSysmem = 2,
    }
impl_from_enum_to_u8!(FalconFbifTarget);

// TODO[FPRI]: replace with `FromPrimitive`.
impl TryFrom<u8> for FalconFbifTarget {
    type Error = Error;

    fn try_from(value: u8) -> Result<Self> {
        let res = match value {
            0 => Self::LocalFb,
            1 => Self::CoherentSysmem,
            2 => Self::NoncoherentSysmem,
            _ => return Err(EINVAL),
        };

        Ok(res)
    }
}

bounded_enum! {
    /// Type of memory addresses to use.
#[derive(Debug, Clone, Default)]
pub(crate) enum FalconFbifMemType {
    #[derive(Debug, Copy, Clone)]
    pub(crate) enum FalconFbifMemType with From<Bounded<u32, 1>> {
        /// Virtual memory addresses.
    #[default]
        Virtual = 0,
        /// Physical memory addresses.
        Physical = 1,
    }

/// Conversion from a single-bit register field.
impl From<bool> for FalconFbifMemType {
    fn from(value: bool) -> Self {
        match value {
            false => Self::Virtual,
            true => Self::Physical,
        }
    }
}

impl From<FalconFbifMemType> for bool {
    fn from(value: FalconFbifMemType) -> Self {
        match value {
            FalconFbifMemType::Virtual => false,
            FalconFbifMemType::Physical => true,
        }
    }
}

/// Type used to represent the `PFALCON` registers address base for a given falcon engine.
@@ -323,13 +175,10 @@ fn from(value: FalconFbifMemType) -> Self {

/// Trait defining the parameters of a given Falcon engine.
///
/// Each engine provides one base for `PFALCON` and `PFALCON2` registers. The `ID` constant is used
/// to identify a given Falcon instance with register I/O methods.
/// Each engine provides one base for `PFALCON` and `PFALCON2` registers.
pub(crate) trait FalconEngine:
    Send + Sync + RegisterBase<PFalconBase> + RegisterBase<PFalcon2Base> + Sized
{
    /// Singleton of the engine, used to identify it with register I/O methods.
    const ID: Self;
}

/// Represents a portion of the firmware to be loaded into a particular memory (e.g. IMEM or DMEM)
@@ -523,8 +372,14 @@ pub(crate) fn new(dev: &device::Device, chipset: Chipset) -> Result<Self> {

    /// Resets DMA-related registers.
    pub(crate) fn dma_reset(&self, bar: &Bar0) {
        regs::NV_PFALCON_FBIF_CTL::update(bar, &E::ID, |v| v.set_allow_phys_no_ctx(true));
        regs::NV_PFALCON_FALCON_DMACTL::default().write(bar, &E::ID);
        bar.update(regs::NV_PFALCON_FBIF_CTL::of::<E>(), |v| {
            v.with_allow_phys_no_ctx(true)
        });

        bar.write(
            WithBase::of::<E>(),
            regs::NV_PFALCON_FALCON_DMACTL::zeroed(),
        );
    }

    /// Reset the controller, select the falcon core, and wait for memory scrubbing to complete.
@@ -533,9 +388,10 @@ pub(crate) fn reset(&self, bar: &Bar0) -> Result {
        self.hal.select_core(self, bar)?;
        self.hal.reset_wait_mem_scrubbing(bar)?;

        regs::NV_PFALCON_FALCON_RM::default()
            .set_value(bar.read(regs::NV_PMC_BOOT_0).into())
            .write(bar, &E::ID);
        bar.write(
            WithBase::of::<E>(),
            regs::NV_PFALCON_FALCON_RM::from(bar.read(regs::NV_PMC_BOOT_0).into_raw()),
        );

        Ok(())
    }
@@ -553,25 +409,27 @@ fn pio_wr_imem_slice(&self, bar: &Bar0, load_offsets: FalconPioImemLoadTarget<'_
            return Err(EINVAL);
        }

        regs::NV_PFALCON_FALCON_IMEMC::default()
            .set_secure(load_offsets.secure)
            .set_aincw(true)
            .set_offs(load_offsets.dst_start)
            .write(bar, &E::ID, Self::PIO_PORT);
        bar.write(
            WithBase::of::<E>().at(Self::PIO_PORT),
            regs::NV_PFALCON_FALCON_IMEMC::zeroed()
                .with_secure(load_offsets.secure)
                .with_aincw(true)
                .with_offs(load_offsets.dst_start),
        );

        for (n, block) in load_offsets.data.chunks(MEM_BLOCK_ALIGNMENT).enumerate() {
            let n = u16::try_from(n)?;
            let tag: u16 = load_offsets.start_tag.checked_add(n).ok_or(ERANGE)?;
            regs::NV_PFALCON_FALCON_IMEMT::default().set_tag(tag).write(
                bar,
                &E::ID,
                Self::PIO_PORT,
            bar.write(
                WithBase::of::<E>().at(Self::PIO_PORT),
                regs::NV_PFALCON_FALCON_IMEMT::zeroed().with_tag(tag),
            );
            for word in block.chunks_exact(4) {
                let w = [word[0], word[1], word[2], word[3]];
                regs::NV_PFALCON_FALCON_IMEMD::default()
                    .set_data(u32::from_le_bytes(w))
                    .write(bar, &E::ID, Self::PIO_PORT);
                bar.write(
                    WithBase::of::<E>().at(Self::PIO_PORT),
                    regs::NV_PFALCON_FALCON_IMEMD::zeroed().with_data(u32::from_le_bytes(w)),
                );
            }
        }

@@ -588,16 +446,19 @@ fn pio_wr_dmem_slice(&self, bar: &Bar0, load_offsets: FalconPioDmemLoadTarget<'_
            return Err(EINVAL);
        }

        regs::NV_PFALCON_FALCON_DMEMC::default()
            .set_aincw(true)
            .set_offs(load_offsets.dst_start)
            .write(bar, &E::ID, Self::PIO_PORT);
        bar.write(
            WithBase::of::<E>().at(Self::PIO_PORT),
            regs::NV_PFALCON_FALCON_DMEMC::zeroed()
                .with_aincw(true)
                .with_offs(load_offsets.dst_start),
        );

        for word in load_offsets.data.chunks_exact(4) {
            let w = [word[0], word[1], word[2], word[3]];
            regs::NV_PFALCON_FALCON_DMEMD::default()
                .set_data(u32::from_le_bytes(w))
                .write(bar, &E::ID, Self::PIO_PORT);
            bar.write(
                WithBase::of::<E>().at(Self::PIO_PORT),
                regs::NV_PFALCON_FALCON_DMEMD::zeroed().with_data(u32::from_le_bytes(w)),
            );
        }

        Ok(())
@@ -609,11 +470,14 @@ pub(crate) fn pio_load<F: FalconFirmware<Target = E> + FalconPioLoadable>(
        bar: &Bar0,
        fw: &F,
    ) -> Result {
        regs::NV_PFALCON_FBIF_CTL::read(bar, &E::ID)
            .set_allow_phys_no_ctx(true)
            .write(bar, &E::ID);
        bar.update(regs::NV_PFALCON_FBIF_CTL::of::<E>(), |v| {
            v.with_allow_phys_no_ctx(true)
        });

        regs::NV_PFALCON_FALCON_DMACTL::default().write(bar, &E::ID);
        bar.write(
            WithBase::of::<E>(),
            regs::NV_PFALCON_FALCON_DMACTL::zeroed(),
        );

        if let Some(imem_ns) = fw.imem_ns_load_params() {
            self.pio_wr_imem_slice(bar, imem_ns)?;
@@ -625,9 +489,10 @@ pub(crate) fn pio_load<F: FalconFirmware<Target = E> + FalconPioLoadable>(

        self.hal.program_brom(self, bar, &fw.brom_params())?;

        regs::NV_PFALCON_FALCON_BOOTVEC::default()
            .set_value(fw.boot_addr())
            .write(bar, &E::ID);
        bar.write(
            WithBase::of::<E>(),
            regs::NV_PFALCON_FALCON_BOOTVEC::zeroed().with_value(fw.boot_addr()),
        );

        Ok(())
    }
@@ -696,36 +561,42 @@ fn dma_wr(

        // Set up the base source DMA address.

        regs::NV_PFALCON_FALCON_DMATRFBASE::default()
            // CAST: `as u32` is used on purpose since we do want to strip the upper bits, which
            // will be written to `NV_PFALCON_FALCON_DMATRFBASE1`.
            .set_base((dma_start >> 8) as u32)
            .write(bar, &E::ID);
        regs::NV_PFALCON_FALCON_DMATRFBASE1::default()
            // CAST: `as u16` is used on purpose since the remaining bits are guaranteed to fit
            // within a `u16`.
            .set_base((dma_start >> 40) as u16)
            .write(bar, &E::ID);

        let cmd = regs::NV_PFALCON_FALCON_DMATRFCMD::default()
            .set_size(DmaTrfCmdSize::Size256B)
        bar.write(
            WithBase::of::<E>(),
            regs::NV_PFALCON_FALCON_DMATRFBASE::zeroed().with_base(
                // CAST: `as u32` is used on purpose since we do want to strip the upper bits,
                // which will be written to `NV_PFALCON_FALCON_DMATRFBASE1`.
                (dma_start >> 8) as u32,
            ),
        );
        bar.write(
            WithBase::of::<E>(),
            regs::NV_PFALCON_FALCON_DMATRFBASE1::zeroed().try_with_base(dma_start >> 40)?,
        );

        let cmd = regs::NV_PFALCON_FALCON_DMATRFCMD::zeroed()
            .with_size(DmaTrfCmdSize::Size256B)
            .with_falcon_mem(target_mem);

        for pos in (0..num_transfers).map(|i| i * DMA_LEN) {
            // Perform a transfer of size `DMA_LEN`.
            regs::NV_PFALCON_FALCON_DMATRFMOFFS::default()
                .set_offs(load_offsets.dst_start + pos)
                .write(bar, &E::ID);
            regs::NV_PFALCON_FALCON_DMATRFFBOFFS::default()
                .set_offs(src_start + pos)
                .write(bar, &E::ID);
            cmd.write(bar, &E::ID);
            bar.write(
                WithBase::of::<E>(),
                regs::NV_PFALCON_FALCON_DMATRFMOFFS::zeroed()
                    .try_with_offs(load_offsets.dst_start + pos)?,
            );
            bar.write(
                WithBase::of::<E>(),
                regs::NV_PFALCON_FALCON_DMATRFFBOFFS::zeroed().with_offs(src_start + pos),
            );

            bar.write(WithBase::of::<E>(), cmd);

            // Wait for the transfer to complete.
            // TIMEOUT: arbitrarily large value, no DMA transfer to the falcon's small memories
            // should ever take that long.
            read_poll_timeout(
                || Ok(regs::NV_PFALCON_FALCON_DMATRFCMD::read(bar, &E::ID)),
                || Ok(bar.read(regs::NV_PFALCON_FALCON_DMATRFCMD::of::<E>())),
                |r| r.idle(),
                Delta::ZERO,
                Delta::from_secs(2),
@@ -746,9 +617,9 @@ fn dma_load<F: FalconFirmware<Target = E> + FalconDmaLoadable>(
        let dma_obj = DmaObject::from_data(dev, fw.as_slice())?;

        self.dma_reset(bar);
        regs::NV_PFALCON_FBIF_TRANSCFG::update(bar, &E::ID, 0, |v| {
            v.set_target(FalconFbifTarget::CoherentSysmem)
                .set_mem_type(FalconFbifMemType::Physical)
        bar.update(regs::NV_PFALCON_FBIF_TRANSCFG::of::<E>().at(0), |v| {
            v.with_target(FalconFbifTarget::CoherentSysmem)
                .with_mem_type(FalconFbifMemType::Physical)
        });

        self.dma_wr(
@@ -762,9 +633,10 @@ fn dma_load<F: FalconFirmware<Target = E> + FalconDmaLoadable>(
        self.hal.program_brom(self, bar, &fw.brom_params())?;

        // Set `BootVec` to start of non-secure code.
        regs::NV_PFALCON_FALCON_BOOTVEC::default()
            .set_value(fw.boot_addr())
            .write(bar, &E::ID);
        bar.write(
            WithBase::of::<E>(),
            regs::NV_PFALCON_FALCON_BOOTVEC::zeroed().with_value(fw.boot_addr()),
        );

        Ok(())
    }
@@ -773,7 +645,7 @@ fn dma_load<F: FalconFirmware<Target = E> + FalconDmaLoadable>(
    pub(crate) fn wait_till_halted(&self, bar: &Bar0) -> Result<()> {
        // TIMEOUT: arbitrarily large value, firmwares should complete in less than 2 seconds.
        read_poll_timeout(
            || Ok(regs::NV_PFALCON_FALCON_CPUCTL::read(bar, &E::ID)),
            || Ok(bar.read(regs::NV_PFALCON_FALCON_CPUCTL::of::<E>())),
            |r| r.halted(),
            Delta::ZERO,
            Delta::from_secs(2),
@@ -784,13 +656,18 @@ pub(crate) fn wait_till_halted(&self, bar: &Bar0) -> Result<()> {

    /// Start the falcon CPU.
    pub(crate) fn start(&self, bar: &Bar0) -> Result<()> {
        match regs::NV_PFALCON_FALCON_CPUCTL::read(bar, &E::ID).alias_en() {
            true => regs::NV_PFALCON_FALCON_CPUCTL_ALIAS::default()
                .set_startcpu(true)
                .write(bar, &E::ID),
            false => regs::NV_PFALCON_FALCON_CPUCTL::default()
                .set_startcpu(true)
                .write(bar, &E::ID),
        match bar
            .read(regs::NV_PFALCON_FALCON_CPUCTL::of::<E>())
            .alias_en()
        {
            true => bar.write(
                WithBase::of::<E>(),
                regs::NV_PFALCON_FALCON_CPUCTL_ALIAS::zeroed().with_startcpu(true),
            ),
            false => bar.write(
                WithBase::of::<E>(),
                regs::NV_PFALCON_FALCON_CPUCTL::zeroed().with_startcpu(true),
            ),
        }

        Ok(())
@@ -799,26 +676,30 @@ pub(crate) fn start(&self, bar: &Bar0) -> Result<()> {
    /// Writes values to the mailbox registers if provided.
    pub(crate) fn write_mailboxes(&self, bar: &Bar0, mbox0: Option<u32>, mbox1: Option<u32>) {
        if let Some(mbox0) = mbox0 {
            regs::NV_PFALCON_FALCON_MAILBOX0::default()
                .set_value(mbox0)
                .write(bar, &E::ID);
            bar.write(
                WithBase::of::<E>(),
                regs::NV_PFALCON_FALCON_MAILBOX0::zeroed().with_value(mbox0),
            );
        }

        if let Some(mbox1) = mbox1 {
            regs::NV_PFALCON_FALCON_MAILBOX1::default()
                .set_value(mbox1)
                .write(bar, &E::ID);
            bar.write(
                WithBase::of::<E>(),
                regs::NV_PFALCON_FALCON_MAILBOX1::zeroed().with_value(mbox1),
            );
        }
    }

    /// Reads the value from `mbox0` register.
    pub(crate) fn read_mailbox0(&self, bar: &Bar0) -> u32 {
        regs::NV_PFALCON_FALCON_MAILBOX0::read(bar, &E::ID).value()
        bar.read(regs::NV_PFALCON_FALCON_MAILBOX0::of::<E>())
            .value()
    }

    /// Reads the value from `mbox1` register.
    pub(crate) fn read_mailbox1(&self, bar: &Bar0) -> u32 {
        regs::NV_PFALCON_FALCON_MAILBOX1::read(bar, &E::ID).value()
        bar.read(regs::NV_PFALCON_FALCON_MAILBOX1::of::<E>())
            .value()
    }

    /// Reads values from both mailbox registers.
@@ -883,8 +764,9 @@ pub(crate) fn load<F: FalconFirmware<Target = E> + FalconDmaLoadable>(

    /// Write the application version to the OS register.
    pub(crate) fn write_os_version(&self, bar: &Bar0, app_version: u32) {
        regs::NV_PFALCON_FALCON_OS::default()
            .set_value(app_version)
            .write(bar, &E::ID);
        bar.write(
            WithBase::of::<E>(),
            regs::NV_PFALCON_FALCON_OS::zeroed().with_value(app_version),
        );
    }
}
+11 −11
Original line number Diff line number Diff line
@@ -3,7 +3,11 @@
use kernel::{
    io::{
        poll::read_poll_timeout,
        Io, //
        register::{
            RegisterBase,
            WithBase, //
        },
        Io,
    },
    prelude::*,
    time::Delta, //
@@ -17,10 +21,7 @@
        PFalcon2Base,
        PFalconBase, //
    },
    regs::{
        self,
        macros::RegisterBase, //
    },
    regs,
};

/// Type specifying the `Gsp` falcon engine. Cannot be instantiated.
@@ -34,17 +35,16 @@ impl RegisterBase<PFalcon2Base> for Gsp {
    const BASE: usize = 0x00111000;
}

impl FalconEngine for Gsp {
    const ID: Self = Gsp(());
}
impl FalconEngine for Gsp {}

impl Falcon<Gsp> {
    /// Clears the SWGEN0 bit in the Falcon's IRQ status clear register to
    /// allow GSP to signal CPU for processing new messages in message queue.
    pub(crate) fn clear_swgen0_intr(&self, bar: &Bar0) {
        regs::NV_PFALCON_FALCON_IRQSCLR::default()
            .set_swgen0(true)
            .write(bar, &Gsp::ID);
        bar.write(
            WithBase::of::<Gsp>(),
            regs::NV_PFALCON_FALCON_IRQSCLR::zeroed().with_swgen0(true),
        );
    }

    /// Checks if GSP reload/resume has completed during the boot process.
+32 −23

File changed.

Preview size limit exceeded, changes collapsed.

+8 −4
Original line number Diff line number Diff line
@@ -3,7 +3,11 @@
use core::marker::PhantomData;

use kernel::{
    io::poll::read_poll_timeout,
    io::{
        poll::read_poll_timeout,
        register::WithBase,
        Io, //
    },
    prelude::*,
    time::Delta, //
};
@@ -49,14 +53,14 @@ fn program_brom(&self, _falcon: &Falcon<E>, _bar: &Bar0, _params: &FalconBromPar
    }

    fn is_riscv_active(&self, bar: &Bar0) -> bool {
        let cpuctl = regs::NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS::read(bar, &E::ID);
        cpuctl.active_stat()
        bar.read(regs::NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS::of::<E>())
            .active_stat()
    }

    fn reset_wait_mem_scrubbing(&self, bar: &Bar0) -> Result {
        // TIMEOUT: memory scrubbing should complete in less than 10ms.
        read_poll_timeout(
            || Ok(regs::NV_PFALCON_FALCON_DMACTL::read(bar, &E::ID)),
            || Ok(bar.read(regs::NV_PFALCON_FALCON_DMACTL::of::<E>())),
            |r| r.mem_scrubbing_done(),
            Delta::ZERO,
            Delta::from_millis(10),
+7 −10
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0

use crate::{
    falcon::{
use kernel::io::register::RegisterBase;

use crate::falcon::{
    FalconEngine,
    PFalcon2Base,
    PFalconBase, //
    },
    regs::macros::RegisterBase,
};

/// Type specifying the `Sec2` falcon engine. Cannot be instantiated.
@@ -20,6 +19,4 @@ impl RegisterBase<PFalcon2Base> for Sec2 {
    const BASE: usize = 0x00841000;
}

impl FalconEngine for Sec2 {
    const ID: Self = Sec2(());
}
impl FalconEngine for Sec2 {}
Loading