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