xref: /linux/drivers/gpu/drm/i915/i915_hwmon.c (revision d2c3c8c3d3833c45c09be671da48f9d46b79e347)
1b3b088e2SDale B Stimson // SPDX-License-Identifier: MIT
2b3b088e2SDale B Stimson /*
3b3b088e2SDale B Stimson  * Copyright © 2022 Intel Corporation
4b3b088e2SDale B Stimson  */
5b3b088e2SDale B Stimson 
6b3b088e2SDale B Stimson #include <linux/hwmon.h>
7b3b088e2SDale B Stimson #include <linux/hwmon-sysfs.h>
8b3b088e2SDale B Stimson #include <linux/types.h>
9b3b088e2SDale B Stimson 
10b3b088e2SDale B Stimson #include "i915_drv.h"
11b3b088e2SDale B Stimson #include "i915_hwmon.h"
12b3b088e2SDale B Stimson #include "i915_reg.h"
13b3b088e2SDale B Stimson #include "intel_mchbar_regs.h"
14c8939848SAshutosh Dixit #include "intel_pcode.h"
15a6a924abSDale B Stimson #include "gt/intel_gt.h"
16f8572bb6SRiana Tauro #include "gt/intel_gt_regs.h"
17f8572bb6SRiana Tauro 
18f8572bb6SRiana Tauro /*
19f8572bb6SRiana Tauro  * SF_* - scale factors for particular quantities according to hwmon spec.
20f8572bb6SRiana Tauro  * - voltage  - millivolts
2199f55efbSDale B Stimson  * - power  - microwatts
22c8939848SAshutosh Dixit  * - curr   - milliamperes
23c41b8bdcSDale B Stimson  * - energy - microjoules
244c2572feSAshutosh Dixit  * - time   - milliseconds
25f8572bb6SRiana Tauro  */
26f8572bb6SRiana Tauro #define SF_VOLTAGE	1000
2799f55efbSDale B Stimson #define SF_POWER	1000000
28c8939848SAshutosh Dixit #define SF_CURR		1000
29c41b8bdcSDale B Stimson #define SF_ENERGY	1000000
304c2572feSAshutosh Dixit #define SF_TIME		1000
31b3b088e2SDale B Stimson 
32b3b088e2SDale B Stimson struct hwm_reg {
33f8572bb6SRiana Tauro 	i915_reg_t gt_perf_status;
3499f55efbSDale B Stimson 	i915_reg_t pkg_power_sku_unit;
3599f55efbSDale B Stimson 	i915_reg_t pkg_power_sku;
3699f55efbSDale B Stimson 	i915_reg_t pkg_rapl_limit;
37c41b8bdcSDale B Stimson 	i915_reg_t energy_status_all;
38a6a924abSDale B Stimson 	i915_reg_t energy_status_tile;
39c41b8bdcSDale B Stimson };
40c41b8bdcSDale B Stimson 
41c41b8bdcSDale B Stimson struct hwm_energy_info {
42c41b8bdcSDale B Stimson 	u32 reg_val_prev;
43c41b8bdcSDale B Stimson 	long accum_energy;			/* Accumulated energy for energy1_input */
44b3b088e2SDale B Stimson };
45b3b088e2SDale B Stimson 
46b3b088e2SDale B Stimson struct hwm_drvdata {
47b3b088e2SDale B Stimson 	struct i915_hwmon *hwmon;
48b3b088e2SDale B Stimson 	struct intel_uncore *uncore;
49b3b088e2SDale B Stimson 	struct device *hwmon_dev;
50c41b8bdcSDale B Stimson 	struct hwm_energy_info ei;		/*  Energy info for energy1_input */
51b3b088e2SDale B Stimson 	char name[12];
52a6a924abSDale B Stimson 	int gt_n;
53b3b088e2SDale B Stimson };
54b3b088e2SDale B Stimson 
55b3b088e2SDale B Stimson struct i915_hwmon {
56b3b088e2SDale B Stimson 	struct hwm_drvdata ddat;
57a6a924abSDale B Stimson 	struct hwm_drvdata ddat_gt[I915_MAX_GT];
58b3b088e2SDale B Stimson 	struct mutex hwmon_lock;		/* counter overflow logic and rmw */
59b3b088e2SDale B Stimson 	struct hwm_reg rg;
6099f55efbSDale B Stimson 	int scl_shift_power;
61c41b8bdcSDale B Stimson 	int scl_shift_energy;
624c2572feSAshutosh Dixit 	int scl_shift_time;
63b3b088e2SDale B Stimson };
64b3b088e2SDale B Stimson 
6599f55efbSDale B Stimson static void
6699f55efbSDale B Stimson hwm_locked_with_pm_intel_uncore_rmw(struct hwm_drvdata *ddat,
6799f55efbSDale B Stimson 				    i915_reg_t reg, u32 clear, u32 set)
6899f55efbSDale B Stimson {
6999f55efbSDale B Stimson 	struct i915_hwmon *hwmon = ddat->hwmon;
7099f55efbSDale B Stimson 	struct intel_uncore *uncore = ddat->uncore;
7199f55efbSDale B Stimson 	intel_wakeref_t wakeref;
7299f55efbSDale B Stimson 
7399f55efbSDale B Stimson 	mutex_lock(&hwmon->hwmon_lock);
7499f55efbSDale B Stimson 
7599f55efbSDale B Stimson 	with_intel_runtime_pm(uncore->rpm, wakeref)
7699f55efbSDale B Stimson 		intel_uncore_rmw(uncore, reg, clear, set);
7799f55efbSDale B Stimson 
7899f55efbSDale B Stimson 	mutex_unlock(&hwmon->hwmon_lock);
7999f55efbSDale B Stimson }
8099f55efbSDale B Stimson 
8199f55efbSDale B Stimson /*
8299f55efbSDale B Stimson  * This function's return type of u64 allows for the case where the scaling
8399f55efbSDale B Stimson  * of the field taken from the 32-bit register value might cause a result to
8499f55efbSDale B Stimson  * exceed 32 bits.
8599f55efbSDale B Stimson  */
8699f55efbSDale B Stimson static u64
8799f55efbSDale B Stimson hwm_field_read_and_scale(struct hwm_drvdata *ddat, i915_reg_t rgadr,
8899f55efbSDale B Stimson 			 u32 field_msk, int nshift, u32 scale_factor)
8999f55efbSDale B Stimson {
9099f55efbSDale B Stimson 	struct intel_uncore *uncore = ddat->uncore;
9199f55efbSDale B Stimson 	intel_wakeref_t wakeref;
9299f55efbSDale B Stimson 	u32 reg_value;
9399f55efbSDale B Stimson 
9499f55efbSDale B Stimson 	with_intel_runtime_pm(uncore->rpm, wakeref)
9599f55efbSDale B Stimson 		reg_value = intel_uncore_read(uncore, rgadr);
9699f55efbSDale B Stimson 
9799f55efbSDale B Stimson 	reg_value = REG_FIELD_GET(field_msk, reg_value);
9899f55efbSDale B Stimson 
9999f55efbSDale B Stimson 	return mul_u64_u32_shr(reg_value, scale_factor, nshift);
10099f55efbSDale B Stimson }
10199f55efbSDale B Stimson 
10299f55efbSDale B Stimson static void
10399f55efbSDale B Stimson hwm_field_scale_and_write(struct hwm_drvdata *ddat, i915_reg_t rgadr,
1048f956e9aSGwan-gyeong Mun 			  int nshift, unsigned int scale_factor, long lval)
10599f55efbSDale B Stimson {
10699f55efbSDale B Stimson 	u32 nval;
10799f55efbSDale B Stimson 
10899f55efbSDale B Stimson 	/* Computation in 64-bits to avoid overflow. Round to nearest. */
10999f55efbSDale B Stimson 	nval = DIV_ROUND_CLOSEST_ULL((u64)lval << nshift, scale_factor);
11099f55efbSDale B Stimson 
11199f55efbSDale B Stimson 	hwm_locked_with_pm_intel_uncore_rmw(ddat, rgadr,
1128f956e9aSGwan-gyeong Mun 					    PKG_PWR_LIM_1,
1138f956e9aSGwan-gyeong Mun 					    REG_FIELD_PREP(PKG_PWR_LIM_1, nval));
11499f55efbSDale B Stimson }
11599f55efbSDale B Stimson 
116c41b8bdcSDale B Stimson /*
117c41b8bdcSDale B Stimson  * hwm_energy - Obtain energy value
118c41b8bdcSDale B Stimson  *
119c41b8bdcSDale B Stimson  * The underlying energy hardware register is 32-bits and is subject to
120c41b8bdcSDale B Stimson  * overflow. How long before overflow? For example, with an example
121c41b8bdcSDale B Stimson  * scaling bit shift of 14 bits (see register *PACKAGE_POWER_SKU_UNIT) and
122c41b8bdcSDale B Stimson  * a power draw of 1000 watts, the 32-bit counter will overflow in
123c41b8bdcSDale B Stimson  * approximately 4.36 minutes.
124c41b8bdcSDale B Stimson  *
125c41b8bdcSDale B Stimson  * Examples:
126c41b8bdcSDale B Stimson  *    1 watt:  (2^32 >> 14) /    1 W / (60 * 60 * 24) secs/day -> 3 days
127c41b8bdcSDale B Stimson  * 1000 watts: (2^32 >> 14) / 1000 W / 60             secs/min -> 4.36 minutes
128c41b8bdcSDale B Stimson  *
129c41b8bdcSDale B Stimson  * The function significantly increases overflow duration (from 4.36
130c41b8bdcSDale B Stimson  * minutes) by accumulating the energy register into a 'long' as allowed by
131c41b8bdcSDale B Stimson  * the hwmon API. Using x86_64 128 bit arithmetic (see mul_u64_u32_shr()),
132c41b8bdcSDale B Stimson  * a 'long' of 63 bits, SF_ENERGY of 1e6 (~20 bits) and
133c41b8bdcSDale B Stimson  * hwmon->scl_shift_energy of 14 bits we have 57 (63 - 20 + 14) bits before
134c41b8bdcSDale B Stimson  * energy1_input overflows. This at 1000 W is an overflow duration of 278 years.
135c41b8bdcSDale B Stimson  */
136c41b8bdcSDale B Stimson static void
137c41b8bdcSDale B Stimson hwm_energy(struct hwm_drvdata *ddat, long *energy)
138c41b8bdcSDale B Stimson {
139c41b8bdcSDale B Stimson 	struct intel_uncore *uncore = ddat->uncore;
140c41b8bdcSDale B Stimson 	struct i915_hwmon *hwmon = ddat->hwmon;
141c41b8bdcSDale B Stimson 	struct hwm_energy_info *ei = &ddat->ei;
142c41b8bdcSDale B Stimson 	intel_wakeref_t wakeref;
143c41b8bdcSDale B Stimson 	i915_reg_t rgaddr;
144c41b8bdcSDale B Stimson 	u32 reg_val;
145c41b8bdcSDale B Stimson 
146a6a924abSDale B Stimson 	if (ddat->gt_n >= 0)
147a6a924abSDale B Stimson 		rgaddr = hwmon->rg.energy_status_tile;
148a6a924abSDale B Stimson 	else
149c41b8bdcSDale B Stimson 		rgaddr = hwmon->rg.energy_status_all;
150c41b8bdcSDale B Stimson 
151c41b8bdcSDale B Stimson 	mutex_lock(&hwmon->hwmon_lock);
152c41b8bdcSDale B Stimson 
153c41b8bdcSDale B Stimson 	with_intel_runtime_pm(uncore->rpm, wakeref)
154c41b8bdcSDale B Stimson 		reg_val = intel_uncore_read(uncore, rgaddr);
155c41b8bdcSDale B Stimson 
156c41b8bdcSDale B Stimson 	if (reg_val >= ei->reg_val_prev)
157c41b8bdcSDale B Stimson 		ei->accum_energy += reg_val - ei->reg_val_prev;
158c41b8bdcSDale B Stimson 	else
159c41b8bdcSDale B Stimson 		ei->accum_energy += UINT_MAX - ei->reg_val_prev + reg_val;
160c41b8bdcSDale B Stimson 	ei->reg_val_prev = reg_val;
161c41b8bdcSDale B Stimson 
162c41b8bdcSDale B Stimson 	*energy = mul_u64_u32_shr(ei->accum_energy, SF_ENERGY,
163c41b8bdcSDale B Stimson 				  hwmon->scl_shift_energy);
164c41b8bdcSDale B Stimson 	mutex_unlock(&hwmon->hwmon_lock);
165c41b8bdcSDale B Stimson }
166c41b8bdcSDale B Stimson 
1674c2572feSAshutosh Dixit static ssize_t
1684c2572feSAshutosh Dixit hwm_power1_max_interval_show(struct device *dev, struct device_attribute *attr,
1694c2572feSAshutosh Dixit 			     char *buf)
1704c2572feSAshutosh Dixit {
1714c2572feSAshutosh Dixit 	struct hwm_drvdata *ddat = dev_get_drvdata(dev);
1724c2572feSAshutosh Dixit 	struct i915_hwmon *hwmon = ddat->hwmon;
1734c2572feSAshutosh Dixit 	intel_wakeref_t wakeref;
1744c2572feSAshutosh Dixit 	u32 r, x, y, x_w = 2; /* 2 bits */
1754c2572feSAshutosh Dixit 	u64 tau4, out;
1764c2572feSAshutosh Dixit 
1774c2572feSAshutosh Dixit 	with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
1784c2572feSAshutosh Dixit 		r = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit);
1794c2572feSAshutosh Dixit 
1804c2572feSAshutosh Dixit 	x = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_X, r);
1814c2572feSAshutosh Dixit 	y = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_Y, r);
1824c2572feSAshutosh Dixit 	/*
1834c2572feSAshutosh Dixit 	 * tau = 1.x * power(2,y), x = bits(23:22), y = bits(21:17)
1844c2572feSAshutosh Dixit 	 *     = (4 | x) << (y - 2)
1854c2572feSAshutosh Dixit 	 * where (y - 2) ensures a 1.x fixed point representation of 1.x
1864c2572feSAshutosh Dixit 	 * However because y can be < 2, we compute
1874c2572feSAshutosh Dixit 	 *     tau4 = (4 | x) << y
1884c2572feSAshutosh Dixit 	 * but add 2 when doing the final right shift to account for units
1894c2572feSAshutosh Dixit 	 */
1904c2572feSAshutosh Dixit 	tau4 = ((1 << x_w) | x) << y;
1914c2572feSAshutosh Dixit 	/* val in hwmon interface units (millisec) */
1924c2572feSAshutosh Dixit 	out = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
1934c2572feSAshutosh Dixit 
1944c2572feSAshutosh Dixit 	return sysfs_emit(buf, "%llu\n", out);
1954c2572feSAshutosh Dixit }
1964c2572feSAshutosh Dixit 
1974c2572feSAshutosh Dixit static ssize_t
1984c2572feSAshutosh Dixit hwm_power1_max_interval_store(struct device *dev,
1994c2572feSAshutosh Dixit 			      struct device_attribute *attr,
2004c2572feSAshutosh Dixit 			      const char *buf, size_t count)
2014c2572feSAshutosh Dixit {
2024c2572feSAshutosh Dixit 	struct hwm_drvdata *ddat = dev_get_drvdata(dev);
2034c2572feSAshutosh Dixit 	struct i915_hwmon *hwmon = ddat->hwmon;
2044c2572feSAshutosh Dixit 	u32 x, y, rxy, x_w = 2; /* 2 bits */
2054c2572feSAshutosh Dixit 	u64 tau4, r, max_win;
2064c2572feSAshutosh Dixit 	unsigned long val;
2074c2572feSAshutosh Dixit 	int ret;
2084c2572feSAshutosh Dixit 
2094c2572feSAshutosh Dixit 	ret = kstrtoul(buf, 0, &val);
2104c2572feSAshutosh Dixit 	if (ret)
2114c2572feSAshutosh Dixit 		return ret;
2124c2572feSAshutosh Dixit 
2134c2572feSAshutosh Dixit 	/*
2144c2572feSAshutosh Dixit 	 * Max HW supported tau in '1.x * power(2,y)' format, x = 0, y = 0x12
2154c2572feSAshutosh Dixit 	 * The hwmon->scl_shift_time default of 0xa results in a max tau of 256 seconds
2164c2572feSAshutosh Dixit 	 */
2174c2572feSAshutosh Dixit #define PKG_MAX_WIN_DEFAULT 0x12ull
2184c2572feSAshutosh Dixit 
2194c2572feSAshutosh Dixit 	/*
2204c2572feSAshutosh Dixit 	 * val must be < max in hwmon interface units. The steps below are
2214c2572feSAshutosh Dixit 	 * explained in i915_power1_max_interval_show()
2224c2572feSAshutosh Dixit 	 */
2234c2572feSAshutosh Dixit 	r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT);
2244c2572feSAshutosh Dixit 	x = REG_FIELD_GET(PKG_MAX_WIN_X, r);
2254c2572feSAshutosh Dixit 	y = REG_FIELD_GET(PKG_MAX_WIN_Y, r);
2264c2572feSAshutosh Dixit 	tau4 = ((1 << x_w) | x) << y;
2274c2572feSAshutosh Dixit 	max_win = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
2284c2572feSAshutosh Dixit 
2294c2572feSAshutosh Dixit 	if (val > max_win)
2304c2572feSAshutosh Dixit 		return -EINVAL;
2314c2572feSAshutosh Dixit 
2324c2572feSAshutosh Dixit 	/* val in hw units */
2334c2572feSAshutosh Dixit 	val = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_time, SF_TIME);
2344c2572feSAshutosh Dixit 	/* Convert to 1.x * power(2,y) */
2354c2572feSAshutosh Dixit 	if (!val)
2364c2572feSAshutosh Dixit 		return -EINVAL;
2374c2572feSAshutosh Dixit 	y = ilog2(val);
2384c2572feSAshutosh Dixit 	/* x = (val - (1 << y)) >> (y - 2); */
2394c2572feSAshutosh Dixit 	x = (val - (1ul << y)) << x_w >> y;
2404c2572feSAshutosh Dixit 
2414c2572feSAshutosh Dixit 	rxy = REG_FIELD_PREP(PKG_PWR_LIM_1_TIME_X, x) | REG_FIELD_PREP(PKG_PWR_LIM_1_TIME_Y, y);
2424c2572feSAshutosh Dixit 
2434c2572feSAshutosh Dixit 	hwm_locked_with_pm_intel_uncore_rmw(ddat, hwmon->rg.pkg_rapl_limit,
2444c2572feSAshutosh Dixit 					    PKG_PWR_LIM_1_TIME, rxy);
2454c2572feSAshutosh Dixit 	return count;
2464c2572feSAshutosh Dixit }
2474c2572feSAshutosh Dixit 
2484c2572feSAshutosh Dixit static SENSOR_DEVICE_ATTR(power1_max_interval, 0664,
2494c2572feSAshutosh Dixit 			  hwm_power1_max_interval_show,
2504c2572feSAshutosh Dixit 			  hwm_power1_max_interval_store, 0);
2514c2572feSAshutosh Dixit 
2524c2572feSAshutosh Dixit static struct attribute *hwm_attributes[] = {
2534c2572feSAshutosh Dixit 	&sensor_dev_attr_power1_max_interval.dev_attr.attr,
2544c2572feSAshutosh Dixit 	NULL
2554c2572feSAshutosh Dixit };
2564c2572feSAshutosh Dixit 
2574c2572feSAshutosh Dixit static umode_t hwm_attributes_visible(struct kobject *kobj,
2584c2572feSAshutosh Dixit 				      struct attribute *attr, int index)
2594c2572feSAshutosh Dixit {
2604c2572feSAshutosh Dixit 	struct device *dev = kobj_to_dev(kobj);
2614c2572feSAshutosh Dixit 	struct hwm_drvdata *ddat = dev_get_drvdata(dev);
2624c2572feSAshutosh Dixit 	struct i915_hwmon *hwmon = ddat->hwmon;
2634c2572feSAshutosh Dixit 
2644c2572feSAshutosh Dixit 	if (attr == &sensor_dev_attr_power1_max_interval.dev_attr.attr)
2654c2572feSAshutosh Dixit 		return i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit) ? attr->mode : 0;
2664c2572feSAshutosh Dixit 
2674c2572feSAshutosh Dixit 	return 0;
2684c2572feSAshutosh Dixit }
2694c2572feSAshutosh Dixit 
2704c2572feSAshutosh Dixit static const struct attribute_group hwm_attrgroup = {
2714c2572feSAshutosh Dixit 	.attrs = hwm_attributes,
2724c2572feSAshutosh Dixit 	.is_visible = hwm_attributes_visible,
2734c2572feSAshutosh Dixit };
2744c2572feSAshutosh Dixit 
2754c2572feSAshutosh Dixit static const struct attribute_group *hwm_groups[] = {
2764c2572feSAshutosh Dixit 	&hwm_attrgroup,
2774c2572feSAshutosh Dixit 	NULL
2784c2572feSAshutosh Dixit };
2794c2572feSAshutosh Dixit 
280b3b088e2SDale B Stimson static const struct hwmon_channel_info *hwm_info[] = {
281f8572bb6SRiana Tauro 	HWMON_CHANNEL_INFO(in, HWMON_I_INPUT),
282c8939848SAshutosh Dixit 	HWMON_CHANNEL_INFO(power, HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_CRIT),
283c41b8bdcSDale B Stimson 	HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT),
284c8939848SAshutosh Dixit 	HWMON_CHANNEL_INFO(curr, HWMON_C_CRIT),
285b3b088e2SDale B Stimson 	NULL
286b3b088e2SDale B Stimson };
287b3b088e2SDale B Stimson 
288a6a924abSDale B Stimson static const struct hwmon_channel_info *hwm_gt_info[] = {
289a6a924abSDale B Stimson 	HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT),
290a6a924abSDale B Stimson 	NULL
291a6a924abSDale B Stimson };
292a6a924abSDale B Stimson 
293c8939848SAshutosh Dixit /* I1 is exposed as power_crit or as curr_crit depending on bit 31 */
294c8939848SAshutosh Dixit static int hwm_pcode_read_i1(struct drm_i915_private *i915, u32 *uval)
295c8939848SAshutosh Dixit {
2963d0f98faSAshutosh Dixit 	/* Avoid ILLEGAL_SUBCOMMAND "mailbox access failed" warning in snb_pcode_read */
2973d0f98faSAshutosh Dixit 	if (IS_DG1(i915) || IS_DG2(i915))
2983d0f98faSAshutosh Dixit 		return -ENXIO;
2993d0f98faSAshutosh Dixit 
300c8939848SAshutosh Dixit 	return snb_pcode_read_p(&i915->uncore, PCODE_POWER_SETUP,
301c8939848SAshutosh Dixit 				POWER_SETUP_SUBCOMMAND_READ_I1, 0, uval);
302c8939848SAshutosh Dixit }
303c8939848SAshutosh Dixit 
304c8939848SAshutosh Dixit static int hwm_pcode_write_i1(struct drm_i915_private *i915, u32 uval)
305c8939848SAshutosh Dixit {
306c8939848SAshutosh Dixit 	return  snb_pcode_write_p(&i915->uncore, PCODE_POWER_SETUP,
307c8939848SAshutosh Dixit 				  POWER_SETUP_SUBCOMMAND_WRITE_I1, 0, uval);
308c8939848SAshutosh Dixit }
309c8939848SAshutosh Dixit 
310b3b088e2SDale B Stimson static umode_t
311f8572bb6SRiana Tauro hwm_in_is_visible(const struct hwm_drvdata *ddat, u32 attr)
312f8572bb6SRiana Tauro {
313f8572bb6SRiana Tauro 	struct drm_i915_private *i915 = ddat->uncore->i915;
314f8572bb6SRiana Tauro 
315f8572bb6SRiana Tauro 	switch (attr) {
316f8572bb6SRiana Tauro 	case hwmon_in_input:
317f8572bb6SRiana Tauro 		return IS_DG1(i915) || IS_DG2(i915) ? 0444 : 0;
318f8572bb6SRiana Tauro 	default:
319f8572bb6SRiana Tauro 		return 0;
320f8572bb6SRiana Tauro 	}
321f8572bb6SRiana Tauro }
322f8572bb6SRiana Tauro 
323f8572bb6SRiana Tauro static int
324f8572bb6SRiana Tauro hwm_in_read(struct hwm_drvdata *ddat, u32 attr, long *val)
325f8572bb6SRiana Tauro {
326f8572bb6SRiana Tauro 	struct i915_hwmon *hwmon = ddat->hwmon;
327f8572bb6SRiana Tauro 	intel_wakeref_t wakeref;
328f8572bb6SRiana Tauro 	u32 reg_value;
329f8572bb6SRiana Tauro 
330f8572bb6SRiana Tauro 	switch (attr) {
331f8572bb6SRiana Tauro 	case hwmon_in_input:
332f8572bb6SRiana Tauro 		with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
333f8572bb6SRiana Tauro 			reg_value = intel_uncore_read(ddat->uncore, hwmon->rg.gt_perf_status);
334f8572bb6SRiana Tauro 		/* HW register value in units of 2.5 millivolt */
335f8572bb6SRiana Tauro 		*val = DIV_ROUND_CLOSEST(REG_FIELD_GET(GEN12_VOLTAGE_MASK, reg_value) * 25, 10);
336f8572bb6SRiana Tauro 		return 0;
337f8572bb6SRiana Tauro 	default:
338f8572bb6SRiana Tauro 		return -EOPNOTSUPP;
339f8572bb6SRiana Tauro 	}
340f8572bb6SRiana Tauro }
341f8572bb6SRiana Tauro 
342f8572bb6SRiana Tauro static umode_t
34399f55efbSDale B Stimson hwm_power_is_visible(const struct hwm_drvdata *ddat, u32 attr, int chan)
34499f55efbSDale B Stimson {
345c8939848SAshutosh Dixit 	struct drm_i915_private *i915 = ddat->uncore->i915;
34699f55efbSDale B Stimson 	struct i915_hwmon *hwmon = ddat->hwmon;
347c8939848SAshutosh Dixit 	u32 uval;
34899f55efbSDale B Stimson 
34999f55efbSDale B Stimson 	switch (attr) {
35099f55efbSDale B Stimson 	case hwmon_power_max:
35199f55efbSDale B Stimson 		return i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit) ? 0664 : 0;
35299f55efbSDale B Stimson 	case hwmon_power_rated_max:
35399f55efbSDale B Stimson 		return i915_mmio_reg_valid(hwmon->rg.pkg_power_sku) ? 0444 : 0;
354c8939848SAshutosh Dixit 	case hwmon_power_crit:
355c8939848SAshutosh Dixit 		return (hwm_pcode_read_i1(i915, &uval) ||
356c8939848SAshutosh Dixit 			!(uval & POWER_SETUP_I1_WATTS)) ? 0 : 0644;
35799f55efbSDale B Stimson 	default:
35899f55efbSDale B Stimson 		return 0;
35999f55efbSDale B Stimson 	}
36099f55efbSDale B Stimson }
36199f55efbSDale B Stimson 
362*d2c3c8c3SAshutosh Dixit /*
363*d2c3c8c3SAshutosh Dixit  * HW allows arbitrary PL1 limits to be set but silently clamps these values to
364*d2c3c8c3SAshutosh Dixit  * "typical but not guaranteed" min/max values in rg.pkg_power_sku. Follow the
365*d2c3c8c3SAshutosh Dixit  * same pattern for sysfs, allow arbitrary PL1 limits to be set but display
366*d2c3c8c3SAshutosh Dixit  * clamped values when read. Write/read I1 also follows the same pattern.
367*d2c3c8c3SAshutosh Dixit  */
368*d2c3c8c3SAshutosh Dixit static int
369*d2c3c8c3SAshutosh Dixit hwm_power_max_read(struct hwm_drvdata *ddat, long *val)
370*d2c3c8c3SAshutosh Dixit {
371*d2c3c8c3SAshutosh Dixit 	struct i915_hwmon *hwmon = ddat->hwmon;
372*d2c3c8c3SAshutosh Dixit 	intel_wakeref_t wakeref;
373*d2c3c8c3SAshutosh Dixit 	u64 r, min, max;
374*d2c3c8c3SAshutosh Dixit 
375*d2c3c8c3SAshutosh Dixit 	*val = hwm_field_read_and_scale(ddat,
376*d2c3c8c3SAshutosh Dixit 					hwmon->rg.pkg_rapl_limit,
377*d2c3c8c3SAshutosh Dixit 					PKG_PWR_LIM_1,
378*d2c3c8c3SAshutosh Dixit 					hwmon->scl_shift_power,
379*d2c3c8c3SAshutosh Dixit 					SF_POWER);
380*d2c3c8c3SAshutosh Dixit 
381*d2c3c8c3SAshutosh Dixit 	with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
382*d2c3c8c3SAshutosh Dixit 		r = intel_uncore_read64(ddat->uncore, hwmon->rg.pkg_power_sku);
383*d2c3c8c3SAshutosh Dixit 	min = REG_FIELD_GET(PKG_MIN_PWR, r);
384*d2c3c8c3SAshutosh Dixit 	min = mul_u64_u32_shr(min, SF_POWER, hwmon->scl_shift_power);
385*d2c3c8c3SAshutosh Dixit 	max = REG_FIELD_GET(PKG_MAX_PWR, r);
386*d2c3c8c3SAshutosh Dixit 	max = mul_u64_u32_shr(max, SF_POWER, hwmon->scl_shift_power);
387*d2c3c8c3SAshutosh Dixit 
388*d2c3c8c3SAshutosh Dixit 	if (min && max)
389*d2c3c8c3SAshutosh Dixit 		*val = clamp_t(u64, *val, min, max);
390*d2c3c8c3SAshutosh Dixit 
391*d2c3c8c3SAshutosh Dixit 	return 0;
392*d2c3c8c3SAshutosh Dixit }
393*d2c3c8c3SAshutosh Dixit 
39499f55efbSDale B Stimson static int
39599f55efbSDale B Stimson hwm_power_read(struct hwm_drvdata *ddat, u32 attr, int chan, long *val)
39699f55efbSDale B Stimson {
39799f55efbSDale B Stimson 	struct i915_hwmon *hwmon = ddat->hwmon;
398c8939848SAshutosh Dixit 	int ret;
399c8939848SAshutosh Dixit 	u32 uval;
40099f55efbSDale B Stimson 
40199f55efbSDale B Stimson 	switch (attr) {
40299f55efbSDale B Stimson 	case hwmon_power_max:
403*d2c3c8c3SAshutosh Dixit 		return hwm_power_max_read(ddat, val);
40499f55efbSDale B Stimson 	case hwmon_power_rated_max:
40599f55efbSDale B Stimson 		*val = hwm_field_read_and_scale(ddat,
40699f55efbSDale B Stimson 						hwmon->rg.pkg_power_sku,
40799f55efbSDale B Stimson 						PKG_PKG_TDP,
40899f55efbSDale B Stimson 						hwmon->scl_shift_power,
40999f55efbSDale B Stimson 						SF_POWER);
41099f55efbSDale B Stimson 		return 0;
411c8939848SAshutosh Dixit 	case hwmon_power_crit:
412c8939848SAshutosh Dixit 		ret = hwm_pcode_read_i1(ddat->uncore->i915, &uval);
413c8939848SAshutosh Dixit 		if (ret)
414c8939848SAshutosh Dixit 			return ret;
415c8939848SAshutosh Dixit 		if (!(uval & POWER_SETUP_I1_WATTS))
416c8939848SAshutosh Dixit 			return -ENODEV;
417c8939848SAshutosh Dixit 		*val = mul_u64_u32_shr(REG_FIELD_GET(POWER_SETUP_I1_DATA_MASK, uval),
418c8939848SAshutosh Dixit 				       SF_POWER, POWER_SETUP_I1_SHIFT);
419c8939848SAshutosh Dixit 		return 0;
42099f55efbSDale B Stimson 	default:
42199f55efbSDale B Stimson 		return -EOPNOTSUPP;
42299f55efbSDale B Stimson 	}
42399f55efbSDale B Stimson }
42499f55efbSDale B Stimson 
42599f55efbSDale B Stimson static int
42699f55efbSDale B Stimson hwm_power_write(struct hwm_drvdata *ddat, u32 attr, int chan, long val)
42799f55efbSDale B Stimson {
42899f55efbSDale B Stimson 	struct i915_hwmon *hwmon = ddat->hwmon;
429c8939848SAshutosh Dixit 	u32 uval;
43099f55efbSDale B Stimson 
43199f55efbSDale B Stimson 	switch (attr) {
43299f55efbSDale B Stimson 	case hwmon_power_max:
43399f55efbSDale B Stimson 		hwm_field_scale_and_write(ddat,
43499f55efbSDale B Stimson 					  hwmon->rg.pkg_rapl_limit,
43599f55efbSDale B Stimson 					  hwmon->scl_shift_power,
43699f55efbSDale B Stimson 					  SF_POWER, val);
43799f55efbSDale B Stimson 		return 0;
438c8939848SAshutosh Dixit 	case hwmon_power_crit:
439c8939848SAshutosh Dixit 		uval = DIV_ROUND_CLOSEST_ULL(val << POWER_SETUP_I1_SHIFT, SF_POWER);
440c8939848SAshutosh Dixit 		return hwm_pcode_write_i1(ddat->uncore->i915, uval);
44199f55efbSDale B Stimson 	default:
44299f55efbSDale B Stimson 		return -EOPNOTSUPP;
44399f55efbSDale B Stimson 	}
44499f55efbSDale B Stimson }
44599f55efbSDale B Stimson 
44699f55efbSDale B Stimson static umode_t
447c41b8bdcSDale B Stimson hwm_energy_is_visible(const struct hwm_drvdata *ddat, u32 attr)
448c41b8bdcSDale B Stimson {
449c41b8bdcSDale B Stimson 	struct i915_hwmon *hwmon = ddat->hwmon;
450c41b8bdcSDale B Stimson 	i915_reg_t rgaddr;
451c41b8bdcSDale B Stimson 
452c41b8bdcSDale B Stimson 	switch (attr) {
453c41b8bdcSDale B Stimson 	case hwmon_energy_input:
454a6a924abSDale B Stimson 		if (ddat->gt_n >= 0)
455a6a924abSDale B Stimson 			rgaddr = hwmon->rg.energy_status_tile;
456a6a924abSDale B Stimson 		else
457c41b8bdcSDale B Stimson 			rgaddr = hwmon->rg.energy_status_all;
458c41b8bdcSDale B Stimson 		return i915_mmio_reg_valid(rgaddr) ? 0444 : 0;
459c41b8bdcSDale B Stimson 	default:
460c41b8bdcSDale B Stimson 		return 0;
461c41b8bdcSDale B Stimson 	}
462c41b8bdcSDale B Stimson }
463c41b8bdcSDale B Stimson 
464c41b8bdcSDale B Stimson static int
465c41b8bdcSDale B Stimson hwm_energy_read(struct hwm_drvdata *ddat, u32 attr, long *val)
466c41b8bdcSDale B Stimson {
467c41b8bdcSDale B Stimson 	switch (attr) {
468c41b8bdcSDale B Stimson 	case hwmon_energy_input:
469c41b8bdcSDale B Stimson 		hwm_energy(ddat, val);
470c41b8bdcSDale B Stimson 		return 0;
471c41b8bdcSDale B Stimson 	default:
472c41b8bdcSDale B Stimson 		return -EOPNOTSUPP;
473c41b8bdcSDale B Stimson 	}
474c41b8bdcSDale B Stimson }
475c41b8bdcSDale B Stimson 
476c41b8bdcSDale B Stimson static umode_t
477c8939848SAshutosh Dixit hwm_curr_is_visible(const struct hwm_drvdata *ddat, u32 attr)
478c8939848SAshutosh Dixit {
479c8939848SAshutosh Dixit 	struct drm_i915_private *i915 = ddat->uncore->i915;
480c8939848SAshutosh Dixit 	u32 uval;
481c8939848SAshutosh Dixit 
482c8939848SAshutosh Dixit 	switch (attr) {
483c8939848SAshutosh Dixit 	case hwmon_curr_crit:
484c8939848SAshutosh Dixit 		return (hwm_pcode_read_i1(i915, &uval) ||
485c8939848SAshutosh Dixit 			(uval & POWER_SETUP_I1_WATTS)) ? 0 : 0644;
486c8939848SAshutosh Dixit 	default:
487c8939848SAshutosh Dixit 		return 0;
488c8939848SAshutosh Dixit 	}
489c8939848SAshutosh Dixit }
490c8939848SAshutosh Dixit 
491c8939848SAshutosh Dixit static int
492c8939848SAshutosh Dixit hwm_curr_read(struct hwm_drvdata *ddat, u32 attr, long *val)
493c8939848SAshutosh Dixit {
494c8939848SAshutosh Dixit 	int ret;
495c8939848SAshutosh Dixit 	u32 uval;
496c8939848SAshutosh Dixit 
497c8939848SAshutosh Dixit 	switch (attr) {
498c8939848SAshutosh Dixit 	case hwmon_curr_crit:
499c8939848SAshutosh Dixit 		ret = hwm_pcode_read_i1(ddat->uncore->i915, &uval);
500c8939848SAshutosh Dixit 		if (ret)
501c8939848SAshutosh Dixit 			return ret;
502c8939848SAshutosh Dixit 		if (uval & POWER_SETUP_I1_WATTS)
503c8939848SAshutosh Dixit 			return -ENODEV;
504c8939848SAshutosh Dixit 		*val = mul_u64_u32_shr(REG_FIELD_GET(POWER_SETUP_I1_DATA_MASK, uval),
505c8939848SAshutosh Dixit 				       SF_CURR, POWER_SETUP_I1_SHIFT);
506c8939848SAshutosh Dixit 		return 0;
507c8939848SAshutosh Dixit 	default:
508c8939848SAshutosh Dixit 		return -EOPNOTSUPP;
509c8939848SAshutosh Dixit 	}
510c8939848SAshutosh Dixit }
511c8939848SAshutosh Dixit 
512c8939848SAshutosh Dixit static int
513c8939848SAshutosh Dixit hwm_curr_write(struct hwm_drvdata *ddat, u32 attr, long val)
514c8939848SAshutosh Dixit {
515c8939848SAshutosh Dixit 	u32 uval;
516c8939848SAshutosh Dixit 
517c8939848SAshutosh Dixit 	switch (attr) {
518c8939848SAshutosh Dixit 	case hwmon_curr_crit:
519c8939848SAshutosh Dixit 		uval = DIV_ROUND_CLOSEST_ULL(val << POWER_SETUP_I1_SHIFT, SF_CURR);
520c8939848SAshutosh Dixit 		return hwm_pcode_write_i1(ddat->uncore->i915, uval);
521c8939848SAshutosh Dixit 	default:
522c8939848SAshutosh Dixit 		return -EOPNOTSUPP;
523c8939848SAshutosh Dixit 	}
524c8939848SAshutosh Dixit }
525c8939848SAshutosh Dixit 
526c8939848SAshutosh Dixit static umode_t
527b3b088e2SDale B Stimson hwm_is_visible(const void *drvdata, enum hwmon_sensor_types type,
528b3b088e2SDale B Stimson 	       u32 attr, int channel)
529b3b088e2SDale B Stimson {
530f8572bb6SRiana Tauro 	struct hwm_drvdata *ddat = (struct hwm_drvdata *)drvdata;
531f8572bb6SRiana Tauro 
532b3b088e2SDale B Stimson 	switch (type) {
533f8572bb6SRiana Tauro 	case hwmon_in:
534f8572bb6SRiana Tauro 		return hwm_in_is_visible(ddat, attr);
53599f55efbSDale B Stimson 	case hwmon_power:
53699f55efbSDale B Stimson 		return hwm_power_is_visible(ddat, attr, channel);
537c41b8bdcSDale B Stimson 	case hwmon_energy:
538c41b8bdcSDale B Stimson 		return hwm_energy_is_visible(ddat, attr);
539c8939848SAshutosh Dixit 	case hwmon_curr:
540c8939848SAshutosh Dixit 		return hwm_curr_is_visible(ddat, attr);
541b3b088e2SDale B Stimson 	default:
542b3b088e2SDale B Stimson 		return 0;
543b3b088e2SDale B Stimson 	}
544b3b088e2SDale B Stimson }
545b3b088e2SDale B Stimson 
546b3b088e2SDale B Stimson static int
547b3b088e2SDale B Stimson hwm_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
548b3b088e2SDale B Stimson 	 int channel, long *val)
549b3b088e2SDale B Stimson {
550f8572bb6SRiana Tauro 	struct hwm_drvdata *ddat = dev_get_drvdata(dev);
551f8572bb6SRiana Tauro 
552b3b088e2SDale B Stimson 	switch (type) {
553f8572bb6SRiana Tauro 	case hwmon_in:
554f8572bb6SRiana Tauro 		return hwm_in_read(ddat, attr, val);
55599f55efbSDale B Stimson 	case hwmon_power:
55699f55efbSDale B Stimson 		return hwm_power_read(ddat, attr, channel, val);
557c41b8bdcSDale B Stimson 	case hwmon_energy:
558c41b8bdcSDale B Stimson 		return hwm_energy_read(ddat, attr, val);
559c8939848SAshutosh Dixit 	case hwmon_curr:
560c8939848SAshutosh Dixit 		return hwm_curr_read(ddat, attr, val);
561b3b088e2SDale B Stimson 	default:
562b3b088e2SDale B Stimson 		return -EOPNOTSUPP;
563b3b088e2SDale B Stimson 	}
564b3b088e2SDale B Stimson }
565b3b088e2SDale B Stimson 
566b3b088e2SDale B Stimson static int
567b3b088e2SDale B Stimson hwm_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
568b3b088e2SDale B Stimson 	  int channel, long val)
569b3b088e2SDale B Stimson {
57099f55efbSDale B Stimson 	struct hwm_drvdata *ddat = dev_get_drvdata(dev);
57199f55efbSDale B Stimson 
572b3b088e2SDale B Stimson 	switch (type) {
57399f55efbSDale B Stimson 	case hwmon_power:
57499f55efbSDale B Stimson 		return hwm_power_write(ddat, attr, channel, val);
575c8939848SAshutosh Dixit 	case hwmon_curr:
576c8939848SAshutosh Dixit 		return hwm_curr_write(ddat, attr, val);
577b3b088e2SDale B Stimson 	default:
578b3b088e2SDale B Stimson 		return -EOPNOTSUPP;
579b3b088e2SDale B Stimson 	}
580b3b088e2SDale B Stimson }
581b3b088e2SDale B Stimson 
582b3b088e2SDale B Stimson static const struct hwmon_ops hwm_ops = {
583b3b088e2SDale B Stimson 	.is_visible = hwm_is_visible,
584b3b088e2SDale B Stimson 	.read = hwm_read,
585b3b088e2SDale B Stimson 	.write = hwm_write,
586b3b088e2SDale B Stimson };
587b3b088e2SDale B Stimson 
588b3b088e2SDale B Stimson static const struct hwmon_chip_info hwm_chip_info = {
589b3b088e2SDale B Stimson 	.ops = &hwm_ops,
590b3b088e2SDale B Stimson 	.info = hwm_info,
591b3b088e2SDale B Stimson };
592b3b088e2SDale B Stimson 
593a6a924abSDale B Stimson static umode_t
594a6a924abSDale B Stimson hwm_gt_is_visible(const void *drvdata, enum hwmon_sensor_types type,
595a6a924abSDale B Stimson 		  u32 attr, int channel)
596a6a924abSDale B Stimson {
597a6a924abSDale B Stimson 	struct hwm_drvdata *ddat = (struct hwm_drvdata *)drvdata;
598a6a924abSDale B Stimson 
599a6a924abSDale B Stimson 	switch (type) {
600a6a924abSDale B Stimson 	case hwmon_energy:
601a6a924abSDale B Stimson 		return hwm_energy_is_visible(ddat, attr);
602a6a924abSDale B Stimson 	default:
603a6a924abSDale B Stimson 		return 0;
604a6a924abSDale B Stimson 	}
605a6a924abSDale B Stimson }
606a6a924abSDale B Stimson 
607a6a924abSDale B Stimson static int
608a6a924abSDale B Stimson hwm_gt_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
609a6a924abSDale B Stimson 	    int channel, long *val)
610a6a924abSDale B Stimson {
611a6a924abSDale B Stimson 	struct hwm_drvdata *ddat = dev_get_drvdata(dev);
612a6a924abSDale B Stimson 
613a6a924abSDale B Stimson 	switch (type) {
614a6a924abSDale B Stimson 	case hwmon_energy:
615a6a924abSDale B Stimson 		return hwm_energy_read(ddat, attr, val);
616a6a924abSDale B Stimson 	default:
617a6a924abSDale B Stimson 		return -EOPNOTSUPP;
618a6a924abSDale B Stimson 	}
619a6a924abSDale B Stimson }
620a6a924abSDale B Stimson 
621a6a924abSDale B Stimson static const struct hwmon_ops hwm_gt_ops = {
622a6a924abSDale B Stimson 	.is_visible = hwm_gt_is_visible,
623a6a924abSDale B Stimson 	.read = hwm_gt_read,
624a6a924abSDale B Stimson };
625a6a924abSDale B Stimson 
626a6a924abSDale B Stimson static const struct hwmon_chip_info hwm_gt_chip_info = {
627a6a924abSDale B Stimson 	.ops = &hwm_gt_ops,
628a6a924abSDale B Stimson 	.info = hwm_gt_info,
629a6a924abSDale B Stimson };
630a6a924abSDale B Stimson 
631b3b088e2SDale B Stimson static void
632b3b088e2SDale B Stimson hwm_get_preregistration_info(struct drm_i915_private *i915)
633b3b088e2SDale B Stimson {
634f8572bb6SRiana Tauro 	struct i915_hwmon *hwmon = i915->hwmon;
63599f55efbSDale B Stimson 	struct intel_uncore *uncore = &i915->uncore;
636c41b8bdcSDale B Stimson 	struct hwm_drvdata *ddat = &hwmon->ddat;
63799f55efbSDale B Stimson 	intel_wakeref_t wakeref;
63899f55efbSDale B Stimson 	u32 val_sku_unit = 0;
639a6a924abSDale B Stimson 	struct intel_gt *gt;
640c41b8bdcSDale B Stimson 	long energy;
641a6a924abSDale B Stimson 	int i;
642f8572bb6SRiana Tauro 
643f8572bb6SRiana Tauro 	/* Available for all Gen12+/dGfx */
644f8572bb6SRiana Tauro 	hwmon->rg.gt_perf_status = GEN12_RPSTAT1;
64599f55efbSDale B Stimson 
64699f55efbSDale B Stimson 	if (IS_DG1(i915) || IS_DG2(i915)) {
64799f55efbSDale B Stimson 		hwmon->rg.pkg_power_sku_unit = PCU_PACKAGE_POWER_SKU_UNIT;
64899f55efbSDale B Stimson 		hwmon->rg.pkg_power_sku = PCU_PACKAGE_POWER_SKU;
64999f55efbSDale B Stimson 		hwmon->rg.pkg_rapl_limit = PCU_PACKAGE_RAPL_LIMIT;
650c41b8bdcSDale B Stimson 		hwmon->rg.energy_status_all = PCU_PACKAGE_ENERGY_STATUS;
651a6a924abSDale B Stimson 		hwmon->rg.energy_status_tile = INVALID_MMIO_REG;
652a6a924abSDale B Stimson 	} else if (IS_XEHPSDV(i915)) {
653a6a924abSDale B Stimson 		hwmon->rg.pkg_power_sku_unit = GT0_PACKAGE_POWER_SKU_UNIT;
654a6a924abSDale B Stimson 		hwmon->rg.pkg_power_sku = INVALID_MMIO_REG;
655a6a924abSDale B Stimson 		hwmon->rg.pkg_rapl_limit = GT0_PACKAGE_RAPL_LIMIT;
656a6a924abSDale B Stimson 		hwmon->rg.energy_status_all = GT0_PLATFORM_ENERGY_STATUS;
657a6a924abSDale B Stimson 		hwmon->rg.energy_status_tile = GT0_PACKAGE_ENERGY_STATUS;
65899f55efbSDale B Stimson 	} else {
65999f55efbSDale B Stimson 		hwmon->rg.pkg_power_sku_unit = INVALID_MMIO_REG;
66099f55efbSDale B Stimson 		hwmon->rg.pkg_power_sku = INVALID_MMIO_REG;
66199f55efbSDale B Stimson 		hwmon->rg.pkg_rapl_limit = INVALID_MMIO_REG;
662c41b8bdcSDale B Stimson 		hwmon->rg.energy_status_all = INVALID_MMIO_REG;
663a6a924abSDale B Stimson 		hwmon->rg.energy_status_tile = INVALID_MMIO_REG;
66499f55efbSDale B Stimson 	}
66599f55efbSDale B Stimson 
66699f55efbSDale B Stimson 	with_intel_runtime_pm(uncore->rpm, wakeref) {
66799f55efbSDale B Stimson 		/*
66899f55efbSDale B Stimson 		 * The contents of register hwmon->rg.pkg_power_sku_unit do not change,
66999f55efbSDale B Stimson 		 * so read it once and store the shift values.
67099f55efbSDale B Stimson 		 */
67199f55efbSDale B Stimson 		if (i915_mmio_reg_valid(hwmon->rg.pkg_power_sku_unit))
67299f55efbSDale B Stimson 			val_sku_unit = intel_uncore_read(uncore,
67399f55efbSDale B Stimson 							 hwmon->rg.pkg_power_sku_unit);
674c41b8bdcSDale B Stimson 	}
67599f55efbSDale B Stimson 
67699f55efbSDale B Stimson 	hwmon->scl_shift_power = REG_FIELD_GET(PKG_PWR_UNIT, val_sku_unit);
677c41b8bdcSDale B Stimson 	hwmon->scl_shift_energy = REG_FIELD_GET(PKG_ENERGY_UNIT, val_sku_unit);
6784c2572feSAshutosh Dixit 	hwmon->scl_shift_time = REG_FIELD_GET(PKG_TIME_UNIT, val_sku_unit);
679c41b8bdcSDale B Stimson 
680c41b8bdcSDale B Stimson 	/*
681c41b8bdcSDale B Stimson 	 * Initialize 'struct hwm_energy_info', i.e. set fields to the
682c41b8bdcSDale B Stimson 	 * first value of the energy register read
683c41b8bdcSDale B Stimson 	 */
684c41b8bdcSDale B Stimson 	if (i915_mmio_reg_valid(hwmon->rg.energy_status_all))
685c41b8bdcSDale B Stimson 		hwm_energy(ddat, &energy);
686a6a924abSDale B Stimson 	if (i915_mmio_reg_valid(hwmon->rg.energy_status_tile)) {
687a6a924abSDale B Stimson 		for_each_gt(gt, i915, i)
688a6a924abSDale B Stimson 			hwm_energy(&hwmon->ddat_gt[i], &energy);
689a6a924abSDale B Stimson 	}
690b3b088e2SDale B Stimson }
691b3b088e2SDale B Stimson 
692b3b088e2SDale B Stimson void i915_hwmon_register(struct drm_i915_private *i915)
693b3b088e2SDale B Stimson {
694b3b088e2SDale B Stimson 	struct device *dev = i915->drm.dev;
695b3b088e2SDale B Stimson 	struct i915_hwmon *hwmon;
696b3b088e2SDale B Stimson 	struct device *hwmon_dev;
697b3b088e2SDale B Stimson 	struct hwm_drvdata *ddat;
698a6a924abSDale B Stimson 	struct hwm_drvdata *ddat_gt;
699a6a924abSDale B Stimson 	struct intel_gt *gt;
700a6a924abSDale B Stimson 	int i;
701b3b088e2SDale B Stimson 
702b3b088e2SDale B Stimson 	/* hwmon is available only for dGfx */
703b3b088e2SDale B Stimson 	if (!IS_DGFX(i915))
704b3b088e2SDale B Stimson 		return;
705b3b088e2SDale B Stimson 
706b3b088e2SDale B Stimson 	hwmon = devm_kzalloc(dev, sizeof(*hwmon), GFP_KERNEL);
707b3b088e2SDale B Stimson 	if (!hwmon)
708b3b088e2SDale B Stimson 		return;
709b3b088e2SDale B Stimson 
710b3b088e2SDale B Stimson 	i915->hwmon = hwmon;
711b3b088e2SDale B Stimson 	mutex_init(&hwmon->hwmon_lock);
712b3b088e2SDale B Stimson 	ddat = &hwmon->ddat;
713b3b088e2SDale B Stimson 
714b3b088e2SDale B Stimson 	ddat->hwmon = hwmon;
715b3b088e2SDale B Stimson 	ddat->uncore = &i915->uncore;
716b3b088e2SDale B Stimson 	snprintf(ddat->name, sizeof(ddat->name), "i915");
717a6a924abSDale B Stimson 	ddat->gt_n = -1;
718a6a924abSDale B Stimson 
719a6a924abSDale B Stimson 	for_each_gt(gt, i915, i) {
720a6a924abSDale B Stimson 		ddat_gt = hwmon->ddat_gt + i;
721a6a924abSDale B Stimson 
722a6a924abSDale B Stimson 		ddat_gt->hwmon = hwmon;
723a6a924abSDale B Stimson 		ddat_gt->uncore = gt->uncore;
724a6a924abSDale B Stimson 		snprintf(ddat_gt->name, sizeof(ddat_gt->name), "i915_gt%u", i);
725a6a924abSDale B Stimson 		ddat_gt->gt_n = i;
726a6a924abSDale B Stimson 	}
727b3b088e2SDale B Stimson 
728b3b088e2SDale B Stimson 	hwm_get_preregistration_info(i915);
729b3b088e2SDale B Stimson 
730b3b088e2SDale B Stimson 	/*  hwmon_dev points to device hwmon<i> */
731b3b088e2SDale B Stimson 	hwmon_dev = devm_hwmon_device_register_with_info(dev, ddat->name,
732b3b088e2SDale B Stimson 							 ddat,
733b3b088e2SDale B Stimson 							 &hwm_chip_info,
7344c2572feSAshutosh Dixit 							 hwm_groups);
735b3b088e2SDale B Stimson 	if (IS_ERR(hwmon_dev)) {
736b3b088e2SDale B Stimson 		i915->hwmon = NULL;
737b3b088e2SDale B Stimson 		return;
738b3b088e2SDale B Stimson 	}
739b3b088e2SDale B Stimson 
740b3b088e2SDale B Stimson 	ddat->hwmon_dev = hwmon_dev;
741a6a924abSDale B Stimson 
742a6a924abSDale B Stimson 	for_each_gt(gt, i915, i) {
743a6a924abSDale B Stimson 		ddat_gt = hwmon->ddat_gt + i;
744a6a924abSDale B Stimson 		/*
745a6a924abSDale B Stimson 		 * Create per-gt directories only if a per-gt attribute is
746a6a924abSDale B Stimson 		 * visible. Currently this is only energy
747a6a924abSDale B Stimson 		 */
748a6a924abSDale B Stimson 		if (!hwm_gt_is_visible(ddat_gt, hwmon_energy, hwmon_energy_input, 0))
749a6a924abSDale B Stimson 			continue;
750a6a924abSDale B Stimson 
751a6a924abSDale B Stimson 		hwmon_dev = devm_hwmon_device_register_with_info(dev, ddat_gt->name,
752a6a924abSDale B Stimson 								 ddat_gt,
753a6a924abSDale B Stimson 								 &hwm_gt_chip_info,
754a6a924abSDale B Stimson 								 NULL);
755a6a924abSDale B Stimson 		if (!IS_ERR(hwmon_dev))
756a6a924abSDale B Stimson 			ddat_gt->hwmon_dev = hwmon_dev;
757a6a924abSDale B Stimson 	}
758b3b088e2SDale B Stimson }
759b3b088e2SDale B Stimson 
760b3b088e2SDale B Stimson void i915_hwmon_unregister(struct drm_i915_private *i915)
761b3b088e2SDale B Stimson {
762b3b088e2SDale B Stimson 	fetch_and_zero(&i915->hwmon);
763b3b088e2SDale B Stimson }
764