File Index
Files and directories
Sign in
FILE

gpu.rs

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/tyr/gpu.rs RUST
  1// SPDX-License-Identifier: GPL-2.0 or MIT
  2
  3use kernel::bits::genmask_u32;
  4use kernel::device::Bound;
  5use kernel::device::Device;
  6use kernel::devres::Devres;
  7use kernel::platform;
  8use kernel::prelude::*;
  9use kernel::time;
 10use kernel::transmute::AsBytes;
 11
 12use crate::driver::IoMem;
 13use crate::regs;
 14
 15/// Struct containing information that can be queried by userspace. This is read from
 16/// the GPU's registers.
 17///
 18/// # Invariants
 19///
 20/// - The layout of this struct identical to the C `struct drm_panthor_gpu_info`.
 21#[repr(C)]
 22pub(crate) struct GpuInfo {
 23    pub(crate) gpu_id: u32,
 24    pub(crate) gpu_rev: u32,
 25    pub(crate) csf_id: u32,
 26    pub(crate) l2_features: u32,
 27    pub(crate) tiler_features: u32,
 28    pub(crate) mem_features: u32,
 29    pub(crate) mmu_features: u32,
 30    pub(crate) thread_features: u32,
 31    pub(crate) max_threads: u32,
 32    pub(crate) thread_max_workgroup_size: u32,
 33    pub(crate) thread_max_barrier_size: u32,
 34    pub(crate) coherency_features: u32,
 35    pub(crate) texture_features: [u32; 4],
 36    pub(crate) as_present: u32,
 37    pub(crate) pad0: u32,
 38    pub(crate) shader_present: u64,
 39    pub(crate) l2_present: u64,
 40    pub(crate) tiler_present: u64,
 41    pub(crate) core_features: u32,
 42    pub(crate) pad: u32,
 43}
 44
 45impl GpuInfo {
 46    pub(crate) fn new(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result<Self> {
 47        let gpu_id = regs::GPU_ID.read(dev, iomem)?;
 48        let csf_id = regs::GPU_CSF_ID.read(dev, iomem)?;
 49        let gpu_rev = regs::GPU_REVID.read(dev, iomem)?;
 50        let core_features = regs::GPU_CORE_FEATURES.read(dev, iomem)?;
 51        let l2_features = regs::GPU_L2_FEATURES.read(dev, iomem)?;
 52        let tiler_features = regs::GPU_TILER_FEATURES.read(dev, iomem)?;
 53        let mem_features = regs::GPU_MEM_FEATURES.read(dev, iomem)?;
 54        let mmu_features = regs::GPU_MMU_FEATURES.read(dev, iomem)?;
 55        let thread_features = regs::GPU_THREAD_FEATURES.read(dev, iomem)?;
 56        let max_threads = regs::GPU_THREAD_MAX_THREADS.read(dev, iomem)?;
 57        let thread_max_workgroup_size = regs::GPU_THREAD_MAX_WORKGROUP_SIZE.read(dev, iomem)?;
 58        let thread_max_barrier_size = regs::GPU_THREAD_MAX_BARRIER_SIZE.read(dev, iomem)?;
 59        let coherency_features = regs::GPU_COHERENCY_FEATURES.read(dev, iomem)?;
 60
 61        let texture_features = regs::GPU_TEXTURE_FEATURES0.read(dev, iomem)?;
 62
 63        let as_present = regs::GPU_AS_PRESENT.read(dev, iomem)?;
 64
 65        let shader_present = u64::from(regs::GPU_SHADER_PRESENT_LO.read(dev, iomem)?);
 66        let shader_present =
 67            shader_present | u64::from(regs::GPU_SHADER_PRESENT_HI.read(dev, iomem)?) << 32;
 68
 69        let tiler_present = u64::from(regs::GPU_TILER_PRESENT_LO.read(dev, iomem)?);
 70        let tiler_present =
 71            tiler_present | u64::from(regs::GPU_TILER_PRESENT_HI.read(dev, iomem)?) << 32;
 72
 73        let l2_present = u64::from(regs::GPU_L2_PRESENT_LO.read(dev, iomem)?);
 74        let l2_present = l2_present | u64::from(regs::GPU_L2_PRESENT_HI.read(dev, iomem)?) << 32;
 75
 76        Ok(Self {
 77            gpu_id,
 78            gpu_rev,
 79            csf_id,
 80            l2_features,
 81            tiler_features,
 82            mem_features,
 83            mmu_features,
 84            thread_features,
 85            max_threads,
 86            thread_max_workgroup_size,
 87            thread_max_barrier_size,
 88            coherency_features,
 89            // TODO: Add texture_features_{1,2,3}.
 90            texture_features: [texture_features, 0, 0, 0],
 91            as_present,
 92            pad0: 0,
 93            shader_present,
 94            l2_present,
 95            tiler_present,
 96            core_features,
 97            pad: 0,
 98        })
 99    }
100
101    pub(crate) fn log(&self, pdev: &platform::Device) {
102        let major = (self.gpu_id >> 16) & 0xff;
103        let minor = (self.gpu_id >> 8) & 0xff;
104        let status = self.gpu_id & 0xff;
105
106        let model_name = if let Some(model) = GPU_MODELS
107            .iter()
108            .find(|&f| f.major == major && f.minor == minor)
109        {
110            model.name
111        } else {
112            "unknown"
113        };
114
115        dev_info!(
116            pdev.as_ref(),
117            "mali-{} id 0x{:x} major 0x{:x} minor 0x{:x} status 0x{:x}",
118            model_name,
119            self.gpu_id >> 16,
120            major,
121            minor,
122            status
123        );
124
125        dev_info!(
126            pdev.as_ref(),
127            "Features: L2:{:#x} Tiler:{:#x} Mem:{:#x} MMU:{:#x} AS:{:#x}",
128            self.l2_features,
129            self.tiler_features,
130            self.mem_features,
131            self.mmu_features,
132            self.as_present
133        );
134
135        dev_info!(
136            pdev.as_ref(),
137            "shader_present=0x{:016x} l2_present=0x{:016x} tiler_present=0x{:016x}",
138            self.shader_present,
139            self.l2_present,
140            self.tiler_present
141        );
142    }
143
144    /// Returns the number of virtual address bits supported by the GPU.
145    #[expect(dead_code)]
146    pub(crate) fn va_bits(&self) -> u32 {
147        self.mmu_features & genmask_u32(0..=7)
148    }
149
150    /// Returns the number of physical address bits supported by the GPU.
151    #[expect(dead_code)]
152    pub(crate) fn pa_bits(&self) -> u32 {
153        (self.mmu_features >> 8) & genmask_u32(0..=7)
154    }
155}
156
157// SAFETY: `GpuInfo`'s invariant guarantees that it is the same type that is
158// already exposed to userspace by the C driver. This implies that it fulfills
159// the requirements for `AsBytes`.
160//
161// This means:
162//
163// - No implicit padding,
164// - No kernel pointers,
165// - No interior mutability.
166unsafe impl AsBytes for GpuInfo {}
167
168struct GpuModels {
169    name: &'static str,
170    major: u32,
171    minor: u32,
172}
173
174const GPU_MODELS: [GpuModels; 1] = [GpuModels {
175    name: "g610",
176    major: 10,
177    minor: 7,
178}];
179
180#[allow(dead_code)]
181pub(crate) struct GpuId {
182    pub(crate) arch_major: u32,
183    pub(crate) arch_minor: u32,
184    pub(crate) arch_rev: u32,
185    pub(crate) prod_major: u32,
186    pub(crate) ver_major: u32,
187    pub(crate) ver_minor: u32,
188    pub(crate) ver_status: u32,
189}
190
191impl From<u32> for GpuId {
192    fn from(value: u32) -> Self {
193        GpuId {
194            arch_major: (value & genmask_u32(28..=31)) >> 28,
195            arch_minor: (value & genmask_u32(24..=27)) >> 24,
196            arch_rev: (value & genmask_u32(20..=23)) >> 20,
197            prod_major: (value & genmask_u32(16..=19)) >> 16,
198            ver_major: (value & genmask_u32(12..=15)) >> 12,
199            ver_minor: (value & genmask_u32(4..=11)) >> 4,
200            ver_status: value & genmask_u32(0..=3),
201        }
202    }
203}
204
205/// Powers on the l2 block.
206pub(crate) fn l2_power_on(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result {
207    regs::L2_PWRON_LO.write(dev, iomem, 1)?;
208
209    // TODO: We cannot poll, as there is no support in Rust currently, so we
210    // sleep. Change this when read_poll_timeout() is implemented in Rust.
211    kernel::time::delay::fsleep(time::Delta::from_millis(100));
212
213    if regs::L2_READY_LO.read(dev, iomem)? != 1 {
214        dev_err!(dev, "Failed to power on the GPU\n");
215        return Err(EIO);
216    }
217
218    Ok(())
219}
~/ Read-only file preview.