drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c
Extension
.c
Size
6529 bytes
Lines
238
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: MIT
/*
 * Copyright © 2020 Intel Corporation
 */

#include "i915_drv.h"
#include "i915_freq.h"
#include "i915_reg.h"
#include "intel_gt.h"
#include "intel_gt_clock_utils.h"
#include "intel_gt_print.h"
#include "intel_gt_regs.h"

static u32 read_reference_ts_freq(struct intel_uncore *uncore)
{
	u32 ts_override = intel_uncore_read(uncore, GEN9_TIMESTAMP_OVERRIDE);
	u32 base_freq, frac_freq;

	base_freq = ((ts_override & GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_MASK) >>
		     GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_SHIFT) + 1;
	base_freq *= 1000000;

	frac_freq = ((ts_override &
		      GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_MASK) >>
		     GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_SHIFT);
	frac_freq = 1000000 / (frac_freq + 1);

	return base_freq + frac_freq;
}

static u32 gen11_get_crystal_clock_freq(struct intel_uncore *uncore,
					u32 rpm_config_reg)
{
	u32 f19_2_mhz = 19200000;
	u32 f24_mhz = 24000000;
	u32 f25_mhz = 25000000;
	u32 f38_4_mhz = 38400000;
	u32 crystal_clock = rpm_config_reg & GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK;

	switch (crystal_clock) {
	case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ:
		return f24_mhz;
	case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ:
		return f19_2_mhz;
	case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_38_4_MHZ:
		return f38_4_mhz;
	case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_25_MHZ:
		return f25_mhz;
	default:
		MISSING_CASE(crystal_clock);
		return 0;
	}
}

static u32 gen11_read_clock_frequency(struct intel_uncore *uncore)
{
	u32 ctc_reg = intel_uncore_read(uncore, CTC_MODE);
	u32 freq = 0;

	/*
	 * Note that on gen11+, the clock frequency may be reconfigured.
	 * We do not, and we assume nobody else does.
	 *
	 * First figure out the reference frequency. There are 2 ways
	 * we can compute the frequency, either through the
	 * TIMESTAMP_OVERRIDE register or through RPM_CONFIG. CTC_MODE
	 * tells us which one we should use.
	 */
	if ((ctc_reg & CTC_SOURCE_PARAMETER_MASK) == CTC_SOURCE_DIVIDE_LOGIC) {
		freq = read_reference_ts_freq(uncore);
	} else {
		u32 c0 = intel_uncore_read(uncore, RPM_CONFIG0);

		freq = gen11_get_crystal_clock_freq(uncore, c0);

		/*
		 * Now figure out how the command stream's timestamp
		 * register increments from this frequency (it might
		 * increment only every few clock cycle).
		 */
		freq >>= 3 - REG_FIELD_GET(GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK, c0);
	}

	return freq;
}

static u32 gen9_read_clock_frequency(struct intel_uncore *uncore)
{
	u32 ctc_reg = intel_uncore_read(uncore, CTC_MODE);
	u32 freq = 0;

Annotation

Implementation Notes