diff --git a/drivers/gpu/drm/panthor-rs/gpu.rs b/drivers/gpu/drm/panthor-rs/gpu.rs new file mode 100644 index 0000000000000000000000000000000000000000..3600379e5aca2234e59a90d9815c61d2fa965b16 --- /dev/null +++ b/drivers/gpu/drm/panthor-rs/gpu.rs @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0-only OR MIT + +use core::ffi; + +use kernel::bindings; +use kernel::error::Result; +use kernel::pr_err; +use kernel::pr_info; +use kernel::sync::Arc; +use kernel::types::ForeignOwnable; + +use crate::driver::PanthorData; +use crate::regs::GpuIdV; + +/// Define a GPU model. A GPU product can be uniquely identified by a +/// combination of the major architecture version and the major product version. +struct PanthorModel { + name: &'static str, + arch_major: u32, + product_major: u32, +} + +const GPU_MODELS: &[PanthorModel] = &[PanthorModel { + name: "g610", + arch_major: 10, + product_major: 7, +}]; + +fn read_gpu_info(ptdev: *mut bindings::panthor_device) -> Result { + // Safety: `ptdev` is a valid pointer to a `panthor_device` instance. The + // `rust_data` field was populated using `into_foreign` in `driver.rs`. + let data: Arc<PanthorData> = unsafe { Arc::from_foreign((*ptdev).rust_data) }; + let iomem = &data.regs.iomem; + + let gpu_id = data.regs.gpu_id.read_u32(iomem)?; + let csf_id = data.regs.csf_id.read_u32(iomem)?; + let gpu_rev = data.regs.rev_idr.read(iomem)?; + let core_features = data.regs.core_features.read_u32(iomem)?; + let l2_features = data.regs.l2_features.read_u32(iomem)?; + let tiler_features = data.regs.tiler_features.read_u32(iomem)?; + let mem_features = data.regs.mem_features.read_u32(iomem)?; + let mmu_features = data.regs.mmu_features.read_u32(iomem)?; + let thread_features = data.regs.thread_features.read_u32(iomem)?; + let max_threads = data.regs.max_threads.read(iomem)?; + let thread_max_workgroup_size = data.regs.max_workgroup_size.read(iomem)?; + let thread_max_barrier_size = data.regs.max_barrier_size.read(iomem)?; + let coherency_features = data.regs.coherency_features.read_u32(iomem)?; + let texture_features = data.regs.texture_features.read(iomem)?; + + let as_present = data.regs.as_present.read(iomem)?; + let shader_present = data.regs.shader_present.read(iomem)?; + let tiler_present = data.regs.tiler_present.read(iomem)?; + let l2_present = data.regs.l2_present.read(iomem)?; + + // Safety: we trust the pointer passed from the C side. + unsafe { + (*ptdev).gpu_info.gpu_id = gpu_id; + (*ptdev).gpu_info.csf_id = csf_id; + (*ptdev).gpu_info.gpu_rev = gpu_rev; + (*ptdev).gpu_info.core_features = core_features; + (*ptdev).gpu_info.l2_features = l2_features; + (*ptdev).gpu_info.tiler_features = tiler_features; + (*ptdev).gpu_info.mem_features = mem_features; + (*ptdev).gpu_info.mmu_features = mmu_features; + (*ptdev).gpu_info.thread_features = thread_features; + (*ptdev).gpu_info.max_threads = max_threads; + (*ptdev).gpu_info.thread_max_workgroup_size = thread_max_workgroup_size; + (*ptdev).gpu_info.thread_max_barrier_size = thread_max_barrier_size; + (*ptdev).gpu_info.coherency_features = coherency_features; + for i in 0..4 { + (*ptdev).gpu_info.texture_features[i] = texture_features.value(i); + } + } + + let GpuIdV { + arch_major, + arch_minor, + arch_rev, + prod_major, + ver_major, + ver_minor, + ver_status, + } = data.regs.gpu_id.read(iomem)?; + + let model_name = GPU_MODELS + .iter() + .find(|model| model.arch_major == arch_major && model.product_major == prod_major) + .map_or("unknown", |model| model.name); + + pr_info!( + "mali-{} id 0x{:x} major 0x{:x} minor 0x{:x} status 0x{:x}", + model_name, + prod_major, + arch_major, + arch_minor, + ver_status + ); + + pr_info!( + "Features: L2:{:#x} Tiler:{:#x} Mem:{:#x} MMU:{:#x} AS:{:#x}", + l2_features, + tiler_features, + mem_features, + mmu_features, + as_present + ); + + pr_info!( + "shader_present=0x{:0x} l2_present=0x{:0x} tiler_present=0x{:0x}", + shader_present, + l2_present, + tiler_present + ); + + Ok(()) +} + +#[no_mangle] +pub(crate) extern "C" fn panthor_gpu_init_info(ptdev: *mut bindings::panthor_device) -> ffi::c_int { + match read_gpu_info(ptdev) { + Ok(_) => 0, + Err(e) => { + pr_err!("Failed to read GPU info: {:?}", e); + e.to_errno() + } + } +} diff --git a/drivers/gpu/drm/panthor-rs/panthor.rs b/drivers/gpu/drm/panthor-rs/panthor.rs index 7734b4b1e20dfba90fce963b55ac86c3c7bbece3..06588c55f1681b4b81b9a5a0364532d435eec51e 100644 --- a/drivers/gpu/drm/panthor-rs/panthor.rs +++ b/drivers/gpu/drm/panthor-rs/panthor.rs @@ -10,6 +10,7 @@ mod driver; mod file; mod gem; +mod gpu; mod regs; use kernel::module_platform_driver; diff --git a/drivers/gpu/drm/panthor-rs/panthor_device.h b/drivers/gpu/drm/panthor-rs/panthor_device.h index cfc832110b3ecf654cb298ccc7c2de1c80eec024..8ac8624016ac6c6d707b8a1a89fefc5b4d8b26d2 100644 --- a/drivers/gpu/drm/panthor-rs/panthor_device.h +++ b/drivers/gpu/drm/panthor-rs/panthor_device.h @@ -163,6 +163,12 @@ struct panthor_device { */ struct page *dummy_latest_flush; } pm; + + /** + * @rust_data: An opaque pointer to data interpreted by the Rust layer of + * the driver. + */ + void *rust_data; }; /** diff --git a/drivers/gpu/drm/panthor-rs/panthor_gpu.c b/drivers/gpu/drm/panthor-rs/panthor_gpu.c index ae29403468d879eaaaf561dd3019af205c8480e7..adafb70d8882cfb4870972d212a8b6d7bcf56cc0 100644 --- a/drivers/gpu/drm/panthor-rs/panthor_gpu.c +++ b/drivers/gpu/drm/panthor-rs/panthor_gpu.c @@ -66,81 +66,14 @@ struct panthor_model { .product_major = _product_major, \ } -static const struct panthor_model gpu_models[] = { - GPU_MODEL(g610, 10, 7), - {}, -}; - #define GPU_INTERRUPTS_MASK \ (GPU_IRQ_FAULT | \ GPU_IRQ_PROTM_FAULT | \ GPU_IRQ_RESET_COMPLETED | \ GPU_IRQ_CLEAN_CACHES_COMPLETED) -static void panthor_gpu_init_info(struct panthor_device *ptdev) -{ - const struct panthor_model *model; - u32 arch_major, product_major; - u32 major, minor, status; - unsigned int i; - - ptdev->gpu_info.gpu_id = gpu_read(ptdev, GPU_ID); - ptdev->gpu_info.csf_id = gpu_read(ptdev, GPU_CSF_ID); - ptdev->gpu_info.gpu_rev = gpu_read(ptdev, GPU_REVID); - ptdev->gpu_info.core_features = gpu_read(ptdev, GPU_CORE_FEATURES); - ptdev->gpu_info.l2_features = gpu_read(ptdev, GPU_L2_FEATURES); - ptdev->gpu_info.tiler_features = gpu_read(ptdev, GPU_TILER_FEATURES); - ptdev->gpu_info.mem_features = gpu_read(ptdev, GPU_MEM_FEATURES); - ptdev->gpu_info.mmu_features = gpu_read(ptdev, GPU_MMU_FEATURES); - ptdev->gpu_info.thread_features = gpu_read(ptdev, GPU_THREAD_FEATURES); - ptdev->gpu_info.max_threads = gpu_read(ptdev, GPU_THREAD_MAX_THREADS); - ptdev->gpu_info.thread_max_workgroup_size = gpu_read(ptdev, GPU_THREAD_MAX_WORKGROUP_SIZE); - ptdev->gpu_info.thread_max_barrier_size = gpu_read(ptdev, GPU_THREAD_MAX_BARRIER_SIZE); - ptdev->gpu_info.coherency_features = gpu_read(ptdev, GPU_COHERENCY_FEATURES); - for (i = 0; i < 4; i++) - ptdev->gpu_info.texture_features[i] = gpu_read(ptdev, GPU_TEXTURE_FEATURES(i)); - - ptdev->gpu_info.as_present = gpu_read(ptdev, GPU_AS_PRESENT); - - ptdev->gpu_info.shader_present = gpu_read(ptdev, GPU_SHADER_PRESENT_LO); - ptdev->gpu_info.shader_present |= (u64)gpu_read(ptdev, GPU_SHADER_PRESENT_HI) << 32; - - ptdev->gpu_info.tiler_present = gpu_read(ptdev, GPU_TILER_PRESENT_LO); - ptdev->gpu_info.tiler_present |= (u64)gpu_read(ptdev, GPU_TILER_PRESENT_HI) << 32; - - ptdev->gpu_info.l2_present = gpu_read(ptdev, GPU_L2_PRESENT_LO); - ptdev->gpu_info.l2_present |= (u64)gpu_read(ptdev, GPU_L2_PRESENT_HI) << 32; - - arch_major = GPU_ARCH_MAJOR(ptdev->gpu_info.gpu_id); - product_major = GPU_PROD_MAJOR(ptdev->gpu_info.gpu_id); - major = GPU_VER_MAJOR(ptdev->gpu_info.gpu_id); - minor = GPU_VER_MINOR(ptdev->gpu_info.gpu_id); - status = GPU_VER_STATUS(ptdev->gpu_info.gpu_id); - - for (model = gpu_models; model->name; model++) { - if (model->arch_major == arch_major && - model->product_major == product_major) - break; - } - - drm_info(ptdev->base, - "mali-%s id 0x%x major 0x%x minor 0x%x status 0x%x", - model->name ?: "unknown", ptdev->gpu_info.gpu_id >> 16, - major, minor, status); - - drm_info(ptdev->base, - "Features: L2:%#x Tiler:%#x Mem:%#x MMU:%#x AS:%#x", - ptdev->gpu_info.l2_features, - ptdev->gpu_info.tiler_features, - ptdev->gpu_info.mem_features, - ptdev->gpu_info.mmu_features, - ptdev->gpu_info.as_present); - - drm_info(ptdev->base, - "shader_present=0x%0llx l2_present=0x%0llx tiler_present=0x%0llx", - ptdev->gpu_info.shader_present, ptdev->gpu_info.l2_present, - ptdev->gpu_info.tiler_present); -} +/* defined in gpu.rs */ +void panthor_gpu_init_info(struct panthor_device *ptdev); static void panthor_gpu_irq_handler(struct panthor_device *ptdev, u32 status) {