diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 1cb5a4f1929335fcf0a135ccf7cc30acf958da8c..f6019a4c53206694b6f630e8be7d2096ca19908c 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -452,6 +452,7 @@ source "drivers/gpu/drm/lima/Kconfig"
 source "drivers/gpu/drm/panfrost/Kconfig"
 
 source "drivers/gpu/drm/panthor/Kconfig"
+source "drivers/gpu/drm/panthor-rs/Kconfig"
 
 source "drivers/gpu/drm/aspeed/Kconfig"
 
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 784229d4504dcb7d4ad6427fe238b024c5946946..f13d37d6d76871a42caa32f9565cca0df6283d1e 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -209,6 +209,7 @@ obj-$(CONFIG_DRM_VBOXVIDEO) += vboxvideo/
 obj-$(CONFIG_DRM_LIMA)  += lima/
 obj-$(CONFIG_DRM_PANFROST) += panfrost/
 obj-$(CONFIG_DRM_PANTHOR) += panthor/
+obj-$(CONFIG_DRM_PANTHOR_RS) += panthor-rs/
 obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/
 obj-$(CONFIG_DRM_MCDE) += mcde/
 obj-$(CONFIG_DRM_TIDSS) += tidss/
diff --git a/drivers/gpu/drm/panthor-rs/Kconfig b/drivers/gpu/drm/panthor-rs/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..9356325f778cd2695b92b561e402c73c4fc32dec
--- /dev/null
+++ b/drivers/gpu/drm/panthor-rs/Kconfig
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0 or MIT
+
+config DRM_PANTHOR_RS
+	tristate "Panthor Rust-based (DRM support for ARM Mali CSF-based GPUs)"
+	depends on DRM=y
+	depends on RUST
+	depends on ARM || ARM64 || COMPILE_TEST
+	depends on !GENERIC_ATOMIC64  # for IOMMU_IO_PGTABLE_LPAE
+	depends on MMU
+	depends on DRM_PANTHOR=n
+	select DEVFREQ_GOV_SIMPLE_ONDEMAND
+	select DRM_EXEC
+	select DRM_GEM_SHMEM_HELPER
+	select DRM_GPUVM
+	select DRM_SCHED
+	select IOMMU_IO_PGTABLE_LPAE
+	depends on IOMMU_SUPPORT
+	select PM_DEVFREQ
+	help
+	  DRM driver for ARM Mali CSF-based GPUs.
+
+	  This driver is for Mali (or Immortalis) Valhall Gxxx GPUs.
+
+	  Note that the Mali-G68 and Mali-G78, while Valhall architecture, will
+	  be supported with the panfrost driver as they are not CSF GPUs.
diff --git a/drivers/gpu/drm/panthor-rs/Makefile b/drivers/gpu/drm/panthor-rs/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..c39521d5ca9e3aa8929f113e65b51cf5f0215415
--- /dev/null
+++ b/drivers/gpu/drm/panthor-rs/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0 or MIT
+
+panthor_rs-y := \
+	panthor.o
+
+obj-$(CONFIG_DRM_PANTHOR_RS) += panthor_rs.o
+
+CFLAGS_panthor_drv.o := -Wno-missing-prototypes -Wno-unused-function -Wno-unused-const-variable
diff --git a/drivers/gpu/drm/panthor-rs/driver.rs b/drivers/gpu/drm/panthor-rs/driver.rs
new file mode 100644
index 0000000000000000000000000000000000000000..546c1df47b95e4baa23323688b5d7e5dced3fb81
--- /dev/null
+++ b/drivers/gpu/drm/panthor-rs/driver.rs
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+
+//! Top-level GPU driver implementation.
+
+use kernel::{
+    bindings, c_str, drm, drm::drv, drm::ioctl, error::Result, of, platform, prelude::*, sync::Arc,
+};
+
+use core::ffi;
+use kernel::macros::vtable;
+use kernel::types::ARef;
+
+extern "C" {
+    fn panthor_device_init(ptdev: *mut bindings::panthor_device) -> ffi::c_int;
+}
+
+/// Driver metadata
+const INFO: drm::drv::DriverInfo = drm::drv::DriverInfo {
+    major: 0,
+    minor: 0,
+    patchlevel: 0,
+    name: c_str!("panthor"),
+    desc: c_str!("Panthor DRM driver"),
+    date: c_str!("20230801"),
+};
+
+/// Device data for the driver registration.
+///
+/// Holds a reference to the top-level `GpuManager` object.
+#[allow(dead_code)]
+#[pin_data]
+pub(crate) struct PanthorData {
+    #[pin]
+    pub(crate) ptdev: *mut bindings::panthor_device,
+    pub(crate) pdev: platform::Device,
+}
+
+//HACK
+unsafe impl Send for PanthorData {}
+unsafe impl Sync for PanthorData {}
+
+pub(crate) struct PanthorDriver(ARef<PanthorDevice>);
+
+/// Convenience type alias for the DRM device type for this driver.
+pub(crate) type PanthorDevice = kernel::drm::device::Device<PanthorDriver>;
+pub(crate) type PanthorDevRef = ARef<PanthorDevice>;
+
+/// DRM Driver implementation for `PanthorDriver`.
+#[vtable]
+impl drv::Driver for PanthorDriver {
+    /// Our `DeviceData` type, reference-counted
+    type Data = Arc<PanthorData>;
+    /// Our `File` type.
+    type File = crate::file::File;
+    /// Our `Object` type.
+    type Object = crate::gem::Object;
+
+    const INFO: drv::DriverInfo = INFO;
+    const FEATURES: u32 = drv::FEAT_GEM
+        | drv::FEAT_RENDER
+        | drv::FEAT_SYNCOBJ
+        | drv::FEAT_SYNCOBJ_TIMELINE
+        | drv::FEAT_GEM_GPUVA;
+
+    kernel::declare_drm_ioctls! {
+        (PANTHOR_DEV_QUERY,      drm_panthor_dev_query,
+            ioctl::RENDER_ALLOW, crate::file::File::dev_query),
+        (PANTHOR_VM_CREATE,      drm_panthor_vm_create,
+            ioctl::RENDER_ALLOW, crate::file::File::vm_create),
+        (PANTHOR_VM_DESTROY,     drm_panthor_vm_destroy,
+            ioctl::RENDER_ALLOW, crate::file::File::vm_destroy),
+        (PANTHOR_VM_BIND,        drm_panthor_vm_bind,
+            ioctl::RENDER_ALLOW, crate::file::File::vm_bind),
+        (PANTHOR_VM_GET_STATE,   drm_panthor_vm_get_state,
+            ioctl::RENDER_ALLOW, crate::file::File::vm_get_state),
+        (PANTHOR_BO_CREATE,      drm_panthor_bo_create,
+            ioctl::RENDER_ALLOW, crate::file::File::bo_create),
+        (PANTHOR_BO_MMAP_OFFSET, drm_panthor_bo_mmap_offset,
+            ioctl::RENDER_ALLOW, crate::file::File::bo_mmap_offset),
+        (PANTHOR_GROUP_CREATE,   drm_panthor_group_create,
+            ioctl::RENDER_ALLOW, crate::file::File::group_create),
+        (PANTHOR_GROUP_DESTROY,  drm_panthor_group_destroy,
+            ioctl::RENDER_ALLOW, crate::file::File::group_destroy),
+        (PANTHOR_GROUP_SUBMIT,   drm_panthor_group_submit,
+            ioctl::RENDER_ALLOW, crate::file::File::group_submit),
+        (PANTHOR_GROUP_GET_STATE, drm_panthor_group_get_state,
+            ioctl::RENDER_ALLOW, crate::file::File::group_get_state),
+        (PANTHOR_TILER_HEAP_CREATE, drm_panthor_tiler_heap_create,
+            ioctl::RENDER_ALLOW, crate::file::File::tiler_heap_create),
+        (PANTHOR_TILER_HEAP_DESTROY, drm_panthor_tiler_heap_destroy,
+            ioctl::RENDER_ALLOW, crate::file::File::tiler_heap_destroy),
+    }
+}
+
+kernel::of_device_table!(
+    OF_TABLE,
+    MODULE_OF_TABLE,
+    <PanthorDriver as platform::Driver>::IdInfo,
+    [
+        (of::DeviceId::new(c_str!("rockchip,rk3588-mali")), ()),
+        (of::DeviceId::new(c_str!("arm,mali-valhall-csf")), ()),
+    ]
+);
+
+/// Platform Driver implementation for `PanthorDriver`.
+impl platform::Driver for PanthorDriver {
+    type IdInfo = ();
+    const ID_TABLE: platform::IdTable<Self::IdInfo> = &OF_TABLE;
+
+    /// Device probe function.
+    fn probe(
+        pdev: &mut platform::Device,
+        id_info: Option<&Self::IdInfo>,
+    ) -> Result<Pin<KBox<Self>>> {
+        dev_info!(pdev.as_ref(), "Probing...\n");
+
+        let data = Arc::new(
+            PanthorData {
+                ptdev: unsafe { bindings::panthor_device_alloc() },
+                pdev: pdev.clone(),
+            },
+            GFP_KERNEL,
+        )?;
+
+        let drm = drm::device::Device::<PanthorDriver>::new(pdev.as_ref(), data.clone())?;
+
+        unsafe {
+            (*data.ptdev).base = drm.as_raw();
+            panthor_device_init(data.ptdev);
+        }
+
+        drm::drv::Registration::new_foreign_owned(drm.clone(), 0)?;
+
+        dev_info!(pdev.as_ref(), "Probed!\n");
+        Ok(KBox::new(Self(drm), GFP_KERNEL)?.into())
+    }
+}
+
+impl Drop for PanthorDriver {
+    fn drop(&mut self) {
+        let data = self.0.data();
+
+        dev_dbg!(data.pdev.as_ref(), "Remove Panthor GPU driver.\n");
+    }
+}
diff --git a/drivers/gpu/drm/panthor-rs/file.rs b/drivers/gpu/drm/panthor-rs/file.rs
new file mode 100644
index 0000000000000000000000000000000000000000..1146fbefda5bf0c51524dc4106b6ac6a9df2c811
--- /dev/null
+++ b/drivers/gpu/drm/panthor-rs/file.rs
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+#![allow(clippy::unusual_byte_groupings)]
+
+//! File implementation, which represents a single DRM client.
+//!
+//! This is in charge of managing the resources associated with one GPU client, including an
+//! arbitrary number of submission queues and Vm objects, and reporting hardware/driver
+//! information to userspace and accepting submissions.
+
+//use crate::debug::*;
+use crate::driver::PanthorDevice;
+use crate::driver::PanthorDriver;
+//use crate::{alloc, buffer, driver, gem, mmu, queue, util::RangeExt};
+//use kernel::drm::gem::BaseObject;
+//use kernel::io_buffer::{IoBufferReader, IoBufferWriter};
+use core;
+use core::ffi;
+use core::ptr;
+use kernel::prelude::*;
+use kernel::{
+    drm::file::GenericFile,
+    drm::{self, device::Device as DrmDevice},
+    error::to_result,
+    uapi,
+};
+
+/// Convenience type alias for our DRM `File` type.
+pub(crate) type DrmFile = drm::file::File<File>;
+
+/// State associated with a client.
+pub(crate) struct File();
+
+impl drm::file::DriverFile for File {
+    type Driver = PanthorDriver;
+
+    fn open(_dev: &DrmDevice<Self::Driver>) -> Result<Pin<Box<Self>>> {
+        pr_info!("DRM Device :: open()\n");
+
+        Ok(Box::into_pin(Box::new(Self(), GFP_KERNEL)?))
+    }
+}
+
+impl File {
+    /// IOCTL: dev_query
+    pub(crate) fn dev_query(
+        device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_dev_query,
+        _file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: vm_create
+    pub(crate) fn vm_create(
+        device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_vm_create,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: vm_destroy
+    pub(crate) fn vm_destroy(
+        _device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_vm_destroy,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: vm_bind
+    pub(crate) fn vm_bind(
+        _device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_vm_bind,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: vm_get_state
+    pub(crate) fn vm_get_state(
+        _device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_vm_get_state,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: bo_create
+    pub(crate) fn bo_create(
+        device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_bo_create,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: bo_mmap_offset
+    pub(crate) fn bo_mmap_offset(
+        _device: &PanthorDevice,
+        _data: &mut uapi::drm_panthor_bo_mmap_offset,
+        _file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: group_create
+    pub(crate) fn group_create(
+        _device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_group_create,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: group_destroy
+    pub(crate) fn group_destroy(
+        _device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_group_destroy,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: group_get_state
+    pub(crate) fn group_get_state(
+        _device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_group_get_state,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: tiler_heap_create
+    pub(crate) fn tiler_heap_create(
+        _device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_tiler_heap_create,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: tiler_heap_destroy
+    pub(crate) fn tiler_heap_destroy(
+        _device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_tiler_heap_destroy,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: group_submit
+    pub(crate) fn group_submit(
+        device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_group_submit,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+}
+
+impl Drop for File {
+    fn drop(&mut self) {}
+}
diff --git a/drivers/gpu/drm/panthor-rs/gem.rs b/drivers/gpu/drm/panthor-rs/gem.rs
new file mode 100644
index 0000000000000000000000000000000000000000..8e824bcd591f98c4d7f15741b9d0052e7b577f7d
--- /dev/null
+++ b/drivers/gpu/drm/panthor-rs/gem.rs
@@ -0,0 +1,29 @@
+use core::sync::atomic::{AtomicU64, Ordering};
+
+use kernel::{drm::gem, prelude::*};
+
+use crate::driver::{PanthorDevice, PanthorDriver};
+
+static GEM_ID: AtomicU64 = AtomicU64::new(0);
+
+/// GEM Object implementation
+#[pin_data]
+pub(crate) struct DriverObject {
+    /// ID for debugging
+    id: u64,
+}
+
+pub(crate) type Object = gem::Object<DriverObject>;
+
+impl gem::BaseDriverObject<Object> for DriverObject {
+    fn new(_dev: &PanthorDevice, _size: usize) -> impl PinInit<Self, Error> {
+        let id = GEM_ID.fetch_add(1, Ordering::Relaxed);
+
+        pr_debug!("DriverObject::new() id={}\n", id);
+        DriverObject { id }
+    }
+}
+
+impl gem::DriverObject for DriverObject {
+    type Driver = PanthorDriver;
+}
diff --git a/drivers/gpu/drm/panthor-rs/panthor.rs b/drivers/gpu/drm/panthor-rs/panthor.rs
new file mode 100644
index 0000000000000000000000000000000000000000..a177f8b6eee9e987353b262d9751499cbf1b58af
--- /dev/null
+++ b/drivers/gpu/drm/panthor-rs/panthor.rs
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+#![recursion_limit = "2048"]
+
+//! Driver for the Arm Mali CSF-based GPUs.
+
+#![allow(improper_ctypes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+mod driver;
+mod file;
+mod gem;
+
+use kernel::module_platform_driver;
+
+module_platform_driver! {
+    type: driver::PanthorDriver,
+    name: "panthor_rs",
+    author: "Arm",
+    license: "Dual MIT/GPL",
+}
diff --git a/drivers/gpu/drm/panthor-rs/panthor_device.c b/drivers/gpu/drm/panthor-rs/panthor_device.c
index 6dcc4b55c05a0389f9a0c4a7613f1f874ede003f..e4a88a8dcb4e16047ccd7bf7f0ad40295799272d 100644
--- a/drivers/gpu/drm/panthor-rs/panthor_device.c
+++ b/drivers/gpu/drm/panthor-rs/panthor_device.c
@@ -271,6 +271,13 @@ int panthor_device_init(struct panthor_device *ptdev)
 	return ret;
 }
 
+struct panthor_device *panthor_device_alloc(void)
+{
+	struct panthor_device *ptdev = kzalloc(sizeof(struct panthor_device), GFP_KERNEL);
+	return ptdev;
+}
+
+
 #define PANTHOR_EXCEPTION(id) \
 	[DRM_PANTHOR_EXCEPTION_ ## id] = { \
 		.name = #id, \
diff --git a/drivers/gpu/drm/panthor-rs/panthor_device.h b/drivers/gpu/drm/panthor-rs/panthor_device.h
index 2bdf6270d06806ed1556b6771cd4f51147547f71..cfc832110b3ecf654cb298ccc7c2de1c80eec024 100644
--- a/drivers/gpu/drm/panthor-rs/panthor_device.h
+++ b/drivers/gpu/drm/panthor-rs/panthor_device.h
@@ -180,6 +180,8 @@ struct panthor_file {
 };
 
 int panthor_device_init(struct panthor_device *ptdev);
+struct panthor_device *panthor_device_alloc(void);
+
 void panthor_device_unplug(struct panthor_device *ptdev);
 
 /**
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index e1ddee135d12a0fdc5595843919e43e905e31b04..8de125de722545cd2965f03a45e96273b2f89b59 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -32,6 +32,8 @@
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 
+#include <../drivers/gpu/drm/panthor-rs/panthor_device.h>
+
 /* `bindgen` gets confused at certain things. */
 const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
 const size_t RUST_CONST_HELPER_PAGE_SIZE = PAGE_SIZE;
diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs
index e4e060d93ad12e1cb577cec5499389adf66e36a9..d0baf52b7a6241d7b73f2f3bb29d611a9264f7a4 100644
--- a/rust/kernel/drm/gem/mod.rs
+++ b/rust/kernel/drm/gem/mod.rs
@@ -412,5 +412,6 @@ pub(super) const fn create_fops() -> bindings::file_operations {
     fops.mmap = Some(bindings::drm_gem_mmap);
     fops.fop_flags = bindings::FOP_UNSIGNED_OFFSET;
 
+    fops.fop_flags = 1 << 5; // FIXME use FOP_UNSIGNED_OFFSET
     fops
 }
diff --git a/rust/uapi/uapi_helper.h b/rust/uapi/uapi_helper.h
index 19587e55e604128d405a0cffa5059e75273199d3..7a78013c3ecb5f185b09b705d3bc6a16fe95c305 100644
--- a/rust/uapi/uapi_helper.h
+++ b/rust/uapi/uapi_helper.h
@@ -8,6 +8,7 @@
 
 #include <uapi/asm-generic/ioctl.h>
 #include <uapi/drm/drm.h>
+#include <uapi/drm/panthor_drm.h>
 #include <uapi/linux/mdio.h>
 #include <uapi/linux/mii.h>
 #include <uapi/linux/ethtool.h>