xref: /linux/drivers/gpu/nova-core/gpu.rs (revision 85502b2214d50ba0ddf2a5fb454e4d28a160d175)
154e6baf1SDanilo Krummrich // SPDX-License-Identifier: GPL-2.0
254e6baf1SDanilo Krummrich 
354e6baf1SDanilo Krummrich use kernel::{device, devres::Devres, error::code::*, pci, prelude::*};
454e6baf1SDanilo Krummrich 
554e6baf1SDanilo Krummrich use crate::driver::Bar0;
654e6baf1SDanilo Krummrich use crate::firmware::{Firmware, FIRMWARE_VERSION};
754e6baf1SDanilo Krummrich use crate::regs;
854e6baf1SDanilo Krummrich use crate::util;
954e6baf1SDanilo Krummrich use core::fmt;
1054e6baf1SDanilo Krummrich 
1154e6baf1SDanilo Krummrich macro_rules! define_chipset {
1254e6baf1SDanilo Krummrich     ({ $($variant:ident = $value:expr),* $(,)* }) =>
1354e6baf1SDanilo Krummrich     {
1454e6baf1SDanilo Krummrich         /// Enum representation of the GPU chipset.
1554e6baf1SDanilo Krummrich         #[derive(fmt::Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
1654e6baf1SDanilo Krummrich         pub(crate) enum Chipset {
1754e6baf1SDanilo Krummrich             $($variant = $value),*,
1854e6baf1SDanilo Krummrich         }
1954e6baf1SDanilo Krummrich 
2054e6baf1SDanilo Krummrich         impl Chipset {
2154e6baf1SDanilo Krummrich             pub(crate) const ALL: &'static [Chipset] = &[
2254e6baf1SDanilo Krummrich                 $( Chipset::$variant, )*
2354e6baf1SDanilo Krummrich             ];
2454e6baf1SDanilo Krummrich 
2554e6baf1SDanilo Krummrich             pub(crate) const NAMES: [&'static str; Self::ALL.len()] = [
2654e6baf1SDanilo Krummrich                 $( util::const_bytes_to_str(
2754e6baf1SDanilo Krummrich                         util::to_lowercase_bytes::<{ stringify!($variant).len() }>(
2854e6baf1SDanilo Krummrich                             stringify!($variant)
2954e6baf1SDanilo Krummrich                         ).as_slice()
3054e6baf1SDanilo Krummrich                 ), )*
3154e6baf1SDanilo Krummrich             ];
3254e6baf1SDanilo Krummrich         }
3354e6baf1SDanilo Krummrich 
3454e6baf1SDanilo Krummrich         // TODO replace with something like derive(FromPrimitive)
3554e6baf1SDanilo Krummrich         impl TryFrom<u32> for Chipset {
3654e6baf1SDanilo Krummrich             type Error = kernel::error::Error;
3754e6baf1SDanilo Krummrich 
3854e6baf1SDanilo Krummrich             fn try_from(value: u32) -> Result<Self, Self::Error> {
3954e6baf1SDanilo Krummrich                 match value {
4054e6baf1SDanilo Krummrich                     $( $value => Ok(Chipset::$variant), )*
4154e6baf1SDanilo Krummrich                     _ => Err(ENODEV),
4254e6baf1SDanilo Krummrich                 }
4354e6baf1SDanilo Krummrich             }
4454e6baf1SDanilo Krummrich         }
4554e6baf1SDanilo Krummrich     }
4654e6baf1SDanilo Krummrich }
4754e6baf1SDanilo Krummrich 
4854e6baf1SDanilo Krummrich define_chipset!({
4954e6baf1SDanilo Krummrich     // Turing
5054e6baf1SDanilo Krummrich     TU102 = 0x162,
5154e6baf1SDanilo Krummrich     TU104 = 0x164,
5254e6baf1SDanilo Krummrich     TU106 = 0x166,
5354e6baf1SDanilo Krummrich     TU117 = 0x167,
5454e6baf1SDanilo Krummrich     TU116 = 0x168,
5554e6baf1SDanilo Krummrich     // Ampere
5654e6baf1SDanilo Krummrich     GA100 = 0x170,
5754e6baf1SDanilo Krummrich     GA102 = 0x172,
5854e6baf1SDanilo Krummrich     GA103 = 0x173,
5954e6baf1SDanilo Krummrich     GA104 = 0x174,
6054e6baf1SDanilo Krummrich     GA106 = 0x176,
6154e6baf1SDanilo Krummrich     GA107 = 0x177,
6254e6baf1SDanilo Krummrich     // Ada
6354e6baf1SDanilo Krummrich     AD102 = 0x192,
6454e6baf1SDanilo Krummrich     AD103 = 0x193,
6554e6baf1SDanilo Krummrich     AD104 = 0x194,
6654e6baf1SDanilo Krummrich     AD106 = 0x196,
6754e6baf1SDanilo Krummrich     AD107 = 0x197,
6854e6baf1SDanilo Krummrich });
6954e6baf1SDanilo Krummrich 
7054e6baf1SDanilo Krummrich impl Chipset {
arch(&self) -> Architecture7154e6baf1SDanilo Krummrich     pub(crate) fn arch(&self) -> Architecture {
7254e6baf1SDanilo Krummrich         match self {
7354e6baf1SDanilo Krummrich             Self::TU102 | Self::TU104 | Self::TU106 | Self::TU117 | Self::TU116 => {
7454e6baf1SDanilo Krummrich                 Architecture::Turing
7554e6baf1SDanilo Krummrich             }
7654e6baf1SDanilo Krummrich             Self::GA100 | Self::GA102 | Self::GA103 | Self::GA104 | Self::GA106 | Self::GA107 => {
7754e6baf1SDanilo Krummrich                 Architecture::Ampere
7854e6baf1SDanilo Krummrich             }
7954e6baf1SDanilo Krummrich             Self::AD102 | Self::AD103 | Self::AD104 | Self::AD106 | Self::AD107 => {
8054e6baf1SDanilo Krummrich                 Architecture::Ada
8154e6baf1SDanilo Krummrich             }
8254e6baf1SDanilo Krummrich         }
8354e6baf1SDanilo Krummrich     }
8454e6baf1SDanilo Krummrich }
8554e6baf1SDanilo Krummrich 
8654e6baf1SDanilo Krummrich // TODO
8754e6baf1SDanilo Krummrich //
8854e6baf1SDanilo Krummrich // The resulting strings are used to generate firmware paths, hence the
8954e6baf1SDanilo Krummrich // generated strings have to be stable.
9054e6baf1SDanilo Krummrich //
9154e6baf1SDanilo Krummrich // Hence, replace with something like strum_macros derive(Display).
9254e6baf1SDanilo Krummrich //
9354e6baf1SDanilo Krummrich // For now, redirect to fmt::Debug for convenience.
9454e6baf1SDanilo Krummrich impl fmt::Display for Chipset {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result9554e6baf1SDanilo Krummrich     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96*211dcf77SMiguel Ojeda         write!(f, "{self:?}")
9754e6baf1SDanilo Krummrich     }
9854e6baf1SDanilo Krummrich }
9954e6baf1SDanilo Krummrich 
10054e6baf1SDanilo Krummrich /// Enum representation of the GPU generation.
10154e6baf1SDanilo Krummrich #[derive(fmt::Debug)]
10254e6baf1SDanilo Krummrich pub(crate) enum Architecture {
10354e6baf1SDanilo Krummrich     Turing = 0x16,
10454e6baf1SDanilo Krummrich     Ampere = 0x17,
10554e6baf1SDanilo Krummrich     Ada = 0x19,
10654e6baf1SDanilo Krummrich }
10754e6baf1SDanilo Krummrich 
10854e6baf1SDanilo Krummrich impl TryFrom<u8> for Architecture {
10954e6baf1SDanilo Krummrich     type Error = Error;
11054e6baf1SDanilo Krummrich 
try_from(value: u8) -> Result<Self>11154e6baf1SDanilo Krummrich     fn try_from(value: u8) -> Result<Self> {
11254e6baf1SDanilo Krummrich         match value {
11354e6baf1SDanilo Krummrich             0x16 => Ok(Self::Turing),
11454e6baf1SDanilo Krummrich             0x17 => Ok(Self::Ampere),
11554e6baf1SDanilo Krummrich             0x19 => Ok(Self::Ada),
11654e6baf1SDanilo Krummrich             _ => Err(ENODEV),
11754e6baf1SDanilo Krummrich         }
11854e6baf1SDanilo Krummrich     }
11954e6baf1SDanilo Krummrich }
12054e6baf1SDanilo Krummrich 
12154e6baf1SDanilo Krummrich pub(crate) struct Revision {
12254e6baf1SDanilo Krummrich     major: u8,
12354e6baf1SDanilo Krummrich     minor: u8,
12454e6baf1SDanilo Krummrich }
12554e6baf1SDanilo Krummrich 
12654e6baf1SDanilo Krummrich impl Revision {
from_boot0(boot0: regs::NV_PMC_BOOT_0) -> Self12754e6baf1SDanilo Krummrich     fn from_boot0(boot0: regs::NV_PMC_BOOT_0) -> Self {
12854e6baf1SDanilo Krummrich         Self {
12954e6baf1SDanilo Krummrich             major: boot0.major_revision(),
13054e6baf1SDanilo Krummrich             minor: boot0.minor_revision(),
13154e6baf1SDanilo Krummrich         }
13254e6baf1SDanilo Krummrich     }
13354e6baf1SDanilo Krummrich }
13454e6baf1SDanilo Krummrich 
13554e6baf1SDanilo Krummrich impl fmt::Display for Revision {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result13654e6baf1SDanilo Krummrich     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
13754e6baf1SDanilo Krummrich         write!(f, "{:x}.{:x}", self.major, self.minor)
13854e6baf1SDanilo Krummrich     }
13954e6baf1SDanilo Krummrich }
14054e6baf1SDanilo Krummrich 
14154e6baf1SDanilo Krummrich /// Structure holding the metadata of the GPU.
14254e6baf1SDanilo Krummrich pub(crate) struct Spec {
14354e6baf1SDanilo Krummrich     chipset: Chipset,
14454e6baf1SDanilo Krummrich     /// The revision of the chipset.
14554e6baf1SDanilo Krummrich     revision: Revision,
14654e6baf1SDanilo Krummrich }
14754e6baf1SDanilo Krummrich 
14854e6baf1SDanilo Krummrich impl Spec {
new(bar: &Bar0) -> Result<Spec>14954e6baf1SDanilo Krummrich     fn new(bar: &Bar0) -> Result<Spec> {
15054e6baf1SDanilo Krummrich         let boot0 = regs::NV_PMC_BOOT_0::read(bar);
15154e6baf1SDanilo Krummrich 
15254e6baf1SDanilo Krummrich         Ok(Self {
15354e6baf1SDanilo Krummrich             chipset: boot0.chipset()?,
15454e6baf1SDanilo Krummrich             revision: Revision::from_boot0(boot0),
15554e6baf1SDanilo Krummrich         })
15654e6baf1SDanilo Krummrich     }
15754e6baf1SDanilo Krummrich }
15854e6baf1SDanilo Krummrich 
15954e6baf1SDanilo Krummrich /// Structure holding the resources required to operate the GPU.
16054e6baf1SDanilo Krummrich #[pin_data]
16154e6baf1SDanilo Krummrich pub(crate) struct Gpu {
16254e6baf1SDanilo Krummrich     spec: Spec,
16354e6baf1SDanilo Krummrich     /// MMIO mapping of PCI BAR 0
16454e6baf1SDanilo Krummrich     bar: Devres<Bar0>,
16554e6baf1SDanilo Krummrich     fw: Firmware,
16654e6baf1SDanilo Krummrich }
16754e6baf1SDanilo Krummrich 
16854e6baf1SDanilo Krummrich impl Gpu {
new( pdev: &pci::Device<device::Bound>, devres_bar: Devres<Bar0>, ) -> Result<impl PinInit<Self>>16954e6baf1SDanilo Krummrich     pub(crate) fn new(
17054e6baf1SDanilo Krummrich         pdev: &pci::Device<device::Bound>,
17154e6baf1SDanilo Krummrich         devres_bar: Devres<Bar0>,
17254e6baf1SDanilo Krummrich     ) -> Result<impl PinInit<Self>> {
17354e6baf1SDanilo Krummrich         let bar = devres_bar.access(pdev.as_ref())?;
17454e6baf1SDanilo Krummrich         let spec = Spec::new(bar)?;
17554e6baf1SDanilo Krummrich         let fw = Firmware::new(pdev.as_ref(), spec.chipset, FIRMWARE_VERSION)?;
17654e6baf1SDanilo Krummrich 
17754e6baf1SDanilo Krummrich         dev_info!(
17854e6baf1SDanilo Krummrich             pdev.as_ref(),
17954e6baf1SDanilo Krummrich             "NVIDIA (Chipset: {}, Architecture: {:?}, Revision: {})\n",
18054e6baf1SDanilo Krummrich             spec.chipset,
18154e6baf1SDanilo Krummrich             spec.chipset.arch(),
18254e6baf1SDanilo Krummrich             spec.revision
18354e6baf1SDanilo Krummrich         );
18454e6baf1SDanilo Krummrich 
18554e6baf1SDanilo Krummrich         Ok(pin_init!(Self {
18654e6baf1SDanilo Krummrich             spec,
18754e6baf1SDanilo Krummrich             bar: devres_bar,
18854e6baf1SDanilo Krummrich             fw
18954e6baf1SDanilo Krummrich         }))
19054e6baf1SDanilo Krummrich     }
19154e6baf1SDanilo Krummrich }
19254e6baf1SDanilo Krummrich