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_pwm + 1)
14
hl_build_hwmon_channel_info(struct hl_device * hdev,struct cpucp_sensor * sensors_arr)15 int hl_build_hwmon_channel_info(struct hl_device *hdev,
16 struct cpucp_sensor *sensors_arr)
17 {
18 u32 counts[HWMON_NR_SENSOR_TYPES] = {0};
19 u32 *sensors_by_type[HWMON_NR_SENSOR_TYPES] = {NULL};
20 u32 sensors_by_type_next_index[HWMON_NR_SENSOR_TYPES] = {0};
21 struct hwmon_channel_info **channels_info;
22 u32 num_sensors_for_type, num_active_sensor_types = 0,
23 arr_size = 0, *curr_arr;
24 enum hwmon_sensor_types type;
25 int rc, i, j;
26
27 for (i = 0 ; i < CPUCP_MAX_SENSORS ; i++) {
28 type = le32_to_cpu(sensors_arr[i].type);
29
30 if ((type == 0) && (sensors_arr[i].flags == 0))
31 break;
32
33 if (type >= HWMON_NR_SENSOR_TYPES) {
34 dev_err(hdev->dev,
35 "Got wrong sensor type %d from device\n", type);
36 return -EINVAL;
37 }
38
39 counts[type]++;
40 arr_size++;
41 }
42
43 for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) {
44 if (counts[i] == 0)
45 continue;
46
47 num_sensors_for_type = counts[i] + 1;
48 curr_arr = kcalloc(num_sensors_for_type, sizeof(*curr_arr),
49 GFP_KERNEL);
50 if (!curr_arr) {
51 rc = -ENOMEM;
52 goto sensors_type_err;
53 }
54
55 num_active_sensor_types++;
56 sensors_by_type[i] = curr_arr;
57 }
58
59 for (i = 0 ; i < arr_size ; i++) {
60 type = le32_to_cpu(sensors_arr[i].type);
61 curr_arr = sensors_by_type[type];
62 curr_arr[sensors_by_type_next_index[type]++] =
63 le32_to_cpu(sensors_arr[i].flags);
64 }
65
66 channels_info = kcalloc(num_active_sensor_types + 1,
67 sizeof(*channels_info), GFP_KERNEL);
68 if (!channels_info) {
69 rc = -ENOMEM;
70 goto channels_info_array_err;
71 }
72
73 for (i = 0 ; i < num_active_sensor_types ; i++) {
74 channels_info[i] = kzalloc(sizeof(*channels_info[i]),
75 GFP_KERNEL);
76 if (!channels_info[i]) {
77 rc = -ENOMEM;
78 goto channel_info_err;
79 }
80 }
81
82 for (i = 0, j = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) {
83 if (!sensors_by_type[i])
84 continue;
85
86 channels_info[j]->type = i;
87 channels_info[j]->config = sensors_by_type[i];
88 j++;
89 }
90
91 hdev->hl_chip_info->info =
92 (const struct hwmon_channel_info **)channels_info;
93
94 return 0;
95
96 channel_info_err:
97 for (i = 0 ; i < num_active_sensor_types ; i++)
98 if (channels_info[i]) {
99 kfree(channels_info[i]->config);
100 kfree(channels_info[i]);
101 }
102 kfree(channels_info);
103 channels_info_array_err:
104 sensors_type_err:
105 for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++)
106 kfree(sensors_by_type[i]);
107
108 return rc;
109 }
110
hl_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)111 static int hl_read(struct device *dev, enum hwmon_sensor_types type,
112 u32 attr, int channel, long *val)
113 {
114 struct hl_device *hdev = dev_get_drvdata(dev);
115 int rc;
116 u32 cpucp_attr;
117 bool use_cpucp_enum = (hdev->asic_prop.fw_app_cpu_boot_dev_sts0 &
118 CPU_BOOT_DEV_STS0_MAP_HWMON_EN) ? true : false;
119
120 if (!hl_device_operational(hdev, NULL))
121 return -ENODEV;
122
123 switch (type) {
124 case hwmon_temp:
125 switch (attr) {
126 case hwmon_temp_input:
127 cpucp_attr = cpucp_temp_input;
128 break;
129 case hwmon_temp_max:
130 cpucp_attr = cpucp_temp_max;
131 break;
132 case hwmon_temp_crit:
133 cpucp_attr = cpucp_temp_crit;
134 break;
135 case hwmon_temp_max_hyst:
136 cpucp_attr = cpucp_temp_max_hyst;
137 break;
138 case hwmon_temp_crit_hyst:
139 cpucp_attr = cpucp_temp_crit_hyst;
140 break;
141 case hwmon_temp_offset:
142 cpucp_attr = cpucp_temp_offset;
143 break;
144 case hwmon_temp_highest:
145 cpucp_attr = cpucp_temp_highest;
146 break;
147 default:
148 return -EINVAL;
149 }
150
151 if (use_cpucp_enum)
152 rc = hl_get_temperature(hdev, channel, cpucp_attr, val);
153 else
154 rc = hl_get_temperature(hdev, channel, attr, val);
155 break;
156 case hwmon_in:
157 switch (attr) {
158 case hwmon_in_input:
159 cpucp_attr = cpucp_in_input;
160 break;
161 case hwmon_in_min:
162 cpucp_attr = cpucp_in_min;
163 break;
164 case hwmon_in_max:
165 cpucp_attr = cpucp_in_max;
166 break;
167 case hwmon_in_highest:
168 cpucp_attr = cpucp_in_highest;
169 break;
170 default:
171 return -EINVAL;
172 }
173
174 if (use_cpucp_enum)
175 rc = hl_get_voltage(hdev, channel, cpucp_attr, val);
176 else
177 rc = hl_get_voltage(hdev, channel, attr, val);
178 break;
179 case hwmon_curr:
180 switch (attr) {
181 case hwmon_curr_input:
182 cpucp_attr = cpucp_curr_input;
183 break;
184 case hwmon_curr_min:
185 cpucp_attr = cpucp_curr_min;
186 break;
187 case hwmon_curr_max:
188 cpucp_attr = cpucp_curr_max;
189 break;
190 case hwmon_curr_highest:
191 cpucp_attr = cpucp_curr_highest;
192 break;
193 default:
194 return -EINVAL;
195 }
196
197 if (use_cpucp_enum)
198 rc = hl_get_current(hdev, channel, cpucp_attr, val);
199 else
200 rc = hl_get_current(hdev, channel, attr, val);
201 break;
202 case hwmon_fan:
203 switch (attr) {
204 case hwmon_fan_input:
205 cpucp_attr = cpucp_fan_input;
206 break;
207 case hwmon_fan_min:
208 cpucp_attr = cpucp_fan_min;
209 break;
210 case hwmon_fan_max:
211 cpucp_attr = cpucp_fan_max;
212 break;
213 default:
214 return -EINVAL;
215 }
216
217 if (use_cpucp_enum)
218 rc = hl_get_fan_speed(hdev, channel, cpucp_attr, val);
219 else
220 rc = hl_get_fan_speed(hdev, channel, attr, val);
221 break;
222 case hwmon_pwm:
223 switch (attr) {
224 case hwmon_pwm_input:
225 cpucp_attr = cpucp_pwm_input;
226 break;
227 case hwmon_pwm_enable:
228 cpucp_attr = cpucp_pwm_enable;
229 break;
230 default:
231 return -EINVAL;
232 }
233
234 if (use_cpucp_enum)
235 rc = hl_get_pwm_info(hdev, channel, cpucp_attr, val);
236 else
237 rc = hl_get_pwm_info(hdev, channel, attr, val);
238 break;
239 case hwmon_power:
240 switch (attr) {
241 case hwmon_power_input:
242 cpucp_attr = CPUCP_POWER_INPUT;
243 break;
244 case hwmon_power_input_highest:
245 cpucp_attr = CPUCP_POWER_INPUT_HIGHEST;
246 break;
247 default:
248 return -EINVAL;
249 }
250
251 if (use_cpucp_enum)
252 rc = hl_get_power(hdev, channel, cpucp_attr, val);
253 else
254 rc = hl_get_power(hdev, channel, attr, val);
255 break;
256 default:
257 return -EINVAL;
258 }
259 return rc;
260 }
261
hl_write(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long val)262 static int hl_write(struct device *dev, enum hwmon_sensor_types type,
263 u32 attr, int channel, long val)
264 {
265 struct hl_device *hdev = dev_get_drvdata(dev);
266 u32 cpucp_attr;
267 bool use_cpucp_enum = (hdev->asic_prop.fw_app_cpu_boot_dev_sts0 &
268 CPU_BOOT_DEV_STS0_MAP_HWMON_EN) ? true : false;
269
270 if (!hl_device_operational(hdev, NULL))
271 return -ENODEV;
272
273 switch (type) {
274 case hwmon_temp:
275 switch (attr) {
276 case hwmon_temp_offset:
277 cpucp_attr = cpucp_temp_offset;
278 break;
279 case hwmon_temp_reset_history:
280 cpucp_attr = cpucp_temp_reset_history;
281 break;
282 default:
283 return -EINVAL;
284 }
285
286 if (use_cpucp_enum)
287 hl_set_temperature(hdev, channel, cpucp_attr, val);
288 else
289 hl_set_temperature(hdev, channel, attr, val);
290 break;
291 case hwmon_pwm:
292 switch (attr) {
293 case hwmon_pwm_input:
294 cpucp_attr = cpucp_pwm_input;
295 break;
296 case hwmon_pwm_enable:
297 cpucp_attr = cpucp_pwm_enable;
298 break;
299 default:
300 return -EINVAL;
301 }
302
303 if (use_cpucp_enum)
304 hl_set_pwm_info(hdev, channel, cpucp_attr, val);
305 else
306 hl_set_pwm_info(hdev, channel, attr, val);
307 break;
308 case hwmon_in:
309 switch (attr) {
310 case hwmon_in_reset_history:
311 cpucp_attr = cpucp_in_reset_history;
312 break;
313 default:
314 return -EINVAL;
315 }
316
317 if (use_cpucp_enum)
318 hl_set_voltage(hdev, channel, cpucp_attr, val);
319 else
320 hl_set_voltage(hdev, channel, attr, val);
321 break;
322 case hwmon_curr:
323 switch (attr) {
324 case hwmon_curr_reset_history:
325 cpucp_attr = cpucp_curr_reset_history;
326 break;
327 default:
328 return -EINVAL;
329 }
330
331 if (use_cpucp_enum)
332 hl_set_current(hdev, channel, cpucp_attr, val);
333 else
334 hl_set_current(hdev, channel, attr, val);
335 break;
336 case hwmon_power:
337 switch (attr) {
338 case hwmon_power_reset_history:
339 cpucp_attr = CPUCP_POWER_RESET_INPUT_HISTORY;
340 break;
341 default:
342 return -EINVAL;
343 }
344
345 if (use_cpucp_enum)
346 hl_set_power(hdev, channel, cpucp_attr, val);
347 else
348 hl_set_power(hdev, channel, attr, val);
349 break;
350 default:
351 return -EINVAL;
352 }
353 return 0;
354 }
355
hl_is_visible(const void * data,enum hwmon_sensor_types type,u32 attr,int channel)356 static umode_t hl_is_visible(const void *data, enum hwmon_sensor_types type,
357 u32 attr, int channel)
358 {
359 switch (type) {
360 case hwmon_temp:
361 switch (attr) {
362 case hwmon_temp_input:
363 case hwmon_temp_max:
364 case hwmon_temp_max_hyst:
365 case hwmon_temp_crit:
366 case hwmon_temp_crit_hyst:
367 case hwmon_temp_highest:
368 return 0444;
369 case hwmon_temp_offset:
370 return 0644;
371 case hwmon_temp_reset_history:
372 return 0200;
373 }
374 break;
375 case hwmon_in:
376 switch (attr) {
377 case hwmon_in_input:
378 case hwmon_in_min:
379 case hwmon_in_max:
380 case hwmon_in_highest:
381 return 0444;
382 case hwmon_in_reset_history:
383 return 0200;
384 }
385 break;
386 case hwmon_curr:
387 switch (attr) {
388 case hwmon_curr_input:
389 case hwmon_curr_min:
390 case hwmon_curr_max:
391 case hwmon_curr_highest:
392 return 0444;
393 case hwmon_curr_reset_history:
394 return 0200;
395 }
396 break;
397 case hwmon_fan:
398 switch (attr) {
399 case hwmon_fan_input:
400 case hwmon_fan_min:
401 case hwmon_fan_max:
402 return 0444;
403 }
404 break;
405 case hwmon_pwm:
406 switch (attr) {
407 case hwmon_pwm_input:
408 case hwmon_pwm_enable:
409 return 0644;
410 }
411 break;
412 case hwmon_power:
413 switch (attr) {
414 case hwmon_power_input:
415 case hwmon_power_input_highest:
416 return 0444;
417 case hwmon_power_reset_history:
418 return 0200;
419 }
420 break;
421 default:
422 break;
423 }
424 return 0;
425 }
426
427 static const struct hwmon_ops hl_hwmon_ops = {
428 .is_visible = hl_is_visible,
429 .read = hl_read,
430 .write = hl_write
431 };
432
hl_get_temperature(struct hl_device * hdev,int sensor_index,u32 attr,long * value)433 int hl_get_temperature(struct hl_device *hdev,
434 int sensor_index, u32 attr, long *value)
435 {
436 struct cpucp_packet pkt;
437 u64 result;
438 int rc;
439
440 memset(&pkt, 0, sizeof(pkt));
441
442 pkt.ctl = cpu_to_le32(CPUCP_PACKET_TEMPERATURE_GET <<
443 CPUCP_PKT_CTL_OPCODE_SHIFT);
444 pkt.sensor_index = __cpu_to_le16(sensor_index);
445 pkt.type = __cpu_to_le16(attr);
446
447 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
448 0, &result);
449
450 *value = (long) result;
451
452 if (rc) {
453 dev_err(hdev->dev,
454 "Failed to get temperature from sensor %d, error %d\n",
455 sensor_index, rc);
456 *value = 0;
457 }
458
459 return rc;
460 }
461
hl_set_temperature(struct hl_device * hdev,int sensor_index,u32 attr,long value)462 int hl_set_temperature(struct hl_device *hdev,
463 int sensor_index, u32 attr, long value)
464 {
465 struct cpucp_packet pkt;
466 int rc;
467
468 memset(&pkt, 0, sizeof(pkt));
469
470 pkt.ctl = cpu_to_le32(CPUCP_PACKET_TEMPERATURE_SET <<
471 CPUCP_PKT_CTL_OPCODE_SHIFT);
472 pkt.sensor_index = __cpu_to_le16(sensor_index);
473 pkt.type = __cpu_to_le16(attr);
474 pkt.value = __cpu_to_le64(value);
475
476 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
477 0, NULL);
478
479 if (rc)
480 dev_err(hdev->dev,
481 "Failed to set temperature of sensor %d, error %d\n",
482 sensor_index, rc);
483
484 return rc;
485 }
486
hl_get_voltage(struct hl_device * hdev,int sensor_index,u32 attr,long * value)487 int hl_get_voltage(struct hl_device *hdev,
488 int sensor_index, u32 attr, long *value)
489 {
490 struct cpucp_packet pkt;
491 u64 result;
492 int rc;
493
494 memset(&pkt, 0, sizeof(pkt));
495
496 pkt.ctl = cpu_to_le32(CPUCP_PACKET_VOLTAGE_GET <<
497 CPUCP_PKT_CTL_OPCODE_SHIFT);
498 pkt.sensor_index = __cpu_to_le16(sensor_index);
499 pkt.type = __cpu_to_le16(attr);
500
501 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
502 0, &result);
503
504 *value = (long) result;
505
506 if (rc) {
507 dev_err(hdev->dev,
508 "Failed to get voltage from sensor %d, error %d\n",
509 sensor_index, rc);
510 *value = 0;
511 }
512
513 return rc;
514 }
515
hl_get_current(struct hl_device * hdev,int sensor_index,u32 attr,long * value)516 int hl_get_current(struct hl_device *hdev,
517 int sensor_index, u32 attr, long *value)
518 {
519 struct cpucp_packet pkt;
520 u64 result;
521 int rc;
522
523 memset(&pkt, 0, sizeof(pkt));
524
525 pkt.ctl = cpu_to_le32(CPUCP_PACKET_CURRENT_GET <<
526 CPUCP_PKT_CTL_OPCODE_SHIFT);
527 pkt.sensor_index = __cpu_to_le16(sensor_index);
528 pkt.type = __cpu_to_le16(attr);
529
530 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
531 0, &result);
532
533 *value = (long) result;
534
535 if (rc) {
536 dev_err(hdev->dev,
537 "Failed to get current from sensor %d, error %d\n",
538 sensor_index, rc);
539 *value = 0;
540 }
541
542 return rc;
543 }
544
hl_get_fan_speed(struct hl_device * hdev,int sensor_index,u32 attr,long * value)545 int hl_get_fan_speed(struct hl_device *hdev,
546 int sensor_index, u32 attr, long *value)
547 {
548 struct cpucp_packet pkt;
549 u64 result;
550 int rc;
551
552 memset(&pkt, 0, sizeof(pkt));
553
554 pkt.ctl = cpu_to_le32(CPUCP_PACKET_FAN_SPEED_GET <<
555 CPUCP_PKT_CTL_OPCODE_SHIFT);
556 pkt.sensor_index = __cpu_to_le16(sensor_index);
557 pkt.type = __cpu_to_le16(attr);
558
559 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
560 0, &result);
561
562 *value = (long) result;
563
564 if (rc) {
565 dev_err(hdev->dev,
566 "Failed to get fan speed from sensor %d, error %d\n",
567 sensor_index, rc);
568 *value = 0;
569 }
570
571 return rc;
572 }
573
hl_get_pwm_info(struct hl_device * hdev,int sensor_index,u32 attr,long * value)574 int hl_get_pwm_info(struct hl_device *hdev,
575 int sensor_index, u32 attr, long *value)
576 {
577 struct cpucp_packet pkt;
578 u64 result;
579 int rc;
580
581 memset(&pkt, 0, sizeof(pkt));
582
583 pkt.ctl = cpu_to_le32(CPUCP_PACKET_PWM_GET <<
584 CPUCP_PKT_CTL_OPCODE_SHIFT);
585 pkt.sensor_index = __cpu_to_le16(sensor_index);
586 pkt.type = __cpu_to_le16(attr);
587
588 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
589 0, &result);
590
591 *value = (long) result;
592
593 if (rc) {
594 dev_err(hdev->dev,
595 "Failed to get pwm info from sensor %d, error %d\n",
596 sensor_index, rc);
597 *value = 0;
598 }
599
600 return rc;
601 }
602
hl_set_pwm_info(struct hl_device * hdev,int sensor_index,u32 attr,long value)603 void hl_set_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr,
604 long value)
605 {
606 struct cpucp_packet pkt;
607 int rc;
608
609 memset(&pkt, 0, sizeof(pkt));
610
611 pkt.ctl = cpu_to_le32(CPUCP_PACKET_PWM_SET <<
612 CPUCP_PKT_CTL_OPCODE_SHIFT);
613 pkt.sensor_index = __cpu_to_le16(sensor_index);
614 pkt.type = __cpu_to_le16(attr);
615 pkt.value = cpu_to_le64(value);
616
617 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
618 0, NULL);
619
620 if (rc)
621 dev_err(hdev->dev,
622 "Failed to set pwm info to sensor %d, error %d\n",
623 sensor_index, rc);
624 }
625
hl_set_voltage(struct hl_device * hdev,int sensor_index,u32 attr,long value)626 int hl_set_voltage(struct hl_device *hdev,
627 int sensor_index, u32 attr, long value)
628 {
629 struct cpucp_packet pkt;
630 int rc;
631
632 memset(&pkt, 0, sizeof(pkt));
633
634 pkt.ctl = cpu_to_le32(CPUCP_PACKET_VOLTAGE_SET <<
635 CPUCP_PKT_CTL_OPCODE_SHIFT);
636 pkt.sensor_index = __cpu_to_le16(sensor_index);
637 pkt.type = __cpu_to_le16(attr);
638 pkt.value = __cpu_to_le64(value);
639
640 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
641 0, NULL);
642
643 if (rc)
644 dev_err(hdev->dev,
645 "Failed to set voltage of sensor %d, error %d\n",
646 sensor_index, rc);
647
648 return rc;
649 }
650
hl_set_current(struct hl_device * hdev,int sensor_index,u32 attr,long value)651 int hl_set_current(struct hl_device *hdev,
652 int sensor_index, u32 attr, long value)
653 {
654 struct cpucp_packet pkt;
655 int rc;
656
657 memset(&pkt, 0, sizeof(pkt));
658
659 pkt.ctl = cpu_to_le32(CPUCP_PACKET_CURRENT_SET <<
660 CPUCP_PKT_CTL_OPCODE_SHIFT);
661 pkt.sensor_index = __cpu_to_le16(sensor_index);
662 pkt.type = __cpu_to_le16(attr);
663 pkt.value = __cpu_to_le64(value);
664
665 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
666 0, NULL);
667
668 if (rc)
669 dev_err(hdev->dev,
670 "Failed to set current of sensor %d, error %d\n",
671 sensor_index, rc);
672
673 return rc;
674 }
675
hl_set_power(struct hl_device * hdev,int sensor_index,u32 attr,long value)676 int hl_set_power(struct hl_device *hdev,
677 int sensor_index, u32 attr, long value)
678 {
679 struct cpucp_packet pkt;
680 int rc;
681
682 memset(&pkt, 0, sizeof(pkt));
683
684 pkt.ctl = cpu_to_le32(CPUCP_PACKET_POWER_GET <<
685 CPUCP_PKT_CTL_OPCODE_SHIFT);
686 pkt.sensor_index = __cpu_to_le16(sensor_index);
687 pkt.type = __cpu_to_le16(attr);
688 pkt.value = __cpu_to_le64(value);
689
690 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
691 0, NULL);
692
693 if (rc)
694 dev_err(hdev->dev,
695 "Failed to set power of sensor %d, error %d\n",
696 sensor_index, rc);
697
698 return rc;
699 }
700
hl_get_power(struct hl_device * hdev,int sensor_index,u32 attr,long * value)701 int hl_get_power(struct hl_device *hdev,
702 int sensor_index, u32 attr, long *value)
703 {
704 struct cpucp_packet pkt;
705 u64 result;
706 int rc;
707
708 memset(&pkt, 0, sizeof(pkt));
709
710 pkt.ctl = cpu_to_le32(CPUCP_PACKET_POWER_GET <<
711 CPUCP_PKT_CTL_OPCODE_SHIFT);
712 pkt.sensor_index = __cpu_to_le16(sensor_index);
713 pkt.type = __cpu_to_le16(attr);
714
715 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
716 0, &result);
717
718 *value = (long) result;
719
720 if (rc) {
721 dev_err(hdev->dev,
722 "Failed to get power of sensor %d, error %d\n",
723 sensor_index, rc);
724 *value = 0;
725 }
726
727 return rc;
728 }
729
hl_hwmon_init(struct hl_device * hdev)730 int hl_hwmon_init(struct hl_device *hdev)
731 {
732 struct device *dev = hdev->pdev ? &hdev->pdev->dev : hdev->dev;
733 struct asic_fixed_properties *prop = &hdev->asic_prop;
734 int rc;
735
736 if ((hdev->hwmon_initialized) || !(hdev->cpu_queues_enable))
737 return 0;
738
739 if (hdev->hl_chip_info->info) {
740 hdev->hl_chip_info->ops = &hl_hwmon_ops;
741
742 hdev->hwmon_dev = hwmon_device_register_with_info(dev,
743 prop->cpucp_info.card_name, hdev,
744 hdev->hl_chip_info, NULL);
745 if (IS_ERR(hdev->hwmon_dev)) {
746 rc = PTR_ERR(hdev->hwmon_dev);
747 dev_err(hdev->dev,
748 "Unable to register hwmon device: %d\n", rc);
749 return rc;
750 }
751
752 dev_info(hdev->dev, "%s: add sensors information\n",
753 dev_name(hdev->hwmon_dev));
754
755 hdev->hwmon_initialized = true;
756 } else {
757 dev_info(hdev->dev, "no available sensors\n");
758 }
759
760 return 0;
761 }
762
hl_hwmon_fini(struct hl_device * hdev)763 void hl_hwmon_fini(struct hl_device *hdev)
764 {
765 if (!hdev->hwmon_initialized)
766 return;
767
768 hwmon_device_unregister(hdev->hwmon_dev);
769 }
770