gpu.rs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // SPDX-License-Identifier: GPL-2.0 or MIT
  2. use core::ops::Deref;
  3. use core::ops::DerefMut;
  4. use kernel::bits::genmask_u32;
  5. use kernel::device::Bound;
  6. use kernel::device::Device;
  7. use kernel::devres::Devres;
  8. use kernel::io::poll;
  9. use kernel::platform;
  10. use kernel::prelude::*;
  11. use kernel::time::Delta;
  12. use kernel::transmute::AsBytes;
  13. use kernel::uapi;
  14. use crate::driver::IoMem;
  15. use crate::regs;
  16. /// Struct containing information that can be queried by userspace. This is read from
  17. /// the GPU's registers.
  18. ///
  19. /// # Invariants
  20. ///
  21. /// - The layout of this struct identical to the C `struct drm_panthor_gpu_info`.
  22. #[repr(transparent)]
  23. #[derive(Clone, Copy)]
  24. pub(crate) struct GpuInfo(pub(crate) uapi::drm_panthor_gpu_info);
  25. impl GpuInfo {
  26. pub(crate) fn new(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result<Self> {
  27. let gpu_id = regs::GPU_ID.read(dev, iomem)?;
  28. let csf_id = regs::GPU_CSF_ID.read(dev, iomem)?;
  29. let gpu_rev = regs::GPU_REVID.read(dev, iomem)?;
  30. let core_features = regs::GPU_CORE_FEATURES.read(dev, iomem)?;
  31. let l2_features = regs::GPU_L2_FEATURES.read(dev, iomem)?;
  32. let tiler_features = regs::GPU_TILER_FEATURES.read(dev, iomem)?;
  33. let mem_features = regs::GPU_MEM_FEATURES.read(dev, iomem)?;
  34. let mmu_features = regs::GPU_MMU_FEATURES.read(dev, iomem)?;
  35. let thread_features = regs::GPU_THREAD_FEATURES.read(dev, iomem)?;
  36. let max_threads = regs::GPU_THREAD_MAX_THREADS.read(dev, iomem)?;
  37. let thread_max_workgroup_size = regs::GPU_THREAD_MAX_WORKGROUP_SIZE.read(dev, iomem)?;
  38. let thread_max_barrier_size = regs::GPU_THREAD_MAX_BARRIER_SIZE.read(dev, iomem)?;
  39. let coherency_features = regs::GPU_COHERENCY_FEATURES.read(dev, iomem)?;
  40. let texture_features = regs::GPU_TEXTURE_FEATURES0.read(dev, iomem)?;
  41. let as_present = regs::GPU_AS_PRESENT.read(dev, iomem)?;
  42. let shader_present = u64::from(regs::GPU_SHADER_PRESENT_LO.read(dev, iomem)?);
  43. let shader_present =
  44. shader_present | u64::from(regs::GPU_SHADER_PRESENT_HI.read(dev, iomem)?) << 32;
  45. let tiler_present = u64::from(regs::GPU_TILER_PRESENT_LO.read(dev, iomem)?);
  46. let tiler_present =
  47. tiler_present | u64::from(regs::GPU_TILER_PRESENT_HI.read(dev, iomem)?) << 32;
  48. let l2_present = u64::from(regs::GPU_L2_PRESENT_LO.read(dev, iomem)?);
  49. let l2_present = l2_present | u64::from(regs::GPU_L2_PRESENT_HI.read(dev, iomem)?) << 32;
  50. Ok(Self(uapi::drm_panthor_gpu_info {
  51. gpu_id,
  52. gpu_rev,
  53. csf_id,
  54. l2_features,
  55. tiler_features,
  56. mem_features,
  57. mmu_features,
  58. thread_features,
  59. max_threads,
  60. thread_max_workgroup_size,
  61. thread_max_barrier_size,
  62. coherency_features,
  63. // TODO: Add texture_features_{1,2,3}.
  64. texture_features: [texture_features, 0, 0, 0],
  65. as_present,
  66. selected_coherency: uapi::drm_panthor_gpu_coherency_DRM_PANTHOR_GPU_COHERENCY_NONE,
  67. shader_present,
  68. l2_present,
  69. tiler_present,
  70. core_features,
  71. pad: 0,
  72. gpu_features: 0,
  73. }))
  74. }
  75. pub(crate) fn log(&self, pdev: &platform::Device) {
  76. let major = (self.gpu_id >> 16) & 0xff;
  77. let minor = (self.gpu_id >> 8) & 0xff;
  78. let status = self.gpu_id & 0xff;
  79. let model_name = if let Some(model) = GPU_MODELS
  80. .iter()
  81. .find(|&f| f.major == major && f.minor == minor)
  82. {
  83. model.name
  84. } else {
  85. "unknown"
  86. };
  87. dev_info!(
  88. pdev,
  89. "mali-{} id 0x{:x} major 0x{:x} minor 0x{:x} status 0x{:x}",
  90. model_name,
  91. self.gpu_id >> 16,
  92. major,
  93. minor,
  94. status
  95. );
  96. dev_info!(
  97. pdev,
  98. "Features: L2:{:#x} Tiler:{:#x} Mem:{:#x} MMU:{:#x} AS:{:#x}",
  99. self.l2_features,
  100. self.tiler_features,
  101. self.mem_features,
  102. self.mmu_features,
  103. self.as_present
  104. );
  105. dev_info!(
  106. pdev,
  107. "shader_present=0x{:016x} l2_present=0x{:016x} tiler_present=0x{:016x}",
  108. self.shader_present,
  109. self.l2_present,
  110. self.tiler_present
  111. );
  112. }
  113. /// Returns the number of virtual address bits supported by the GPU.
  114. #[expect(dead_code)]
  115. pub(crate) fn va_bits(&self) -> u32 {
  116. self.mmu_features & genmask_u32(0..=7)
  117. }
  118. /// Returns the number of physical address bits supported by the GPU.
  119. #[expect(dead_code)]
  120. pub(crate) fn pa_bits(&self) -> u32 {
  121. (self.mmu_features >> 8) & genmask_u32(0..=7)
  122. }
  123. }
  124. impl Deref for GpuInfo {
  125. type Target = uapi::drm_panthor_gpu_info;
  126. fn deref(&self) -> &Self::Target {
  127. &self.0
  128. }
  129. }
  130. impl DerefMut for GpuInfo {
  131. fn deref_mut(&mut self) -> &mut Self::Target {
  132. &mut self.0
  133. }
  134. }
  135. // SAFETY: `GpuInfo`'s invariant guarantees that it is the same type that is
  136. // already exposed to userspace by the C driver. This implies that it fulfills
  137. // the requirements for `AsBytes`.
  138. //
  139. // This means:
  140. //
  141. // - No implicit padding,
  142. // - No kernel pointers,
  143. // - No interior mutability.
  144. unsafe impl AsBytes for GpuInfo {}
  145. struct GpuModels {
  146. name: &'static str,
  147. major: u32,
  148. minor: u32,
  149. }
  150. const GPU_MODELS: [GpuModels; 1] = [GpuModels {
  151. name: "g610",
  152. major: 10,
  153. minor: 7,
  154. }];
  155. #[allow(dead_code)]
  156. pub(crate) struct GpuId {
  157. pub(crate) arch_major: u32,
  158. pub(crate) arch_minor: u32,
  159. pub(crate) arch_rev: u32,
  160. pub(crate) prod_major: u32,
  161. pub(crate) ver_major: u32,
  162. pub(crate) ver_minor: u32,
  163. pub(crate) ver_status: u32,
  164. }
  165. impl From<u32> for GpuId {
  166. fn from(value: u32) -> Self {
  167. GpuId {
  168. arch_major: (value & genmask_u32(28..=31)) >> 28,
  169. arch_minor: (value & genmask_u32(24..=27)) >> 24,
  170. arch_rev: (value & genmask_u32(20..=23)) >> 20,
  171. prod_major: (value & genmask_u32(16..=19)) >> 16,
  172. ver_major: (value & genmask_u32(12..=15)) >> 12,
  173. ver_minor: (value & genmask_u32(4..=11)) >> 4,
  174. ver_status: value & genmask_u32(0..=3),
  175. }
  176. }
  177. }
  178. /// Powers on the l2 block.
  179. pub(crate) fn l2_power_on(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result {
  180. regs::L2_PWRON_LO.write(dev, iomem, 1)?;
  181. poll::read_poll_timeout(
  182. || regs::L2_READY_LO.read(dev, iomem),
  183. |status| *status == 1,
  184. Delta::from_millis(1),
  185. Delta::from_millis(100),
  186. )
  187. .inspect_err(|_| dev_err!(dev, "Failed to power on the GPU."))?;
  188. Ok(())
  189. }