File Index
Files and directories
Sign in
FILE

driver.rs

File preview with syntax highlighting.

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