diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index 671eed4ad890c24b6229c17e7dfd5384136ec1a2..790c4ad311437ea5a82974f78901dc2ad8eedba4 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -3,6 +3,10 @@ /* Copyright 2019 Linaro, Ltd., Rob Herring <robh@kernel.org> */ /* Copyright 2019 Collabora ltd. */ +#ifdef CONFIG_ARM_ARCH_TIMER +#include <asm/arch_timer.h> +#endif + #include <linux/module.h> #include <linux/of.h> #include <linux/pagemap.h> @@ -24,10 +28,28 @@ static bool unstable_ioctls; module_param_unsafe(unstable_ioctls, bool, 0600); +static int panfrost_ioctl_query_timestamp(struct panfrost_device *pfdev, + u64 *arg) +{ + int ret; + + ret = pm_runtime_resume_and_get(pfdev->dev); + if (ret) + return ret; + + panfrost_cycle_counter_get(pfdev); + *arg = panfrost_timestamp_read(pfdev); + panfrost_cycle_counter_put(pfdev); + + pm_runtime_put(pfdev->dev); + return 0; +} + static int panfrost_ioctl_get_param(struct drm_device *ddev, void *data, struct drm_file *file) { struct drm_panfrost_get_param *param = data; struct panfrost_device *pfdev = ddev->dev_private; + int ret; if (param->pad != 0) return -EINVAL; @@ -69,6 +91,21 @@ static int panfrost_ioctl_get_param(struct drm_device *ddev, void *data, struct PANFROST_FEATURE_ARRAY(JS_FEATURES, js_features, 15); PANFROST_FEATURE(NR_CORE_GROUPS, nr_core_groups); PANFROST_FEATURE(THREAD_TLS_ALLOC, thread_tls_alloc); + + case DRM_PANFROST_PARAM_SYSTEM_TIMESTAMP: + ret = panfrost_ioctl_query_timestamp(pfdev, ¶m->value); + if (ret) + return ret; + break; + + case DRM_PANFROST_PARAM_SYSTEM_TIMESTAMP_FREQUENCY: +#ifdef CONFIG_ARM_ARCH_TIMER + param->value = arch_timer_get_cntfrq(); +#else + param->value = 0; +#endif + break; + default: return -EINVAL; } diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c index fd8e44992184fa2e63a11e1810ea8e79f9e929a4..f19f918e2330eb28c39449b9be461f161a92c49b 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gpu.c +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c @@ -380,6 +380,18 @@ unsigned long long panfrost_cycle_counter_read(struct panfrost_device *pfdev) return ((u64)hi << 32) | lo; } +unsigned long long panfrost_timestamp_read(struct panfrost_device *pfdev) +{ + u32 hi, lo; + + do { + hi = gpu_read(pfdev, GPU_TIMESTAMP_HI); + lo = gpu_read(pfdev, GPU_TIMESTAMP_LO); + } while (hi != gpu_read(pfdev, GPU_TIMESTAMP_HI)); + + return ((u64)hi << 32) | lo; +} + static u64 panfrost_get_core_mask(struct panfrost_device *pfdev) { u64 core_mask; diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.h b/drivers/gpu/drm/panfrost/panfrost_gpu.h index d841b86504ea893659a5645e423265e3032d1707..b4fef11211d5fbb55cf7b5be5b575c1b125f501d 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gpu.h +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.h @@ -20,6 +20,7 @@ void panfrost_gpu_suspend_irq(struct panfrost_device *pfdev); void panfrost_cycle_counter_get(struct panfrost_device *pfdev); void panfrost_cycle_counter_put(struct panfrost_device *pfdev); unsigned long long panfrost_cycle_counter_read(struct panfrost_device *pfdev); +unsigned long long panfrost_timestamp_read(struct panfrost_device *pfdev); void panfrost_gpu_amlogic_quirk(struct panfrost_device *pfdev); diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h index c25743b05c551453cd6ee0ae3a26565168e05753..c7bba476ab3f34d6ae110dc81733b41e35865be7 100644 --- a/drivers/gpu/drm/panfrost/panfrost_regs.h +++ b/drivers/gpu/drm/panfrost/panfrost_regs.h @@ -78,6 +78,8 @@ #define GPU_CYCLE_COUNT_LO 0x90 #define GPU_CYCLE_COUNT_HI 0x94 +#define GPU_TIMESTAMP_LO 0x98 +#define GPU_TIMESTAMP_HI 0x9C #define GPU_THREAD_MAX_THREADS 0x0A0 /* (RO) Maximum number of threads per core */ #define GPU_THREAD_MAX_WORKGROUP_SIZE 0x0A4 /* (RO) Maximum workgroup size */ diff --git a/include/uapi/drm/panfrost_drm.h b/include/uapi/drm/panfrost_drm.h index 9f231d40a146a91aec18bacd8f8915b94dd8ed30..52b050e2b660429aaff3c04c73f45b9006f8aa1d 100644 --- a/include/uapi/drm/panfrost_drm.h +++ b/include/uapi/drm/panfrost_drm.h @@ -172,6 +172,8 @@ enum drm_panfrost_param { DRM_PANFROST_PARAM_NR_CORE_GROUPS, DRM_PANFROST_PARAM_THREAD_TLS_ALLOC, DRM_PANFROST_PARAM_AFBC_FEATURES, + DRM_PANFROST_PARAM_SYSTEM_TIMESTAMP, + DRM_PANFROST_PARAM_SYSTEM_TIMESTAMP_FREQUENCY, }; struct drm_panfrost_get_param {