932 lines · c
1// SPDX-License-Identifier: GPL-2.02 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_ENABLE16 17static 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_ratelimited(hdev->dev, "unsupported h/w sensor type %d\n", type);50 flags = cpucp_flags;51 break;52 }53 54 return flags;55}56 57static u32 fixup_attr_legacy_fw(u32 attr)58{59 return (attr - 1);60}61 62#else63 64static 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 70static u32 fixup_attr_legacy_fw(u32 attr)71{72 return attr;73}74 75#endif /* !_HAS_HWMON_HWMON_T_ENABLE */76 77static 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 the87 * 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 else96 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 else104 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 else112 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 else120 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 else133 flags = (cpucp_flags << 1) | HWMON_P_ENABLE;134 break;135 136 default:137 dev_err_ratelimited(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 148int 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_ratelimited(hdev->dev,166 "Got wrong sensor type %d from device\n", type);167 return -EINVAL;168 }169 170 counts[type]++;171 arr_size++;172 }173 174 for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) {175 if (counts[i] == 0)176 continue;177 178 num_sensors_for_type = counts[i] + 1;179 dev_dbg(hdev->dev, "num_sensors_for_type %d = %d\n", i, num_sensors_for_type);180 181 curr_arr = kcalloc(num_sensors_for_type, sizeof(*curr_arr), GFP_KERNEL);182 if (!curr_arr) {183 rc = -ENOMEM;184 goto sensors_type_err;185 }186 187 num_active_sensor_types++;188 sensors_by_type[i] = curr_arr;189 }190 191 for (i = 0 ; i < arr_size ; i++) {192 type = le32_to_cpu(sensors_arr[i].type);193 curr_arr = sensors_by_type[type];194 flags = adjust_hwmon_flags(hdev, type, le32_to_cpu(sensors_arr[i].flags));195 curr_arr[sensors_by_type_next_index[type]++] = flags;196 }197 198 channels_info = kcalloc(num_active_sensor_types + 1, sizeof(struct hwmon_channel_info *),199 GFP_KERNEL);200 if (!channels_info) {201 rc = -ENOMEM;202 goto channels_info_array_err;203 }204 205 for (i = 0 ; i < num_active_sensor_types ; i++) {206 channels_info[i] = kzalloc(sizeof(*channels_info[i]), GFP_KERNEL);207 if (!channels_info[i]) {208 rc = -ENOMEM;209 goto channel_info_err;210 }211 }212 213 for (i = 0, j = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) {214 if (!sensors_by_type[i])215 continue;216 217 channels_info[j]->type = i;218 channels_info[j]->config = sensors_by_type[i];219 j++;220 }221 222 hdev->hl_chip_info->info = (const struct hwmon_channel_info **)channels_info;223 224 return 0;225 226channel_info_err:227 for (i = 0 ; i < num_active_sensor_types ; i++) {228 if (channels_info[i]) {229 kfree(channels_info[i]->config);230 kfree(channels_info[i]);231 }232 }233 kfree(channels_info);234 235channels_info_array_err:236sensors_type_err:237 for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++)238 kfree(sensors_by_type[i]);239 240 return rc;241}242 243static int hl_read(struct device *dev, enum hwmon_sensor_types type,244 u32 attr, int channel, long *val)245{246 struct hl_device *hdev = dev_get_drvdata(dev);247 bool use_cpucp_enum;248 u32 cpucp_attr;249 int rc;250 251 if (!hl_device_operational(hdev, NULL))252 return -ENODEV;253 254 use_cpucp_enum = (hdev->asic_prop.fw_app_cpu_boot_dev_sts0 &255 CPU_BOOT_DEV_STS0_MAP_HWMON_EN) ? true : false;256 257 switch (type) {258 case hwmon_temp:259 switch (attr) {260 case hwmon_temp_input:261 cpucp_attr = cpucp_temp_input;262 break;263 case hwmon_temp_max:264 cpucp_attr = cpucp_temp_max;265 break;266 case hwmon_temp_crit:267 cpucp_attr = cpucp_temp_crit;268 break;269 case hwmon_temp_max_hyst:270 cpucp_attr = cpucp_temp_max_hyst;271 break;272 case hwmon_temp_crit_hyst:273 cpucp_attr = cpucp_temp_crit_hyst;274 break;275 case hwmon_temp_offset:276 cpucp_attr = cpucp_temp_offset;277 break;278 case hwmon_temp_highest:279 cpucp_attr = cpucp_temp_highest;280 break;281 default:282 return -EINVAL;283 }284 285 if (use_cpucp_enum)286 rc = hl_get_temperature(hdev, channel, cpucp_attr, val);287 else288 rc = hl_get_temperature(hdev, channel, fixup_attr_legacy_fw(attr), val);289 break;290 case hwmon_in:291 switch (attr) {292 case hwmon_in_input:293 cpucp_attr = cpucp_in_input;294 break;295 case hwmon_in_min:296 cpucp_attr = cpucp_in_min;297 break;298 case hwmon_in_max:299 cpucp_attr = cpucp_in_max;300 break;301 case hwmon_in_highest:302 cpucp_attr = cpucp_in_highest;303 break;304 default:305 return -EINVAL;306 }307 308 if (use_cpucp_enum)309 rc = hl_get_voltage(hdev, channel, cpucp_attr, val);310 else311 rc = hl_get_voltage(hdev, channel, fixup_attr_legacy_fw(attr), val);312 break;313 case hwmon_curr:314 switch (attr) {315 case hwmon_curr_input:316 cpucp_attr = cpucp_curr_input;317 break;318 case hwmon_curr_min:319 cpucp_attr = cpucp_curr_min;320 break;321 case hwmon_curr_max:322 cpucp_attr = cpucp_curr_max;323 break;324 case hwmon_curr_highest:325 cpucp_attr = cpucp_curr_highest;326 break;327 default:328 return -EINVAL;329 }330 331 if (use_cpucp_enum)332 rc = hl_get_current(hdev, channel, cpucp_attr, val);333 else334 rc = hl_get_current(hdev, channel, fixup_attr_legacy_fw(attr), val);335 break;336 case hwmon_fan:337 switch (attr) {338 case hwmon_fan_input:339 cpucp_attr = cpucp_fan_input;340 break;341 case hwmon_fan_min:342 cpucp_attr = cpucp_fan_min;343 break;344 case hwmon_fan_max:345 cpucp_attr = cpucp_fan_max;346 break;347 default:348 return -EINVAL;349 }350 351 if (use_cpucp_enum)352 rc = hl_get_fan_speed(hdev, channel, cpucp_attr, val);353 else354 rc = hl_get_fan_speed(hdev, channel, fixup_attr_legacy_fw(attr), val);355 break;356 case hwmon_pwm:357 switch (attr) {358 case hwmon_pwm_input:359 cpucp_attr = cpucp_pwm_input;360 break;361 case hwmon_pwm_enable:362 cpucp_attr = cpucp_pwm_enable;363 break;364 default:365 return -EINVAL;366 }367 368 if (use_cpucp_enum)369 rc = hl_get_pwm_info(hdev, channel, cpucp_attr, val);370 else371 /* no need for fixup as pwm was aligned from day 1 */372 rc = hl_get_pwm_info(hdev, channel, attr, val);373 break;374 case hwmon_power:375 switch (attr) {376 case hwmon_power_input:377 cpucp_attr = CPUCP_POWER_INPUT;378 break;379 case hwmon_power_input_highest:380 cpucp_attr = CPUCP_POWER_INPUT_HIGHEST;381 break;382 default:383 return -EINVAL;384 }385 386 if (use_cpucp_enum)387 rc = hl_get_power(hdev, channel, cpucp_attr, val);388 else389 rc = hl_get_power(hdev, channel, fixup_attr_legacy_fw(attr), val);390 break;391 default:392 return -EINVAL;393 }394 return rc;395}396 397static int hl_write(struct device *dev, enum hwmon_sensor_types type,398 u32 attr, int channel, long val)399{400 struct hl_device *hdev = dev_get_drvdata(dev);401 u32 cpucp_attr;402 bool use_cpucp_enum = (hdev->asic_prop.fw_app_cpu_boot_dev_sts0 &403 CPU_BOOT_DEV_STS0_MAP_HWMON_EN) ? true : false;404 405 if (!hl_device_operational(hdev, NULL))406 return -ENODEV;407 408 switch (type) {409 case hwmon_temp:410 switch (attr) {411 case hwmon_temp_offset:412 cpucp_attr = cpucp_temp_offset;413 break;414 case hwmon_temp_reset_history:415 cpucp_attr = cpucp_temp_reset_history;416 break;417 default:418 return -EINVAL;419 }420 421 if (use_cpucp_enum)422 hl_set_temperature(hdev, channel, cpucp_attr, val);423 else424 hl_set_temperature(hdev, channel, fixup_attr_legacy_fw(attr), val);425 break;426 case hwmon_pwm:427 switch (attr) {428 case hwmon_pwm_input:429 cpucp_attr = cpucp_pwm_input;430 break;431 case hwmon_pwm_enable:432 cpucp_attr = cpucp_pwm_enable;433 break;434 default:435 return -EINVAL;436 }437 438 if (use_cpucp_enum)439 hl_set_pwm_info(hdev, channel, cpucp_attr, val);440 else441 /* no need for fixup as pwm was aligned from day 1 */442 hl_set_pwm_info(hdev, channel, attr, val);443 break;444 case hwmon_in:445 switch (attr) {446 case hwmon_in_reset_history:447 cpucp_attr = cpucp_in_reset_history;448 break;449 default:450 return -EINVAL;451 }452 453 if (use_cpucp_enum)454 hl_set_voltage(hdev, channel, cpucp_attr, val);455 else456 hl_set_voltage(hdev, channel, fixup_attr_legacy_fw(attr), val);457 break;458 case hwmon_curr:459 switch (attr) {460 case hwmon_curr_reset_history:461 cpucp_attr = cpucp_curr_reset_history;462 break;463 default:464 return -EINVAL;465 }466 467 if (use_cpucp_enum)468 hl_set_current(hdev, channel, cpucp_attr, val);469 else470 hl_set_current(hdev, channel, fixup_attr_legacy_fw(attr), val);471 break;472 case hwmon_power:473 switch (attr) {474 case hwmon_power_reset_history:475 cpucp_attr = CPUCP_POWER_RESET_INPUT_HISTORY;476 break;477 default:478 return -EINVAL;479 }480 481 if (use_cpucp_enum)482 hl_set_power(hdev, channel, cpucp_attr, val);483 else484 hl_set_power(hdev, channel, fixup_attr_legacy_fw(attr), val);485 break;486 default:487 return -EINVAL;488 }489 return 0;490}491 492static umode_t hl_is_visible(const void *data, enum hwmon_sensor_types type,493 u32 attr, int channel)494{495 switch (type) {496 case hwmon_temp:497 switch (attr) {498 case hwmon_temp_input:499 case hwmon_temp_max:500 case hwmon_temp_max_hyst:501 case hwmon_temp_crit:502 case hwmon_temp_crit_hyst:503 case hwmon_temp_highest:504 return 0444;505 case hwmon_temp_offset:506 return 0644;507 case hwmon_temp_reset_history:508 return 0200;509 }510 break;511 case hwmon_in:512 switch (attr) {513 case hwmon_in_input:514 case hwmon_in_min:515 case hwmon_in_max:516 case hwmon_in_highest:517 return 0444;518 case hwmon_in_reset_history:519 return 0200;520 }521 break;522 case hwmon_curr:523 switch (attr) {524 case hwmon_curr_input:525 case hwmon_curr_min:526 case hwmon_curr_max:527 case hwmon_curr_highest:528 return 0444;529 case hwmon_curr_reset_history:530 return 0200;531 }532 break;533 case hwmon_fan:534 switch (attr) {535 case hwmon_fan_input:536 case hwmon_fan_min:537 case hwmon_fan_max:538 return 0444;539 }540 break;541 case hwmon_pwm:542 switch (attr) {543 case hwmon_pwm_input:544 case hwmon_pwm_enable:545 return 0644;546 }547 break;548 case hwmon_power:549 switch (attr) {550 case hwmon_power_input:551 case hwmon_power_input_highest:552 return 0444;553 case hwmon_power_reset_history:554 return 0200;555 }556 break;557 default:558 break;559 }560 return 0;561}562 563static const struct hwmon_ops hl_hwmon_ops = {564 .is_visible = hl_is_visible,565 .read = hl_read,566 .write = hl_write567};568 569int hl_get_temperature(struct hl_device *hdev,570 int sensor_index, u32 attr, long *value)571{572 struct cpucp_packet pkt;573 u64 result;574 int rc;575 576 memset(&pkt, 0, sizeof(pkt));577 578 pkt.ctl = cpu_to_le32(CPUCP_PACKET_TEMPERATURE_GET <<579 CPUCP_PKT_CTL_OPCODE_SHIFT);580 pkt.sensor_index = __cpu_to_le16(sensor_index);581 pkt.type = __cpu_to_le16(attr);582 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),583 0, &result);584 585 *value = (long) result;586 587 if (rc) {588 if (rc != -EAGAIN)589 dev_err_ratelimited(hdev->dev,590 "Failed to get temperature from sensor %d, error %d\n",591 sensor_index, rc);592 *value = 0;593 }594 595 return rc;596}597 598int hl_set_temperature(struct hl_device *hdev,599 int sensor_index, u32 attr, long value)600{601 struct cpucp_packet pkt;602 int rc;603 604 memset(&pkt, 0, sizeof(pkt));605 606 pkt.ctl = cpu_to_le32(CPUCP_PACKET_TEMPERATURE_SET <<607 CPUCP_PKT_CTL_OPCODE_SHIFT);608 pkt.sensor_index = __cpu_to_le16(sensor_index);609 pkt.type = __cpu_to_le16(attr);610 pkt.value = __cpu_to_le64(value);611 612 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),613 0, NULL);614 if (rc && rc != -EAGAIN)615 dev_err_ratelimited(hdev->dev,616 "Failed to set temperature of sensor %d, error %d\n",617 sensor_index, rc);618 619 return rc;620}621 622int hl_get_voltage(struct hl_device *hdev,623 int sensor_index, u32 attr, long *value)624{625 struct cpucp_packet pkt;626 u64 result;627 int rc;628 629 memset(&pkt, 0, sizeof(pkt));630 631 pkt.ctl = cpu_to_le32(CPUCP_PACKET_VOLTAGE_GET <<632 CPUCP_PKT_CTL_OPCODE_SHIFT);633 pkt.sensor_index = __cpu_to_le16(sensor_index);634 pkt.type = __cpu_to_le16(attr);635 636 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),637 0, &result);638 639 *value = (long) result;640 641 if (rc) {642 if (rc != -EAGAIN)643 dev_err_ratelimited(hdev->dev,644 "Failed to get voltage from sensor %d, error %d\n",645 sensor_index, rc);646 *value = 0;647 }648 649 return rc;650}651 652int hl_get_current(struct hl_device *hdev,653 int sensor_index, u32 attr, long *value)654{655 struct cpucp_packet pkt;656 u64 result;657 int rc;658 659 memset(&pkt, 0, sizeof(pkt));660 661 pkt.ctl = cpu_to_le32(CPUCP_PACKET_CURRENT_GET <<662 CPUCP_PKT_CTL_OPCODE_SHIFT);663 pkt.sensor_index = __cpu_to_le16(sensor_index);664 pkt.type = __cpu_to_le16(attr);665 666 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),667 0, &result);668 669 *value = (long) result;670 671 if (rc) {672 if (rc != -EAGAIN)673 dev_err_ratelimited(hdev->dev,674 "Failed to get current from sensor %d, error %d\n",675 sensor_index, rc);676 *value = 0;677 }678 679 return rc;680}681 682int hl_get_fan_speed(struct hl_device *hdev,683 int sensor_index, u32 attr, long *value)684{685 struct cpucp_packet pkt;686 u64 result;687 int rc;688 689 memset(&pkt, 0, sizeof(pkt));690 691 pkt.ctl = cpu_to_le32(CPUCP_PACKET_FAN_SPEED_GET <<692 CPUCP_PKT_CTL_OPCODE_SHIFT);693 pkt.sensor_index = __cpu_to_le16(sensor_index);694 pkt.type = __cpu_to_le16(attr);695 696 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),697 0, &result);698 699 *value = (long) result;700 701 if (rc) {702 if (rc != -EAGAIN)703 dev_err_ratelimited(hdev->dev,704 "Failed to get fan speed from sensor %d, error %d\n",705 sensor_index, rc);706 *value = 0;707 }708 709 return rc;710}711 712int hl_get_pwm_info(struct hl_device *hdev,713 int sensor_index, u32 attr, long *value)714{715 struct cpucp_packet pkt;716 u64 result;717 int rc;718 719 memset(&pkt, 0, sizeof(pkt));720 721 pkt.ctl = cpu_to_le32(CPUCP_PACKET_PWM_GET <<722 CPUCP_PKT_CTL_OPCODE_SHIFT);723 pkt.sensor_index = __cpu_to_le16(sensor_index);724 pkt.type = __cpu_to_le16(attr);725 726 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),727 0, &result);728 729 *value = (long) result;730 731 if (rc) {732 if (rc != -EAGAIN)733 dev_err_ratelimited(hdev->dev,734 "Failed to get pwm info from sensor %d, error %d\n",735 sensor_index, rc);736 *value = 0;737 }738 739 return rc;740}741 742void hl_set_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr,743 long value)744{745 struct cpucp_packet pkt;746 int rc;747 748 memset(&pkt, 0, sizeof(pkt));749 750 pkt.ctl = cpu_to_le32(CPUCP_PACKET_PWM_SET <<751 CPUCP_PKT_CTL_OPCODE_SHIFT);752 pkt.sensor_index = __cpu_to_le16(sensor_index);753 pkt.type = __cpu_to_le16(attr);754 pkt.value = cpu_to_le64(value);755 756 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),757 0, NULL);758 if (rc && rc != -EAGAIN)759 dev_err_ratelimited(hdev->dev,760 "Failed to set pwm info to sensor %d, error %d\n",761 sensor_index, rc);762}763 764int hl_set_voltage(struct hl_device *hdev,765 int sensor_index, u32 attr, long value)766{767 struct cpucp_packet pkt;768 int rc;769 770 memset(&pkt, 0, sizeof(pkt));771 772 pkt.ctl = cpu_to_le32(CPUCP_PACKET_VOLTAGE_SET <<773 CPUCP_PKT_CTL_OPCODE_SHIFT);774 pkt.sensor_index = __cpu_to_le16(sensor_index);775 pkt.type = __cpu_to_le16(attr);776 pkt.value = __cpu_to_le64(value);777 778 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),779 0, NULL);780 if (rc && rc != -EAGAIN)781 dev_err_ratelimited(hdev->dev,782 "Failed to set voltage of sensor %d, error %d\n",783 sensor_index, rc);784 785 return rc;786}787 788int hl_set_current(struct hl_device *hdev,789 int sensor_index, u32 attr, long value)790{791 struct cpucp_packet pkt;792 int rc;793 794 memset(&pkt, 0, sizeof(pkt));795 796 pkt.ctl = cpu_to_le32(CPUCP_PACKET_CURRENT_SET <<797 CPUCP_PKT_CTL_OPCODE_SHIFT);798 pkt.sensor_index = __cpu_to_le16(sensor_index);799 pkt.type = __cpu_to_le16(attr);800 pkt.value = __cpu_to_le64(value);801 802 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 0, NULL);803 if (rc && rc != -EAGAIN)804 dev_err_ratelimited(hdev->dev,805 "Failed to set current of sensor %d, error %d\n",806 sensor_index, rc);807 808 return rc;809}810 811int hl_set_power(struct hl_device *hdev,812 int sensor_index, u32 attr, long value)813{814 struct cpucp_packet pkt;815 struct asic_fixed_properties *prop = &hdev->asic_prop;816 int rc;817 818 memset(&pkt, 0, sizeof(pkt));819 820 if (prop->use_get_power_for_reset_history)821 pkt.ctl = cpu_to_le32(CPUCP_PACKET_POWER_GET <<822 CPUCP_PKT_CTL_OPCODE_SHIFT);823 else824 pkt.ctl = cpu_to_le32(CPUCP_PACKET_POWER_SET <<825 CPUCP_PKT_CTL_OPCODE_SHIFT);826 827 pkt.sensor_index = __cpu_to_le16(sensor_index);828 pkt.type = __cpu_to_le16(attr);829 pkt.value = __cpu_to_le64(value);830 831 rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),832 0, NULL);833 if (rc && rc != -EAGAIN)834 dev_err_ratelimited(hdev->dev,835 "Failed to set power of sensor %d, error %d\n",836 sensor_index, rc);837 838 return rc;839}840 841int 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 if (rc != -EAGAIN)862 dev_err_ratelimited(hdev->dev,863 "Failed to get power of sensor %d, error %d\n",864 sensor_index, rc);865 *value = 0;866 }867 868 return rc;869}870 871int hl_hwmon_init(struct hl_device *hdev)872{873 struct device *dev = hdev->pdev ? &hdev->pdev->dev : hdev->dev;874 struct asic_fixed_properties *prop = &hdev->asic_prop;875 int rc;876 877 if ((hdev->hwmon_initialized) || !(hdev->cpu_queues_enable))878 return 0;879 880 if (hdev->hl_chip_info->info) {881 hdev->hl_chip_info->ops = &hl_hwmon_ops;882 883 hdev->hwmon_dev = hwmon_device_register_with_info(dev,884 prop->cpucp_info.card_name, hdev,885 hdev->hl_chip_info, NULL);886 if (IS_ERR(hdev->hwmon_dev)) {887 rc = PTR_ERR(hdev->hwmon_dev);888 dev_err(hdev->dev,889 "Unable to register hwmon device: %d\n", rc);890 return rc;891 }892 893 dev_info(hdev->dev, "%s: add sensors information\n",894 dev_name(hdev->hwmon_dev));895 896 hdev->hwmon_initialized = true;897 } else {898 dev_info(hdev->dev, "no available sensors\n");899 }900 901 return 0;902}903 904void hl_hwmon_fini(struct hl_device *hdev)905{906 if (!hdev->hwmon_initialized)907 return;908 909 hwmon_device_unregister(hdev->hwmon_dev);910}911 912void hl_hwmon_release_resources(struct hl_device *hdev)913{914 const struct hwmon_channel_info * const *channel_info_arr;915 int i = 0;916 917 if (!hdev->hl_chip_info->info)918 return;919 920 channel_info_arr = hdev->hl_chip_info->info;921 922 while (channel_info_arr[i]) {923 kfree(channel_info_arr[i]->config);924 kfree(channel_info_arr[i]);925 i++;926 }927 928 kfree(channel_info_arr);929 930 hdev->hl_chip_info->info = NULL;931}932