Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/panfrost: Add SYSTEM_TIMESTAMP and SYSTEM_TIMESTAMP_FREQUENCY parameters

Expose system timestamp and frequency supported by the GPU.

Mali uses an external timer as GPU system time. On ARM, this is wired to
the generic arch timer so we wire cntfrq_el0 as device frequency.

This new uAPI will be used in Mesa to implement timestamp queries and
VK_KHR_calibrated_timestamps.

v2:
- Rewrote to use GPU timestamp register
- Add missing include for arch_timer_get_cntfrq
- Rework commit message

v3:
- Move panfrost_cycle_counter_get and panfrost_cycle_counter_put to
panfrost_ioctl_query_timestamp
- Handle possible overflow in panfrost_timestamp_read

Signed-off-by: Mary Guillemard <mary.guillemard@collabora.com>
Tested-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Steven Price <steven.price@arm.com>
Signed-off-by: Steven Price <steven.price@arm.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240819080224.24914-2-mary.guillemard@collabora.com

authored by

Mary Guillemard and committed by
Steven Price
9c75b16c 2872a57c

+54
+37
drivers/gpu/drm/panfrost/panfrost_drv.c
··· 3 3 /* Copyright 2019 Linaro, Ltd., Rob Herring <robh@kernel.org> */ 4 4 /* Copyright 2019 Collabora ltd. */ 5 5 6 + #ifdef CONFIG_ARM_ARCH_TIMER 7 + #include <asm/arch_timer.h> 8 + #endif 9 + 6 10 #include <linux/module.h> 7 11 #include <linux/of.h> 8 12 #include <linux/pagemap.h> ··· 28 24 static bool unstable_ioctls; 29 25 module_param_unsafe(unstable_ioctls, bool, 0600); 30 26 27 + static int panfrost_ioctl_query_timestamp(struct panfrost_device *pfdev, 28 + u64 *arg) 29 + { 30 + int ret; 31 + 32 + ret = pm_runtime_resume_and_get(pfdev->dev); 33 + if (ret) 34 + return ret; 35 + 36 + panfrost_cycle_counter_get(pfdev); 37 + *arg = panfrost_timestamp_read(pfdev); 38 + panfrost_cycle_counter_put(pfdev); 39 + 40 + pm_runtime_put(pfdev->dev); 41 + return 0; 42 + } 43 + 31 44 static int panfrost_ioctl_get_param(struct drm_device *ddev, void *data, struct drm_file *file) 32 45 { 33 46 struct drm_panfrost_get_param *param = data; 34 47 struct panfrost_device *pfdev = ddev->dev_private; 48 + int ret; 35 49 36 50 if (param->pad != 0) 37 51 return -EINVAL; ··· 91 69 PANFROST_FEATURE_ARRAY(JS_FEATURES, js_features, 15); 92 70 PANFROST_FEATURE(NR_CORE_GROUPS, nr_core_groups); 93 71 PANFROST_FEATURE(THREAD_TLS_ALLOC, thread_tls_alloc); 72 + 73 + case DRM_PANFROST_PARAM_SYSTEM_TIMESTAMP: 74 + ret = panfrost_ioctl_query_timestamp(pfdev, &param->value); 75 + if (ret) 76 + return ret; 77 + break; 78 + 79 + case DRM_PANFROST_PARAM_SYSTEM_TIMESTAMP_FREQUENCY: 80 + #ifdef CONFIG_ARM_ARCH_TIMER 81 + param->value = arch_timer_get_cntfrq(); 82 + #else 83 + param->value = 0; 84 + #endif 85 + break; 86 + 94 87 default: 95 88 return -EINVAL; 96 89 }
+12
drivers/gpu/drm/panfrost/panfrost_gpu.c
··· 380 380 return ((u64)hi << 32) | lo; 381 381 } 382 382 383 + unsigned long long panfrost_timestamp_read(struct panfrost_device *pfdev) 384 + { 385 + u32 hi, lo; 386 + 387 + do { 388 + hi = gpu_read(pfdev, GPU_TIMESTAMP_HI); 389 + lo = gpu_read(pfdev, GPU_TIMESTAMP_LO); 390 + } while (hi != gpu_read(pfdev, GPU_TIMESTAMP_HI)); 391 + 392 + return ((u64)hi << 32) | lo; 393 + } 394 + 383 395 static u64 panfrost_get_core_mask(struct panfrost_device *pfdev) 384 396 { 385 397 u64 core_mask;
+1
drivers/gpu/drm/panfrost/panfrost_gpu.h
··· 20 20 void panfrost_cycle_counter_get(struct panfrost_device *pfdev); 21 21 void panfrost_cycle_counter_put(struct panfrost_device *pfdev); 22 22 unsigned long long panfrost_cycle_counter_read(struct panfrost_device *pfdev); 23 + unsigned long long panfrost_timestamp_read(struct panfrost_device *pfdev); 23 24 24 25 void panfrost_gpu_amlogic_quirk(struct panfrost_device *pfdev); 25 26
+2
drivers/gpu/drm/panfrost/panfrost_regs.h
··· 78 78 79 79 #define GPU_CYCLE_COUNT_LO 0x90 80 80 #define GPU_CYCLE_COUNT_HI 0x94 81 + #define GPU_TIMESTAMP_LO 0x98 82 + #define GPU_TIMESTAMP_HI 0x9C 81 83 82 84 #define GPU_THREAD_MAX_THREADS 0x0A0 /* (RO) Maximum number of threads per core */ 83 85 #define GPU_THREAD_MAX_WORKGROUP_SIZE 0x0A4 /* (RO) Maximum workgroup size */
+2
include/uapi/drm/panfrost_drm.h
··· 172 172 DRM_PANFROST_PARAM_NR_CORE_GROUPS, 173 173 DRM_PANFROST_PARAM_THREAD_TLS_ALLOC, 174 174 DRM_PANFROST_PARAM_AFBC_FEATURES, 175 + DRM_PANFROST_PARAM_SYSTEM_TIMESTAMP, 176 + DRM_PANFROST_PARAM_SYSTEM_TIMESTAMP_FREQUENCY, 175 177 }; 176 178 177 179 struct drm_panfrost_get_param {