Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright © 2022 Intel Corporation
  4 */
  5
  6#include <linux/math64.h>
  7
  8#include "xe_gt_clock.h"
  9
 10#include "regs/xe_gt_regs.h"
 11#include "regs/xe_regs.h"
 12#include "xe_assert.h"
 13#include "xe_device.h"
 14#include "xe_gt.h"
 15#include "xe_macros.h"
 16#include "xe_mmio.h"
 17
 18static u32 read_reference_ts_freq(struct xe_gt *gt)
 19{
 20	u32 ts_override = xe_mmio_read32(&gt->mmio, TIMESTAMP_OVERRIDE);
 21	u32 base_freq, frac_freq;
 22
 23	base_freq = REG_FIELD_GET(TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_MASK,
 24				  ts_override) + 1;
 25	base_freq *= 1000000;
 26
 27	frac_freq = REG_FIELD_GET(TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_MASK,
 28				  ts_override);
 29	frac_freq = 1000000 / (frac_freq + 1);
 30
 31	return base_freq + frac_freq;
 32}
 33
 34static u32 get_crystal_clock_freq(u32 rpm_config_reg)
 35{
 36	const u32 f19_2_mhz = 19200000;
 37	const u32 f24_mhz = 24000000;
 38	const u32 f25_mhz = 25000000;
 39	const u32 f38_4_mhz = 38400000;
 40	u32 crystal_clock = REG_FIELD_GET(RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK,
 41					  rpm_config_reg);
 42
 43	switch (crystal_clock) {
 44	case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ:
 45		return f24_mhz;
 46	case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ:
 47		return f19_2_mhz;
 48	case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_38_4_MHZ:
 49		return f38_4_mhz;
 50	case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_25_MHZ:
 51		return f25_mhz;
 52	default:
 53		XE_WARN_ON("NOT_POSSIBLE");
 54		return 0;
 55	}
 56}
 57
 58int xe_gt_clock_init(struct xe_gt *gt)
 59{
 60	u32 ctc_reg = xe_mmio_read32(&gt->mmio, CTC_MODE);
 61	u32 freq = 0;
 62
 63	/* Assuming gen11+ so assert this assumption is correct */
 64	xe_gt_assert(gt, GRAPHICS_VER(gt_to_xe(gt)) >= 11);
 65
 66	if (ctc_reg & CTC_SOURCE_DIVIDE_LOGIC) {
 67		freq = read_reference_ts_freq(gt);
 68	} else {
 69		u32 c0 = xe_mmio_read32(&gt->mmio, RPM_CONFIG0);
 70
 71		freq = get_crystal_clock_freq(c0);
 72
 73		/*
 74		 * Now figure out how the command stream's timestamp
 75		 * register increments from this frequency (it might
 76		 * increment only every few clock cycle).
 77		 */
 78		freq >>= 3 - REG_FIELD_GET(RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK, c0);
 79	}
 80
 81	gt->info.reference_clock = freq;
 82	return 0;
 83}
 84
 85static u64 div_u64_roundup(u64 n, u32 d)
 86{
 87	return div_u64(n + d - 1, d);
 88}
 89
 90/**
 91 * xe_gt_clock_interval_to_ms - Convert sampled GT clock ticks to msec
 92 *
 93 * @gt: the &xe_gt
 94 * @count: count of GT clock ticks
 95 *
 96 * Returns: time in msec
 97 */
 98u64 xe_gt_clock_interval_to_ms(struct xe_gt *gt, u64 count)
 99{
100	return div_u64_roundup(count * MSEC_PER_SEC, gt->info.reference_clock);
101}