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 14 static 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 40 void 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) 53 void 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 64 static u64 div_u64_roundup(u64 nom, u32 den) 65 { 66 return div_u64(nom + den - 1, den); 67 } 68 69 u32 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 75 u32 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 80 u32 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 86 u32 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 } 103