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