summaryrefslogtreecommitdiff
path: root/drivers/gpu/nova-core
diff options
context:
space:
mode:
authorJohn Hubbard <jhubbard@nvidia.com>2026-06-03 16:30:18 +0900
committerAlexandre Courbot <acourbot@nvidia.com>2026-06-03 22:11:07 +0900
commit6d6c3189f9b2b143efe1f536e8ea8b082e054a01 (patch)
tree2de07f18f5993c9198b8bc97e15e6256d55961ad /drivers/gpu/nova-core
parent0023a1e8d01a9d400257d30c851bd16a29568809 (diff)
downloadlwn-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.rs80
-rw-r--r--drivers/gpu/nova-core/regs.rs18
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 {