driver.rs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // SPDX-License-Identifier: GPL-2.0 or MIT
  2. use kernel::clk::Clk;
  3. use kernel::clk::OptionalClk;
  4. use kernel::device::Bound;
  5. use kernel::device::Core;
  6. use kernel::device::Device;
  7. use kernel::devres::Devres;
  8. use kernel::drm;
  9. use kernel::drm::ioctl;
  10. use kernel::io::poll;
  11. use kernel::new_mutex;
  12. use kernel::of;
  13. use kernel::platform;
  14. use kernel::prelude::*;
  15. use kernel::regulator;
  16. use kernel::regulator::Regulator;
  17. use kernel::sizes::SZ_2M;
  18. use kernel::sync::aref::ARef;
  19. use kernel::sync::Arc;
  20. use kernel::sync::Mutex;
  21. use kernel::time;
  22. use crate::file::File;
  23. use crate::gem::TyrObject;
  24. use crate::gpu;
  25. use crate::gpu::GpuInfo;
  26. use crate::regs;
  27. pub(crate) type IoMem = kernel::io::mem::IoMem<SZ_2M>;
  28. /// Convenience type alias for the DRM device type for this driver.
  29. pub(crate) type TyrDevice = drm::Device<TyrDriver>;
  30. #[pin_data(PinnedDrop)]
  31. pub(crate) struct TyrDriver {
  32. _device: ARef<TyrDevice>,
  33. }
  34. #[pin_data(PinnedDrop)]
  35. pub(crate) struct TyrData {
  36. pub(crate) pdev: ARef<platform::Device>,
  37. #[pin]
  38. clks: Mutex<Clocks>,
  39. #[pin]
  40. regulators: Mutex<Regulators>,
  41. /// Some information on the GPU.
  42. ///
  43. /// This is mainly queried by userspace, i.e.: Mesa.
  44. pub(crate) gpu_info: GpuInfo,
  45. }
  46. // Both `Clk` and `Regulator` do not implement `Send` or `Sync`, but they
  47. // should. There are patches on the mailing list to address this, but they have
  48. // not landed yet.
  49. //
  50. // For now, add this workaround so that this patch compiles with the promise
  51. // that it will be removed in a future patch.
  52. //
  53. // SAFETY: This will be removed in a future patch.
  54. unsafe impl Send for TyrData {}
  55. // SAFETY: This will be removed in a future patch.
  56. unsafe impl Sync for TyrData {}
  57. fn issue_soft_reset(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result {
  58. regs::GPU_CMD.write(dev, iomem, regs::GPU_CMD_SOFT_RESET)?;
  59. poll::read_poll_timeout(
  60. || regs::GPU_IRQ_RAWSTAT.read(dev, iomem),
  61. |status| *status & regs::GPU_IRQ_RAWSTAT_RESET_COMPLETED != 0,
  62. time::Delta::from_millis(1),
  63. time::Delta::from_millis(100),
  64. )
  65. .inspect_err(|_| dev_err!(dev, "GPU reset failed."))?;
  66. Ok(())
  67. }
  68. kernel::of_device_table!(
  69. OF_TABLE,
  70. MODULE_OF_TABLE,
  71. <TyrDriver as platform::Driver>::IdInfo,
  72. [
  73. (of::DeviceId::new(c"rockchip,rk3588-mali"), ()),
  74. (of::DeviceId::new(c"arm,mali-valhall-csf"), ())
  75. ]
  76. );
  77. impl platform::Driver for TyrDriver {
  78. type IdInfo = ();
  79. const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
  80. fn probe(
  81. pdev: &platform::Device<Core>,
  82. _info: Option<&Self::IdInfo>,
  83. ) -> impl PinInit<Self, Error> {
  84. let core_clk = Clk::get(pdev.as_ref(), Some(c"core"))?;
  85. let stacks_clk = OptionalClk::get(pdev.as_ref(), Some(c"stacks"))?;
  86. let coregroup_clk = OptionalClk::get(pdev.as_ref(), Some(c"coregroup"))?;
  87. core_clk.prepare_enable()?;
  88. stacks_clk.prepare_enable()?;
  89. coregroup_clk.prepare_enable()?;
  90. let mali_regulator = Regulator::<regulator::Enabled>::get(pdev.as_ref(), c"mali")?;
  91. let sram_regulator = Regulator::<regulator::Enabled>::get(pdev.as_ref(), c"sram")?;
  92. let request = pdev.io_request_by_index(0).ok_or(ENODEV)?;
  93. let iomem = Arc::pin_init(request.iomap_sized::<SZ_2M>(), GFP_KERNEL)?;
  94. issue_soft_reset(pdev.as_ref(), &iomem)?;
  95. gpu::l2_power_on(pdev.as_ref(), &iomem)?;
  96. let gpu_info = GpuInfo::new(pdev.as_ref(), &iomem)?;
  97. gpu_info.log(pdev);
  98. let platform: ARef<platform::Device> = pdev.into();
  99. let data = try_pin_init!(TyrData {
  100. pdev: platform.clone(),
  101. clks <- new_mutex!(Clocks {
  102. core: core_clk,
  103. stacks: stacks_clk,
  104. coregroup: coregroup_clk,
  105. }),
  106. regulators <- new_mutex!(Regulators {
  107. _mali: mali_regulator,
  108. _sram: sram_regulator,
  109. }),
  110. gpu_info,
  111. });
  112. let tdev: ARef<TyrDevice> = drm::Device::new(pdev.as_ref(), data)?;
  113. drm::driver::Registration::new_foreign_owned(&tdev, pdev.as_ref(), 0)?;
  114. let driver = TyrDriver { _device: tdev };
  115. // We need this to be dev_info!() because dev_dbg!() does not work at
  116. // all in Rust for now, and we need to see whether probe succeeded.
  117. dev_info!(pdev, "Tyr initialized correctly.\n");
  118. Ok(driver)
  119. }
  120. }
  121. #[pinned_drop]
  122. impl PinnedDrop for TyrDriver {
  123. fn drop(self: Pin<&mut Self>) {}
  124. }
  125. #[pinned_drop]
  126. impl PinnedDrop for TyrData {
  127. fn drop(self: Pin<&mut Self>) {
  128. // TODO: the type-state pattern for Clks will fix this.
  129. let clks = self.clks.lock();
  130. clks.core.disable_unprepare();
  131. clks.stacks.disable_unprepare();
  132. clks.coregroup.disable_unprepare();
  133. }
  134. }
  135. // We need to retain the name "panthor" to achieve drop-in compatibility with
  136. // the C driver in the userspace stack.
  137. const INFO: drm::DriverInfo = drm::DriverInfo {
  138. major: 1,
  139. minor: 5,
  140. patchlevel: 0,
  141. name: c"panthor",
  142. desc: c"ARM Mali Tyr DRM driver",
  143. };
  144. #[vtable]
  145. impl drm::Driver for TyrDriver {
  146. type Data = TyrData;
  147. type File = File;
  148. type Object = drm::gem::Object<TyrObject>;
  149. const INFO: drm::DriverInfo = INFO;
  150. kernel::declare_drm_ioctls! {
  151. (PANTHOR_DEV_QUERY, drm_panthor_dev_query, ioctl::RENDER_ALLOW, File::dev_query),
  152. }
  153. }
  154. #[pin_data]
  155. struct Clocks {
  156. core: Clk,
  157. stacks: OptionalClk,
  158. coregroup: OptionalClk,
  159. }
  160. #[pin_data]
  161. struct Regulators {
  162. _mali: Regulator<regulator::Enabled>,
  163. _sram: Regulator<regulator::Enabled>,
  164. }