xref: /linux/drivers/gpu/drm/tyr/gpu.rs (revision bba2c3615bd6cfee7456d1130f2e6b01b3f4e9ba)
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