5
5
6
6
#include <linux/hwmon.h>
7
7
#include <linux/hwmon-sysfs.h>
8
+ #include <linux/jiffies.h>
8
9
#include <linux/types.h>
9
10
10
11
#include "i915_drv.h"
@@ -36,18 +37,25 @@ struct hwm_reg {
36
37
i915_reg_t pkg_rapl_limit ;
37
38
i915_reg_t energy_status_all ;
38
39
i915_reg_t energy_status_tile ;
40
+ i915_reg_t fan_speed ;
39
41
};
40
42
41
43
struct hwm_energy_info {
42
44
u32 reg_val_prev ;
43
45
long accum_energy ; /* Accumulated energy for energy1_input */
44
46
};
45
47
48
+ struct hwm_fan_info {
49
+ u32 reg_val_prev ;
50
+ u64 time_prev ;
51
+ };
52
+
46
53
struct hwm_drvdata {
47
54
struct i915_hwmon * hwmon ;
48
55
struct intel_uncore * uncore ;
49
56
struct device * hwmon_dev ;
50
57
struct hwm_energy_info ei ; /* Energy info for energy1_input */
58
+ struct hwm_fan_info fi ; /* Fan info for fan1_input */
51
59
char name [12 ];
52
60
int gt_n ;
53
61
bool reset_in_progress ;
@@ -276,6 +284,7 @@ static const struct hwmon_channel_info * const hwm_info[] = {
276
284
HWMON_CHANNEL_INFO (power , HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_CRIT ),
277
285
HWMON_CHANNEL_INFO (energy , HWMON_E_INPUT ),
278
286
HWMON_CHANNEL_INFO (curr , HWMON_C_CRIT ),
287
+ HWMON_CHANNEL_INFO (fan , HWMON_F_INPUT ),
279
288
NULL
280
289
};
281
290
@@ -613,6 +622,69 @@ hwm_curr_write(struct hwm_drvdata *ddat, u32 attr, long val)
613
622
}
614
623
}
615
624
625
+ static umode_t
626
+ hwm_fan_is_visible (const struct hwm_drvdata * ddat , u32 attr )
627
+ {
628
+ struct i915_hwmon * hwmon = ddat -> hwmon ;
629
+
630
+ if (attr == hwmon_fan_input && i915_mmio_reg_valid (hwmon -> rg .fan_speed ))
631
+ return 0444 ;
632
+
633
+ return 0 ;
634
+ }
635
+
636
+ static int
637
+ hwm_fan_input_read (struct hwm_drvdata * ddat , long * val )
638
+ {
639
+ struct i915_hwmon * hwmon = ddat -> hwmon ;
640
+ struct hwm_fan_info * fi = & ddat -> fi ;
641
+ u64 rotations , time_now , time ;
642
+ intel_wakeref_t wakeref ;
643
+ u32 reg_val ;
644
+ int ret = 0 ;
645
+
646
+ wakeref = intel_runtime_pm_get (ddat -> uncore -> rpm );
647
+ mutex_lock (& hwmon -> hwmon_lock );
648
+
649
+ reg_val = intel_uncore_read (ddat -> uncore , hwmon -> rg .fan_speed );
650
+ time_now = get_jiffies_64 ();
651
+
652
+ /*
653
+ * HW register value is accumulated count of pulses from
654
+ * PWM fan with the scale of 2 pulses per rotation.
655
+ */
656
+ rotations = (reg_val - fi -> reg_val_prev ) / 2 ;
657
+
658
+ time = jiffies_delta_to_msecs (time_now - fi -> time_prev );
659
+ if (unlikely (!time )) {
660
+ ret = - EAGAIN ;
661
+ goto exit ;
662
+ }
663
+
664
+ /*
665
+ * Calculate fan speed in RPM by time averaging two subsequent
666
+ * readings in minutes.
667
+ * RPM = number of rotations * msecs per minute / time in msecs
668
+ */
669
+ * val = DIV_ROUND_UP_ULL (rotations * (MSEC_PER_SEC * 60 ), time );
670
+
671
+ fi -> reg_val_prev = reg_val ;
672
+ fi -> time_prev = time_now ;
673
+ exit :
674
+ mutex_unlock (& hwmon -> hwmon_lock );
675
+ intel_runtime_pm_put (ddat -> uncore -> rpm , wakeref );
676
+ return ret ;
677
+ }
678
+
679
+ static int
680
+ hwm_fan_read (struct hwm_drvdata * ddat , u32 attr , long * val )
681
+ {
682
+ if (attr == hwmon_fan_input )
683
+ return hwm_fan_input_read (ddat , val );
684
+
685
+ return - EOPNOTSUPP ;
686
+ }
687
+
616
688
static umode_t
617
689
hwm_is_visible (const void * drvdata , enum hwmon_sensor_types type ,
618
690
u32 attr , int channel )
@@ -628,6 +700,8 @@ hwm_is_visible(const void *drvdata, enum hwmon_sensor_types type,
628
700
return hwm_energy_is_visible (ddat , attr );
629
701
case hwmon_curr :
630
702
return hwm_curr_is_visible (ddat , attr );
703
+ case hwmon_fan :
704
+ return hwm_fan_is_visible (ddat , attr );
631
705
default :
632
706
return 0 ;
633
707
}
@@ -648,6 +722,8 @@ hwm_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
648
722
return hwm_energy_read (ddat , attr , val );
649
723
case hwmon_curr :
650
724
return hwm_curr_read (ddat , attr , val );
725
+ case hwmon_fan :
726
+ return hwm_fan_read (ddat , attr , val );
651
727
default :
652
728
return - EOPNOTSUPP ;
653
729
}
@@ -739,12 +815,14 @@ hwm_get_preregistration_info(struct drm_i915_private *i915)
739
815
hwmon -> rg .pkg_rapl_limit = PCU_PACKAGE_RAPL_LIMIT ;
740
816
hwmon -> rg .energy_status_all = PCU_PACKAGE_ENERGY_STATUS ;
741
817
hwmon -> rg .energy_status_tile = INVALID_MMIO_REG ;
818
+ hwmon -> rg .fan_speed = PCU_PWM_FAN_SPEED ;
742
819
} else {
743
820
hwmon -> rg .pkg_power_sku_unit = INVALID_MMIO_REG ;
744
821
hwmon -> rg .pkg_power_sku = INVALID_MMIO_REG ;
745
822
hwmon -> rg .pkg_rapl_limit = INVALID_MMIO_REG ;
746
823
hwmon -> rg .energy_status_all = INVALID_MMIO_REG ;
747
824
hwmon -> rg .energy_status_tile = INVALID_MMIO_REG ;
825
+ hwmon -> rg .fan_speed = INVALID_MMIO_REG ;
748
826
}
749
827
750
828
with_intel_runtime_pm (uncore -> rpm , wakeref ) {
@@ -755,6 +833,16 @@ hwm_get_preregistration_info(struct drm_i915_private *i915)
755
833
if (i915_mmio_reg_valid (hwmon -> rg .pkg_power_sku_unit ))
756
834
val_sku_unit = intel_uncore_read (uncore ,
757
835
hwmon -> rg .pkg_power_sku_unit );
836
+
837
+ /*
838
+ * Store the initial fan register value, so that we can use it for
839
+ * initial fan speed calculation.
840
+ */
841
+ if (i915_mmio_reg_valid (hwmon -> rg .fan_speed )) {
842
+ ddat -> fi .reg_val_prev = intel_uncore_read (uncore ,
843
+ hwmon -> rg .fan_speed );
844
+ ddat -> fi .time_prev = get_jiffies_64 ();
845
+ }
758
846
}
759
847
760
848
hwmon -> scl_shift_power = REG_FIELD_GET (PKG_PWR_UNIT , val_sku_unit );
0 commit comments