1 | // SPDX-License-Identifier: MIT |
2 | /* |
3 | * Copyright © 2022 Intel Corporation |
4 | */ |
5 | |
6 | #include <linux/hwmon.h> |
7 | #include <linux/hwmon-sysfs.h> |
8 | #include <linux/types.h> |
9 | |
10 | #include "i915_drv.h" |
11 | #include "i915_hwmon.h" |
12 | #include "i915_reg.h" |
13 | #include "intel_mchbar_regs.h" |
14 | #include "intel_pcode.h" |
15 | #include "gt/intel_gt.h" |
16 | #include "gt/intel_gt_regs.h" |
17 | |
18 | /* |
19 | * SF_* - scale factors for particular quantities according to hwmon spec. |
20 | * - voltage - millivolts |
21 | * - power - microwatts |
22 | * - curr - milliamperes |
23 | * - energy - microjoules |
24 | * - time - milliseconds |
25 | */ |
26 | #define SF_VOLTAGE 1000 |
27 | #define SF_POWER 1000000 |
28 | #define SF_CURR 1000 |
29 | #define SF_ENERGY 1000000 |
30 | #define SF_TIME 1000 |
31 | |
32 | struct hwm_reg { |
33 | i915_reg_t gt_perf_status; |
34 | i915_reg_t pkg_power_sku_unit; |
35 | i915_reg_t pkg_power_sku; |
36 | i915_reg_t pkg_rapl_limit; |
37 | i915_reg_t energy_status_all; |
38 | i915_reg_t energy_status_tile; |
39 | }; |
40 | |
41 | struct hwm_energy_info { |
42 | u32 reg_val_prev; |
43 | long accum_energy; /* Accumulated energy for energy1_input */ |
44 | }; |
45 | |
46 | struct hwm_drvdata { |
47 | struct i915_hwmon *hwmon; |
48 | struct intel_uncore *uncore; |
49 | struct device *hwmon_dev; |
50 | struct hwm_energy_info ei; /* Energy info for energy1_input */ |
51 | char name[12]; |
52 | int gt_n; |
53 | bool reset_in_progress; |
54 | wait_queue_head_t waitq; |
55 | }; |
56 | |
57 | struct i915_hwmon { |
58 | struct hwm_drvdata ddat; |
59 | struct hwm_drvdata ddat_gt[I915_MAX_GT]; |
60 | struct mutex hwmon_lock; /* counter overflow logic and rmw */ |
61 | struct hwm_reg rg; |
62 | int scl_shift_power; |
63 | int scl_shift_energy; |
64 | int scl_shift_time; |
65 | }; |
66 | |
67 | static void |
68 | hwm_locked_with_pm_intel_uncore_rmw(struct hwm_drvdata *ddat, |
69 | i915_reg_t reg, u32 clear, u32 set) |
70 | { |
71 | struct i915_hwmon *hwmon = ddat->hwmon; |
72 | struct intel_uncore *uncore = ddat->uncore; |
73 | intel_wakeref_t wakeref; |
74 | |
75 | with_intel_runtime_pm(uncore->rpm, wakeref) { |
76 | mutex_lock(&hwmon->hwmon_lock); |
77 | |
78 | intel_uncore_rmw(uncore, reg, clear, set); |
79 | |
80 | mutex_unlock(lock: &hwmon->hwmon_lock); |
81 | } |
82 | } |
83 | |
84 | /* |
85 | * This function's return type of u64 allows for the case where the scaling |
86 | * of the field taken from the 32-bit register value might cause a result to |
87 | * exceed 32 bits. |
88 | */ |
89 | static u64 |
90 | hwm_field_read_and_scale(struct hwm_drvdata *ddat, i915_reg_t rgadr, |
91 | u32 field_msk, int nshift, u32 scale_factor) |
92 | { |
93 | struct intel_uncore *uncore = ddat->uncore; |
94 | intel_wakeref_t wakeref; |
95 | u32 reg_value; |
96 | |
97 | with_intel_runtime_pm(uncore->rpm, wakeref) |
98 | reg_value = intel_uncore_read(uncore, reg: rgadr); |
99 | |
100 | reg_value = REG_FIELD_GET(field_msk, reg_value); |
101 | |
102 | return mul_u64_u32_shr(a: reg_value, mul: scale_factor, shift: nshift); |
103 | } |
104 | |
105 | /* |
106 | * hwm_energy - Obtain energy value |
107 | * |
108 | * The underlying energy hardware register is 32-bits and is subject to |
109 | * overflow. How long before overflow? For example, with an example |
110 | * scaling bit shift of 14 bits (see register *PACKAGE_POWER_SKU_UNIT) and |
111 | * a power draw of 1000 watts, the 32-bit counter will overflow in |
112 | * approximately 4.36 minutes. |
113 | * |
114 | * Examples: |
115 | * 1 watt: (2^32 >> 14) / 1 W / (60 * 60 * 24) secs/day -> 3 days |
116 | * 1000 watts: (2^32 >> 14) / 1000 W / 60 secs/min -> 4.36 minutes |
117 | * |
118 | * The function significantly increases overflow duration (from 4.36 |
119 | * minutes) by accumulating the energy register into a 'long' as allowed by |
120 | * the hwmon API. Using x86_64 128 bit arithmetic (see mul_u64_u32_shr()), |
121 | * a 'long' of 63 bits, SF_ENERGY of 1e6 (~20 bits) and |
122 | * hwmon->scl_shift_energy of 14 bits we have 57 (63 - 20 + 14) bits before |
123 | * energy1_input overflows. This at 1000 W is an overflow duration of 278 years. |
124 | */ |
125 | static void |
126 | hwm_energy(struct hwm_drvdata *ddat, long *energy) |
127 | { |
128 | struct intel_uncore *uncore = ddat->uncore; |
129 | struct i915_hwmon *hwmon = ddat->hwmon; |
130 | struct hwm_energy_info *ei = &ddat->ei; |
131 | intel_wakeref_t wakeref; |
132 | i915_reg_t rgaddr; |
133 | u32 reg_val; |
134 | |
135 | if (ddat->gt_n >= 0) |
136 | rgaddr = hwmon->rg.energy_status_tile; |
137 | else |
138 | rgaddr = hwmon->rg.energy_status_all; |
139 | |
140 | with_intel_runtime_pm(uncore->rpm, wakeref) { |
141 | mutex_lock(&hwmon->hwmon_lock); |
142 | |
143 | reg_val = intel_uncore_read(uncore, reg: rgaddr); |
144 | |
145 | if (reg_val >= ei->reg_val_prev) |
146 | ei->accum_energy += reg_val - ei->reg_val_prev; |
147 | else |
148 | ei->accum_energy += UINT_MAX - ei->reg_val_prev + reg_val; |
149 | ei->reg_val_prev = reg_val; |
150 | |
151 | *energy = mul_u64_u32_shr(a: ei->accum_energy, SF_ENERGY, |
152 | shift: hwmon->scl_shift_energy); |
153 | mutex_unlock(lock: &hwmon->hwmon_lock); |
154 | } |
155 | } |
156 | |
157 | static ssize_t |
158 | hwm_power1_max_interval_show(struct device *dev, struct device_attribute *attr, |
159 | char *buf) |
160 | { |
161 | struct hwm_drvdata *ddat = dev_get_drvdata(dev); |
162 | struct i915_hwmon *hwmon = ddat->hwmon; |
163 | intel_wakeref_t wakeref; |
164 | u32 r, x, y, x_w = 2; /* 2 bits */ |
165 | u64 tau4, out; |
166 | |
167 | with_intel_runtime_pm(ddat->uncore->rpm, wakeref) |
168 | r = intel_uncore_read(uncore: ddat->uncore, reg: hwmon->rg.pkg_rapl_limit); |
169 | |
170 | x = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_X, r); |
171 | y = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_Y, r); |
172 | /* |
173 | * tau = 1.x * power(2,y), x = bits(23:22), y = bits(21:17) |
174 | * = (4 | x) << (y - 2) |
175 | * where (y - 2) ensures a 1.x fixed point representation of 1.x |
176 | * However because y can be < 2, we compute |
177 | * tau4 = (4 | x) << y |
178 | * but add 2 when doing the final right shift to account for units |
179 | */ |
180 | tau4 = (u64)((1 << x_w) | x) << y; |
181 | /* val in hwmon interface units (millisec) */ |
182 | out = mul_u64_u32_shr(a: tau4, SF_TIME, shift: hwmon->scl_shift_time + x_w); |
183 | |
184 | return sysfs_emit(buf, fmt: "%llu\n" , out); |
185 | } |
186 | |
187 | static ssize_t |
188 | hwm_power1_max_interval_store(struct device *dev, |
189 | struct device_attribute *attr, |
190 | const char *buf, size_t count) |
191 | { |
192 | struct hwm_drvdata *ddat = dev_get_drvdata(dev); |
193 | struct i915_hwmon *hwmon = ddat->hwmon; |
194 | u32 x, y, rxy, x_w = 2; /* 2 bits */ |
195 | u64 tau4, r, max_win; |
196 | unsigned long val; |
197 | int ret; |
198 | |
199 | ret = kstrtoul(s: buf, base: 0, res: &val); |
200 | if (ret) |
201 | return ret; |
202 | |
203 | /* |
204 | * Max HW supported tau in '1.x * power(2,y)' format, x = 0, y = 0x12 |
205 | * The hwmon->scl_shift_time default of 0xa results in a max tau of 256 seconds |
206 | */ |
207 | #define PKG_MAX_WIN_DEFAULT 0x12ull |
208 | |
209 | /* |
210 | * val must be < max in hwmon interface units. The steps below are |
211 | * explained in i915_power1_max_interval_show() |
212 | */ |
213 | r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT); |
214 | x = REG_FIELD_GET(PKG_MAX_WIN_X, r); |
215 | y = REG_FIELD_GET(PKG_MAX_WIN_Y, r); |
216 | tau4 = (u64)((1 << x_w) | x) << y; |
217 | max_win = mul_u64_u32_shr(a: tau4, SF_TIME, shift: hwmon->scl_shift_time + x_w); |
218 | |
219 | if (val > max_win) |
220 | return -EINVAL; |
221 | |
222 | /* val in hw units */ |
223 | val = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_time, SF_TIME); |
224 | /* Convert to 1.x * power(2,y) */ |
225 | if (!val) { |
226 | /* Avoid ilog2(0) */ |
227 | y = 0; |
228 | x = 0; |
229 | } else { |
230 | y = ilog2(val); |
231 | /* x = (val - (1 << y)) >> (y - 2); */ |
232 | x = (val - (1ul << y)) << x_w >> y; |
233 | } |
234 | |
235 | rxy = REG_FIELD_PREP(PKG_PWR_LIM_1_TIME_X, x) | REG_FIELD_PREP(PKG_PWR_LIM_1_TIME_Y, y); |
236 | |
237 | hwm_locked_with_pm_intel_uncore_rmw(ddat, reg: hwmon->rg.pkg_rapl_limit, |
238 | PKG_PWR_LIM_1_TIME, set: rxy); |
239 | return count; |
240 | } |
241 | |
242 | static SENSOR_DEVICE_ATTR(power1_max_interval, 0664, |
243 | hwm_power1_max_interval_show, |
244 | hwm_power1_max_interval_store, 0); |
245 | |
246 | static struct attribute *hwm_attributes[] = { |
247 | &sensor_dev_attr_power1_max_interval.dev_attr.attr, |
248 | NULL |
249 | }; |
250 | |
251 | static umode_t hwm_attributes_visible(struct kobject *kobj, |
252 | struct attribute *attr, int index) |
253 | { |
254 | struct device *dev = kobj_to_dev(kobj); |
255 | struct hwm_drvdata *ddat = dev_get_drvdata(dev); |
256 | struct i915_hwmon *hwmon = ddat->hwmon; |
257 | |
258 | if (attr == &sensor_dev_attr_power1_max_interval.dev_attr.attr) |
259 | return i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit) ? attr->mode : 0; |
260 | |
261 | return 0; |
262 | } |
263 | |
264 | static const struct attribute_group hwm_attrgroup = { |
265 | .attrs = hwm_attributes, |
266 | .is_visible = hwm_attributes_visible, |
267 | }; |
268 | |
269 | static const struct attribute_group *hwm_groups[] = { |
270 | &hwm_attrgroup, |
271 | NULL |
272 | }; |
273 | |
274 | static const struct hwmon_channel_info * const hwm_info[] = { |
275 | HWMON_CHANNEL_INFO(in, HWMON_I_INPUT), |
276 | HWMON_CHANNEL_INFO(power, HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_CRIT), |
277 | HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT), |
278 | HWMON_CHANNEL_INFO(curr, HWMON_C_CRIT), |
279 | NULL |
280 | }; |
281 | |
282 | static const struct hwmon_channel_info * const hwm_gt_info[] = { |
283 | HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT), |
284 | NULL |
285 | }; |
286 | |
287 | /* I1 is exposed as power_crit or as curr_crit depending on bit 31 */ |
288 | static int hwm_pcode_read_i1(struct drm_i915_private *i915, u32 *uval) |
289 | { |
290 | /* Avoid ILLEGAL_SUBCOMMAND "mailbox access failed" warning in snb_pcode_read */ |
291 | if (IS_DG1(i915) || IS_DG2(i915)) |
292 | return -ENXIO; |
293 | |
294 | return snb_pcode_read_p(uncore: &i915->uncore, PCODE_POWER_SETUP, |
295 | POWER_SETUP_SUBCOMMAND_READ_I1, p2: 0, val: uval); |
296 | } |
297 | |
298 | static int hwm_pcode_write_i1(struct drm_i915_private *i915, u32 uval) |
299 | { |
300 | return snb_pcode_write_p(uncore: &i915->uncore, PCODE_POWER_SETUP, |
301 | POWER_SETUP_SUBCOMMAND_WRITE_I1, p2: 0, val: uval); |
302 | } |
303 | |
304 | static umode_t |
305 | hwm_in_is_visible(const struct hwm_drvdata *ddat, u32 attr) |
306 | { |
307 | struct drm_i915_private *i915 = ddat->uncore->i915; |
308 | |
309 | switch (attr) { |
310 | case hwmon_in_input: |
311 | return IS_DG1(i915) || IS_DG2(i915) ? 0444 : 0; |
312 | default: |
313 | return 0; |
314 | } |
315 | } |
316 | |
317 | static int |
318 | hwm_in_read(struct hwm_drvdata *ddat, u32 attr, long *val) |
319 | { |
320 | struct i915_hwmon *hwmon = ddat->hwmon; |
321 | intel_wakeref_t wakeref; |
322 | u32 reg_value; |
323 | |
324 | switch (attr) { |
325 | case hwmon_in_input: |
326 | with_intel_runtime_pm(ddat->uncore->rpm, wakeref) |
327 | reg_value = intel_uncore_read(uncore: ddat->uncore, reg: hwmon->rg.gt_perf_status); |
328 | /* HW register value in units of 2.5 millivolt */ |
329 | *val = DIV_ROUND_CLOSEST(REG_FIELD_GET(GEN12_VOLTAGE_MASK, reg_value) * 25, 10); |
330 | return 0; |
331 | default: |
332 | return -EOPNOTSUPP; |
333 | } |
334 | } |
335 | |
336 | static umode_t |
337 | hwm_power_is_visible(const struct hwm_drvdata *ddat, u32 attr, int chan) |
338 | { |
339 | struct drm_i915_private *i915 = ddat->uncore->i915; |
340 | struct i915_hwmon *hwmon = ddat->hwmon; |
341 | u32 uval; |
342 | |
343 | switch (attr) { |
344 | case hwmon_power_max: |
345 | return i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit) ? 0664 : 0; |
346 | case hwmon_power_rated_max: |
347 | return i915_mmio_reg_valid(hwmon->rg.pkg_power_sku) ? 0444 : 0; |
348 | case hwmon_power_crit: |
349 | return (hwm_pcode_read_i1(i915, uval: &uval) || |
350 | !(uval & POWER_SETUP_I1_WATTS)) ? 0 : 0644; |
351 | default: |
352 | return 0; |
353 | } |
354 | } |
355 | |
356 | #define PL1_DISABLE 0 |
357 | |
358 | /* |
359 | * HW allows arbitrary PL1 limits to be set but silently clamps these values to |
360 | * "typical but not guaranteed" min/max values in rg.pkg_power_sku. Follow the |
361 | * same pattern for sysfs, allow arbitrary PL1 limits to be set but display |
362 | * clamped values when read. Write/read I1 also follows the same pattern. |
363 | */ |
364 | static int |
365 | hwm_power_max_read(struct hwm_drvdata *ddat, long *val) |
366 | { |
367 | struct i915_hwmon *hwmon = ddat->hwmon; |
368 | intel_wakeref_t wakeref; |
369 | u64 r, min, max; |
370 | |
371 | /* Check if PL1 limit is disabled */ |
372 | with_intel_runtime_pm(ddat->uncore->rpm, wakeref) |
373 | r = intel_uncore_read(uncore: ddat->uncore, reg: hwmon->rg.pkg_rapl_limit); |
374 | if (!(r & PKG_PWR_LIM_1_EN)) { |
375 | *val = PL1_DISABLE; |
376 | return 0; |
377 | } |
378 | |
379 | *val = hwm_field_read_and_scale(ddat, |
380 | rgadr: hwmon->rg.pkg_rapl_limit, |
381 | PKG_PWR_LIM_1, |
382 | nshift: hwmon->scl_shift_power, |
383 | SF_POWER); |
384 | |
385 | with_intel_runtime_pm(ddat->uncore->rpm, wakeref) |
386 | r = intel_uncore_read64(uncore: ddat->uncore, reg: hwmon->rg.pkg_power_sku); |
387 | min = REG_FIELD_GET(PKG_MIN_PWR, r); |
388 | min = mul_u64_u32_shr(a: min, SF_POWER, shift: hwmon->scl_shift_power); |
389 | max = REG_FIELD_GET(PKG_MAX_PWR, r); |
390 | max = mul_u64_u32_shr(a: max, SF_POWER, shift: hwmon->scl_shift_power); |
391 | |
392 | if (min && max) |
393 | *val = clamp_t(u64, *val, min, max); |
394 | |
395 | return 0; |
396 | } |
397 | |
398 | static int |
399 | hwm_power_max_write(struct hwm_drvdata *ddat, long val) |
400 | { |
401 | struct i915_hwmon *hwmon = ddat->hwmon; |
402 | intel_wakeref_t wakeref; |
403 | DEFINE_WAIT(wait); |
404 | int ret = 0; |
405 | u32 nval; |
406 | |
407 | /* Block waiting for GuC reset to complete when needed */ |
408 | for (;;) { |
409 | wakeref = intel_runtime_pm_get(rpm: ddat->uncore->rpm); |
410 | mutex_lock(&hwmon->hwmon_lock); |
411 | |
412 | prepare_to_wait(wq_head: &ddat->waitq, wq_entry: &wait, TASK_INTERRUPTIBLE); |
413 | |
414 | if (!hwmon->ddat.reset_in_progress) |
415 | break; |
416 | |
417 | if (signal_pending(current)) { |
418 | ret = -EINTR; |
419 | break; |
420 | } |
421 | |
422 | mutex_unlock(lock: &hwmon->hwmon_lock); |
423 | intel_runtime_pm_put(rpm: ddat->uncore->rpm, wref: wakeref); |
424 | |
425 | schedule(); |
426 | } |
427 | finish_wait(wq_head: &ddat->waitq, wq_entry: &wait); |
428 | if (ret) |
429 | goto exit; |
430 | |
431 | /* Disable PL1 limit and verify, because the limit cannot be disabled on all platforms */ |
432 | if (val == PL1_DISABLE) { |
433 | intel_uncore_rmw(uncore: ddat->uncore, reg: hwmon->rg.pkg_rapl_limit, |
434 | PKG_PWR_LIM_1_EN, set: 0); |
435 | nval = intel_uncore_read(uncore: ddat->uncore, reg: hwmon->rg.pkg_rapl_limit); |
436 | |
437 | if (nval & PKG_PWR_LIM_1_EN) |
438 | ret = -ENODEV; |
439 | goto exit; |
440 | } |
441 | |
442 | /* Computation in 64-bits to avoid overflow. Round to nearest. */ |
443 | nval = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_power, SF_POWER); |
444 | nval = PKG_PWR_LIM_1_EN | REG_FIELD_PREP(PKG_PWR_LIM_1, nval); |
445 | |
446 | intel_uncore_rmw(uncore: ddat->uncore, reg: hwmon->rg.pkg_rapl_limit, |
447 | PKG_PWR_LIM_1_EN | PKG_PWR_LIM_1, set: nval); |
448 | exit: |
449 | mutex_unlock(lock: &hwmon->hwmon_lock); |
450 | intel_runtime_pm_put(rpm: ddat->uncore->rpm, wref: wakeref); |
451 | return ret; |
452 | } |
453 | |
454 | static int |
455 | hwm_power_read(struct hwm_drvdata *ddat, u32 attr, int chan, long *val) |
456 | { |
457 | struct i915_hwmon *hwmon = ddat->hwmon; |
458 | int ret; |
459 | u32 uval; |
460 | |
461 | switch (attr) { |
462 | case hwmon_power_max: |
463 | return hwm_power_max_read(ddat, val); |
464 | case hwmon_power_rated_max: |
465 | *val = hwm_field_read_and_scale(ddat, |
466 | rgadr: hwmon->rg.pkg_power_sku, |
467 | PKG_PKG_TDP, |
468 | nshift: hwmon->scl_shift_power, |
469 | SF_POWER); |
470 | return 0; |
471 | case hwmon_power_crit: |
472 | ret = hwm_pcode_read_i1(i915: ddat->uncore->i915, uval: &uval); |
473 | if (ret) |
474 | return ret; |
475 | if (!(uval & POWER_SETUP_I1_WATTS)) |
476 | return -ENODEV; |
477 | *val = mul_u64_u32_shr(REG_FIELD_GET(POWER_SETUP_I1_DATA_MASK, uval), |
478 | SF_POWER, POWER_SETUP_I1_SHIFT); |
479 | return 0; |
480 | default: |
481 | return -EOPNOTSUPP; |
482 | } |
483 | } |
484 | |
485 | static int |
486 | hwm_power_write(struct hwm_drvdata *ddat, u32 attr, int chan, long val) |
487 | { |
488 | u32 uval; |
489 | |
490 | switch (attr) { |
491 | case hwmon_power_max: |
492 | return hwm_power_max_write(ddat, val); |
493 | case hwmon_power_crit: |
494 | uval = DIV_ROUND_CLOSEST_ULL(val << POWER_SETUP_I1_SHIFT, SF_POWER); |
495 | return hwm_pcode_write_i1(i915: ddat->uncore->i915, uval); |
496 | default: |
497 | return -EOPNOTSUPP; |
498 | } |
499 | } |
500 | |
501 | void i915_hwmon_power_max_disable(struct drm_i915_private *i915, bool *old) |
502 | { |
503 | struct i915_hwmon *hwmon = i915->hwmon; |
504 | u32 r; |
505 | |
506 | if (!hwmon || !i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit)) |
507 | return; |
508 | |
509 | mutex_lock(&hwmon->hwmon_lock); |
510 | |
511 | hwmon->ddat.reset_in_progress = true; |
512 | r = intel_uncore_rmw(uncore: hwmon->ddat.uncore, reg: hwmon->rg.pkg_rapl_limit, |
513 | PKG_PWR_LIM_1_EN, set: 0); |
514 | *old = !!(r & PKG_PWR_LIM_1_EN); |
515 | |
516 | mutex_unlock(lock: &hwmon->hwmon_lock); |
517 | } |
518 | |
519 | void i915_hwmon_power_max_restore(struct drm_i915_private *i915, bool old) |
520 | { |
521 | struct i915_hwmon *hwmon = i915->hwmon; |
522 | |
523 | if (!hwmon || !i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit)) |
524 | return; |
525 | |
526 | mutex_lock(&hwmon->hwmon_lock); |
527 | |
528 | intel_uncore_rmw(uncore: hwmon->ddat.uncore, reg: hwmon->rg.pkg_rapl_limit, |
529 | PKG_PWR_LIM_1_EN, set: old ? PKG_PWR_LIM_1_EN : 0); |
530 | hwmon->ddat.reset_in_progress = false; |
531 | wake_up_all(&hwmon->ddat.waitq); |
532 | |
533 | mutex_unlock(lock: &hwmon->hwmon_lock); |
534 | } |
535 | |
536 | static umode_t |
537 | hwm_energy_is_visible(const struct hwm_drvdata *ddat, u32 attr) |
538 | { |
539 | struct i915_hwmon *hwmon = ddat->hwmon; |
540 | i915_reg_t rgaddr; |
541 | |
542 | switch (attr) { |
543 | case hwmon_energy_input: |
544 | if (ddat->gt_n >= 0) |
545 | rgaddr = hwmon->rg.energy_status_tile; |
546 | else |
547 | rgaddr = hwmon->rg.energy_status_all; |
548 | return i915_mmio_reg_valid(rgaddr) ? 0444 : 0; |
549 | default: |
550 | return 0; |
551 | } |
552 | } |
553 | |
554 | static int |
555 | hwm_energy_read(struct hwm_drvdata *ddat, u32 attr, long *val) |
556 | { |
557 | switch (attr) { |
558 | case hwmon_energy_input: |
559 | hwm_energy(ddat, energy: val); |
560 | return 0; |
561 | default: |
562 | return -EOPNOTSUPP; |
563 | } |
564 | } |
565 | |
566 | static umode_t |
567 | hwm_curr_is_visible(const struct hwm_drvdata *ddat, u32 attr) |
568 | { |
569 | struct drm_i915_private *i915 = ddat->uncore->i915; |
570 | u32 uval; |
571 | |
572 | switch (attr) { |
573 | case hwmon_curr_crit: |
574 | return (hwm_pcode_read_i1(i915, uval: &uval) || |
575 | (uval & POWER_SETUP_I1_WATTS)) ? 0 : 0644; |
576 | default: |
577 | return 0; |
578 | } |
579 | } |
580 | |
581 | static int |
582 | hwm_curr_read(struct hwm_drvdata *ddat, u32 attr, long *val) |
583 | { |
584 | int ret; |
585 | u32 uval; |
586 | |
587 | switch (attr) { |
588 | case hwmon_curr_crit: |
589 | ret = hwm_pcode_read_i1(i915: ddat->uncore->i915, uval: &uval); |
590 | if (ret) |
591 | return ret; |
592 | if (uval & POWER_SETUP_I1_WATTS) |
593 | return -ENODEV; |
594 | *val = mul_u64_u32_shr(REG_FIELD_GET(POWER_SETUP_I1_DATA_MASK, uval), |
595 | SF_CURR, POWER_SETUP_I1_SHIFT); |
596 | return 0; |
597 | default: |
598 | return -EOPNOTSUPP; |
599 | } |
600 | } |
601 | |
602 | static int |
603 | hwm_curr_write(struct hwm_drvdata *ddat, u32 attr, long val) |
604 | { |
605 | u32 uval; |
606 | |
607 | switch (attr) { |
608 | case hwmon_curr_crit: |
609 | uval = DIV_ROUND_CLOSEST_ULL(val << POWER_SETUP_I1_SHIFT, SF_CURR); |
610 | return hwm_pcode_write_i1(i915: ddat->uncore->i915, uval); |
611 | default: |
612 | return -EOPNOTSUPP; |
613 | } |
614 | } |
615 | |
616 | static umode_t |
617 | hwm_is_visible(const void *drvdata, enum hwmon_sensor_types type, |
618 | u32 attr, int channel) |
619 | { |
620 | struct hwm_drvdata *ddat = (struct hwm_drvdata *)drvdata; |
621 | |
622 | switch (type) { |
623 | case hwmon_in: |
624 | return hwm_in_is_visible(ddat, attr); |
625 | case hwmon_power: |
626 | return hwm_power_is_visible(ddat, attr, chan: channel); |
627 | case hwmon_energy: |
628 | return hwm_energy_is_visible(ddat, attr); |
629 | case hwmon_curr: |
630 | return hwm_curr_is_visible(ddat, attr); |
631 | default: |
632 | return 0; |
633 | } |
634 | } |
635 | |
636 | static int |
637 | hwm_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, |
638 | int channel, long *val) |
639 | { |
640 | struct hwm_drvdata *ddat = dev_get_drvdata(dev); |
641 | |
642 | switch (type) { |
643 | case hwmon_in: |
644 | return hwm_in_read(ddat, attr, val); |
645 | case hwmon_power: |
646 | return hwm_power_read(ddat, attr, chan: channel, val); |
647 | case hwmon_energy: |
648 | return hwm_energy_read(ddat, attr, val); |
649 | case hwmon_curr: |
650 | return hwm_curr_read(ddat, attr, val); |
651 | default: |
652 | return -EOPNOTSUPP; |
653 | } |
654 | } |
655 | |
656 | static int |
657 | hwm_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, |
658 | int channel, long val) |
659 | { |
660 | struct hwm_drvdata *ddat = dev_get_drvdata(dev); |
661 | |
662 | switch (type) { |
663 | case hwmon_power: |
664 | return hwm_power_write(ddat, attr, chan: channel, val); |
665 | case hwmon_curr: |
666 | return hwm_curr_write(ddat, attr, val); |
667 | default: |
668 | return -EOPNOTSUPP; |
669 | } |
670 | } |
671 | |
672 | static const struct hwmon_ops hwm_ops = { |
673 | .is_visible = hwm_is_visible, |
674 | .read = hwm_read, |
675 | .write = hwm_write, |
676 | }; |
677 | |
678 | static const struct hwmon_chip_info hwm_chip_info = { |
679 | .ops = &hwm_ops, |
680 | .info = hwm_info, |
681 | }; |
682 | |
683 | static umode_t |
684 | hwm_gt_is_visible(const void *drvdata, enum hwmon_sensor_types type, |
685 | u32 attr, int channel) |
686 | { |
687 | struct hwm_drvdata *ddat = (struct hwm_drvdata *)drvdata; |
688 | |
689 | switch (type) { |
690 | case hwmon_energy: |
691 | return hwm_energy_is_visible(ddat, attr); |
692 | default: |
693 | return 0; |
694 | } |
695 | } |
696 | |
697 | static int |
698 | hwm_gt_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, |
699 | int channel, long *val) |
700 | { |
701 | struct hwm_drvdata *ddat = dev_get_drvdata(dev); |
702 | |
703 | switch (type) { |
704 | case hwmon_energy: |
705 | return hwm_energy_read(ddat, attr, val); |
706 | default: |
707 | return -EOPNOTSUPP; |
708 | } |
709 | } |
710 | |
711 | static const struct hwmon_ops hwm_gt_ops = { |
712 | .is_visible = hwm_gt_is_visible, |
713 | .read = hwm_gt_read, |
714 | }; |
715 | |
716 | static const struct hwmon_chip_info hwm_gt_chip_info = { |
717 | .ops = &hwm_gt_ops, |
718 | .info = hwm_gt_info, |
719 | }; |
720 | |
721 | static void |
722 | hwm_get_preregistration_info(struct drm_i915_private *i915) |
723 | { |
724 | struct i915_hwmon *hwmon = i915->hwmon; |
725 | struct intel_uncore *uncore = &i915->uncore; |
726 | struct hwm_drvdata *ddat = &hwmon->ddat; |
727 | intel_wakeref_t wakeref; |
728 | u32 val_sku_unit = 0; |
729 | struct intel_gt *gt; |
730 | long energy; |
731 | int i; |
732 | |
733 | /* Available for all Gen12+/dGfx */ |
734 | hwmon->rg.gt_perf_status = GEN12_RPSTAT1; |
735 | |
736 | if (IS_DG1(i915) || IS_DG2(i915)) { |
737 | hwmon->rg.pkg_power_sku_unit = PCU_PACKAGE_POWER_SKU_UNIT; |
738 | hwmon->rg.pkg_power_sku = PCU_PACKAGE_POWER_SKU; |
739 | hwmon->rg.pkg_rapl_limit = PCU_PACKAGE_RAPL_LIMIT; |
740 | hwmon->rg.energy_status_all = PCU_PACKAGE_ENERGY_STATUS; |
741 | hwmon->rg.energy_status_tile = INVALID_MMIO_REG; |
742 | } else if (IS_XEHPSDV(i915)) { |
743 | hwmon->rg.pkg_power_sku_unit = GT0_PACKAGE_POWER_SKU_UNIT; |
744 | hwmon->rg.pkg_power_sku = INVALID_MMIO_REG; |
745 | hwmon->rg.pkg_rapl_limit = GT0_PACKAGE_RAPL_LIMIT; |
746 | hwmon->rg.energy_status_all = GT0_PLATFORM_ENERGY_STATUS; |
747 | hwmon->rg.energy_status_tile = GT0_PACKAGE_ENERGY_STATUS; |
748 | } else { |
749 | hwmon->rg.pkg_power_sku_unit = INVALID_MMIO_REG; |
750 | hwmon->rg.pkg_power_sku = INVALID_MMIO_REG; |
751 | hwmon->rg.pkg_rapl_limit = INVALID_MMIO_REG; |
752 | hwmon->rg.energy_status_all = INVALID_MMIO_REG; |
753 | hwmon->rg.energy_status_tile = INVALID_MMIO_REG; |
754 | } |
755 | |
756 | with_intel_runtime_pm(uncore->rpm, wakeref) { |
757 | /* |
758 | * The contents of register hwmon->rg.pkg_power_sku_unit do not change, |
759 | * so read it once and store the shift values. |
760 | */ |
761 | if (i915_mmio_reg_valid(hwmon->rg.pkg_power_sku_unit)) |
762 | val_sku_unit = intel_uncore_read(uncore, |
763 | reg: hwmon->rg.pkg_power_sku_unit); |
764 | } |
765 | |
766 | hwmon->scl_shift_power = REG_FIELD_GET(PKG_PWR_UNIT, val_sku_unit); |
767 | hwmon->scl_shift_energy = REG_FIELD_GET(PKG_ENERGY_UNIT, val_sku_unit); |
768 | hwmon->scl_shift_time = REG_FIELD_GET(PKG_TIME_UNIT, val_sku_unit); |
769 | |
770 | /* |
771 | * Initialize 'struct hwm_energy_info', i.e. set fields to the |
772 | * first value of the energy register read |
773 | */ |
774 | if (i915_mmio_reg_valid(hwmon->rg.energy_status_all)) |
775 | hwm_energy(ddat, energy: &energy); |
776 | if (i915_mmio_reg_valid(hwmon->rg.energy_status_tile)) { |
777 | for_each_gt(gt, i915, i) |
778 | hwm_energy(ddat: &hwmon->ddat_gt[i], energy: &energy); |
779 | } |
780 | } |
781 | |
782 | void i915_hwmon_register(struct drm_i915_private *i915) |
783 | { |
784 | struct device *dev = i915->drm.dev; |
785 | struct i915_hwmon *hwmon; |
786 | struct device *hwmon_dev; |
787 | struct hwm_drvdata *ddat; |
788 | struct hwm_drvdata *ddat_gt; |
789 | struct intel_gt *gt; |
790 | int i; |
791 | |
792 | /* hwmon is available only for dGfx */ |
793 | if (!IS_DGFX(i915)) |
794 | return; |
795 | |
796 | hwmon = devm_kzalloc(dev, size: sizeof(*hwmon), GFP_KERNEL); |
797 | if (!hwmon) |
798 | return; |
799 | |
800 | i915->hwmon = hwmon; |
801 | mutex_init(&hwmon->hwmon_lock); |
802 | ddat = &hwmon->ddat; |
803 | |
804 | ddat->hwmon = hwmon; |
805 | ddat->uncore = &i915->uncore; |
806 | snprintf(buf: ddat->name, size: sizeof(ddat->name), fmt: "i915" ); |
807 | ddat->gt_n = -1; |
808 | init_waitqueue_head(&ddat->waitq); |
809 | |
810 | for_each_gt(gt, i915, i) { |
811 | ddat_gt = hwmon->ddat_gt + i; |
812 | |
813 | ddat_gt->hwmon = hwmon; |
814 | ddat_gt->uncore = gt->uncore; |
815 | snprintf(buf: ddat_gt->name, size: sizeof(ddat_gt->name), fmt: "i915_gt%u" , i); |
816 | ddat_gt->gt_n = i; |
817 | } |
818 | |
819 | hwm_get_preregistration_info(i915); |
820 | |
821 | /* hwmon_dev points to device hwmon<i> */ |
822 | hwmon_dev = devm_hwmon_device_register_with_info(dev, name: ddat->name, |
823 | drvdata: ddat, |
824 | info: &hwm_chip_info, |
825 | extra_groups: hwm_groups); |
826 | if (IS_ERR(ptr: hwmon_dev)) { |
827 | i915->hwmon = NULL; |
828 | return; |
829 | } |
830 | |
831 | ddat->hwmon_dev = hwmon_dev; |
832 | |
833 | for_each_gt(gt, i915, i) { |
834 | ddat_gt = hwmon->ddat_gt + i; |
835 | /* |
836 | * Create per-gt directories only if a per-gt attribute is |
837 | * visible. Currently this is only energy |
838 | */ |
839 | if (!hwm_gt_is_visible(drvdata: ddat_gt, type: hwmon_energy, attr: hwmon_energy_input, channel: 0)) |
840 | continue; |
841 | |
842 | hwmon_dev = devm_hwmon_device_register_with_info(dev, name: ddat_gt->name, |
843 | drvdata: ddat_gt, |
844 | info: &hwm_gt_chip_info, |
845 | NULL); |
846 | if (!IS_ERR(ptr: hwmon_dev)) |
847 | ddat_gt->hwmon_dev = hwmon_dev; |
848 | } |
849 | } |
850 | |
851 | void i915_hwmon_unregister(struct drm_i915_private *i915) |
852 | { |
853 | fetch_and_zero(&i915->hwmon); |
854 | } |
855 | |