@@ -38,6 +38,7 @@ enum xe_hwmon_reg_operation {
3838#define SF_CURR 1000 /* milliamperes */
3939#define SF_VOLTAGE 1000 /* millivolts */
4040#define SF_ENERGY 1000000 /* microjoules */
41+ #define SF_TIME 1000 /* milliseconds */
4142
4243/**
4344 * struct xe_hwmon_energy_info - to accumulate energy
@@ -63,6 +64,8 @@ struct xe_hwmon {
6364 int scl_shift_power ;
6465 /** @scl_shift_energy: pkg energy unit */
6566 int scl_shift_energy ;
67+ /** @scl_shift_time: pkg time unit */
68+ int scl_shift_time ;
6669 /** @ei: Energy info for energy1_input */
6770 struct xe_hwmon_energy_info ei ;
6871};
@@ -253,6 +256,152 @@ xe_hwmon_energy_get(struct xe_hwmon *hwmon, long *energy)
253256 hwmon -> scl_shift_energy );
254257}
255258
259+ static ssize_t
260+ xe_hwmon_power1_max_interval_show (struct device * dev , struct device_attribute * attr ,
261+ char * buf )
262+ {
263+ struct xe_hwmon * hwmon = dev_get_drvdata (dev );
264+ u32 x , y , x_w = 2 ; /* 2 bits */
265+ u64 r , tau4 , out ;
266+
267+ xe_device_mem_access_get (gt_to_xe (hwmon -> gt ));
268+
269+ mutex_lock (& hwmon -> hwmon_lock );
270+
271+ xe_hwmon_process_reg (hwmon , REG_PKG_RAPL_LIMIT ,
272+ REG_READ32 , & r , 0 , 0 );
273+
274+ mutex_unlock (& hwmon -> hwmon_lock );
275+
276+ xe_device_mem_access_put (gt_to_xe (hwmon -> gt ));
277+
278+ x = REG_FIELD_GET (PKG_PWR_LIM_1_TIME_X , r );
279+ y = REG_FIELD_GET (PKG_PWR_LIM_1_TIME_Y , r );
280+
281+ /*
282+ * tau = 1.x * power(2,y), x = bits(23:22), y = bits(21:17)
283+ * = (4 | x) << (y - 2)
284+ *
285+ * Here (y - 2) ensures a 1.x fixed point representation of 1.x
286+ * As x is 2 bits so 1.x can be 1.0, 1.25, 1.50, 1.75
287+ *
288+ * As y can be < 2, we compute tau4 = (4 | x) << y
289+ * and then add 2 when doing the final right shift to account for units
290+ */
291+ tau4 = ((1 << x_w ) | x ) << y ;
292+
293+ /* val in hwmon interface units (millisec) */
294+ out = mul_u64_u32_shr (tau4 , SF_TIME , hwmon -> scl_shift_time + x_w );
295+
296+ return sysfs_emit (buf , "%llu\n" , out );
297+ }
298+
299+ static ssize_t
300+ xe_hwmon_power1_max_interval_store (struct device * dev , struct device_attribute * attr ,
301+ const char * buf , size_t count )
302+ {
303+ struct xe_hwmon * hwmon = dev_get_drvdata (dev );
304+ u32 x , y , rxy , x_w = 2 ; /* 2 bits */
305+ u64 tau4 , r , max_win ;
306+ unsigned long val ;
307+ int ret ;
308+
309+ ret = kstrtoul (buf , 0 , & val );
310+ if (ret )
311+ return ret ;
312+
313+ /*
314+ * Max HW supported tau in '1.x * power(2,y)' format, x = 0, y = 0x12.
315+ * The hwmon->scl_shift_time default of 0xa results in a max tau of 256 seconds.
316+ *
317+ * The ideal scenario is for PKG_MAX_WIN to be read from the PKG_PWR_SKU register.
318+ * However, it is observed that existing discrete GPUs does not provide correct
319+ * PKG_MAX_WIN value, therefore a using default constant value. For future discrete GPUs
320+ * this may get resolved, in which case PKG_MAX_WIN should be obtained from PKG_PWR_SKU.
321+ */
322+ #define PKG_MAX_WIN_DEFAULT 0x12ull
323+
324+ /*
325+ * val must be < max in hwmon interface units. The steps below are
326+ * explained in xe_hwmon_power1_max_interval_show()
327+ */
328+ r = FIELD_PREP (PKG_MAX_WIN , PKG_MAX_WIN_DEFAULT );
329+ x = REG_FIELD_GET (PKG_MAX_WIN_X , r );
330+ y = REG_FIELD_GET (PKG_MAX_WIN_Y , r );
331+ tau4 = ((1 << x_w ) | x ) << y ;
332+ max_win = mul_u64_u32_shr (tau4 , SF_TIME , hwmon -> scl_shift_time + x_w );
333+
334+ if (val > max_win )
335+ return - EINVAL ;
336+
337+ /* val in hw units */
338+ val = DIV_ROUND_CLOSEST_ULL ((u64 )val << hwmon -> scl_shift_time , SF_TIME );
339+
340+ /*
341+ * Convert val to 1.x * power(2,y)
342+ * y = ilog2(val)
343+ * x = (val - (1 << y)) >> (y - 2)
344+ */
345+ if (!val ) {
346+ y = 0 ;
347+ x = 0 ;
348+ } else {
349+ y = ilog2 (val );
350+ x = (val - (1ul << y )) << x_w >> y ;
351+ }
352+
353+ rxy = REG_FIELD_PREP (PKG_PWR_LIM_1_TIME_X , x ) | REG_FIELD_PREP (PKG_PWR_LIM_1_TIME_Y , y );
354+
355+ xe_device_mem_access_get (gt_to_xe (hwmon -> gt ));
356+
357+ mutex_lock (& hwmon -> hwmon_lock );
358+
359+ xe_hwmon_process_reg (hwmon , REG_PKG_RAPL_LIMIT , REG_RMW32 , (u64 * )& r ,
360+ PKG_PWR_LIM_1_TIME , rxy );
361+
362+ mutex_unlock (& hwmon -> hwmon_lock );
363+
364+ xe_device_mem_access_put (gt_to_xe (hwmon -> gt ));
365+
366+ return count ;
367+ }
368+
369+ static SENSOR_DEVICE_ATTR (power1_max_interval , 0664 ,
370+ xe_hwmon_power1_max_interval_show ,
371+ xe_hwmon_power1_max_interval_store , 0 ) ;
372+
373+ static struct attribute * hwmon_attributes [] = {
374+ & sensor_dev_attr_power1_max_interval .dev_attr .attr ,
375+ NULL
376+ };
377+
378+ static umode_t xe_hwmon_attributes_visible (struct kobject * kobj ,
379+ struct attribute * attr , int index )
380+ {
381+ struct device * dev = kobj_to_dev (kobj );
382+ struct xe_hwmon * hwmon = dev_get_drvdata (dev );
383+ int ret = 0 ;
384+
385+ xe_device_mem_access_get (gt_to_xe (hwmon -> gt ));
386+
387+ if (attr == & sensor_dev_attr_power1_max_interval .dev_attr .attr )
388+ ret = xe_hwmon_get_reg (hwmon , REG_PKG_RAPL_LIMIT ) ? attr -> mode : 0 ;
389+
390+ xe_device_mem_access_put (gt_to_xe (hwmon -> gt ));
391+
392+ return ret ;
393+ }
394+
395+ static const struct attribute_group hwmon_attrgroup = {
396+ .attrs = hwmon_attributes ,
397+ .is_visible = xe_hwmon_attributes_visible ,
398+ };
399+
400+ static const struct attribute_group * hwmon_groups [] = {
401+ & hwmon_attrgroup ,
402+ NULL
403+ };
404+
256405static const struct hwmon_channel_info * hwmon_info [] = {
257406 HWMON_CHANNEL_INFO (power , HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_CRIT ),
258407 HWMON_CHANNEL_INFO (curr , HWMON_C_CRIT ),
@@ -569,6 +718,7 @@ xe_hwmon_get_preregistration_info(struct xe_device *xe)
569718 REG_READ32 , & val_sku_unit , 0 , 0 );
570719 hwmon -> scl_shift_power = REG_FIELD_GET (PKG_PWR_UNIT , val_sku_unit );
571720 hwmon -> scl_shift_energy = REG_FIELD_GET (PKG_ENERGY_UNIT , val_sku_unit );
721+ hwmon -> scl_shift_time = REG_FIELD_GET (PKG_TIME_UNIT , val_sku_unit );
572722 }
573723
574724 /*
@@ -615,7 +765,8 @@ void xe_hwmon_register(struct xe_device *xe)
615765 /* hwmon_dev points to device hwmon<i> */
616766 hwmon -> hwmon_dev = devm_hwmon_device_register_with_info (dev , "xe" , hwmon ,
617767 & hwmon_chip_info ,
618- NULL );
768+ hwmon_groups );
769+
619770 if (IS_ERR (hwmon -> hwmon_dev )) {
620771 drm_warn (& xe -> drm , "Failed to register xe hwmon (%pe)\n" , hwmon -> hwmon_dev );
621772 xe -> hwmon = NULL ;
0 commit comments