diff options
| author | John Hubbard <jhubbard@nvidia.com> | 2026-06-03 16:30:18 +0900 |
|---|---|---|
| committer | Alexandre Courbot <acourbot@nvidia.com> | 2026-06-03 22:11:07 +0900 |
| commit | 6d6c3189f9b2b143efe1f536e8ea8b082e054a01 (patch) | |
| tree | 2de07f18f5993c9198b8bc97e15e6256d55961ad /drivers/gpu/nova-core | |
| parent | 0023a1e8d01a9d400257d30c851bd16a29568809 (diff) | |
| download | lwn-6d6c3189f9b2b143efe1f536e8ea8b082e054a01.tar.gz lwn-6d6c3189f9b2b143efe1f536e8ea8b082e054a01.zip | |
gpu: nova-core: Hopper/Blackwell: add FSP falcon EMEM operations
Add external memory (EMEM) read/write operations to the GPU's FSP falcon
engine. These operations use Falcon PIO (Programmed I/O) to communicate
with the FSP through indirect memory access.
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
Reviewed-by: Eliot Courtney <ecourtney@nvidia.com>
Link: https://patch.msgid.link/20260603-b4-blackwell-v13-1-d9f3a06939e0@nvidia.com
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Diffstat (limited to 'drivers/gpu/nova-core')
| -rw-r--r-- | drivers/gpu/nova-core/falcon/fsp.rs | 80 | ||||
| -rw-r--r-- | drivers/gpu/nova-core/regs.rs | 18 |
2 files changed, 93 insertions, 5 deletions
diff --git a/drivers/gpu/nova-core/falcon/fsp.rs b/drivers/gpu/nova-core/falcon/fsp.rs index d9f87262e8b1..0956a75ef7aa 100644 --- a/drivers/gpu/nova-core/falcon/fsp.rs +++ b/drivers/gpu/nova-core/falcon/fsp.rs @@ -6,12 +6,26 @@ //! The FSP falcon handles secure boot and Chain of Trust operations //! on Hopper and Blackwell architectures, replacing SEC2's role. -use kernel::io::register::RegisterBase; +use kernel::{ + io::{ + register::{ + RegisterBase, + WithBase, // + }, + Io, // + }, + prelude::*, +}; -use crate::falcon::{ - FalconEngine, - PFalcon2Base, - PFalconBase, // +use crate::{ + driver::Bar0, + falcon::{ + Falcon, + FalconEngine, + PFalcon2Base, + PFalconBase, // + }, + regs, }; /// Type specifying the `Fsp` falcon engine. Cannot be instantiated. @@ -26,3 +40,59 @@ impl RegisterBase<PFalcon2Base> for Fsp { } impl FalconEngine for Fsp {} + +impl Falcon<Fsp> { + /// Writes `data` to FSP external memory at offset `0`. + /// + /// `data` is interpreted as little-endian 32-bit words. Returns `EINVAL` + /// if the `data` length is not 4-byte aligned. + #[expect(dead_code)] + fn write_emem(&mut self, bar: &Bar0, data: &[u8]) -> Result { + if data.len() % 4 != 0 { + return Err(EINVAL); + } + + // Begin a write burst at offset `0`, auto-incrementing on each write. + bar.write( + WithBase::of::<Fsp>(), + regs::NV_PFALCON_FALCON_EMEMC::zeroed().with_aincw(true), + ); + + for chunk in data.chunks_exact(4) { + let value = u32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]); + + // Write the next 32-bit `value`; hardware advances the offset. + bar.write( + WithBase::of::<Fsp>(), + regs::NV_PFALCON_FALCON_EMEMD::zeroed().with_data(value), + ); + } + + Ok(()) + } + + /// Reads FSP external memory from offset `0` into `data`. + /// + /// `data` is stored as little-endian 32-bit words. Returns `EINVAL` if + /// the `data` length is not 4-byte aligned. + #[expect(dead_code)] + fn read_emem(&mut self, bar: &Bar0, data: &mut [u8]) -> Result { + if data.len() % 4 != 0 { + return Err(EINVAL); + } + + // Begin a read burst at offset `0`, auto-incrementing on each read. + bar.write( + WithBase::of::<Fsp>(), + regs::NV_PFALCON_FALCON_EMEMC::zeroed().with_aincr(true), + ); + + for chunk in data.chunks_exact_mut(4) { + // Read the next 32-bit word; hardware advances the offset. + let value = bar.read(regs::NV_PFALCON_FALCON_EMEMD::of::<Fsp>()).data(); + chunk.copy_from_slice(&value.to_le_bytes()); + } + + Ok(()) + } +} diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs index 2cb1f02f35a4..e602c7860459 100644 --- a/drivers/gpu/nova-core/regs.rs +++ b/drivers/gpu/nova-core/regs.rs @@ -475,6 +475,24 @@ register! { pub(crate) NV_PFALCON_FBIF_CTL(u32) @ PFalconBase + 0x00000624 { 7:7 allow_phys_no_ctx => bool; } + + // Falcon EMEM PIO registers (used by FSP on Hopper/Blackwell). + // These provide the falcon external memory communication interface. + + pub(crate) NV_PFALCON_FALCON_EMEMC(u32) @ PFalconBase + 0x00000ac0 { + /// EMEM byte offset (4-byte aligned) within the block. + 7:2 offs; + /// EMEM block to access. + 15:8 blk; + /// Auto-increment the offset after each write. + 24:24 aincw => bool; + /// Auto-increment the offset after each read. + 25:25 aincr => bool; + } + + pub(crate) NV_PFALCON_FALCON_EMEMD(u32) @ PFalconBase + 0x00000ac4 { + 31:0 data => u32; + } } impl NV_PFALCON_FALCON_DMACTL { |
