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; 531b44019aSAshutosh Dixit bool reset_in_progress; 54655bd3b9SAshutosh Dixit wait_queue_head_t waitq; 55b3b088e2SDale B Stimson }; 56b3b088e2SDale B Stimson 57b3b088e2SDale B Stimson struct i915_hwmon { 58b3b088e2SDale B Stimson struct hwm_drvdata ddat; 59a6a924abSDale B Stimson struct hwm_drvdata ddat_gt[I915_MAX_GT]; 60b3b088e2SDale B Stimson struct mutex hwmon_lock; /* counter overflow logic and rmw */ 61b3b088e2SDale B Stimson struct hwm_reg rg; 6299f55efbSDale B Stimson int scl_shift_power; 63c41b8bdcSDale B Stimson int scl_shift_energy; 644c2572feSAshutosh Dixit int scl_shift_time; 65b3b088e2SDale B Stimson }; 66b3b088e2SDale B Stimson 6799f55efbSDale B Stimson static void 6899f55efbSDale B Stimson hwm_locked_with_pm_intel_uncore_rmw(struct hwm_drvdata *ddat, 6999f55efbSDale B Stimson i915_reg_t reg, u32 clear, u32 set) 7099f55efbSDale B Stimson { 7199f55efbSDale B Stimson struct i915_hwmon *hwmon = ddat->hwmon; 7299f55efbSDale B Stimson struct intel_uncore *uncore = ddat->uncore; 7399f55efbSDale B Stimson intel_wakeref_t wakeref; 7499f55efbSDale B Stimson 7571b21877SJanusz Krzysztofik with_intel_runtime_pm(uncore->rpm, wakeref) { 7699f55efbSDale B Stimson mutex_lock(&hwmon->hwmon_lock); 7799f55efbSDale B Stimson 7899f55efbSDale B Stimson intel_uncore_rmw(uncore, reg, clear, set); 7999f55efbSDale B Stimson 8099f55efbSDale B Stimson mutex_unlock(&hwmon->hwmon_lock); 8199f55efbSDale B Stimson } 8271b21877SJanusz Krzysztofik } 8399f55efbSDale B Stimson 8499f55efbSDale B Stimson /* 8599f55efbSDale B Stimson * This function's return type of u64 allows for the case where the scaling 8699f55efbSDale B Stimson * of the field taken from the 32-bit register value might cause a result to 8799f55efbSDale B Stimson * exceed 32 bits. 8899f55efbSDale B Stimson */ 8999f55efbSDale B Stimson static u64 9099f55efbSDale B Stimson hwm_field_read_and_scale(struct hwm_drvdata *ddat, i915_reg_t rgadr, 9199f55efbSDale B Stimson u32 field_msk, int nshift, u32 scale_factor) 9299f55efbSDale B Stimson { 9399f55efbSDale B Stimson struct intel_uncore *uncore = ddat->uncore; 9499f55efbSDale B Stimson intel_wakeref_t wakeref; 9599f55efbSDale B Stimson u32 reg_value; 9699f55efbSDale B Stimson 9799f55efbSDale B Stimson with_intel_runtime_pm(uncore->rpm, wakeref) 9899f55efbSDale B Stimson reg_value = intel_uncore_read(uncore, rgadr); 9999f55efbSDale B Stimson 10099f55efbSDale B Stimson reg_value = REG_FIELD_GET(field_msk, reg_value); 10199f55efbSDale B Stimson 10299f55efbSDale B Stimson return mul_u64_u32_shr(reg_value, scale_factor, nshift); 10399f55efbSDale B Stimson } 10499f55efbSDale B Stimson 105c41b8bdcSDale B Stimson /* 106c41b8bdcSDale B Stimson * hwm_energy - Obtain energy value 107c41b8bdcSDale B Stimson * 108c41b8bdcSDale B Stimson * The underlying energy hardware register is 32-bits and is subject to 109c41b8bdcSDale B Stimson * overflow. How long before overflow? For example, with an example 110c41b8bdcSDale B Stimson * scaling bit shift of 14 bits (see register *PACKAGE_POWER_SKU_UNIT) and 111c41b8bdcSDale B Stimson * a power draw of 1000 watts, the 32-bit counter will overflow in 112c41b8bdcSDale B Stimson * approximately 4.36 minutes. 113c41b8bdcSDale B Stimson * 114c41b8bdcSDale B Stimson * Examples: 115c41b8bdcSDale B Stimson * 1 watt: (2^32 >> 14) / 1 W / (60 * 60 * 24) secs/day -> 3 days 116c41b8bdcSDale B Stimson * 1000 watts: (2^32 >> 14) / 1000 W / 60 secs/min -> 4.36 minutes 117c41b8bdcSDale B Stimson * 118c41b8bdcSDale B Stimson * The function significantly increases overflow duration (from 4.36 119c41b8bdcSDale B Stimson * minutes) by accumulating the energy register into a 'long' as allowed by 120c41b8bdcSDale B Stimson * the hwmon API. Using x86_64 128 bit arithmetic (see mul_u64_u32_shr()), 121c41b8bdcSDale B Stimson * a 'long' of 63 bits, SF_ENERGY of 1e6 (~20 bits) and 122c41b8bdcSDale B Stimson * hwmon->scl_shift_energy of 14 bits we have 57 (63 - 20 + 14) bits before 123c41b8bdcSDale B Stimson * energy1_input overflows. This at 1000 W is an overflow duration of 278 years. 124c41b8bdcSDale B Stimson */ 125c41b8bdcSDale B Stimson static void 126c41b8bdcSDale B Stimson hwm_energy(struct hwm_drvdata *ddat, long *energy) 127c41b8bdcSDale B Stimson { 128c41b8bdcSDale B Stimson struct intel_uncore *uncore = ddat->uncore; 129c41b8bdcSDale B Stimson struct i915_hwmon *hwmon = ddat->hwmon; 130c41b8bdcSDale B Stimson struct hwm_energy_info *ei = &ddat->ei; 131c41b8bdcSDale B Stimson intel_wakeref_t wakeref; 132c41b8bdcSDale B Stimson i915_reg_t rgaddr; 133c41b8bdcSDale B Stimson u32 reg_val; 134c41b8bdcSDale B Stimson 135a6a924abSDale B Stimson if (ddat->gt_n >= 0) 136a6a924abSDale B Stimson rgaddr = hwmon->rg.energy_status_tile; 137a6a924abSDale B Stimson else 138c41b8bdcSDale B Stimson rgaddr = hwmon->rg.energy_status_all; 139c41b8bdcSDale B Stimson 14071b21877SJanusz Krzysztofik with_intel_runtime_pm(uncore->rpm, wakeref) { 141c41b8bdcSDale B Stimson mutex_lock(&hwmon->hwmon_lock); 142c41b8bdcSDale B Stimson 143c41b8bdcSDale B Stimson reg_val = intel_uncore_read(uncore, rgaddr); 144c41b8bdcSDale B Stimson 145c41b8bdcSDale B Stimson if (reg_val >= ei->reg_val_prev) 146c41b8bdcSDale B Stimson ei->accum_energy += reg_val - ei->reg_val_prev; 147c41b8bdcSDale B Stimson else 148c41b8bdcSDale B Stimson ei->accum_energy += UINT_MAX - ei->reg_val_prev + reg_val; 149c41b8bdcSDale B Stimson ei->reg_val_prev = reg_val; 150c41b8bdcSDale B Stimson 151c41b8bdcSDale B Stimson *energy = mul_u64_u32_shr(ei->accum_energy, SF_ENERGY, 152c41b8bdcSDale B Stimson hwmon->scl_shift_energy); 153c41b8bdcSDale B Stimson mutex_unlock(&hwmon->hwmon_lock); 154c41b8bdcSDale B Stimson } 15571b21877SJanusz Krzysztofik } 156c41b8bdcSDale B Stimson 1574c2572feSAshutosh Dixit static ssize_t 1584c2572feSAshutosh Dixit hwm_power1_max_interval_show(struct device *dev, struct device_attribute *attr, 1594c2572feSAshutosh Dixit char *buf) 1604c2572feSAshutosh Dixit { 1614c2572feSAshutosh Dixit struct hwm_drvdata *ddat = dev_get_drvdata(dev); 1624c2572feSAshutosh Dixit struct i915_hwmon *hwmon = ddat->hwmon; 1634c2572feSAshutosh Dixit intel_wakeref_t wakeref; 1644c2572feSAshutosh Dixit u32 r, x, y, x_w = 2; /* 2 bits */ 1654c2572feSAshutosh Dixit u64 tau4, out; 1664c2572feSAshutosh Dixit 1674c2572feSAshutosh Dixit with_intel_runtime_pm(ddat->uncore->rpm, wakeref) 1684c2572feSAshutosh Dixit r = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit); 1694c2572feSAshutosh Dixit 1704c2572feSAshutosh Dixit x = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_X, r); 1714c2572feSAshutosh Dixit y = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_Y, r); 1724c2572feSAshutosh Dixit /* 1734c2572feSAshutosh Dixit * tau = 1.x * power(2,y), x = bits(23:22), y = bits(21:17) 1744c2572feSAshutosh Dixit * = (4 | x) << (y - 2) 1754c2572feSAshutosh Dixit * where (y - 2) ensures a 1.x fixed point representation of 1.x 1764c2572feSAshutosh Dixit * However because y can be < 2, we compute 1774c2572feSAshutosh Dixit * tau4 = (4 | x) << y 1784c2572feSAshutosh Dixit * but add 2 when doing the final right shift to account for units 1794c2572feSAshutosh Dixit */ 180ac3420d3SKarthik Poosa tau4 = (u64)((1 << x_w) | x) << y; 1814c2572feSAshutosh Dixit /* val in hwmon interface units (millisec) */ 1824c2572feSAshutosh Dixit out = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w); 1834c2572feSAshutosh Dixit 1844c2572feSAshutosh Dixit return sysfs_emit(buf, "%llu\n", out); 1854c2572feSAshutosh Dixit } 1864c2572feSAshutosh Dixit 1874c2572feSAshutosh Dixit static ssize_t 1884c2572feSAshutosh Dixit hwm_power1_max_interval_store(struct device *dev, 1894c2572feSAshutosh Dixit struct device_attribute *attr, 1904c2572feSAshutosh Dixit const char *buf, size_t count) 1914c2572feSAshutosh Dixit { 1924c2572feSAshutosh Dixit struct hwm_drvdata *ddat = dev_get_drvdata(dev); 1934c2572feSAshutosh Dixit struct i915_hwmon *hwmon = ddat->hwmon; 1944c2572feSAshutosh Dixit u32 x, y, rxy, x_w = 2; /* 2 bits */ 1954c2572feSAshutosh Dixit u64 tau4, r, max_win; 1964c2572feSAshutosh Dixit unsigned long val; 1974c2572feSAshutosh Dixit int ret; 1984c2572feSAshutosh Dixit 1994c2572feSAshutosh Dixit ret = kstrtoul(buf, 0, &val); 2004c2572feSAshutosh Dixit if (ret) 2014c2572feSAshutosh Dixit return ret; 2024c2572feSAshutosh Dixit 2034c2572feSAshutosh Dixit /* 2044c2572feSAshutosh Dixit * Max HW supported tau in '1.x * power(2,y)' format, x = 0, y = 0x12 2054c2572feSAshutosh Dixit * The hwmon->scl_shift_time default of 0xa results in a max tau of 256 seconds 2064c2572feSAshutosh Dixit */ 2074c2572feSAshutosh Dixit #define PKG_MAX_WIN_DEFAULT 0x12ull 2084c2572feSAshutosh Dixit 2094c2572feSAshutosh Dixit /* 2104c2572feSAshutosh Dixit * val must be < max in hwmon interface units. The steps below are 2114c2572feSAshutosh Dixit * explained in i915_power1_max_interval_show() 2124c2572feSAshutosh Dixit */ 2134c2572feSAshutosh Dixit r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT); 2144c2572feSAshutosh Dixit x = REG_FIELD_GET(PKG_MAX_WIN_X, r); 2154c2572feSAshutosh Dixit y = REG_FIELD_GET(PKG_MAX_WIN_Y, r); 216ac3420d3SKarthik Poosa tau4 = (u64)((1 << x_w) | x) << y; 2174c2572feSAshutosh Dixit max_win = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w); 2184c2572feSAshutosh Dixit 2194c2572feSAshutosh Dixit if (val > max_win) 2204c2572feSAshutosh Dixit return -EINVAL; 2214c2572feSAshutosh Dixit 2224c2572feSAshutosh Dixit /* val in hw units */ 2234c2572feSAshutosh Dixit val = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_time, SF_TIME); 2244c2572feSAshutosh Dixit /* Convert to 1.x * power(2,y) */ 22512e8ed96SAshutosh Dixit if (!val) { 22612e8ed96SAshutosh Dixit /* Avoid ilog2(0) */ 22712e8ed96SAshutosh Dixit y = 0; 22812e8ed96SAshutosh Dixit x = 0; 22912e8ed96SAshutosh Dixit } else { 2304c2572feSAshutosh Dixit y = ilog2(val); 2314c2572feSAshutosh Dixit /* x = (val - (1 << y)) >> (y - 2); */ 2324c2572feSAshutosh Dixit x = (val - (1ul << y)) << x_w >> y; 23312e8ed96SAshutosh Dixit } 2344c2572feSAshutosh Dixit 2354c2572feSAshutosh Dixit rxy = REG_FIELD_PREP(PKG_PWR_LIM_1_TIME_X, x) | REG_FIELD_PREP(PKG_PWR_LIM_1_TIME_Y, y); 2364c2572feSAshutosh Dixit 2374c2572feSAshutosh Dixit hwm_locked_with_pm_intel_uncore_rmw(ddat, hwmon->rg.pkg_rapl_limit, 2384c2572feSAshutosh Dixit PKG_PWR_LIM_1_TIME, rxy); 2394c2572feSAshutosh Dixit return count; 2404c2572feSAshutosh Dixit } 2414c2572feSAshutosh Dixit 2424c2572feSAshutosh Dixit static SENSOR_DEVICE_ATTR(power1_max_interval, 0664, 2434c2572feSAshutosh Dixit hwm_power1_max_interval_show, 2444c2572feSAshutosh Dixit hwm_power1_max_interval_store, 0); 2454c2572feSAshutosh Dixit 2464c2572feSAshutosh Dixit static struct attribute *hwm_attributes[] = { 2474c2572feSAshutosh Dixit &sensor_dev_attr_power1_max_interval.dev_attr.attr, 2484c2572feSAshutosh Dixit NULL 2494c2572feSAshutosh Dixit }; 2504c2572feSAshutosh Dixit 2514c2572feSAshutosh Dixit static umode_t hwm_attributes_visible(struct kobject *kobj, 2524c2572feSAshutosh Dixit struct attribute *attr, int index) 2534c2572feSAshutosh Dixit { 2544c2572feSAshutosh Dixit struct device *dev = kobj_to_dev(kobj); 2554c2572feSAshutosh Dixit struct hwm_drvdata *ddat = dev_get_drvdata(dev); 2564c2572feSAshutosh Dixit struct i915_hwmon *hwmon = ddat->hwmon; 2574c2572feSAshutosh Dixit 2584c2572feSAshutosh Dixit if (attr == &sensor_dev_attr_power1_max_interval.dev_attr.attr) 2594c2572feSAshutosh Dixit return i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit) ? attr->mode : 0; 2604c2572feSAshutosh Dixit 2614c2572feSAshutosh Dixit return 0; 2624c2572feSAshutosh Dixit } 2634c2572feSAshutosh Dixit 2644c2572feSAshutosh Dixit static const struct attribute_group hwm_attrgroup = { 2654c2572feSAshutosh Dixit .attrs = hwm_attributes, 2664c2572feSAshutosh Dixit .is_visible = hwm_attributes_visible, 2674c2572feSAshutosh Dixit }; 2684c2572feSAshutosh Dixit 2694c2572feSAshutosh Dixit static const struct attribute_group *hwm_groups[] = { 2704c2572feSAshutosh Dixit &hwm_attrgroup, 2714c2572feSAshutosh Dixit NULL 2724c2572feSAshutosh Dixit }; 2734c2572feSAshutosh Dixit 274861601ffSKrzysztof Kozlowski static const struct hwmon_channel_info * const hwm_info[] = { 275f8572bb6SRiana Tauro HWMON_CHANNEL_INFO(in, HWMON_I_INPUT), 276c8939848SAshutosh Dixit HWMON_CHANNEL_INFO(power, HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_CRIT), 277c41b8bdcSDale B Stimson HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT), 278c8939848SAshutosh Dixit HWMON_CHANNEL_INFO(curr, HWMON_C_CRIT), 279b3b088e2SDale B Stimson NULL 280b3b088e2SDale B Stimson }; 281b3b088e2SDale B Stimson 282861601ffSKrzysztof Kozlowski static const struct hwmon_channel_info * const hwm_gt_info[] = { 283a6a924abSDale B Stimson HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT), 284a6a924abSDale B Stimson NULL 285a6a924abSDale B Stimson }; 286a6a924abSDale B Stimson 287c8939848SAshutosh Dixit /* I1 is exposed as power_crit or as curr_crit depending on bit 31 */ 288c8939848SAshutosh Dixit static int hwm_pcode_read_i1(struct drm_i915_private *i915, u32 *uval) 289c8939848SAshutosh Dixit { 2903d0f98faSAshutosh Dixit /* Avoid ILLEGAL_SUBCOMMAND "mailbox access failed" warning in snb_pcode_read */ 2913d0f98faSAshutosh Dixit if (IS_DG1(i915) || IS_DG2(i915)) 2923d0f98faSAshutosh Dixit return -ENXIO; 2933d0f98faSAshutosh Dixit 294c8939848SAshutosh Dixit return snb_pcode_read_p(&i915->uncore, PCODE_POWER_SETUP, 295c8939848SAshutosh Dixit POWER_SETUP_SUBCOMMAND_READ_I1, 0, uval); 296c8939848SAshutosh Dixit } 297c8939848SAshutosh Dixit 298c8939848SAshutosh Dixit static int hwm_pcode_write_i1(struct drm_i915_private *i915, u32 uval) 299c8939848SAshutosh Dixit { 300c8939848SAshutosh Dixit return snb_pcode_write_p(&i915->uncore, PCODE_POWER_SETUP, 301c8939848SAshutosh Dixit POWER_SETUP_SUBCOMMAND_WRITE_I1, 0, uval); 302c8939848SAshutosh Dixit } 303c8939848SAshutosh Dixit 304b3b088e2SDale B Stimson static umode_t 305f8572bb6SRiana Tauro hwm_in_is_visible(const struct hwm_drvdata *ddat, u32 attr) 306f8572bb6SRiana Tauro { 307f8572bb6SRiana Tauro struct drm_i915_private *i915 = ddat->uncore->i915; 308f8572bb6SRiana Tauro 309f8572bb6SRiana Tauro switch (attr) { 310f8572bb6SRiana Tauro case hwmon_in_input: 311f8572bb6SRiana Tauro return IS_DG1(i915) || IS_DG2(i915) ? 0444 : 0; 312f8572bb6SRiana Tauro default: 313f8572bb6SRiana Tauro return 0; 314f8572bb6SRiana Tauro } 315f8572bb6SRiana Tauro } 316f8572bb6SRiana Tauro 317f8572bb6SRiana Tauro static int 318f8572bb6SRiana Tauro hwm_in_read(struct hwm_drvdata *ddat, u32 attr, long *val) 319f8572bb6SRiana Tauro { 320f8572bb6SRiana Tauro struct i915_hwmon *hwmon = ddat->hwmon; 321f8572bb6SRiana Tauro intel_wakeref_t wakeref; 322f8572bb6SRiana Tauro u32 reg_value; 323f8572bb6SRiana Tauro 324f8572bb6SRiana Tauro switch (attr) { 325f8572bb6SRiana Tauro case hwmon_in_input: 326f8572bb6SRiana Tauro with_intel_runtime_pm(ddat->uncore->rpm, wakeref) 327f8572bb6SRiana Tauro reg_value = intel_uncore_read(ddat->uncore, hwmon->rg.gt_perf_status); 328f8572bb6SRiana Tauro /* HW register value in units of 2.5 millivolt */ 329f8572bb6SRiana Tauro *val = DIV_ROUND_CLOSEST(REG_FIELD_GET(GEN12_VOLTAGE_MASK, reg_value) * 25, 10); 330f8572bb6SRiana Tauro return 0; 331f8572bb6SRiana Tauro default: 332f8572bb6SRiana Tauro return -EOPNOTSUPP; 333f8572bb6SRiana Tauro } 334f8572bb6SRiana Tauro } 335f8572bb6SRiana Tauro 336f8572bb6SRiana Tauro static umode_t 33799f55efbSDale B Stimson hwm_power_is_visible(const struct hwm_drvdata *ddat, u32 attr, int chan) 33899f55efbSDale B Stimson { 339c8939848SAshutosh Dixit struct drm_i915_private *i915 = ddat->uncore->i915; 34099f55efbSDale B Stimson struct i915_hwmon *hwmon = ddat->hwmon; 341c8939848SAshutosh Dixit u32 uval; 34299f55efbSDale B Stimson 34399f55efbSDale B Stimson switch (attr) { 34499f55efbSDale B Stimson case hwmon_power_max: 34599f55efbSDale B Stimson return i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit) ? 0664 : 0; 34699f55efbSDale B Stimson case hwmon_power_rated_max: 34799f55efbSDale B Stimson return i915_mmio_reg_valid(hwmon->rg.pkg_power_sku) ? 0444 : 0; 348c8939848SAshutosh Dixit case hwmon_power_crit: 349c8939848SAshutosh Dixit return (hwm_pcode_read_i1(i915, &uval) || 350c8939848SAshutosh Dixit !(uval & POWER_SETUP_I1_WATTS)) ? 0 : 0644; 35199f55efbSDale B Stimson default: 35299f55efbSDale B Stimson return 0; 35399f55efbSDale B Stimson } 35499f55efbSDale B Stimson } 35599f55efbSDale B Stimson 3564ed22f1eSAshutosh Dixit #define PL1_DISABLE 0 3574ed22f1eSAshutosh Dixit 358d2c3c8c3SAshutosh Dixit /* 359d2c3c8c3SAshutosh Dixit * HW allows arbitrary PL1 limits to be set but silently clamps these values to 360d2c3c8c3SAshutosh Dixit * "typical but not guaranteed" min/max values in rg.pkg_power_sku. Follow the 361d2c3c8c3SAshutosh Dixit * same pattern for sysfs, allow arbitrary PL1 limits to be set but display 362d2c3c8c3SAshutosh Dixit * clamped values when read. Write/read I1 also follows the same pattern. 363d2c3c8c3SAshutosh Dixit */ 364d2c3c8c3SAshutosh Dixit static int 365d2c3c8c3SAshutosh Dixit hwm_power_max_read(struct hwm_drvdata *ddat, long *val) 366d2c3c8c3SAshutosh Dixit { 367d2c3c8c3SAshutosh Dixit struct i915_hwmon *hwmon = ddat->hwmon; 368d2c3c8c3SAshutosh Dixit intel_wakeref_t wakeref; 369d2c3c8c3SAshutosh Dixit u64 r, min, max; 370d2c3c8c3SAshutosh Dixit 3714ed22f1eSAshutosh Dixit /* Check if PL1 limit is disabled */ 3724ed22f1eSAshutosh Dixit with_intel_runtime_pm(ddat->uncore->rpm, wakeref) 3734ed22f1eSAshutosh Dixit r = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit); 3744ed22f1eSAshutosh Dixit if (!(r & PKG_PWR_LIM_1_EN)) { 3754ed22f1eSAshutosh Dixit *val = PL1_DISABLE; 3764ed22f1eSAshutosh Dixit return 0; 3774ed22f1eSAshutosh Dixit } 3784ed22f1eSAshutosh Dixit 379d2c3c8c3SAshutosh Dixit *val = hwm_field_read_and_scale(ddat, 380d2c3c8c3SAshutosh Dixit hwmon->rg.pkg_rapl_limit, 381d2c3c8c3SAshutosh Dixit PKG_PWR_LIM_1, 382d2c3c8c3SAshutosh Dixit hwmon->scl_shift_power, 383d2c3c8c3SAshutosh Dixit SF_POWER); 384d2c3c8c3SAshutosh Dixit 385d2c3c8c3SAshutosh Dixit with_intel_runtime_pm(ddat->uncore->rpm, wakeref) 386d2c3c8c3SAshutosh Dixit r = intel_uncore_read64(ddat->uncore, hwmon->rg.pkg_power_sku); 387d2c3c8c3SAshutosh Dixit min = REG_FIELD_GET(PKG_MIN_PWR, r); 388d2c3c8c3SAshutosh Dixit min = mul_u64_u32_shr(min, SF_POWER, hwmon->scl_shift_power); 389d2c3c8c3SAshutosh Dixit max = REG_FIELD_GET(PKG_MAX_PWR, r); 390d2c3c8c3SAshutosh Dixit max = mul_u64_u32_shr(max, SF_POWER, hwmon->scl_shift_power); 391d2c3c8c3SAshutosh Dixit 392d2c3c8c3SAshutosh Dixit if (min && max) 393d2c3c8c3SAshutosh Dixit *val = clamp_t(u64, *val, min, max); 394d2c3c8c3SAshutosh Dixit 395d2c3c8c3SAshutosh Dixit return 0; 396d2c3c8c3SAshutosh Dixit } 397d2c3c8c3SAshutosh Dixit 39899f55efbSDale B Stimson static int 399f9992638SAshutosh Dixit hwm_power_max_write(struct hwm_drvdata *ddat, long val) 400f9992638SAshutosh Dixit { 401f9992638SAshutosh Dixit struct i915_hwmon *hwmon = ddat->hwmon; 4024ed22f1eSAshutosh Dixit intel_wakeref_t wakeref; 403655bd3b9SAshutosh Dixit DEFINE_WAIT(wait); 404d81268eeSAshutosh Dixit int ret = 0; 405f9992638SAshutosh Dixit u32 nval; 406f9992638SAshutosh Dixit 407655bd3b9SAshutosh Dixit /* Block waiting for GuC reset to complete when needed */ 408655bd3b9SAshutosh Dixit for (;;) { 40971b21877SJanusz Krzysztofik wakeref = intel_runtime_pm_get(ddat->uncore->rpm); 410d81268eeSAshutosh Dixit mutex_lock(&hwmon->hwmon_lock); 411655bd3b9SAshutosh Dixit 412655bd3b9SAshutosh Dixit prepare_to_wait(&ddat->waitq, &wait, TASK_INTERRUPTIBLE); 413655bd3b9SAshutosh Dixit 414655bd3b9SAshutosh Dixit if (!hwmon->ddat.reset_in_progress) 415655bd3b9SAshutosh Dixit break; 416655bd3b9SAshutosh Dixit 417655bd3b9SAshutosh Dixit if (signal_pending(current)) { 418655bd3b9SAshutosh Dixit ret = -EINTR; 419655bd3b9SAshutosh Dixit break; 4201b44019aSAshutosh Dixit } 421655bd3b9SAshutosh Dixit 422655bd3b9SAshutosh Dixit mutex_unlock(&hwmon->hwmon_lock); 42371b21877SJanusz Krzysztofik intel_runtime_pm_put(ddat->uncore->rpm, wakeref); 424655bd3b9SAshutosh Dixit 425655bd3b9SAshutosh Dixit schedule(); 426655bd3b9SAshutosh Dixit } 427655bd3b9SAshutosh Dixit finish_wait(&ddat->waitq, &wait); 428655bd3b9SAshutosh Dixit if (ret) 42971b21877SJanusz Krzysztofik goto exit; 430d81268eeSAshutosh Dixit 4314ed22f1eSAshutosh Dixit /* Disable PL1 limit and verify, because the limit cannot be disabled on all platforms */ 4324ed22f1eSAshutosh Dixit if (val == PL1_DISABLE) { 4334ed22f1eSAshutosh Dixit intel_uncore_rmw(ddat->uncore, hwmon->rg.pkg_rapl_limit, 4344ed22f1eSAshutosh Dixit PKG_PWR_LIM_1_EN, 0); 4354ed22f1eSAshutosh Dixit nval = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit); 4364ed22f1eSAshutosh Dixit 4374ed22f1eSAshutosh Dixit if (nval & PKG_PWR_LIM_1_EN) 438d81268eeSAshutosh Dixit ret = -ENODEV; 439d81268eeSAshutosh Dixit goto exit; 4404ed22f1eSAshutosh Dixit } 4414ed22f1eSAshutosh Dixit 442f9992638SAshutosh Dixit /* Computation in 64-bits to avoid overflow. Round to nearest. */ 443f9992638SAshutosh Dixit nval = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_power, SF_POWER); 4446fd3d8bfSAshutosh Dixit nval = PKG_PWR_LIM_1_EN | REG_FIELD_PREP(PKG_PWR_LIM_1, nval); 445f9992638SAshutosh Dixit 446d81268eeSAshutosh Dixit intel_uncore_rmw(ddat->uncore, hwmon->rg.pkg_rapl_limit, 447d81268eeSAshutosh Dixit PKG_PWR_LIM_1_EN | PKG_PWR_LIM_1, nval); 448d81268eeSAshutosh Dixit exit: 449d81268eeSAshutosh Dixit mutex_unlock(&hwmon->hwmon_lock); 45071b21877SJanusz Krzysztofik intel_runtime_pm_put(ddat->uncore->rpm, wakeref); 451d81268eeSAshutosh Dixit return ret; 452f9992638SAshutosh Dixit } 453f9992638SAshutosh Dixit 454f9992638SAshutosh Dixit static int 45599f55efbSDale B Stimson hwm_power_read(struct hwm_drvdata *ddat, u32 attr, int chan, long *val) 45699f55efbSDale B Stimson { 45799f55efbSDale B Stimson struct i915_hwmon *hwmon = ddat->hwmon; 458c8939848SAshutosh Dixit int ret; 459c8939848SAshutosh Dixit u32 uval; 46099f55efbSDale B Stimson 46199f55efbSDale B Stimson switch (attr) { 46299f55efbSDale B Stimson case hwmon_power_max: 463d2c3c8c3SAshutosh Dixit return hwm_power_max_read(ddat, val); 46499f55efbSDale B Stimson case hwmon_power_rated_max: 46599f55efbSDale B Stimson *val = hwm_field_read_and_scale(ddat, 46699f55efbSDale B Stimson hwmon->rg.pkg_power_sku, 46799f55efbSDale B Stimson PKG_PKG_TDP, 46899f55efbSDale B Stimson hwmon->scl_shift_power, 46999f55efbSDale B Stimson SF_POWER); 47099f55efbSDale B Stimson return 0; 471c8939848SAshutosh Dixit case hwmon_power_crit: 472c8939848SAshutosh Dixit ret = hwm_pcode_read_i1(ddat->uncore->i915, &uval); 473c8939848SAshutosh Dixit if (ret) 474c8939848SAshutosh Dixit return ret; 475c8939848SAshutosh Dixit if (!(uval & POWER_SETUP_I1_WATTS)) 476c8939848SAshutosh Dixit return -ENODEV; 477c8939848SAshutosh Dixit *val = mul_u64_u32_shr(REG_FIELD_GET(POWER_SETUP_I1_DATA_MASK, uval), 478c8939848SAshutosh Dixit SF_POWER, POWER_SETUP_I1_SHIFT); 479c8939848SAshutosh Dixit return 0; 48099f55efbSDale B Stimson default: 48199f55efbSDale B Stimson return -EOPNOTSUPP; 48299f55efbSDale B Stimson } 48399f55efbSDale B Stimson } 48499f55efbSDale B Stimson 48599f55efbSDale B Stimson static int 48699f55efbSDale B Stimson hwm_power_write(struct hwm_drvdata *ddat, u32 attr, int chan, long val) 48799f55efbSDale B Stimson { 488c8939848SAshutosh Dixit u32 uval; 48999f55efbSDale B Stimson 49099f55efbSDale B Stimson switch (attr) { 49199f55efbSDale B Stimson case hwmon_power_max: 492f9992638SAshutosh Dixit return hwm_power_max_write(ddat, val); 493c8939848SAshutosh Dixit case hwmon_power_crit: 494c8939848SAshutosh Dixit uval = DIV_ROUND_CLOSEST_ULL(val << POWER_SETUP_I1_SHIFT, SF_POWER); 495c8939848SAshutosh Dixit return hwm_pcode_write_i1(ddat->uncore->i915, uval); 49699f55efbSDale B Stimson default: 49799f55efbSDale B Stimson return -EOPNOTSUPP; 49899f55efbSDale B Stimson } 49999f55efbSDale B Stimson } 50099f55efbSDale B Stimson 5011b44019aSAshutosh Dixit void i915_hwmon_power_max_disable(struct drm_i915_private *i915, bool *old) 5021b44019aSAshutosh Dixit { 5031b44019aSAshutosh Dixit struct i915_hwmon *hwmon = i915->hwmon; 5041b44019aSAshutosh Dixit u32 r; 5051b44019aSAshutosh Dixit 5061b44019aSAshutosh Dixit if (!hwmon || !i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit)) 5071b44019aSAshutosh Dixit return; 5081b44019aSAshutosh Dixit 5091b44019aSAshutosh Dixit mutex_lock(&hwmon->hwmon_lock); 5101b44019aSAshutosh Dixit 5111b44019aSAshutosh Dixit hwmon->ddat.reset_in_progress = true; 5121b44019aSAshutosh Dixit r = intel_uncore_rmw(hwmon->ddat.uncore, hwmon->rg.pkg_rapl_limit, 5131b44019aSAshutosh Dixit PKG_PWR_LIM_1_EN, 0); 5141b44019aSAshutosh Dixit *old = !!(r & PKG_PWR_LIM_1_EN); 5151b44019aSAshutosh Dixit 5161b44019aSAshutosh Dixit mutex_unlock(&hwmon->hwmon_lock); 5171b44019aSAshutosh Dixit } 5181b44019aSAshutosh Dixit 5191b44019aSAshutosh Dixit void i915_hwmon_power_max_restore(struct drm_i915_private *i915, bool old) 5201b44019aSAshutosh Dixit { 5211b44019aSAshutosh Dixit struct i915_hwmon *hwmon = i915->hwmon; 5221b44019aSAshutosh Dixit 5231b44019aSAshutosh Dixit if (!hwmon || !i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit)) 5241b44019aSAshutosh Dixit return; 5251b44019aSAshutosh Dixit 5261b44019aSAshutosh Dixit mutex_lock(&hwmon->hwmon_lock); 5271b44019aSAshutosh Dixit 5281b44019aSAshutosh Dixit intel_uncore_rmw(hwmon->ddat.uncore, hwmon->rg.pkg_rapl_limit, 5291b44019aSAshutosh Dixit PKG_PWR_LIM_1_EN, old ? PKG_PWR_LIM_1_EN : 0); 5301b44019aSAshutosh Dixit hwmon->ddat.reset_in_progress = false; 531655bd3b9SAshutosh Dixit wake_up_all(&hwmon->ddat.waitq); 5321b44019aSAshutosh Dixit 5331b44019aSAshutosh Dixit mutex_unlock(&hwmon->hwmon_lock); 5341b44019aSAshutosh Dixit } 5351b44019aSAshutosh Dixit 53699f55efbSDale B Stimson static umode_t 537c41b8bdcSDale B Stimson hwm_energy_is_visible(const struct hwm_drvdata *ddat, u32 attr) 538c41b8bdcSDale B Stimson { 539c41b8bdcSDale B Stimson struct i915_hwmon *hwmon = ddat->hwmon; 540c41b8bdcSDale B Stimson i915_reg_t rgaddr; 541c41b8bdcSDale B Stimson 542c41b8bdcSDale B Stimson switch (attr) { 543c41b8bdcSDale B Stimson case hwmon_energy_input: 544a6a924abSDale B Stimson if (ddat->gt_n >= 0) 545a6a924abSDale B Stimson rgaddr = hwmon->rg.energy_status_tile; 546a6a924abSDale B Stimson else 547c41b8bdcSDale B Stimson rgaddr = hwmon->rg.energy_status_all; 548c41b8bdcSDale B Stimson return i915_mmio_reg_valid(rgaddr) ? 0444 : 0; 549c41b8bdcSDale B Stimson default: 550c41b8bdcSDale B Stimson return 0; 551c41b8bdcSDale B Stimson } 552c41b8bdcSDale B Stimson } 553c41b8bdcSDale B Stimson 554c41b8bdcSDale B Stimson static int 555c41b8bdcSDale B Stimson hwm_energy_read(struct hwm_drvdata *ddat, u32 attr, long *val) 556c41b8bdcSDale B Stimson { 557c41b8bdcSDale B Stimson switch (attr) { 558c41b8bdcSDale B Stimson case hwmon_energy_input: 559c41b8bdcSDale B Stimson hwm_energy(ddat, val); 560c41b8bdcSDale B Stimson return 0; 561c41b8bdcSDale B Stimson default: 562c41b8bdcSDale B Stimson return -EOPNOTSUPP; 563c41b8bdcSDale B Stimson } 564c41b8bdcSDale B Stimson } 565c41b8bdcSDale B Stimson 566c41b8bdcSDale B Stimson static umode_t 567c8939848SAshutosh Dixit hwm_curr_is_visible(const struct hwm_drvdata *ddat, u32 attr) 568c8939848SAshutosh Dixit { 569c8939848SAshutosh Dixit struct drm_i915_private *i915 = ddat->uncore->i915; 570c8939848SAshutosh Dixit u32 uval; 571c8939848SAshutosh Dixit 572c8939848SAshutosh Dixit switch (attr) { 573c8939848SAshutosh Dixit case hwmon_curr_crit: 574c8939848SAshutosh Dixit return (hwm_pcode_read_i1(i915, &uval) || 575c8939848SAshutosh Dixit (uval & POWER_SETUP_I1_WATTS)) ? 0 : 0644; 576c8939848SAshutosh Dixit default: 577c8939848SAshutosh Dixit return 0; 578c8939848SAshutosh Dixit } 579c8939848SAshutosh Dixit } 580c8939848SAshutosh Dixit 581c8939848SAshutosh Dixit static int 582c8939848SAshutosh Dixit hwm_curr_read(struct hwm_drvdata *ddat, u32 attr, long *val) 583c8939848SAshutosh Dixit { 584c8939848SAshutosh Dixit int ret; 585c8939848SAshutosh Dixit u32 uval; 586c8939848SAshutosh Dixit 587c8939848SAshutosh Dixit switch (attr) { 588c8939848SAshutosh Dixit case hwmon_curr_crit: 589c8939848SAshutosh Dixit ret = hwm_pcode_read_i1(ddat->uncore->i915, &uval); 590c8939848SAshutosh Dixit if (ret) 591c8939848SAshutosh Dixit return ret; 592c8939848SAshutosh Dixit if (uval & POWER_SETUP_I1_WATTS) 593c8939848SAshutosh Dixit return -ENODEV; 594c8939848SAshutosh Dixit *val = mul_u64_u32_shr(REG_FIELD_GET(POWER_SETUP_I1_DATA_MASK, uval), 595c8939848SAshutosh Dixit SF_CURR, POWER_SETUP_I1_SHIFT); 596c8939848SAshutosh Dixit return 0; 597c8939848SAshutosh Dixit default: 598c8939848SAshutosh Dixit return -EOPNOTSUPP; 599c8939848SAshutosh Dixit } 600c8939848SAshutosh Dixit } 601c8939848SAshutosh Dixit 602c8939848SAshutosh Dixit static int 603c8939848SAshutosh Dixit hwm_curr_write(struct hwm_drvdata *ddat, u32 attr, long val) 604c8939848SAshutosh Dixit { 605c8939848SAshutosh Dixit u32 uval; 606c8939848SAshutosh Dixit 607c8939848SAshutosh Dixit switch (attr) { 608c8939848SAshutosh Dixit case hwmon_curr_crit: 609c8939848SAshutosh Dixit uval = DIV_ROUND_CLOSEST_ULL(val << POWER_SETUP_I1_SHIFT, SF_CURR); 610c8939848SAshutosh Dixit return hwm_pcode_write_i1(ddat->uncore->i915, uval); 611c8939848SAshutosh Dixit default: 612c8939848SAshutosh Dixit return -EOPNOTSUPP; 613c8939848SAshutosh Dixit } 614c8939848SAshutosh Dixit } 615c8939848SAshutosh Dixit 616c8939848SAshutosh Dixit static umode_t 617b3b088e2SDale B Stimson hwm_is_visible(const void *drvdata, enum hwmon_sensor_types type, 618b3b088e2SDale B Stimson u32 attr, int channel) 619b3b088e2SDale B Stimson { 620f8572bb6SRiana Tauro struct hwm_drvdata *ddat = (struct hwm_drvdata *)drvdata; 621f8572bb6SRiana Tauro 622b3b088e2SDale B Stimson switch (type) { 623f8572bb6SRiana Tauro case hwmon_in: 624f8572bb6SRiana Tauro return hwm_in_is_visible(ddat, attr); 62599f55efbSDale B Stimson case hwmon_power: 62699f55efbSDale B Stimson return hwm_power_is_visible(ddat, attr, channel); 627c41b8bdcSDale B Stimson case hwmon_energy: 628c41b8bdcSDale B Stimson return hwm_energy_is_visible(ddat, attr); 629c8939848SAshutosh Dixit case hwmon_curr: 630c8939848SAshutosh Dixit return hwm_curr_is_visible(ddat, attr); 631b3b088e2SDale B Stimson default: 632b3b088e2SDale B Stimson return 0; 633b3b088e2SDale B Stimson } 634b3b088e2SDale B Stimson } 635b3b088e2SDale B Stimson 636b3b088e2SDale B Stimson static int 637b3b088e2SDale B Stimson hwm_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, 638b3b088e2SDale B Stimson int channel, long *val) 639b3b088e2SDale B Stimson { 640f8572bb6SRiana Tauro struct hwm_drvdata *ddat = dev_get_drvdata(dev); 641f8572bb6SRiana Tauro 642b3b088e2SDale B Stimson switch (type) { 643f8572bb6SRiana Tauro case hwmon_in: 644f8572bb6SRiana Tauro return hwm_in_read(ddat, attr, val); 64599f55efbSDale B Stimson case hwmon_power: 64699f55efbSDale B Stimson return hwm_power_read(ddat, attr, channel, val); 647c41b8bdcSDale B Stimson case hwmon_energy: 648c41b8bdcSDale B Stimson return hwm_energy_read(ddat, attr, val); 649c8939848SAshutosh Dixit case hwmon_curr: 650c8939848SAshutosh Dixit return hwm_curr_read(ddat, attr, val); 651b3b088e2SDale B Stimson default: 652b3b088e2SDale B Stimson return -EOPNOTSUPP; 653b3b088e2SDale B Stimson } 654b3b088e2SDale B Stimson } 655b3b088e2SDale B Stimson 656b3b088e2SDale B Stimson static int 657b3b088e2SDale B Stimson hwm_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, 658b3b088e2SDale B Stimson int channel, long val) 659b3b088e2SDale B Stimson { 66099f55efbSDale B Stimson struct hwm_drvdata *ddat = dev_get_drvdata(dev); 66199f55efbSDale B Stimson 662b3b088e2SDale B Stimson switch (type) { 66399f55efbSDale B Stimson case hwmon_power: 66499f55efbSDale B Stimson return hwm_power_write(ddat, attr, channel, val); 665c8939848SAshutosh Dixit case hwmon_curr: 666c8939848SAshutosh Dixit return hwm_curr_write(ddat, attr, val); 667b3b088e2SDale B Stimson default: 668b3b088e2SDale B Stimson return -EOPNOTSUPP; 669b3b088e2SDale B Stimson } 670b3b088e2SDale B Stimson } 671b3b088e2SDale B Stimson 672b3b088e2SDale B Stimson static const struct hwmon_ops hwm_ops = { 673b3b088e2SDale B Stimson .is_visible = hwm_is_visible, 674b3b088e2SDale B Stimson .read = hwm_read, 675b3b088e2SDale B Stimson .write = hwm_write, 676b3b088e2SDale B Stimson }; 677b3b088e2SDale B Stimson 678b3b088e2SDale B Stimson static const struct hwmon_chip_info hwm_chip_info = { 679b3b088e2SDale B Stimson .ops = &hwm_ops, 680b3b088e2SDale B Stimson .info = hwm_info, 681b3b088e2SDale B Stimson }; 682b3b088e2SDale B Stimson 683a6a924abSDale B Stimson static umode_t 684a6a924abSDale B Stimson hwm_gt_is_visible(const void *drvdata, enum hwmon_sensor_types type, 685a6a924abSDale B Stimson u32 attr, int channel) 686a6a924abSDale B Stimson { 687a6a924abSDale B Stimson struct hwm_drvdata *ddat = (struct hwm_drvdata *)drvdata; 688a6a924abSDale B Stimson 689a6a924abSDale B Stimson switch (type) { 690a6a924abSDale B Stimson case hwmon_energy: 691a6a924abSDale B Stimson return hwm_energy_is_visible(ddat, attr); 692a6a924abSDale B Stimson default: 693a6a924abSDale B Stimson return 0; 694a6a924abSDale B Stimson } 695a6a924abSDale B Stimson } 696a6a924abSDale B Stimson 697a6a924abSDale B Stimson static int 698a6a924abSDale B Stimson hwm_gt_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, 699a6a924abSDale B Stimson int channel, long *val) 700a6a924abSDale B Stimson { 701a6a924abSDale B Stimson struct hwm_drvdata *ddat = dev_get_drvdata(dev); 702a6a924abSDale B Stimson 703a6a924abSDale B Stimson switch (type) { 704a6a924abSDale B Stimson case hwmon_energy: 705a6a924abSDale B Stimson return hwm_energy_read(ddat, attr, val); 706a6a924abSDale B Stimson default: 707a6a924abSDale B Stimson return -EOPNOTSUPP; 708a6a924abSDale B Stimson } 709a6a924abSDale B Stimson } 710a6a924abSDale B Stimson 711a6a924abSDale B Stimson static const struct hwmon_ops hwm_gt_ops = { 712a6a924abSDale B Stimson .is_visible = hwm_gt_is_visible, 713a6a924abSDale B Stimson .read = hwm_gt_read, 714a6a924abSDale B Stimson }; 715a6a924abSDale B Stimson 716a6a924abSDale B Stimson static const struct hwmon_chip_info hwm_gt_chip_info = { 717a6a924abSDale B Stimson .ops = &hwm_gt_ops, 718a6a924abSDale B Stimson .info = hwm_gt_info, 719a6a924abSDale B Stimson }; 720a6a924abSDale B Stimson 721b3b088e2SDale B Stimson static void 722b3b088e2SDale B Stimson hwm_get_preregistration_info(struct drm_i915_private *i915) 723b3b088e2SDale B Stimson { 724f8572bb6SRiana Tauro struct i915_hwmon *hwmon = i915->hwmon; 72599f55efbSDale B Stimson struct intel_uncore *uncore = &i915->uncore; 726c41b8bdcSDale B Stimson struct hwm_drvdata *ddat = &hwmon->ddat; 72799f55efbSDale B Stimson intel_wakeref_t wakeref; 72899f55efbSDale B Stimson u32 val_sku_unit = 0; 729a6a924abSDale B Stimson struct intel_gt *gt; 730c41b8bdcSDale B Stimson long energy; 731a6a924abSDale B Stimson int i; 732f8572bb6SRiana Tauro 733f8572bb6SRiana Tauro /* Available for all Gen12+/dGfx */ 734f8572bb6SRiana Tauro hwmon->rg.gt_perf_status = GEN12_RPSTAT1; 73599f55efbSDale B Stimson 73699f55efbSDale B Stimson if (IS_DG1(i915) || IS_DG2(i915)) { 73799f55efbSDale B Stimson hwmon->rg.pkg_power_sku_unit = PCU_PACKAGE_POWER_SKU_UNIT; 73899f55efbSDale B Stimson hwmon->rg.pkg_power_sku = PCU_PACKAGE_POWER_SKU; 73999f55efbSDale B Stimson hwmon->rg.pkg_rapl_limit = PCU_PACKAGE_RAPL_LIMIT; 740c41b8bdcSDale B Stimson hwmon->rg.energy_status_all = PCU_PACKAGE_ENERGY_STATUS; 741a6a924abSDale B Stimson hwmon->rg.energy_status_tile = INVALID_MMIO_REG; 74299f55efbSDale B Stimson } else { 74399f55efbSDale B Stimson hwmon->rg.pkg_power_sku_unit = INVALID_MMIO_REG; 74499f55efbSDale B Stimson hwmon->rg.pkg_power_sku = INVALID_MMIO_REG; 74599f55efbSDale B Stimson hwmon->rg.pkg_rapl_limit = INVALID_MMIO_REG; 746c41b8bdcSDale B Stimson hwmon->rg.energy_status_all = INVALID_MMIO_REG; 747a6a924abSDale B Stimson hwmon->rg.energy_status_tile = INVALID_MMIO_REG; 74899f55efbSDale B Stimson } 74999f55efbSDale B Stimson 75099f55efbSDale B Stimson with_intel_runtime_pm(uncore->rpm, wakeref) { 75199f55efbSDale B Stimson /* 75299f55efbSDale B Stimson * The contents of register hwmon->rg.pkg_power_sku_unit do not change, 75399f55efbSDale B Stimson * so read it once and store the shift values. 75499f55efbSDale B Stimson */ 75599f55efbSDale B Stimson if (i915_mmio_reg_valid(hwmon->rg.pkg_power_sku_unit)) 75699f55efbSDale B Stimson val_sku_unit = intel_uncore_read(uncore, 75799f55efbSDale B Stimson hwmon->rg.pkg_power_sku_unit); 758c41b8bdcSDale B Stimson } 75999f55efbSDale B Stimson 76099f55efbSDale B Stimson hwmon->scl_shift_power = REG_FIELD_GET(PKG_PWR_UNIT, val_sku_unit); 761c41b8bdcSDale B Stimson hwmon->scl_shift_energy = REG_FIELD_GET(PKG_ENERGY_UNIT, val_sku_unit); 7624c2572feSAshutosh Dixit hwmon->scl_shift_time = REG_FIELD_GET(PKG_TIME_UNIT, val_sku_unit); 763c41b8bdcSDale B Stimson 764c41b8bdcSDale B Stimson /* 765c41b8bdcSDale B Stimson * Initialize 'struct hwm_energy_info', i.e. set fields to the 766c41b8bdcSDale B Stimson * first value of the energy register read 767c41b8bdcSDale B Stimson */ 768c41b8bdcSDale B Stimson if (i915_mmio_reg_valid(hwmon->rg.energy_status_all)) 769c41b8bdcSDale B Stimson hwm_energy(ddat, &energy); 770a6a924abSDale B Stimson if (i915_mmio_reg_valid(hwmon->rg.energy_status_tile)) { 771a6a924abSDale B Stimson for_each_gt(gt, i915, i) 772a6a924abSDale B Stimson hwm_energy(&hwmon->ddat_gt[i], &energy); 773a6a924abSDale B Stimson } 774b3b088e2SDale B Stimson } 775b3b088e2SDale B Stimson 776b3b088e2SDale B Stimson void i915_hwmon_register(struct drm_i915_private *i915) 777b3b088e2SDale B Stimson { 778b3b088e2SDale B Stimson struct device *dev = i915->drm.dev; 779b3b088e2SDale B Stimson struct i915_hwmon *hwmon; 780b3b088e2SDale B Stimson struct device *hwmon_dev; 781b3b088e2SDale B Stimson struct hwm_drvdata *ddat; 782a6a924abSDale B Stimson struct hwm_drvdata *ddat_gt; 783a6a924abSDale B Stimson struct intel_gt *gt; 784a6a924abSDale B Stimson int i; 785b3b088e2SDale B Stimson 786b3b088e2SDale B Stimson /* hwmon is available only for dGfx */ 787b3b088e2SDale B Stimson if (!IS_DGFX(i915)) 788b3b088e2SDale B Stimson return; 789b3b088e2SDale B Stimson 790*5bc9de06SAshutosh Dixit hwmon = kzalloc(sizeof(*hwmon), GFP_KERNEL); 791b3b088e2SDale B Stimson if (!hwmon) 792b3b088e2SDale B Stimson return; 793b3b088e2SDale B Stimson 794b3b088e2SDale B Stimson i915->hwmon = hwmon; 795b3b088e2SDale B Stimson mutex_init(&hwmon->hwmon_lock); 796b3b088e2SDale B Stimson ddat = &hwmon->ddat; 797b3b088e2SDale B Stimson 798b3b088e2SDale B Stimson ddat->hwmon = hwmon; 799b3b088e2SDale B Stimson ddat->uncore = &i915->uncore; 800b3b088e2SDale B Stimson snprintf(ddat->name, sizeof(ddat->name), "i915"); 801a6a924abSDale B Stimson ddat->gt_n = -1; 802655bd3b9SAshutosh Dixit init_waitqueue_head(&ddat->waitq); 803a6a924abSDale B Stimson 804a6a924abSDale B Stimson for_each_gt(gt, i915, i) { 805a6a924abSDale B Stimson ddat_gt = hwmon->ddat_gt + i; 806a6a924abSDale B Stimson 807a6a924abSDale B Stimson ddat_gt->hwmon = hwmon; 808a6a924abSDale B Stimson ddat_gt->uncore = gt->uncore; 809a6a924abSDale B Stimson snprintf(ddat_gt->name, sizeof(ddat_gt->name), "i915_gt%u", i); 810a6a924abSDale B Stimson ddat_gt->gt_n = i; 811a6a924abSDale B Stimson } 812b3b088e2SDale B Stimson 813b3b088e2SDale B Stimson hwm_get_preregistration_info(i915); 814b3b088e2SDale B Stimson 815b3b088e2SDale B Stimson /* hwmon_dev points to device hwmon<i> */ 816*5bc9de06SAshutosh Dixit hwmon_dev = hwmon_device_register_with_info(dev, ddat->name, 817b3b088e2SDale B Stimson ddat, 818b3b088e2SDale B Stimson &hwm_chip_info, 8194c2572feSAshutosh Dixit hwm_groups); 820*5bc9de06SAshutosh Dixit if (IS_ERR(hwmon_dev)) 821*5bc9de06SAshutosh Dixit goto err; 822b3b088e2SDale B Stimson 823b3b088e2SDale B Stimson ddat->hwmon_dev = hwmon_dev; 824a6a924abSDale B Stimson 825a6a924abSDale B Stimson for_each_gt(gt, i915, i) { 826a6a924abSDale B Stimson ddat_gt = hwmon->ddat_gt + i; 827a6a924abSDale B Stimson /* 828a6a924abSDale B Stimson * Create per-gt directories only if a per-gt attribute is 829a6a924abSDale B Stimson * visible. Currently this is only energy 830a6a924abSDale B Stimson */ 831a6a924abSDale B Stimson if (!hwm_gt_is_visible(ddat_gt, hwmon_energy, hwmon_energy_input, 0)) 832a6a924abSDale B Stimson continue; 833a6a924abSDale B Stimson 834*5bc9de06SAshutosh Dixit hwmon_dev = hwmon_device_register_with_info(dev, ddat_gt->name, 835a6a924abSDale B Stimson ddat_gt, 836a6a924abSDale B Stimson &hwm_gt_chip_info, 837a6a924abSDale B Stimson NULL); 838a6a924abSDale B Stimson if (!IS_ERR(hwmon_dev)) 839a6a924abSDale B Stimson ddat_gt->hwmon_dev = hwmon_dev; 840a6a924abSDale B Stimson } 841*5bc9de06SAshutosh Dixit return; 842*5bc9de06SAshutosh Dixit err: 843*5bc9de06SAshutosh Dixit i915_hwmon_unregister(i915); 844b3b088e2SDale B Stimson } 845b3b088e2SDale B Stimson 846b3b088e2SDale B Stimson void i915_hwmon_unregister(struct drm_i915_private *i915) 847b3b088e2SDale B Stimson { 848*5bc9de06SAshutosh Dixit struct i915_hwmon *hwmon = i915->hwmon; 849*5bc9de06SAshutosh Dixit struct intel_gt *gt; 850*5bc9de06SAshutosh Dixit int i; 851*5bc9de06SAshutosh Dixit 852*5bc9de06SAshutosh Dixit if (!hwmon) 853*5bc9de06SAshutosh Dixit return; 854*5bc9de06SAshutosh Dixit 855*5bc9de06SAshutosh Dixit for_each_gt(gt, i915, i) 856*5bc9de06SAshutosh Dixit if (hwmon->ddat_gt[i].hwmon_dev) 857*5bc9de06SAshutosh Dixit hwmon_device_unregister(hwmon->ddat_gt[i].hwmon_dev); 858*5bc9de06SAshutosh Dixit 859*5bc9de06SAshutosh Dixit if (hwmon->ddat.hwmon_dev) 860*5bc9de06SAshutosh Dixit hwmon_device_unregister(hwmon->ddat.hwmon_dev); 861*5bc9de06SAshutosh Dixit 862*5bc9de06SAshutosh Dixit mutex_destroy(&hwmon->hwmon_lock); 863*5bc9de06SAshutosh Dixit 864*5bc9de06SAshutosh Dixit kfree(i915->hwmon); 865*5bc9de06SAshutosh Dixit i915->hwmon = NULL; 866b3b088e2SDale B Stimson } 867