Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: MIT
0002 /*
0003  * Copyright © 2020 Intel Corporation
0004  */
0005 
0006 #include "i915_drv.h"
0007 #include "i915_reg.h"
0008 #include "intel_gt.h"
0009 #include "intel_gt_clock_utils.h"
0010 #include "intel_gt_regs.h"
0011 
0012 static u32 read_reference_ts_freq(struct intel_uncore *uncore)
0013 {
0014     u32 ts_override = intel_uncore_read(uncore, GEN9_TIMESTAMP_OVERRIDE);
0015     u32 base_freq, frac_freq;
0016 
0017     base_freq = ((ts_override & GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_MASK) >>
0018              GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_SHIFT) + 1;
0019     base_freq *= 1000000;
0020 
0021     frac_freq = ((ts_override &
0022               GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_MASK) >>
0023              GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_SHIFT);
0024     frac_freq = 1000000 / (frac_freq + 1);
0025 
0026     return base_freq + frac_freq;
0027 }
0028 
0029 static u32 gen9_get_crystal_clock_freq(struct intel_uncore *uncore,
0030                        u32 rpm_config_reg)
0031 {
0032     u32 f19_2_mhz = 19200000;
0033     u32 f24_mhz = 24000000;
0034     u32 crystal_clock =
0035         (rpm_config_reg & GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK) >>
0036         GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT;
0037 
0038     switch (crystal_clock) {
0039     case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ:
0040         return f19_2_mhz;
0041     case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ:
0042         return f24_mhz;
0043     default:
0044         MISSING_CASE(crystal_clock);
0045         return 0;
0046     }
0047 }
0048 
0049 static u32 gen11_get_crystal_clock_freq(struct intel_uncore *uncore,
0050                     u32 rpm_config_reg)
0051 {
0052     u32 f19_2_mhz = 19200000;
0053     u32 f24_mhz = 24000000;
0054     u32 f25_mhz = 25000000;
0055     u32 f38_4_mhz = 38400000;
0056     u32 crystal_clock =
0057         (rpm_config_reg & GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK) >>
0058         GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT;
0059 
0060     switch (crystal_clock) {
0061     case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ:
0062         return f24_mhz;
0063     case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ:
0064         return f19_2_mhz;
0065     case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_38_4_MHZ:
0066         return f38_4_mhz;
0067     case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_25_MHZ:
0068         return f25_mhz;
0069     default:
0070         MISSING_CASE(crystal_clock);
0071         return 0;
0072     }
0073 }
0074 
0075 static u32 read_clock_frequency(struct intel_uncore *uncore)
0076 {
0077     u32 f12_5_mhz = 12500000;
0078     u32 f19_2_mhz = 19200000;
0079     u32 f24_mhz = 24000000;
0080 
0081     if (GRAPHICS_VER(uncore->i915) <= 4) {
0082         /*
0083          * PRMs say:
0084          *
0085          *     "The value in this register increments once every 16
0086          *      hclks." (through the “Clocking Configuration”
0087          *      (“CLKCFG”) MCHBAR register)
0088          */
0089         return RUNTIME_INFO(uncore->i915)->rawclk_freq * 1000 / 16;
0090     } else if (GRAPHICS_VER(uncore->i915) <= 8) {
0091         /*
0092          * PRMs say:
0093          *
0094          *     "The PCU TSC counts 10ns increments; this timestamp
0095          *      reflects bits 38:3 of the TSC (i.e. 80ns granularity,
0096          *      rolling over every 1.5 hours).
0097          */
0098         return f12_5_mhz;
0099     } else if (GRAPHICS_VER(uncore->i915) <= 9) {
0100         u32 ctc_reg = intel_uncore_read(uncore, CTC_MODE);
0101         u32 freq = 0;
0102 
0103         if ((ctc_reg & CTC_SOURCE_PARAMETER_MASK) == CTC_SOURCE_DIVIDE_LOGIC) {
0104             freq = read_reference_ts_freq(uncore);
0105         } else {
0106             freq = IS_GEN9_LP(uncore->i915) ? f19_2_mhz : f24_mhz;
0107 
0108             /*
0109              * Now figure out how the command stream's timestamp
0110              * register increments from this frequency (it might
0111              * increment only every few clock cycle).
0112              */
0113             freq >>= 3 - ((ctc_reg & CTC_SHIFT_PARAMETER_MASK) >>
0114                       CTC_SHIFT_PARAMETER_SHIFT);
0115         }
0116 
0117         return freq;
0118     } else if (GRAPHICS_VER(uncore->i915) <= 12) {
0119         u32 ctc_reg = intel_uncore_read(uncore, CTC_MODE);
0120         u32 freq = 0;
0121 
0122         /*
0123          * First figure out the reference frequency. There are 2 ways
0124          * we can compute the frequency, either through the
0125          * TIMESTAMP_OVERRIDE register or through RPM_CONFIG. CTC_MODE
0126          * tells us which one we should use.
0127          */
0128         if ((ctc_reg & CTC_SOURCE_PARAMETER_MASK) == CTC_SOURCE_DIVIDE_LOGIC) {
0129             freq = read_reference_ts_freq(uncore);
0130         } else {
0131             u32 c0 = intel_uncore_read(uncore, RPM_CONFIG0);
0132 
0133             if (GRAPHICS_VER(uncore->i915) >= 11)
0134                 freq = gen11_get_crystal_clock_freq(uncore, c0);
0135             else
0136                 freq = gen9_get_crystal_clock_freq(uncore, c0);
0137 
0138             /*
0139              * Now figure out how the command stream's timestamp
0140              * register increments from this frequency (it might
0141              * increment only every few clock cycle).
0142              */
0143             freq >>= 3 - ((c0 & GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK) >>
0144                       GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT);
0145         }
0146 
0147         return freq;
0148     }
0149 
0150     MISSING_CASE("Unknown gen, unable to read command streamer timestamp frequency\n");
0151     return 0;
0152 }
0153 
0154 void intel_gt_init_clock_frequency(struct intel_gt *gt)
0155 {
0156     /*
0157      * Note that on gen11+, the clock frequency may be reconfigured.
0158      * We do not, and we assume nobody else does.
0159      */
0160     gt->clock_frequency = read_clock_frequency(gt->uncore);
0161     if (gt->clock_frequency)
0162         gt->clock_period_ns = intel_gt_clock_interval_to_ns(gt, 1);
0163 
0164     /* Icelake appears to use another fixed frequency for CTX_TIMESTAMP */
0165     if (GRAPHICS_VER(gt->i915) == 11)
0166         gt->clock_period_ns = NSEC_PER_SEC / 13750000;
0167 
0168     GT_TRACE(gt,
0169          "Using clock frequency: %dkHz, period: %dns, wrap: %lldms\n",
0170          gt->clock_frequency / 1000,
0171          gt->clock_period_ns,
0172          div_u64(mul_u32_u32(gt->clock_period_ns, S32_MAX),
0173              USEC_PER_SEC));
0174 }
0175 
0176 #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
0177 void intel_gt_check_clock_frequency(const struct intel_gt *gt)
0178 {
0179     if (gt->clock_frequency != read_clock_frequency(gt->uncore)) {
0180         dev_err(gt->i915->drm.dev,
0181             "GT clock frequency changed, was %uHz, now %uHz!\n",
0182             gt->clock_frequency,
0183             read_clock_frequency(gt->uncore));
0184     }
0185 }
0186 #endif
0187 
0188 static u64 div_u64_roundup(u64 nom, u32 den)
0189 {
0190     return div_u64(nom + den - 1, den);
0191 }
0192 
0193 u64 intel_gt_clock_interval_to_ns(const struct intel_gt *gt, u64 count)
0194 {
0195     return div_u64_roundup(count * NSEC_PER_SEC, gt->clock_frequency);
0196 }
0197 
0198 u64 intel_gt_pm_interval_to_ns(const struct intel_gt *gt, u64 count)
0199 {
0200     return intel_gt_clock_interval_to_ns(gt, 16 * count);
0201 }
0202 
0203 u64 intel_gt_ns_to_clock_interval(const struct intel_gt *gt, u64 ns)
0204 {
0205     return div_u64_roundup(gt->clock_frequency * ns, NSEC_PER_SEC);
0206 }
0207 
0208 u64 intel_gt_ns_to_pm_interval(const struct intel_gt *gt, u64 ns)
0209 {
0210     u64 val;
0211 
0212     /*
0213      * Make these a multiple of magic 25 to avoid SNB (eg. Dell XPS
0214      * 8300) freezing up around GPU hangs. Looks as if even
0215      * scheduling/timer interrupts start misbehaving if the RPS
0216      * EI/thresholds are "bad", leading to a very sluggish or even
0217      * frozen machine.
0218      */
0219     val = div_u64_roundup(intel_gt_ns_to_clock_interval(gt, ns), 16);
0220     if (GRAPHICS_VER(gt->i915) == 6)
0221         val = div_u64_roundup(val, 25) * 25;
0222 
0223     return val;
0224 }