162306a36Sopenharmony_ci// SPDX-License-Identifier: MIT 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright © 2022 Intel Corporation 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include "gt/intel_engine_regs.h" 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "i915_drv.h" 962306a36Sopenharmony_ci#include "i915_gem.h" 1062306a36Sopenharmony_ci#include "i915_ioctl.h" 1162306a36Sopenharmony_ci#include "i915_reg.h" 1262306a36Sopenharmony_ci#include "intel_runtime_pm.h" 1362306a36Sopenharmony_ci#include "intel_uncore.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* 1662306a36Sopenharmony_ci * This file is for small ioctl functions that are out of place everywhere else, 1762306a36Sopenharmony_ci * and not big enough to warrant a file of their own. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * This is not the dumping ground for random ioctls. 2062306a36Sopenharmony_ci */ 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistruct reg_whitelist { 2362306a36Sopenharmony_ci i915_reg_t offset_ldw; 2462306a36Sopenharmony_ci i915_reg_t offset_udw; 2562306a36Sopenharmony_ci u8 min_graphics_ver; 2662306a36Sopenharmony_ci u8 max_graphics_ver; 2762306a36Sopenharmony_ci u8 size; 2862306a36Sopenharmony_ci}; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic const struct reg_whitelist reg_read_whitelist[] = { 3162306a36Sopenharmony_ci { 3262306a36Sopenharmony_ci .offset_ldw = RING_TIMESTAMP(RENDER_RING_BASE), 3362306a36Sopenharmony_ci .offset_udw = RING_TIMESTAMP_UDW(RENDER_RING_BASE), 3462306a36Sopenharmony_ci .min_graphics_ver = 4, 3562306a36Sopenharmony_ci .max_graphics_ver = 12, 3662306a36Sopenharmony_ci .size = 8 3762306a36Sopenharmony_ci } 3862306a36Sopenharmony_ci}; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ciint i915_reg_read_ioctl(struct drm_device *dev, 4162306a36Sopenharmony_ci void *data, struct drm_file *unused) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci struct drm_i915_private *i915 = to_i915(dev); 4462306a36Sopenharmony_ci struct intel_uncore *uncore = &i915->uncore; 4562306a36Sopenharmony_ci struct drm_i915_reg_read *reg = data; 4662306a36Sopenharmony_ci struct reg_whitelist const *entry; 4762306a36Sopenharmony_ci intel_wakeref_t wakeref; 4862306a36Sopenharmony_ci unsigned int flags; 4962306a36Sopenharmony_ci int remain; 5062306a36Sopenharmony_ci int ret = 0; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci entry = reg_read_whitelist; 5362306a36Sopenharmony_ci remain = ARRAY_SIZE(reg_read_whitelist); 5462306a36Sopenharmony_ci while (remain) { 5562306a36Sopenharmony_ci u32 entry_offset = i915_mmio_reg_offset(entry->offset_ldw); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci GEM_BUG_ON(!is_power_of_2(entry->size)); 5862306a36Sopenharmony_ci GEM_BUG_ON(entry->size > 8); 5962306a36Sopenharmony_ci GEM_BUG_ON(entry_offset & (entry->size - 1)); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci if (IS_GRAPHICS_VER(i915, entry->min_graphics_ver, entry->max_graphics_ver) && 6262306a36Sopenharmony_ci entry_offset == (reg->offset & -entry->size)) 6362306a36Sopenharmony_ci break; 6462306a36Sopenharmony_ci entry++; 6562306a36Sopenharmony_ci remain--; 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci if (!remain) 6962306a36Sopenharmony_ci return -EINVAL; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci flags = reg->offset & (entry->size - 1); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci with_intel_runtime_pm(&i915->runtime_pm, wakeref) { 7462306a36Sopenharmony_ci if (entry->size == 8 && flags == I915_REG_READ_8B_WA) 7562306a36Sopenharmony_ci reg->val = intel_uncore_read64_2x32(uncore, 7662306a36Sopenharmony_ci entry->offset_ldw, 7762306a36Sopenharmony_ci entry->offset_udw); 7862306a36Sopenharmony_ci else if (entry->size == 8 && flags == 0) 7962306a36Sopenharmony_ci reg->val = intel_uncore_read64(uncore, 8062306a36Sopenharmony_ci entry->offset_ldw); 8162306a36Sopenharmony_ci else if (entry->size == 4 && flags == 0) 8262306a36Sopenharmony_ci reg->val = intel_uncore_read(uncore, entry->offset_ldw); 8362306a36Sopenharmony_ci else if (entry->size == 2 && flags == 0) 8462306a36Sopenharmony_ci reg->val = intel_uncore_read16(uncore, 8562306a36Sopenharmony_ci entry->offset_ldw); 8662306a36Sopenharmony_ci else if (entry->size == 1 && flags == 0) 8762306a36Sopenharmony_ci reg->val = intel_uncore_read8(uncore, 8862306a36Sopenharmony_ci entry->offset_ldw); 8962306a36Sopenharmony_ci else 9062306a36Sopenharmony_ci ret = -EINVAL; 9162306a36Sopenharmony_ci } 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci return ret; 9462306a36Sopenharmony_ci} 95