projects/linux·blob master · refs

175 lines · 5.1 KiB

1// SPDX-License-Identifier: GPL-2.0 or MIT
2
3use core::ops::{
4 Deref,
5 DerefMut, //
6};
7use 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
23use 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)]
39pub(crate) struct GpuInfo(pub(crate) uapi::drm_panthor_gpu_info);
40
41impl 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
125impl Deref for GpuInfo {
126 type Target = uapi::drm_panthor_gpu_info;
127
128 fn deref(&self) -> &Self::Target {
129 &self.0
130 }
131}
132
133impl 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.
148unsafe impl AsBytes for GpuInfo {}
149
150struct GpuModels {
151 name: &'static str,
152 arch_major: u32,
153 prod_major: u32,
154}
155
156const GPU_MODELS: [GpuModels; 1] = [GpuModels {
157 name: "g610",
158 arch_major: 10,
159 prod_major: 7,
160}];
161
162/// Powers on the l2 block.
163pub(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}