Boot the GSP to the RISC-V active state. Completing the boot requires running the CPU sequencer which will be added in a future commit.
Signed-off-by: Alistair Popple <[email protected]> Reviewed-by: Lyude Paul <[email protected]> --- Changes for v4: - Switch wait_on to read_poll_timeout Changes for v3: - Fixed minor nit from John - Added booter load error thanks to Timur's suggestion Changes for v2: - Rebased on Alex's latest tree --- drivers/gpu/nova-core/falcon.rs | 2 - drivers/gpu/nova-core/firmware/riscv.rs | 3 +- drivers/gpu/nova-core/gsp.rs | 2 +- drivers/gpu/nova-core/gsp/boot.rs | 63 ++++++++++++++++++++++++- 4 files changed, 64 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon.rs index 01869b8deb8a..3ee41aacf488 100644 --- a/drivers/gpu/nova-core/falcon.rs +++ b/drivers/gpu/nova-core/falcon.rs @@ -510,14 +510,12 @@ pub(crate) fn signature_reg_fuse_version( /// Check if the RISC-V core is active. /// /// Returns `true` if the RISC-V core is active, `false` otherwise. - #[expect(unused)] pub(crate) fn is_riscv_active(&self, bar: &Bar0) -> bool { let cpuctl = regs::NV_PRISCV_RISCV_CPUCTL::read(bar, &E::ID); cpuctl.active_stat() } /// Write the application version to the OS register. - #[expect(dead_code)] pub(crate) fn write_os_version(&self, bar: &Bar0, app_version: u32) -> Result<()> { regs::NV_PFALCON_FALCON_OS::default() .set_value(app_version) diff --git a/drivers/gpu/nova-core/firmware/riscv.rs b/drivers/gpu/nova-core/firmware/riscv.rs index 76d0d36fee3e..87f2e16bc216 100644 --- a/drivers/gpu/nova-core/firmware/riscv.rs +++ b/drivers/gpu/nova-core/firmware/riscv.rs @@ -52,7 +52,6 @@ fn new(bin_fw: &BinFirmware<'_>) -> Result<Self> { } /// A parsed firmware for a RISC-V core, ready to be loaded and run. -#[expect(unused)] pub(crate) struct RiscvFirmware { /// Offset at which the code starts in the firmware image. pub code_offset: u32, @@ -61,7 +60,7 @@ pub(crate) struct RiscvFirmware { /// Offset at which the manifest starts in the firmware image. pub manifest_offset: u32, /// Application version. - app_version: u32, + pub app_version: u32, /// Device-mapped firmware image. pub ucode: DmaObject, } diff --git a/drivers/gpu/nova-core/gsp.rs b/drivers/gpu/nova-core/gsp.rs index 9b6abb9755ba..0417da8525a8 100644 --- a/drivers/gpu/nova-core/gsp.rs +++ b/drivers/gpu/nova-core/gsp.rs @@ -35,7 +35,7 @@ /// GSP runtime data. #[pin_data] pub(crate) struct Gsp { - libos: CoherentAllocation<LibosMemoryRegionInitArgument>, + pub libos: CoherentAllocation<LibosMemoryRegionInitArgument>, pub loginit: CoherentAllocation<u8>, pub logintr: CoherentAllocation<u8>, pub logrm: CoherentAllocation<u8>, diff --git a/drivers/gpu/nova-core/gsp/boot.rs b/drivers/gpu/nova-core/gsp/boot.rs index 0b306313ec53..7ba7932119e9 100644 --- a/drivers/gpu/nova-core/gsp/boot.rs +++ b/drivers/gpu/nova-core/gsp/boot.rs @@ -3,8 +3,10 @@ use kernel::device; use kernel::dma::CoherentAllocation; use kernel::dma_write; +use kernel::io::poll::read_poll_timeout; use kernel::pci; use kernel::prelude::*; +use kernel::time::Delta; use crate::driver::Bar0; use crate::falcon::{gsp::Gsp, sec2::Sec2, Falcon}; @@ -127,7 +129,7 @@ pub(crate) fn boot( Self::run_fwsec_frts(dev, gsp_falcon, bar, &bios, &fb_layout)?; - let _booter_loader = BooterFirmware::new( + let booter_loader = BooterFirmware::new( dev, BooterKind::Loader, chipset, @@ -143,6 +145,65 @@ pub(crate) fn boot( set_system_info(&mut self.cmdq, pdev, bar)?; build_registry(&mut self.cmdq, bar)?; + gsp_falcon.reset(bar)?; + let libos_handle = self.libos.dma_handle(); + let (mbox0, mbox1) = gsp_falcon.boot( + bar, + Some(libos_handle as u32), + Some((libos_handle >> 32) as u32), + )?; + dev_dbg!( + pdev.as_ref(), + "GSP MBOX0: {:#x}, MBOX1: {:#x}\n", + mbox0, + mbox1 + ); + + dev_dbg!( + pdev.as_ref(), + "Using SEC2 to load and run the booter_load firmware...\n" + ); + + sec2_falcon.reset(bar)?; + sec2_falcon.dma_load(bar, &booter_loader)?; + let wpr_handle = wpr_meta.dma_handle(); + let (mbox0, mbox1) = sec2_falcon.boot( + bar, + Some(wpr_handle as u32), + Some((wpr_handle >> 32) as u32), + )?; + dev_dbg!( + pdev.as_ref(), + "SEC2 MBOX0: {:#x}, MBOX1{:#x}\n", + mbox0, + mbox1 + ); + + if mbox0 != 0 { + dev_err!( + pdev.as_ref(), + "Booter-load failed with error {:#x}\n", + mbox0 + ); + return Err(ENODEV); + } + + gsp_falcon.write_os_version(bar, gsp_fw.bootloader.app_version)?; + + // Poll for RISC-V to become active before running sequencer + read_poll_timeout( + || Ok(gsp_falcon.is_riscv_active(bar)), + |val: &bool| *val, + Delta::from_millis(10), + Delta::from_secs(5), + )?; + + dev_dbg!( + pdev.as_ref(), + "RISC-V active? {}\n", + gsp_falcon.is_riscv_active(bar), + ); + Ok(()) } } -- 2.50.1
