xref: /linux/drivers/accel/habanalabs/common/hwmon.c (revision 24b10e5f8e0d2bee1a10fc67011ea5d936c1a389)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 /*
4  * Copyright 2016-2019 HabanaLabs, Ltd.
5  * All Rights Reserved.
6  */
7 
8 #include "habanalabs.h"
9 
10 #include <linux/pci.h>
11 #include <linux/hwmon.h>
12 
13 #define HWMON_NR_SENSOR_TYPES		(hwmon_max)
14 
15 #ifdef _HAS_HWMON_HWMON_T_ENABLE
16 
17 static u32 fixup_flags_legacy_fw(struct hl_device *hdev, enum hwmon_sensor_types type,
18 					u32 cpucp_flags)
19 {
20 	u32 flags;
21 
22 	switch (type) {
23 	case hwmon_temp:
24 		flags = (cpucp_flags << 1) | HWMON_T_ENABLE;
25 		break;
26 
27 	case hwmon_in:
28 		flags = (cpucp_flags << 1) | HWMON_I_ENABLE;
29 		break;
30 
31 	case hwmon_curr:
32 		flags = (cpucp_flags << 1) | HWMON_C_ENABLE;
33 		break;
34 
35 	case hwmon_fan:
36 		flags = (cpucp_flags << 1) | HWMON_F_ENABLE;
37 		break;
38 
39 	case hwmon_power:
40 		flags = (cpucp_flags << 1) | HWMON_P_ENABLE;
41 		break;
42 
43 	case hwmon_pwm:
44 		/* enable bit was here from day 1, so no need to adjust */
45 		flags = cpucp_flags;
46 		break;
47 
48 	default:
49 		dev_err(hdev->dev, "unsupported h/w sensor type %d\n", type);
50 		flags = cpucp_flags;
51 		break;
52 	}
53 
54 	return flags;
55 }
56 
57 static u32 fixup_attr_legacy_fw(u32 attr)
58 {
59 	return (attr - 1);
60 }
61 
62 #else
63 
64 static u32 fixup_flags_legacy_fw(struct hl_device *hdev, enum hwmon_sensor_types type,
65 						u32 cpucp_flags)
66 {
67 	return cpucp_flags;
68 }
69 
70 static u32 fixup_attr_legacy_fw(u32 attr)
71 {
72 	return attr;
73 }
74 
75 #endif /* !_HAS_HWMON_HWMON_T_ENABLE */
76 
77 static u32 adjust_hwmon_flags(struct hl_device *hdev, enum hwmon_sensor_types type, u32 cpucp_flags)
78 {
79 	u32 flags, cpucp_input_val;
80 	bool use_cpucp_enum;
81 
82 	use_cpucp_enum = (hdev->asic_prop.fw_app_cpu_boot_dev_sts0 &
83 					CPU_BOOT_DEV_STS0_MAP_HWMON_EN) ? true : false;
84 
85 	/* If f/w is using it's own enum, we need to check if the properties values are aligned.
86 	 * If not, it means we need to adjust the values to the new format that is used in the
87 	 * kernel since 5.6 (enum values were incremented by 1 by adding a new enable value).
88 	 */
89 	if (use_cpucp_enum) {
90 		switch (type) {
91 		case hwmon_temp:
92 			cpucp_input_val = cpucp_temp_input;
93 			if (cpucp_input_val == hwmon_temp_input)
94 				flags = cpucp_flags;
95 			else
96 				flags = (cpucp_flags << 1) | HWMON_T_ENABLE;
97 			break;
98 
99 		case hwmon_in:
100 			cpucp_input_val = cpucp_in_input;
101 			if (cpucp_input_val == hwmon_in_input)
102 				flags = cpucp_flags;
103 			else
104 				flags = (cpucp_flags << 1) | HWMON_I_ENABLE;
105 			break;
106 
107 		case hwmon_curr:
108 			cpucp_input_val = cpucp_curr_input;
109 			if (cpucp_input_val == hwmon_curr_input)
110 				flags = cpucp_flags;
111 			else
112 				flags = (cpucp_flags << 1) | HWMON_C_ENABLE;
113 			break;
114 
115 		case hwmon_fan:
116 			cpucp_input_val = cpucp_fan_input;
117 			if (cpucp_input_val == hwmon_fan_input)
118 				flags = cpucp_flags;
119 			else
120 				flags = (cpucp_flags << 1) | HWMON_F_ENABLE;
121 			break;
122 
123 		case hwmon_pwm:
124 			/* enable bit was here from day 1, so no need to adjust */
125 			flags = cpucp_flags;
126 			break;
127 
128 		case hwmon_power:
129 			cpucp_input_val = CPUCP_POWER_INPUT;
130 			if (cpucp_input_val == hwmon_power_input)
131 				flags = cpucp_flags;
132 			else
133 				flags = (cpucp_flags << 1) | HWMON_P_ENABLE;
134 			break;
135 
136 		default:
137 			dev_err(hdev->dev, "unsupported h/w sensor type %d\n", type);
138 			flags = cpucp_flags;
139 			break;
140 		}
141 	} else {
142 		flags = fixup_flags_legacy_fw(hdev, type, cpucp_flags);
143 	}
144 
145 	return flags;
146 }
147 
148 int hl_build_hwmon_channel_info(struct hl_device *hdev, struct cpucp_sensor *sensors_arr)
149 {
150 	u32 num_sensors_for_type, flags, num_active_sensor_types = 0, arr_size = 0, *curr_arr;
151 	u32 sensors_by_type_next_index[HWMON_NR_SENSOR_TYPES] = {0};
152 	u32 *sensors_by_type[HWMON_NR_SENSOR_TYPES] = {NULL};
153 	struct hwmon_channel_info **channels_info;
154 	u32 counts[HWMON_NR_SENSOR_TYPES] = {0};
155 	enum hwmon_sensor_types type;
156 	int rc, i, j;
157 
158 	for (i = 0 ; i < CPUCP_MAX_SENSORS ; i++) {
159 		type = le32_to_cpu(sensors_arr[i].type);
160 
161 		if ((type == 0) && (sensors_arr[i].flags == 0))
162 			break;
163 
164 		if (type >= HWMON_NR_SENSOR_TYPES) {
165 			dev_err(hdev->dev, "Got wrong sensor type %d from device\n", type);
166 			return -EINVAL;
167 		}
168 
169 		counts[type]++;
170 		arr_size++;
171 	}
172 
173 	for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) {
174 		if (counts[i] == 0)
175 			continue;
176 
177 		num_sensors_for_type = counts[i] + 1;
178 		dev_dbg(hdev->dev, "num_sensors_for_type %d = %d\n", i, num_sensors_for_type);
179 
180 		curr_arr = kcalloc(num_sensors_for_type, sizeof(*curr_arr), GFP_KERNEL);
181 		if (!curr_arr) {
182 			rc = -ENOMEM;
183 			goto sensors_type_err;
184 		}
185 
186 		num_active_sensor_types++;
187 		sensors_by_type[i] = curr_arr;
188 	}
189 
190 	for (i = 0 ; i < arr_size ; i++) {
191 		type = le32_to_cpu(sensors_arr[i].type);
192 		curr_arr = sensors_by_type[type];
193 		flags = adjust_hwmon_flags(hdev, type, le32_to_cpu(sensors_arr[i].flags));
194 		curr_arr[sensors_by_type_next_index[type]++] = flags;
195 	}
196 
197 	channels_info = kcalloc(num_active_sensor_types + 1, sizeof(struct hwmon_channel_info *),
198 				GFP_KERNEL);
199 	if (!channels_info) {
200 		rc = -ENOMEM;
201 		goto channels_info_array_err;
202 	}
203 
204 	for (i = 0 ; i < num_active_sensor_types ; i++) {
205 		channels_info[i] = kzalloc(sizeof(*channels_info[i]), GFP_KERNEL);
206 		if (!channels_info[i]) {
207 			rc = -ENOMEM;
208 			goto channel_info_err;
209 		}
210 	}
211 
212 	for (i = 0, j = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) {
213 		if (!sensors_by_type[i])
214 			continue;
215 
216 		channels_info[j]->type = i;
217 		channels_info[j]->config = sensors_by_type[i];
218 		j++;
219 	}
220 
221 	hdev->hl_chip_info->info = (const struct hwmon_channel_info **)channels_info;
222 
223 	return 0;
224 
225 channel_info_err:
226 	for (i = 0 ; i < num_active_sensor_types ; i++) {
227 		if (channels_info[i]) {
228 			kfree(channels_info[i]->config);
229 			kfree(channels_info[i]);
230 		}
231 	}
232 	kfree(channels_info);
233 
234 channels_info_array_err:
235 sensors_type_err:
236 	for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++)
237 		kfree(sensors_by_type[i]);
238 
239 	return rc;
240 }
241 
242 static int hl_read(struct device *dev, enum hwmon_sensor_types type,
243 			u32 attr, int channel, long *val)
244 {
245 	struct hl_device *hdev = dev_get_drvdata(dev);
246 	bool use_cpucp_enum;
247 	u32 cpucp_attr;
248 	int rc;
249 
250 	if (!hl_device_operational(hdev, NULL))
251 		return -ENODEV;
252 
253 	use_cpucp_enum = (hdev->asic_prop.fw_app_cpu_boot_dev_sts0 &
254 					CPU_BOOT_DEV_STS0_MAP_HWMON_EN) ? true : false;
255 
256 	switch (type) {
257 	case hwmon_temp:
258 		switch (attr) {
259 		case hwmon_temp_input:
260 			cpucp_attr = cpucp_temp_input;
261 			break;
262 		case hwmon_temp_max:
263 			cpucp_attr = cpucp_temp_max;
264 			break;
265 		case hwmon_temp_crit:
266 			cpucp_attr = cpucp_temp_crit;
267 			break;
268 		case hwmon_temp_max_hyst:
269 			cpucp_attr = cpucp_temp_max_hyst;
270 			break;
271 		case hwmon_temp_crit_hyst:
272 			cpucp_attr = cpucp_temp_crit_hyst;
273 			break;
274 		case hwmon_temp_offset:
275 			cpucp_attr = cpucp_temp_offset;
276 			break;
277 		case hwmon_temp_highest:
278 			cpucp_attr = cpucp_temp_highest;
279 			break;
280 		default:
281 			return -EINVAL;
282 		}
283 
284 		if (use_cpucp_enum)
285 			rc = hl_get_temperature(hdev, channel, cpucp_attr, val);
286 		else
287 			rc = hl_get_temperature(hdev, channel, fixup_attr_legacy_fw(attr), val);
288 		break;
289 	case hwmon_in:
290 		switch (attr) {
291 		case hwmon_in_input:
292 			cpucp_attr = cpucp_in_input;
293 			break;
294 		case hwmon_in_min:
295 			cpucp_attr = cpucp_in_min;
296 			break;
297 		case hwmon_in_max:
298 			cpucp_attr = cpucp_in_max;
299 			break;
300 		case hwmon_in_highest:
301 			cpucp_attr = cpucp_in_highest;
302 			break;
303 		default:
304 			return -EINVAL;
305 		}
306 
307 		if (use_cpucp_enum)
308 			rc = hl_get_voltage(hdev, channel, cpucp_attr, val);
309 		else
310 			rc = hl_get_voltage(hdev, channel, fixup_attr_legacy_fw(attr), val);
311 		break;
312 	case hwmon_curr:
313 		switch (attr) {
314 		case hwmon_curr_input:
315 			cpucp_attr = cpucp_curr_input;
316 			break;
317 		case hwmon_curr_min:
318 			cpucp_attr = cpucp_curr_min;
319 			break;
320 		case hwmon_curr_max:
321 			cpucp_attr = cpucp_curr_max;
322 			break;
323 		case hwmon_curr_highest:
324 			cpucp_attr = cpucp_curr_highest;
325 			break;
326 		default:
327 			return -EINVAL;
328 		}
329 
330 		if (use_cpucp_enum)
331 			rc = hl_get_current(hdev, channel, cpucp_attr, val);
332 		else
333 			rc = hl_get_current(hdev, channel, fixup_attr_legacy_fw(attr), val);
334 		break;
335 	case hwmon_fan:
336 		switch (attr) {
337 		case hwmon_fan_input:
338 			cpucp_attr = cpucp_fan_input;
339 			break;
340 		case hwmon_fan_min:
341 			cpucp_attr = cpucp_fan_min;
342 			break;
343 		case hwmon_fan_max:
344 			cpucp_attr = cpucp_fan_max;
345 			break;
346 		default:
347 			return -EINVAL;
348 		}
349 
350 		if (use_cpucp_enum)
351 			rc = hl_get_fan_speed(hdev, channel, cpucp_attr, val);
352 		else
353 			rc = hl_get_fan_speed(hdev, channel, fixup_attr_legacy_fw(attr), val);
354 		break;
355 	case hwmon_pwm:
356 		switch (attr) {
357 		case hwmon_pwm_input:
358 			cpucp_attr = cpucp_pwm_input;
359 			break;
360 		case hwmon_pwm_enable:
361 			cpucp_attr = cpucp_pwm_enable;
362 			break;
363 		default:
364 			return -EINVAL;
365 		}
366 
367 		if (use_cpucp_enum)
368 			rc = hl_get_pwm_info(hdev, channel, cpucp_attr, val);
369 		else
370 			/* no need for fixup as pwm was aligned from day 1 */
371 			rc = hl_get_pwm_info(hdev, channel, attr, val);
372 		break;
373 	case hwmon_power:
374 		switch (attr) {
375 		case hwmon_power_input:
376 			cpucp_attr = CPUCP_POWER_INPUT;
377 			break;
378 		case hwmon_power_input_highest:
379 			cpucp_attr = CPUCP_POWER_INPUT_HIGHEST;
380 			break;
381 		default:
382 			return -EINVAL;
383 		}
384 
385 		if (use_cpucp_enum)
386 			rc = hl_get_power(hdev, channel, cpucp_attr, val);
387 		else
388 			rc = hl_get_power(hdev, channel, fixup_attr_legacy_fw(attr), val);
389 		break;
390 	default:
391 		return -EINVAL;
392 	}
393 	return rc;
394 }
395 
396 static int hl_write(struct device *dev, enum hwmon_sensor_types type,
397 			u32 attr, int channel, long val)
398 {
399 	struct hl_device *hdev = dev_get_drvdata(dev);
400 	u32 cpucp_attr;
401 	bool use_cpucp_enum = (hdev->asic_prop.fw_app_cpu_boot_dev_sts0 &
402 				CPU_BOOT_DEV_STS0_MAP_HWMON_EN) ? true : false;
403 
404 	if (!hl_device_operational(hdev, NULL))
405 		return -ENODEV;
406 
407 	switch (type) {
408 	case hwmon_temp:
409 		switch (attr) {
410 		case hwmon_temp_offset:
411 			cpucp_attr = cpucp_temp_offset;
412 			break;
413 		case hwmon_temp_reset_history:
414 			cpucp_attr = cpucp_temp_reset_history;
415 			break;
416 		default:
417 			return -EINVAL;
418 		}
419 
420 		if (use_cpucp_enum)
421 			hl_set_temperature(hdev, channel, cpucp_attr, val);
422 		else
423 			hl_set_temperature(hdev, channel, fixup_attr_legacy_fw(attr), val);
424 		break;
425 	case hwmon_pwm:
426 		switch (attr) {
427 		case hwmon_pwm_input:
428 			cpucp_attr = cpucp_pwm_input;
429 			break;
430 		case hwmon_pwm_enable:
431 			cpucp_attr = cpucp_pwm_enable;
432 			break;
433 		default:
434 			return -EINVAL;
435 		}
436 
437 		if (use_cpucp_enum)
438 			hl_set_pwm_info(hdev, channel, cpucp_attr, val);
439 		else
440 			/* no need for fixup as pwm was aligned from day 1 */
441 			hl_set_pwm_info(hdev, channel, attr, val);
442 		break;
443 	case hwmon_in:
444 		switch (attr) {
445 		case hwmon_in_reset_history:
446 			cpucp_attr = cpucp_in_reset_history;
447 			break;
448 		default:
449 			return -EINVAL;
450 		}
451 
452 		if (use_cpucp_enum)
453 			hl_set_voltage(hdev, channel, cpucp_attr, val);
454 		else
455 			hl_set_voltage(hdev, channel, fixup_attr_legacy_fw(attr), val);
456 		break;
457 	case hwmon_curr:
458 		switch (attr) {
459 		case hwmon_curr_reset_history:
460 			cpucp_attr = cpucp_curr_reset_history;
461 			break;
462 		default:
463 			return -EINVAL;
464 		}
465 
466 		if (use_cpucp_enum)
467 			hl_set_current(hdev, channel, cpucp_attr, val);
468 		else
469 			hl_set_current(hdev, channel, fixup_attr_legacy_fw(attr), val);
470 		break;
471 	case hwmon_power:
472 		switch (attr) {
473 		case hwmon_power_reset_history:
474 			cpucp_attr = CPUCP_POWER_RESET_INPUT_HISTORY;
475 			break;
476 		default:
477 			return -EINVAL;
478 		}
479 
480 		if (use_cpucp_enum)
481 			hl_set_power(hdev, channel, cpucp_attr, val);
482 		else
483 			hl_set_power(hdev, channel, fixup_attr_legacy_fw(attr), val);
484 		break;
485 	default:
486 		return -EINVAL;
487 	}
488 	return 0;
489 }
490 
491 static umode_t hl_is_visible(const void *data, enum hwmon_sensor_types type,
492 				u32 attr, int channel)
493 {
494 	switch (type) {
495 	case hwmon_temp:
496 		switch (attr) {
497 		case hwmon_temp_input:
498 		case hwmon_temp_max:
499 		case hwmon_temp_max_hyst:
500 		case hwmon_temp_crit:
501 		case hwmon_temp_crit_hyst:
502 		case hwmon_temp_highest:
503 			return 0444;
504 		case hwmon_temp_offset:
505 			return 0644;
506 		case hwmon_temp_reset_history:
507 			return 0200;
508 		}
509 		break;
510 	case hwmon_in:
511 		switch (attr) {
512 		case hwmon_in_input:
513 		case hwmon_in_min:
514 		case hwmon_in_max:
515 		case hwmon_in_highest:
516 			return 0444;
517 		case hwmon_in_reset_history:
518 			return 0200;
519 		}
520 		break;
521 	case hwmon_curr:
522 		switch (attr) {
523 		case hwmon_curr_input:
524 		case hwmon_curr_min:
525 		case hwmon_curr_max:
526 		case hwmon_curr_highest:
527 			return 0444;
528 		case hwmon_curr_reset_history:
529 			return 0200;
530 		}
531 		break;
532 	case hwmon_fan:
533 		switch (attr) {
534 		case hwmon_fan_input:
535 		case hwmon_fan_min:
536 		case hwmon_fan_max:
537 			return 0444;
538 		}
539 		break;
540 	case hwmon_pwm:
541 		switch (attr) {
542 		case hwmon_pwm_input:
543 		case hwmon_pwm_enable:
544 			return 0644;
545 		}
546 		break;
547 	case hwmon_power:
548 		switch (attr) {
549 		case hwmon_power_input:
550 		case hwmon_power_input_highest:
551 			return 0444;
552 		case hwmon_power_reset_history:
553 			return 0200;
554 		}
555 		break;
556 	default:
557 		break;
558 	}
559 	return 0;
560 }
561 
562 static const struct hwmon_ops hl_hwmon_ops = {
563 	.is_visible = hl_is_visible,
564 	.read = hl_read,
565 	.write = hl_write
566 };
567 
568 int hl_get_temperature(struct hl_device *hdev,
569 			int sensor_index, u32 attr, long *value)
570 {
571 	struct cpucp_packet pkt;
572 	u64 result;
573 	int rc;
574 
575 	memset(&pkt, 0, sizeof(pkt));
576 
577 	pkt.ctl = cpu_to_le32(CPUCP_PACKET_TEMPERATURE_GET <<
578 				CPUCP_PKT_CTL_OPCODE_SHIFT);
579 	pkt.sensor_index = __cpu_to_le16(sensor_index);
580 	pkt.type = __cpu_to_le16(attr);
581 	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
582 						0, &result);
583 
584 	*value = (long) result;
585 
586 	if (rc) {
587 		dev_err(hdev->dev,
588 			"Failed to get temperature from sensor %d, error %d\n",
589 			sensor_index, rc);
590 		*value = 0;
591 	}
592 
593 	return rc;
594 }
595 
596 int hl_set_temperature(struct hl_device *hdev,
597 			int sensor_index, u32 attr, long value)
598 {
599 	struct cpucp_packet pkt;
600 	int rc;
601 
602 	memset(&pkt, 0, sizeof(pkt));
603 
604 	pkt.ctl = cpu_to_le32(CPUCP_PACKET_TEMPERATURE_SET <<
605 				CPUCP_PKT_CTL_OPCODE_SHIFT);
606 	pkt.sensor_index = __cpu_to_le16(sensor_index);
607 	pkt.type = __cpu_to_le16(attr);
608 	pkt.value = __cpu_to_le64(value);
609 
610 	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
611 						0, NULL);
612 
613 	if (rc)
614 		dev_err(hdev->dev,
615 			"Failed to set temperature of sensor %d, error %d\n",
616 			sensor_index, rc);
617 
618 	return rc;
619 }
620 
621 int hl_get_voltage(struct hl_device *hdev,
622 			int sensor_index, u32 attr, long *value)
623 {
624 	struct cpucp_packet pkt;
625 	u64 result;
626 	int rc;
627 
628 	memset(&pkt, 0, sizeof(pkt));
629 
630 	pkt.ctl = cpu_to_le32(CPUCP_PACKET_VOLTAGE_GET <<
631 				CPUCP_PKT_CTL_OPCODE_SHIFT);
632 	pkt.sensor_index = __cpu_to_le16(sensor_index);
633 	pkt.type = __cpu_to_le16(attr);
634 
635 	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
636 						0, &result);
637 
638 	*value = (long) result;
639 
640 	if (rc) {
641 		dev_err(hdev->dev,
642 			"Failed to get voltage from sensor %d, error %d\n",
643 			sensor_index, rc);
644 		*value = 0;
645 	}
646 
647 	return rc;
648 }
649 
650 int hl_get_current(struct hl_device *hdev,
651 			int sensor_index, u32 attr, long *value)
652 {
653 	struct cpucp_packet pkt;
654 	u64 result;
655 	int rc;
656 
657 	memset(&pkt, 0, sizeof(pkt));
658 
659 	pkt.ctl = cpu_to_le32(CPUCP_PACKET_CURRENT_GET <<
660 				CPUCP_PKT_CTL_OPCODE_SHIFT);
661 	pkt.sensor_index = __cpu_to_le16(sensor_index);
662 	pkt.type = __cpu_to_le16(attr);
663 
664 	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
665 						0, &result);
666 
667 	*value = (long) result;
668 
669 	if (rc) {
670 		dev_err(hdev->dev,
671 			"Failed to get current from sensor %d, error %d\n",
672 			sensor_index, rc);
673 		*value = 0;
674 	}
675 
676 	return rc;
677 }
678 
679 int hl_get_fan_speed(struct hl_device *hdev,
680 			int sensor_index, u32 attr, long *value)
681 {
682 	struct cpucp_packet pkt;
683 	u64 result;
684 	int rc;
685 
686 	memset(&pkt, 0, sizeof(pkt));
687 
688 	pkt.ctl = cpu_to_le32(CPUCP_PACKET_FAN_SPEED_GET <<
689 				CPUCP_PKT_CTL_OPCODE_SHIFT);
690 	pkt.sensor_index = __cpu_to_le16(sensor_index);
691 	pkt.type = __cpu_to_le16(attr);
692 
693 	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
694 						0, &result);
695 
696 	*value = (long) result;
697 
698 	if (rc) {
699 		dev_err(hdev->dev,
700 			"Failed to get fan speed from sensor %d, error %d\n",
701 			sensor_index, rc);
702 		*value = 0;
703 	}
704 
705 	return rc;
706 }
707 
708 int hl_get_pwm_info(struct hl_device *hdev,
709 			int sensor_index, u32 attr, long *value)
710 {
711 	struct cpucp_packet pkt;
712 	u64 result;
713 	int rc;
714 
715 	memset(&pkt, 0, sizeof(pkt));
716 
717 	pkt.ctl = cpu_to_le32(CPUCP_PACKET_PWM_GET <<
718 				CPUCP_PKT_CTL_OPCODE_SHIFT);
719 	pkt.sensor_index = __cpu_to_le16(sensor_index);
720 	pkt.type = __cpu_to_le16(attr);
721 
722 	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
723 						0, &result);
724 
725 	*value = (long) result;
726 
727 	if (rc) {
728 		dev_err(hdev->dev,
729 			"Failed to get pwm info from sensor %d, error %d\n",
730 			sensor_index, rc);
731 		*value = 0;
732 	}
733 
734 	return rc;
735 }
736 
737 void hl_set_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr,
738 			long value)
739 {
740 	struct cpucp_packet pkt;
741 	int rc;
742 
743 	memset(&pkt, 0, sizeof(pkt));
744 
745 	pkt.ctl = cpu_to_le32(CPUCP_PACKET_PWM_SET <<
746 				CPUCP_PKT_CTL_OPCODE_SHIFT);
747 	pkt.sensor_index = __cpu_to_le16(sensor_index);
748 	pkt.type = __cpu_to_le16(attr);
749 	pkt.value = cpu_to_le64(value);
750 
751 	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
752 						0, NULL);
753 
754 	if (rc)
755 		dev_err(hdev->dev,
756 			"Failed to set pwm info to sensor %d, error %d\n",
757 			sensor_index, rc);
758 }
759 
760 int hl_set_voltage(struct hl_device *hdev,
761 			int sensor_index, u32 attr, long value)
762 {
763 	struct cpucp_packet pkt;
764 	int rc;
765 
766 	memset(&pkt, 0, sizeof(pkt));
767 
768 	pkt.ctl = cpu_to_le32(CPUCP_PACKET_VOLTAGE_SET <<
769 				CPUCP_PKT_CTL_OPCODE_SHIFT);
770 	pkt.sensor_index = __cpu_to_le16(sensor_index);
771 	pkt.type = __cpu_to_le16(attr);
772 	pkt.value = __cpu_to_le64(value);
773 
774 	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
775 						0, NULL);
776 
777 	if (rc)
778 		dev_err(hdev->dev,
779 			"Failed to set voltage of sensor %d, error %d\n",
780 			sensor_index, rc);
781 
782 	return rc;
783 }
784 
785 int hl_set_current(struct hl_device *hdev,
786 			int sensor_index, u32 attr, long value)
787 {
788 	struct cpucp_packet pkt;
789 	int rc;
790 
791 	memset(&pkt, 0, sizeof(pkt));
792 
793 	pkt.ctl = cpu_to_le32(CPUCP_PACKET_CURRENT_SET <<
794 				CPUCP_PKT_CTL_OPCODE_SHIFT);
795 	pkt.sensor_index = __cpu_to_le16(sensor_index);
796 	pkt.type = __cpu_to_le16(attr);
797 	pkt.value = __cpu_to_le64(value);
798 
799 	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
800 						0, NULL);
801 
802 	if (rc)
803 		dev_err(hdev->dev,
804 			"Failed to set current of sensor %d, error %d\n",
805 			sensor_index, rc);
806 
807 	return rc;
808 }
809 
810 int hl_set_power(struct hl_device *hdev,
811 			int sensor_index, u32 attr, long value)
812 {
813 	struct cpucp_packet pkt;
814 	struct asic_fixed_properties *prop = &hdev->asic_prop;
815 	int rc;
816 
817 	memset(&pkt, 0, sizeof(pkt));
818 
819 	if (prop->use_get_power_for_reset_history)
820 		pkt.ctl = cpu_to_le32(CPUCP_PACKET_POWER_GET <<
821 				CPUCP_PKT_CTL_OPCODE_SHIFT);
822 	else
823 		pkt.ctl = cpu_to_le32(CPUCP_PACKET_POWER_SET <<
824 				CPUCP_PKT_CTL_OPCODE_SHIFT);
825 
826 	pkt.sensor_index = __cpu_to_le16(sensor_index);
827 	pkt.type = __cpu_to_le16(attr);
828 	pkt.value = __cpu_to_le64(value);
829 
830 	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
831 						0, NULL);
832 
833 	if (rc)
834 		dev_err(hdev->dev,
835 			"Failed to set power of sensor %d, error %d\n",
836 			sensor_index, rc);
837 
838 	return rc;
839 }
840 
841 int hl_get_power(struct hl_device *hdev,
842 			int sensor_index, u32 attr, long *value)
843 {
844 	struct cpucp_packet pkt;
845 	u64 result;
846 	int rc;
847 
848 	memset(&pkt, 0, sizeof(pkt));
849 
850 	pkt.ctl = cpu_to_le32(CPUCP_PACKET_POWER_GET <<
851 				CPUCP_PKT_CTL_OPCODE_SHIFT);
852 	pkt.sensor_index = __cpu_to_le16(sensor_index);
853 	pkt.type = __cpu_to_le16(attr);
854 
855 	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
856 						0, &result);
857 
858 	*value = (long) result;
859 
860 	if (rc) {
861 		dev_err(hdev->dev,
862 			"Failed to get power of sensor %d, error %d\n",
863 			sensor_index, rc);
864 		*value = 0;
865 	}
866 
867 	return rc;
868 }
869 
870 int hl_hwmon_init(struct hl_device *hdev)
871 {
872 	struct device *dev = hdev->pdev ? &hdev->pdev->dev : hdev->dev;
873 	struct asic_fixed_properties *prop = &hdev->asic_prop;
874 	int rc;
875 
876 	if ((hdev->hwmon_initialized) || !(hdev->cpu_queues_enable))
877 		return 0;
878 
879 	if (hdev->hl_chip_info->info) {
880 		hdev->hl_chip_info->ops = &hl_hwmon_ops;
881 
882 		hdev->hwmon_dev = hwmon_device_register_with_info(dev,
883 					prop->cpucp_info.card_name, hdev,
884 					hdev->hl_chip_info, NULL);
885 		if (IS_ERR(hdev->hwmon_dev)) {
886 			rc = PTR_ERR(hdev->hwmon_dev);
887 			dev_err(hdev->dev,
888 				"Unable to register hwmon device: %d\n", rc);
889 			return rc;
890 		}
891 
892 		dev_info(hdev->dev, "%s: add sensors information\n",
893 			dev_name(hdev->hwmon_dev));
894 
895 		hdev->hwmon_initialized = true;
896 	} else {
897 		dev_info(hdev->dev, "no available sensors\n");
898 	}
899 
900 	return 0;
901 }
902 
903 void hl_hwmon_fini(struct hl_device *hdev)
904 {
905 	if (!hdev->hwmon_initialized)
906 		return;
907 
908 	hwmon_device_unregister(hdev->hwmon_dev);
909 }
910 
911 void hl_hwmon_release_resources(struct hl_device *hdev)
912 {
913 	const struct hwmon_channel_info * const *channel_info_arr;
914 	int i = 0;
915 
916 	if (!hdev->hl_chip_info->info)
917 		return;
918 
919 	channel_info_arr = hdev->hl_chip_info->info;
920 
921 	while (channel_info_arr[i]) {
922 		kfree(channel_info_arr[i]->config);
923 		kfree(channel_info_arr[i]);
924 		i++;
925 	}
926 
927 	kfree(channel_info_arr);
928 
929 	hdev->hl_chip_info->info = NULL;
930 }
931