GNU Linux-libre 6.8.9-gnu
[releases.git] / drivers / accel / habanalabs / common / hwmon.c
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 }