brintos

brintos / linux-shallow public Read only

0
0
Text · 20.4 KiB · 52d1e6b Raw
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