Linux Audio

Check our new training course

Yocto distribution development and maintenance

Need a Yocto distribution for your embedded project?
Loading...
Note: File does not exist in v4.6.
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright © 2020 Intel Corporation
  4 */
  5
  6#include "i915_drv.h"
  7#include "intel_gt.h"
  8#include "intel_gt_clock_utils.h"
  9
 10#define MHZ_12   12000000 /* 12MHz (24MHz/2), 83.333ns */
 11#define MHZ_12_5 12500000 /* 12.5MHz (25MHz/2), 80ns */
 12#define MHZ_19_2 19200000 /* 19.2MHz, 52.083ns */
 13
 14static u32 read_clock_frequency(const struct intel_gt *gt)
 15{
 16	if (INTEL_GEN(gt->i915) >= 11) {
 17		u32 config;
 18
 19		config = intel_uncore_read(gt->uncore, RPM_CONFIG0);
 20		config &= GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK;
 21		config >>= GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT;
 22
 23		switch (config) {
 24		case 0: return MHZ_12;
 25		case 1:
 26		case 2: return MHZ_19_2;
 27		default:
 28		case 3: return MHZ_12_5;
 29		}
 30	} else if (INTEL_GEN(gt->i915) >= 9) {
 31		if (IS_GEN9_LP(gt->i915))
 32			return MHZ_19_2;
 33		else
 34			return MHZ_12;
 35	} else {
 36		return MHZ_12_5;
 37	}
 38}
 39
 40void intel_gt_init_clock_frequency(struct intel_gt *gt)
 41{
 42	/*
 43	 * Note that on gen11+, the clock frequency may be reconfigured.
 44	 * We do not, and we assume nobody else does.
 45	 */
 46	gt->clock_frequency = read_clock_frequency(gt);
 47	GT_TRACE(gt,
 48		 "Using clock frequency: %dkHz\n",
 49		 gt->clock_frequency / 1000);
 50}
 51
 52#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
 53void intel_gt_check_clock_frequency(const struct intel_gt *gt)
 54{
 55	if (gt->clock_frequency != read_clock_frequency(gt)) {
 56		dev_err(gt->i915->drm.dev,
 57			"GT clock frequency changed, was %uHz, now %uHz!\n",
 58			gt->clock_frequency,
 59			read_clock_frequency(gt));
 60	}
 61}
 62#endif
 63
 64static u64 div_u64_roundup(u64 nom, u32 den)
 65{
 66	return div_u64(nom + den - 1, den);
 67}
 68
 69u32 intel_gt_clock_interval_to_ns(const struct intel_gt *gt, u32 count)
 70{
 71	return div_u64_roundup(mul_u32_u32(count, 1000 * 1000 * 1000),
 72			       gt->clock_frequency);
 73}
 74
 75u32 intel_gt_pm_interval_to_ns(const struct intel_gt *gt, u32 count)
 76{
 77	return intel_gt_clock_interval_to_ns(gt, 16 * count);
 78}
 79
 80u32 intel_gt_ns_to_clock_interval(const struct intel_gt *gt, u32 ns)
 81{
 82	return div_u64_roundup(mul_u32_u32(gt->clock_frequency, ns),
 83			       1000 * 1000 * 1000);
 84}
 85
 86u32 intel_gt_ns_to_pm_interval(const struct intel_gt *gt, u32 ns)
 87{
 88	u32 val;
 89
 90	/*
 91	 * Make these a multiple of magic 25 to avoid SNB (eg. Dell XPS
 92	 * 8300) freezing up around GPU hangs. Looks as if even
 93	 * scheduling/timer interrupts start misbehaving if the RPS
 94	 * EI/thresholds are "bad", leading to a very sluggish or even
 95	 * frozen machine.
 96	 */
 97	val = DIV_ROUND_UP(intel_gt_ns_to_clock_interval(gt, ns), 16);
 98	if (IS_GEN(gt->i915, 6))
 99		val = roundup(val, 25);
100
101	return val;
102}