All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexandre Courbot <acourbot@nvidia.com>
To: "Danilo Krummrich" <dakr@kernel.org>,
	"David Airlie" <airlied@gmail.com>,
	"John Hubbard" <jhubbard@nvidia.com>,
	"Ben Skeggs" <bskeggs@nvidia.com>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Boqun Feng" <boqun.feng@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <benno.lossin@proton.me>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Simona Vetter" <simona@ffwll.ch>
Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
	 nouveau@lists.freedesktop.org, dri-devel@lists.freedesktop.org,
	 Alexandre Courbot <acourbot@nvidia.com>
Subject: [PATCH RFC v2 5/5] gpu: nova-core: add falcon register definitions and probe code
Date: Tue, 04 Mar 2025 22:54:01 +0900	[thread overview]
Message-ID: <20250304-nova_timer-v2-5-8fb13f3f8cff@nvidia.com> (raw)
In-Reply-To: <20250304-nova_timer-v2-0-8fb13f3f8cff@nvidia.com>

This is still very preliminary work, and is mostly designed to show how
register fields can be turned into safe types that force us to handle
invalid values.

Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
---
 drivers/gpu/nova-core/driver.rs    |   2 +-
 drivers/gpu/nova-core/falcon.rs    | 124 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/nova-core/gpu.rs       |  10 +++
 drivers/gpu/nova-core/nova_core.rs |   1 +
 drivers/gpu/nova-core/regs.rs      | 108 ++++++++++++++++++++++++++++++++
 5 files changed, 244 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver.rs
index 0cd23aa306e4082405f480afc0530a41131485e7..dee5fd22eecb2ce1f4ea765338b0c1b68853b2d3 100644
--- a/drivers/gpu/nova-core/driver.rs
+++ b/drivers/gpu/nova-core/driver.rs
@@ -10,7 +10,7 @@ pub(crate) struct NovaCore {
     pub(crate) gpu: Gpu,
 }
 
-const BAR0_SIZE: usize = 0x9500;
+const BAR0_SIZE: usize = 0x1000000;
 pub(crate) type Bar0 = pci::Bar<BAR0_SIZE>;
 
 kernel::pci_device_table!(
diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon.rs
new file mode 100644
index 0000000000000000000000000000000000000000..5f8496ed1f91ccd19c0c7716440cbc795a7a025f
--- /dev/null
+++ b/drivers/gpu/nova-core/falcon.rs
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Falcon microprocessor base support
+
+use core::hint::unreachable_unchecked;
+use kernel::devres::Devres;
+use kernel::{pci, prelude::*};
+
+use crate::driver::Bar0;
+use crate::regs::{FalconCpuCtl, FalconHwCfg1};
+
+#[repr(u8)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub(crate) enum FalconCoreRev {
+    Rev1 = 1,
+    Rev2 = 2,
+    Rev3 = 3,
+    Rev4 = 4,
+    Rev5 = 5,
+    Rev6 = 6,
+    Rev7 = 7,
+}
+
+impl TryFrom<u32> for FalconCoreRev {
+    type Error = Error;
+
+    fn try_from(value: u32) -> core::result::Result<Self, Self::Error> {
+        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)
+    }
+}
+
+#[repr(u8)]
+#[derive(Debug, Copy, Clone)]
+pub(crate) enum FalconSecurityModel {
+    None = 0,
+    Light = 2,
+    Heavy = 3,
+}
+
+impl TryFrom<u32> for FalconSecurityModel {
+    type Error = Error;
+
+    fn try_from(value: u32) -> core::result::Result<Self, Self::Error> {
+        use FalconSecurityModel::*;
+
+        let sec_model = match value {
+            0 => None,
+            2 => Light,
+            3 => Heavy,
+            _ => return Err(EINVAL),
+        };
+
+        Ok(sec_model)
+    }
+}
+
+#[repr(u8)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub(crate) enum FalconCoreRevSubversion {
+    Subversion0 = 0,
+    Subversion1 = 1,
+    Subversion2 = 2,
+    Subversion3 = 3,
+}
+
+impl From<u32> for FalconCoreRevSubversion {
+    fn from(value: u32) -> Self {
+        use FalconCoreRevSubversion::*;
+
+        match value & 0b11 {
+            0 => Subversion0,
+            1 => Subversion1,
+            2 => Subversion2,
+            3 => Subversion3,
+            // SAFETY: the `0b11` mask limits the possible values to `0..=3`.
+            4..=u32::MAX => unsafe { unreachable_unchecked() },
+        }
+    }
+}
+
+/// Contains the base parameters common to all Falcon instances.
+#[derive(Debug)]
+pub(crate) struct Falcon {
+    /// Base IO address.
+    base: usize,
+}
+
+impl Falcon {
+    pub(crate) fn new(pdev: &pci::Device, bar: &Devres<Bar0>, base: usize) -> Result<Self> {
+        let b = bar.try_access().ok_or(ENXIO)?;
+
+        let hwcfg1 = FalconHwCfg1::read(&b, base);
+        let rev = hwcfg1.core_rev()?;
+        let subver = hwcfg1.core_rev_subversion();
+        let sec_model = hwcfg1.security_model()?;
+
+        dev_info!(
+            pdev.as_ref(),
+            "new falcon: {:?} {:?} {:?}",
+            rev,
+            subver,
+            sec_model
+        );
+
+        Ok(Self { base })
+    }
+
+    pub(crate) fn cpu_ctl(&self, bar: &Bar0) -> FalconCpuCtl {
+        FalconCpuCtl::read(bar, self.base)
+    }
+}
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index 8fa8616c0deccc7297b090fcbe74f3cda5cc9741..8d8b5ee5c9444c4722d1025d4008fc5a8841a247 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -7,6 +7,7 @@
 };
 
 use crate::driver::Bar0;
+use crate::falcon::Falcon;
 use crate::regs;
 use crate::timer::Timer;
 use core::fmt;
@@ -228,6 +229,15 @@ pub(crate) fn new(pdev: &pci::Device, bar: Devres<Bar0>) -> Result<impl PinInit<
 
         let dev = pdev.as_ref().into();
         let timer = Timer::new();
+        let gsp_falcon = Falcon::new(pdev, &bar, regs::FALCON_GSP_BASE)?;
+        let sec2 = Falcon::new(pdev, &bar, regs::FALCON_SEC2_BASE)?;
+        let b = bar.try_access().ok_or(ENXIO)?;
+        dev_info!(
+            pdev.as_ref(),
+            "GSP Falcon CpuCtl: {:?}",
+            gsp_falcon.cpu_ctl(&b)
+        );
+        dev_info!(pdev.as_ref(), "SEC2 Falcon CpuCtl: {:?}", sec2.cpu_ctl(&b));
 
         Ok(pin_init!(Self {
             dev,
diff --git a/drivers/gpu/nova-core/nova_core.rs b/drivers/gpu/nova-core/nova_core.rs
index 891a93ba7656d2aa5e1fa4357d1d84ee3a054942..a5817bda30185d4ec7021f3d3e881cd99230ca94 100644
--- a/drivers/gpu/nova-core/nova_core.rs
+++ b/drivers/gpu/nova-core/nova_core.rs
@@ -3,6 +3,7 @@
 //! Nova Core GPU Driver
 
 mod driver;
+mod falcon;
 mod firmware;
 mod gpu;
 mod regs;
diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs
index 35bbd3c0b58972de3a2478ef20f93f31c69940e7..12a889a785e0713c6041d50284c211352a39303b 100644
--- a/drivers/gpu/nova-core/regs.rs
+++ b/drivers/gpu/nova-core/regs.rs
@@ -3,6 +3,7 @@
 use core::{fmt::Debug, marker::PhantomData, ops::Deref};
 
 use crate::driver::Bar0;
+use crate::falcon::{FalconCoreRev, FalconCoreRevSubversion, FalconSecurityModel};
 use crate::gpu::Chipset;
 
 pub(crate) struct Builder<T>(T, PhantomData<T>);
@@ -180,3 +181,110 @@ impl Builder<$name> {
 nv_reg!(PtimerTime1@0x00009410;
     31:0    hi as (u32), "high 32 bits of the timer"
 );
+
+pub(crate) const FALCON_GSP_BASE: usize = 0x00110000;
+pub(crate) const FALCON_SEC2_BASE: usize = 0x00840000;
+
+nv_reg!(FalconIrqsClr@+0x00000004;
+    4:4     halt as_bit (bool);
+    6:6     swgen0 as_bit (bool);
+);
+
+nv_reg!(FalconMailbox0@+0x00000040;
+    31:0    mailbox0 as (u32)
+);
+nv_reg!(FalconMailbox1@+0x00000044;
+    31:0    mailbox1 as (u32)
+);
+
+nv_reg!(FalconCpuCtl@+0x00000100;
+    1:1     start_cpu as_bit (bool);
+    4:4     halted as_bit (bool);
+    6:6     alias_en as_bit (bool);
+);
+nv_reg!(FalconBootVec@+0x00000104;
+    31:0    boot_vec as (u32)
+);
+
+nv_reg!(FalconHwCfg@+0x00000108;
+    8:0     imem_size as (u32);
+    17:9    dmem_size as (u32);
+);
+
+nv_reg!(FalconDmaCtl@+0x0000010c;
+    0:0     require_ctx as_bit (bool);
+    1:1     dmem_scrubbing  as_bit (bool);
+    2:2     imem_scrubbing as_bit (bool);
+    6:3     dmaq_num as_bit (u8);
+    7:7     secure_stat as_bit (bool);
+);
+
+nv_reg!(FalconDmaTrfBase@+0x00000110;
+    31:0    base as (u32);
+);
+
+nv_reg!(FalconDmaTrfMOffs@+0x00000114;
+    23:0    offs as (u32);
+);
+
+nv_reg!(FalconDmaTrfCmd@+0x00000118;
+    0:0     full as_bit (bool);
+    1:1     idle as_bit (bool);
+    3:2     sec as_bit (u8);
+    4:4     imem as_bit (bool);
+    5:5     is_write as_bit (bool);
+    10:8    size as (u8);
+    14:12   ctxdma as (u8);
+    16:16   set_dmtag as (u8);
+);
+
+nv_reg!(FalconDmaTrfBOffs@+0x0000011c;
+    31:0    offs as (u32);
+);
+
+nv_reg!(FalconDmaTrfBase1@+0x00000128;
+    8:0     base as (u16);
+);
+
+nv_reg!(FalconHwCfg1@+0x0000012c;
+    3:0     core_rev try_into (FalconCoreRev), "core revision of the falcon";
+    5:4     security_model try_into (FalconSecurityModel), "security model of the falcon";
+    7:6     core_rev_subversion into (FalconCoreRevSubversion);
+    11:8    imem_ports as (u8);
+    15:12   dmem_ports as (u8);
+);
+
+// TODO: This should be able to take an index, like +0x180[16; 8]? Then the constructor or read
+// method take the port we want to address as argument.
+nv_reg!(FalconImemC@+0x00000180;
+    7:2     offs as (u8);
+    23:8    blk as (u8);
+    24:24   aincw as_bit (bool);
+    25:25   aincr as_bit (bool);
+    28:28   secure as_bit (bool);
+    29:29   sec_atomic  as_bit (bool);
+);
+
+nv_reg!(FalconImemD@+0x00000184;
+    31:0    data as (u32);
+);
+
+nv_reg!(FalconImemT@+0x00000188;
+    15:0    data as (u16);
+);
+
+nv_reg!(FalconDmemC@+0x000001c0;
+    23:0    addr as (u32);
+    7:2     offs as (u8);
+    23:8    blk as (u8);
+    24:24   aincw as_bit (bool);
+    25:25   aincr as_bit (bool);
+    26:26   settag as_bit (bool);
+    27:27   setlvl as_bit (bool);
+    28:28   va as_bit (bool);
+    29:29   miss  as_bit (bool);
+);
+
+nv_reg!(FalconDmemD@+0x000001c4;
+    31:0    data as (u32);
+);

-- 
2.48.1


      parent reply	other threads:[~2025-03-04 13:55 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-04 13:53 [RFC PATCH v2 0/5] gpu: nova-core: register definitions and basic timer and falcon devices Alexandre Courbot
2025-03-04 13:53 ` [PATCH RFC v2 1/5] rust: add useful ops for u64 Alexandre Courbot
2025-03-10 20:46   ` Timur Tabi
2025-03-04 13:53 ` [PATCH RFC v2 2/5] rust: make ETIMEDOUT error available Alexandre Courbot
2025-03-04 13:53 ` [PATCH RFC v2 3/5] gpu: nova-core: add register definition macro Alexandre Courbot
2025-03-04 13:54 ` [PATCH RFC v2 4/5] gpu: nova-core: add basic timer device Alexandre Courbot
2025-03-04 13:54 ` Alexandre Courbot [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250304-nova_timer-v2-5-8fb13f3f8cff@nvidia.com \
    --to=acourbot@nvidia.com \
    --cc=a.hindborg@kernel.org \
    --cc=airlied@gmail.com \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=benno.lossin@proton.me \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=bskeggs@nvidia.com \
    --cc=dakr@kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=gary@garyguo.net \
    --cc=jhubbard@nvidia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nouveau@lists.freedesktop.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=simona@ffwll.ch \
    --cc=tmgross@umich.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.