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