Commit 82ed3243 authored by Timur Tabi's avatar Timur Tabi Committed by Alexandre Courbot
Browse files

gpu: nova-core: move some functions into the HAL



A few Falcon methods are actually GPU-specific, so move them
into the HAL.

Signed-off-by: default avatarTimur Tabi <ttabi@nvidia.com>
Reviewed-by: default avatarJohn Hubbard <jhubbard@nvidia.com>
Reviewed-by: default avatarGary Guo <gary@garyguo.net>
Acked-by: default avatarDanilo Krummrich <dakr@kernel.org>
Link: https://patch.msgid.link/20260122222848.2555890-7-ttabi@nvidia.com


Signed-off-by: default avatarAlexandre Courbot <acourbot@nvidia.com>
parent f6507640
Loading
Loading
Loading
Loading
+3 −42
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@
    prelude::*,
    sync::aref::ARef,
    time::{
        delay::fsleep,
        Delta, //
    },
};
@@ -398,48 +397,11 @@ pub(crate) fn dma_reset(&self, bar: &Bar0) {
        regs::NV_PFALCON_FALCON_DMACTL::default().write(bar, &E::ID);
    }

    /// Wait for memory scrubbing to complete.
    fn reset_wait_mem_scrubbing(&self, bar: &Bar0) -> Result {
        // TIMEOUT: memory scrubbing should complete in less than 20ms.
        read_poll_timeout(
            || Ok(regs::NV_PFALCON_FALCON_HWCFG2::read(bar, &E::ID)),
            |r| r.mem_scrubbing_done(),
            Delta::ZERO,
            Delta::from_millis(20),
        )
        .map(|_| ())
    }

    /// Reset the falcon engine.
    fn reset_eng(&self, bar: &Bar0) -> Result {
        let _ = regs::NV_PFALCON_FALCON_HWCFG2::read(bar, &E::ID);

        // According to OpenRM's `kflcnPreResetWait_GA102` documentation, HW sometimes does not set
        // RESET_READY so a non-failing timeout is used.
        let _ = read_poll_timeout(
            || Ok(regs::NV_PFALCON_FALCON_HWCFG2::read(bar, &E::ID)),
            |r| r.reset_ready(),
            Delta::ZERO,
            Delta::from_micros(150),
        );

        regs::NV_PFALCON_FALCON_ENGINE::update(bar, &E::ID, |v| v.set_reset(true));

        // TIMEOUT: falcon engine should not take more than 10us to reset.
        fsleep(Delta::from_micros(10));

        regs::NV_PFALCON_FALCON_ENGINE::update(bar, &E::ID, |v| v.set_reset(false));

        self.reset_wait_mem_scrubbing(bar)?;

        Ok(())
    }

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

        regs::NV_PFALCON_FALCON_RM::default()
            .set_value(regs::NV_PMC_BOOT_0::read(bar).into())
@@ -674,8 +636,7 @@ pub(crate) fn signature_reg_fuse_version(
    ///
    /// Returns `true` if the RISC-V core is active, `false` otherwise.
    pub(crate) fn is_riscv_active(&self, bar: &Bar0) -> bool {
        let cpuctl = regs::NV_PRISCV_RISCV_CPUCTL::read(bar, &E::ID);
        cpuctl.active_stat()
        self.hal.is_riscv_active(bar)
    }

    /// Write the application version to the OS register.
+10 −0
Original line number Diff line number Diff line
@@ -37,6 +37,16 @@ fn signature_reg_fuse_version(

    /// Program the boot ROM registers prior to starting a secure firmware.
    fn program_brom(&self, falcon: &Falcon<E>, bar: &Bar0, params: &FalconBromParams) -> Result;

    /// Check if the RISC-V core is active.
    /// Returns `true` if the RISC-V core is active, `false` otherwise.
    fn is_riscv_active(&self, bar: &Bar0) -> bool;

    /// Wait for memory scrubbing to complete.
    fn reset_wait_mem_scrubbing(&self, bar: &Bar0) -> Result;

    /// Reset the falcon engine.
    fn reset_eng(&self, bar: &Bar0) -> Result;
}

/// Returns a boxed falcon HAL adequate for `chipset`.
+41 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
    device,
    io::poll::read_poll_timeout,
    prelude::*,
    time::delay::fsleep,
    time::Delta, //
};

@@ -117,4 +118,44 @@ fn signature_reg_fuse_version(
    fn program_brom(&self, _falcon: &Falcon<E>, bar: &Bar0, params: &FalconBromParams) -> Result {
        program_brom_ga102::<E>(bar, params)
    }

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

    fn reset_wait_mem_scrubbing(&self, bar: &Bar0) -> Result {
        // TIMEOUT: memory scrubbing should complete in less than 20ms.
        read_poll_timeout(
            || Ok(regs::NV_PFALCON_FALCON_HWCFG2::read(bar, &E::ID)),
            |r| r.mem_scrubbing_done(),
            Delta::ZERO,
            Delta::from_millis(20),
        )
        .map(|_| ())
    }

    fn reset_eng(&self, bar: &Bar0) -> Result {
        let _ = regs::NV_PFALCON_FALCON_HWCFG2::read(bar, &E::ID);

        // According to OpenRM's `kflcnPreResetWait_GA102` documentation, HW sometimes does not set
        // RESET_READY so a non-failing timeout is used.
        let _ = read_poll_timeout(
            || Ok(regs::NV_PFALCON_FALCON_HWCFG2::read(bar, &E::ID)),
            |r| r.reset_ready(),
            Delta::ZERO,
            Delta::from_micros(150),
        );

        regs::NV_PFALCON_FALCON_ENGINE::update(bar, &E::ID, |v| v.set_reset(true));

        // TIMEOUT: falcon engine should not take more than 10us to reset.
        fsleep(Delta::from_micros(10));

        regs::NV_PFALCON_FALCON_ENGINE::update(bar, &E::ID, |v| v.set_reset(false));

        self.reset_wait_mem_scrubbing(bar)?;

        Ok(())
    }
}