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