1 // SPDX-License-Identifier: GPL-2.0 or MIT 2 3 use core::ops::{ 4 Deref, 5 DerefMut, // 6 }; 7 use kernel::{ 8 device::{ 9 Bound, 10 Device, // 11 }, 12 io::{ 13 poll, 14 register::Array, 15 Io, // 16 }, 17 prelude::*, 18 time::Delta, 19 transmute::AsBytes, 20 uapi, // 21 }; 22 23 use crate::{ 24 driver::IoMem, 25 regs::{ 26 gpu_control::*, 27 join_u64, // 28 }, // 29 }; 30 31 /// Struct containing information that can be queried by userspace. This is read from 32 /// the GPU's registers. 33 /// 34 /// # Invariants 35 /// 36 /// - The layout of this struct is identical to the C `struct drm_panthor_gpu_info`. 37 #[repr(transparent)] 38 #[derive(Clone, Copy)] 39 pub(crate) struct GpuInfo(pub(crate) uapi::drm_panthor_gpu_info); 40 41 impl GpuInfo { 42 pub(crate) fn new(io: &IoMem<'_>) -> Self { 43 Self(uapi::drm_panthor_gpu_info { 44 gpu_id: io.read(GPU_ID).into_raw(), 45 gpu_rev: io.read(REVIDR).into_raw(), 46 csf_id: io.read(CSF_ID).into_raw(), 47 l2_features: io.read(L2_FEATURES).into_raw(), 48 tiler_features: io.read(TILER_FEATURES).into_raw(), 49 mem_features: io.read(MEM_FEATURES).into_raw(), 50 mmu_features: io.read(MMU_FEATURES).into_raw(), 51 thread_features: io.read(THREAD_FEATURES).into_raw(), 52 max_threads: io.read(THREAD_MAX_THREADS).into_raw(), 53 thread_max_workgroup_size: io.read(THREAD_MAX_WORKGROUP_SIZE).into_raw(), 54 thread_max_barrier_size: io.read(THREAD_MAX_BARRIER_SIZE).into_raw(), 55 coherency_features: io.read(COHERENCY_FEATURES).into_raw(), 56 texture_features: [ 57 io.read(TEXTURE_FEATURES::at(0)).supported_formats().get(), 58 io.read(TEXTURE_FEATURES::at(1)).supported_formats().get(), 59 io.read(TEXTURE_FEATURES::at(2)).supported_formats().get(), 60 io.read(TEXTURE_FEATURES::at(3)).supported_formats().get(), 61 ], 62 as_present: io.read(AS_PRESENT).into_raw(), 63 selected_coherency: uapi::drm_panthor_gpu_coherency_DRM_PANTHOR_GPU_COHERENCY_NONE, 64 shader_present: join_u64( 65 io.read(SHADER_PRESENT_LO).into_raw(), 66 io.read(SHADER_PRESENT_HI).into_raw(), 67 ), 68 l2_present: join_u64( 69 io.read(L2_PRESENT_LO).into_raw(), 70 io.read(L2_PRESENT_HI).into_raw(), 71 ), 72 tiler_present: join_u64( 73 io.read(TILER_PRESENT_LO).into_raw(), 74 io.read(TILER_PRESENT_HI).into_raw(), 75 ), 76 core_features: io.read(CORE_FEATURES).into_raw(), 77 // Padding must be zero. 78 pad: 0, 79 //GPU_FEATURES register is not available; it was introduced in arch 11.x. 80 gpu_features: 0, 81 }) 82 } 83 84 pub(crate) fn log(&self, dev: &Device<Bound>) { 85 let gpu_id = GPU_ID::from_raw(self.gpu_id); 86 87 let model_name = if let Some(model) = GPU_MODELS.iter().find(|&f| { 88 f.arch_major == gpu_id.arch_major().get() && f.prod_major == gpu_id.prod_major().get() 89 }) { 90 model.name 91 } else { 92 "unknown" 93 }; 94 95 dev_info!( 96 dev, 97 "mali-{} GPU_ID 0x{:x} major 0x{:x} minor 0x{:x} status 0x{:x}", 98 model_name, 99 gpu_id.into_raw(), 100 gpu_id.ver_major().get(), 101 gpu_id.ver_minor().get(), 102 gpu_id.ver_status().get() 103 ); 104 105 dev_info!( 106 dev, 107 "Features: L2:{:#x} Tiler:{:#x} Mem:{:#x} MMU:{:#x} AS:{:#x}", 108 self.l2_features, 109 self.tiler_features, 110 self.mem_features, 111 self.mmu_features, 112 self.as_present, 113 ); 114 115 dev_info!( 116 dev, 117 "shader_present=0x{:016x} l2_present=0x{:016x} tiler_present=0x{:016x}", 118 self.shader_present, 119 self.l2_present, 120 self.tiler_present, 121 ); 122 } 123 } 124 125 impl Deref for GpuInfo { 126 type Target = uapi::drm_panthor_gpu_info; 127 128 fn deref(&self) -> &Self::Target { 129 &self.0 130 } 131 } 132 133 impl DerefMut for GpuInfo { 134 fn deref_mut(&mut self) -> &mut Self::Target { 135 &mut self.0 136 } 137 } 138 139 // SAFETY: `GpuInfo`'s invariant guarantees that it is the same type that is 140 // already exposed to userspace by the C driver. This implies that it fulfills 141 // the requirements for `AsBytes`. 142 // 143 // This means: 144 // 145 // - No implicit padding, 146 // - No kernel pointers, 147 // - No interior mutability. 148 unsafe impl AsBytes for GpuInfo {} 149 150 struct GpuModels { 151 name: &'static str, 152 arch_major: u32, 153 prod_major: u32, 154 } 155 156 const GPU_MODELS: [GpuModels; 1] = [GpuModels { 157 name: "g610", 158 arch_major: 10, 159 prod_major: 7, 160 }]; 161 162 /// Powers on the l2 block. 163 pub(crate) fn l2_power_on(dev: &Device, io: &IoMem<'_>) -> Result { 164 io.write_reg(L2_PWRON_LO::zeroed().with_const_request::<1>()); 165 166 poll::read_poll_timeout( 167 || Ok(io.read(L2_READY_LO)), 168 |status| status.ready() == 1, 169 Delta::from_millis(1), 170 Delta::from_millis(100), 171 ) 172 .inspect_err(|_| dev_err!(dev, "Failed to power on the GPU."))?; 173 174 Ok(()) 175 } 176