cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hwmon.c (20244B)


      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
     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(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#else
     63
     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 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
    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(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(*channels_info), GFP_KERNEL);
    198	if (!channels_info) {
    199		rc = -ENOMEM;
    200		goto channels_info_array_err;
    201	}
    202
    203	for (i = 0 ; i < num_active_sensor_types ; i++) {
    204		channels_info[i] = kzalloc(sizeof(*channels_info[i]), GFP_KERNEL);
    205		if (!channels_info[i]) {
    206			rc = -ENOMEM;
    207			goto channel_info_err;
    208		}
    209	}
    210
    211	for (i = 0, j = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) {
    212		if (!sensors_by_type[i])
    213			continue;
    214
    215		channels_info[j]->type = i;
    216		channels_info[j]->config = sensors_by_type[i];
    217		j++;
    218	}
    219
    220	hdev->hl_chip_info->info = (const struct hwmon_channel_info **)channels_info;
    221
    222	return 0;
    223
    224channel_info_err:
    225	for (i = 0 ; i < num_active_sensor_types ; i++) {
    226		if (channels_info[i]) {
    227			kfree(channels_info[i]->config);
    228			kfree(channels_info[i]);
    229		}
    230	}
    231	kfree(channels_info);
    232
    233channels_info_array_err:
    234sensors_type_err:
    235	for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++)
    236		kfree(sensors_by_type[i]);
    237
    238	return rc;
    239}
    240
    241static int hl_read(struct device *dev, enum hwmon_sensor_types type,
    242			u32 attr, int channel, long *val)
    243{
    244	struct hl_device *hdev = dev_get_drvdata(dev);
    245	bool use_cpucp_enum;
    246	u32 cpucp_attr;
    247	int rc;
    248
    249	if (!hl_device_operational(hdev, NULL))
    250		return -ENODEV;
    251
    252	use_cpucp_enum = (hdev->asic_prop.fw_app_cpu_boot_dev_sts0 &
    253					CPU_BOOT_DEV_STS0_MAP_HWMON_EN) ? true : false;
    254
    255	switch (type) {
    256	case hwmon_temp:
    257		switch (attr) {
    258		case hwmon_temp_input:
    259			cpucp_attr = cpucp_temp_input;
    260			break;
    261		case hwmon_temp_max:
    262			cpucp_attr = cpucp_temp_max;
    263			break;
    264		case hwmon_temp_crit:
    265			cpucp_attr = cpucp_temp_crit;
    266			break;
    267		case hwmon_temp_max_hyst:
    268			cpucp_attr = cpucp_temp_max_hyst;
    269			break;
    270		case hwmon_temp_crit_hyst:
    271			cpucp_attr = cpucp_temp_crit_hyst;
    272			break;
    273		case hwmon_temp_offset:
    274			cpucp_attr = cpucp_temp_offset;
    275			break;
    276		case hwmon_temp_highest:
    277			cpucp_attr = cpucp_temp_highest;
    278			break;
    279		default:
    280			return -EINVAL;
    281		}
    282
    283		if (use_cpucp_enum)
    284			rc = hl_get_temperature(hdev, channel, cpucp_attr, val);
    285		else
    286			rc = hl_get_temperature(hdev, channel, fixup_attr_legacy_fw(attr), val);
    287		break;
    288	case hwmon_in:
    289		switch (attr) {
    290		case hwmon_in_input:
    291			cpucp_attr = cpucp_in_input;
    292			break;
    293		case hwmon_in_min:
    294			cpucp_attr = cpucp_in_min;
    295			break;
    296		case hwmon_in_max:
    297			cpucp_attr = cpucp_in_max;
    298			break;
    299		case hwmon_in_highest:
    300			cpucp_attr = cpucp_in_highest;
    301			break;
    302		default:
    303			return -EINVAL;
    304		}
    305
    306		if (use_cpucp_enum)
    307			rc = hl_get_voltage(hdev, channel, cpucp_attr, val);
    308		else
    309			rc = hl_get_voltage(hdev, channel, fixup_attr_legacy_fw(attr), val);
    310		break;
    311	case hwmon_curr:
    312		switch (attr) {
    313		case hwmon_curr_input:
    314			cpucp_attr = cpucp_curr_input;
    315			break;
    316		case hwmon_curr_min:
    317			cpucp_attr = cpucp_curr_min;
    318			break;
    319		case hwmon_curr_max:
    320			cpucp_attr = cpucp_curr_max;
    321			break;
    322		case hwmon_curr_highest:
    323			cpucp_attr = cpucp_curr_highest;
    324			break;
    325		default:
    326			return -EINVAL;
    327		}
    328
    329		if (use_cpucp_enum)
    330			rc = hl_get_current(hdev, channel, cpucp_attr, val);
    331		else
    332			rc = hl_get_current(hdev, channel, fixup_attr_legacy_fw(attr), val);
    333		break;
    334	case hwmon_fan:
    335		switch (attr) {
    336		case hwmon_fan_input:
    337			cpucp_attr = cpucp_fan_input;
    338			break;
    339		case hwmon_fan_min:
    340			cpucp_attr = cpucp_fan_min;
    341			break;
    342		case hwmon_fan_max:
    343			cpucp_attr = cpucp_fan_max;
    344			break;
    345		default:
    346			return -EINVAL;
    347		}
    348
    349		if (use_cpucp_enum)
    350			rc = hl_get_fan_speed(hdev, channel, cpucp_attr, val);
    351		else
    352			rc = hl_get_fan_speed(hdev, channel, fixup_attr_legacy_fw(attr), val);
    353		break;
    354	case hwmon_pwm:
    355		switch (attr) {
    356		case hwmon_pwm_input:
    357			cpucp_attr = cpucp_pwm_input;
    358			break;
    359		case hwmon_pwm_enable:
    360			cpucp_attr = cpucp_pwm_enable;
    361			break;
    362		default:
    363			return -EINVAL;
    364		}
    365
    366		if (use_cpucp_enum)
    367			rc = hl_get_pwm_info(hdev, channel, cpucp_attr, val);
    368		else
    369			/* no need for fixup as pwm was aligned from day 1 */
    370			rc = hl_get_pwm_info(hdev, channel, attr, val);
    371		break;
    372	case hwmon_power:
    373		switch (attr) {
    374		case hwmon_power_input:
    375			cpucp_attr = CPUCP_POWER_INPUT;
    376			break;
    377		case hwmon_power_input_highest:
    378			cpucp_attr = CPUCP_POWER_INPUT_HIGHEST;
    379			break;
    380		default:
    381			return -EINVAL;
    382		}
    383
    384		if (use_cpucp_enum)
    385			rc = hl_get_power(hdev, channel, cpucp_attr, val);
    386		else
    387			rc = hl_get_power(hdev, channel, fixup_attr_legacy_fw(attr), val);
    388		break;
    389	default:
    390		return -EINVAL;
    391	}
    392	return rc;
    393}
    394
    395static int hl_write(struct device *dev, enum hwmon_sensor_types type,
    396			u32 attr, int channel, long val)
    397{
    398	struct hl_device *hdev = dev_get_drvdata(dev);
    399	u32 cpucp_attr;
    400	bool use_cpucp_enum = (hdev->asic_prop.fw_app_cpu_boot_dev_sts0 &
    401				CPU_BOOT_DEV_STS0_MAP_HWMON_EN) ? true : false;
    402
    403	if (!hl_device_operational(hdev, NULL))
    404		return -ENODEV;
    405
    406	switch (type) {
    407	case hwmon_temp:
    408		switch (attr) {
    409		case hwmon_temp_offset:
    410			cpucp_attr = cpucp_temp_offset;
    411			break;
    412		case hwmon_temp_reset_history:
    413			cpucp_attr = cpucp_temp_reset_history;
    414			break;
    415		default:
    416			return -EINVAL;
    417		}
    418
    419		if (use_cpucp_enum)
    420			hl_set_temperature(hdev, channel, cpucp_attr, val);
    421		else
    422			hl_set_temperature(hdev, channel, fixup_attr_legacy_fw(attr), val);
    423		break;
    424	case hwmon_pwm:
    425		switch (attr) {
    426		case hwmon_pwm_input:
    427			cpucp_attr = cpucp_pwm_input;
    428			break;
    429		case hwmon_pwm_enable:
    430			cpucp_attr = cpucp_pwm_enable;
    431			break;
    432		default:
    433			return -EINVAL;
    434		}
    435
    436		if (use_cpucp_enum)
    437			hl_set_pwm_info(hdev, channel, cpucp_attr, val);
    438		else
    439			/* no need for fixup as pwm was aligned from day 1 */
    440			hl_set_pwm_info(hdev, channel, attr, val);
    441		break;
    442	case hwmon_in:
    443		switch (attr) {
    444		case hwmon_in_reset_history:
    445			cpucp_attr = cpucp_in_reset_history;
    446			break;
    447		default:
    448			return -EINVAL;
    449		}
    450
    451		if (use_cpucp_enum)
    452			hl_set_voltage(hdev, channel, cpucp_attr, val);
    453		else
    454			hl_set_voltage(hdev, channel, fixup_attr_legacy_fw(attr), val);
    455		break;
    456	case hwmon_curr:
    457		switch (attr) {
    458		case hwmon_curr_reset_history:
    459			cpucp_attr = cpucp_curr_reset_history;
    460			break;
    461		default:
    462			return -EINVAL;
    463		}
    464
    465		if (use_cpucp_enum)
    466			hl_set_current(hdev, channel, cpucp_attr, val);
    467		else
    468			hl_set_current(hdev, channel, fixup_attr_legacy_fw(attr), val);
    469		break;
    470	case hwmon_power:
    471		switch (attr) {
    472		case hwmon_power_reset_history:
    473			cpucp_attr = CPUCP_POWER_RESET_INPUT_HISTORY;
    474			break;
    475		default:
    476			return -EINVAL;
    477		}
    478
    479		if (use_cpucp_enum)
    480			hl_set_power(hdev, channel, cpucp_attr, val);
    481		else
    482			hl_set_power(hdev, channel, fixup_attr_legacy_fw(attr), val);
    483		break;
    484	default:
    485		return -EINVAL;
    486	}
    487	return 0;
    488}
    489
    490static umode_t hl_is_visible(const void *data, enum hwmon_sensor_types type,
    491				u32 attr, int channel)
    492{
    493	switch (type) {
    494	case hwmon_temp:
    495		switch (attr) {
    496		case hwmon_temp_input:
    497		case hwmon_temp_max:
    498		case hwmon_temp_max_hyst:
    499		case hwmon_temp_crit:
    500		case hwmon_temp_crit_hyst:
    501		case hwmon_temp_highest:
    502			return 0444;
    503		case hwmon_temp_offset:
    504			return 0644;
    505		case hwmon_temp_reset_history:
    506			return 0200;
    507		}
    508		break;
    509	case hwmon_in:
    510		switch (attr) {
    511		case hwmon_in_input:
    512		case hwmon_in_min:
    513		case hwmon_in_max:
    514		case hwmon_in_highest:
    515			return 0444;
    516		case hwmon_in_reset_history:
    517			return 0200;
    518		}
    519		break;
    520	case hwmon_curr:
    521		switch (attr) {
    522		case hwmon_curr_input:
    523		case hwmon_curr_min:
    524		case hwmon_curr_max:
    525		case hwmon_curr_highest:
    526			return 0444;
    527		case hwmon_curr_reset_history:
    528			return 0200;
    529		}
    530		break;
    531	case hwmon_fan:
    532		switch (attr) {
    533		case hwmon_fan_input:
    534		case hwmon_fan_min:
    535		case hwmon_fan_max:
    536			return 0444;
    537		}
    538		break;
    539	case hwmon_pwm:
    540		switch (attr) {
    541		case hwmon_pwm_input:
    542		case hwmon_pwm_enable:
    543			return 0644;
    544		}
    545		break;
    546	case hwmon_power:
    547		switch (attr) {
    548		case hwmon_power_input:
    549		case hwmon_power_input_highest:
    550			return 0444;
    551		case hwmon_power_reset_history:
    552			return 0200;
    553		}
    554		break;
    555	default:
    556		break;
    557	}
    558	return 0;
    559}
    560
    561static const struct hwmon_ops hl_hwmon_ops = {
    562	.is_visible = hl_is_visible,
    563	.read = hl_read,
    564	.write = hl_write
    565};
    566
    567int hl_get_temperature(struct hl_device *hdev,
    568			int sensor_index, u32 attr, long *value)
    569{
    570	struct cpucp_packet pkt;
    571	u64 result;
    572	int rc;
    573
    574	memset(&pkt, 0, sizeof(pkt));
    575
    576	pkt.ctl = cpu_to_le32(CPUCP_PACKET_TEMPERATURE_GET <<
    577				CPUCP_PKT_CTL_OPCODE_SHIFT);
    578	pkt.sensor_index = __cpu_to_le16(sensor_index);
    579	pkt.type = __cpu_to_le16(attr);
    580
    581	dev_dbg(hdev->dev, "get temp, ctl 0x%x, sensor %d, type %d\n",
    582		pkt.ctl, pkt.sensor_index, pkt.type);
    583
    584	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
    585						0, &result);
    586
    587	*value = (long) result;
    588
    589	if (rc) {
    590		dev_err(hdev->dev,
    591			"Failed to get temperature from sensor %d, error %d\n",
    592			sensor_index, rc);
    593		*value = 0;
    594	}
    595
    596	return rc;
    597}
    598
    599int hl_set_temperature(struct hl_device *hdev,
    600			int sensor_index, u32 attr, long value)
    601{
    602	struct cpucp_packet pkt;
    603	int rc;
    604
    605	memset(&pkt, 0, sizeof(pkt));
    606
    607	pkt.ctl = cpu_to_le32(CPUCP_PACKET_TEMPERATURE_SET <<
    608				CPUCP_PKT_CTL_OPCODE_SHIFT);
    609	pkt.sensor_index = __cpu_to_le16(sensor_index);
    610	pkt.type = __cpu_to_le16(attr);
    611	pkt.value = __cpu_to_le64(value);
    612
    613	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
    614						0, NULL);
    615
    616	if (rc)
    617		dev_err(hdev->dev,
    618			"Failed to set temperature of sensor %d, error %d\n",
    619			sensor_index, rc);
    620
    621	return rc;
    622}
    623
    624int hl_get_voltage(struct hl_device *hdev,
    625			int sensor_index, u32 attr, long *value)
    626{
    627	struct cpucp_packet pkt;
    628	u64 result;
    629	int rc;
    630
    631	memset(&pkt, 0, sizeof(pkt));
    632
    633	pkt.ctl = cpu_to_le32(CPUCP_PACKET_VOLTAGE_GET <<
    634				CPUCP_PKT_CTL_OPCODE_SHIFT);
    635	pkt.sensor_index = __cpu_to_le16(sensor_index);
    636	pkt.type = __cpu_to_le16(attr);
    637
    638	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
    639						0, &result);
    640
    641	*value = (long) result;
    642
    643	if (rc) {
    644		dev_err(hdev->dev,
    645			"Failed to get voltage from sensor %d, error %d\n",
    646			sensor_index, rc);
    647		*value = 0;
    648	}
    649
    650	return rc;
    651}
    652
    653int hl_get_current(struct hl_device *hdev,
    654			int sensor_index, u32 attr, long *value)
    655{
    656	struct cpucp_packet pkt;
    657	u64 result;
    658	int rc;
    659
    660	memset(&pkt, 0, sizeof(pkt));
    661
    662	pkt.ctl = cpu_to_le32(CPUCP_PACKET_CURRENT_GET <<
    663				CPUCP_PKT_CTL_OPCODE_SHIFT);
    664	pkt.sensor_index = __cpu_to_le16(sensor_index);
    665	pkt.type = __cpu_to_le16(attr);
    666
    667	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
    668						0, &result);
    669
    670	*value = (long) result;
    671
    672	if (rc) {
    673		dev_err(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		dev_err(hdev->dev,
    703			"Failed to get fan speed from sensor %d, error %d\n",
    704			sensor_index, rc);
    705		*value = 0;
    706	}
    707
    708	return rc;
    709}
    710
    711int hl_get_pwm_info(struct hl_device *hdev,
    712			int sensor_index, u32 attr, long *value)
    713{
    714	struct cpucp_packet pkt;
    715	u64 result;
    716	int rc;
    717
    718	memset(&pkt, 0, sizeof(pkt));
    719
    720	pkt.ctl = cpu_to_le32(CPUCP_PACKET_PWM_GET <<
    721				CPUCP_PKT_CTL_OPCODE_SHIFT);
    722	pkt.sensor_index = __cpu_to_le16(sensor_index);
    723	pkt.type = __cpu_to_le16(attr);
    724
    725	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
    726						0, &result);
    727
    728	*value = (long) result;
    729
    730	if (rc) {
    731		dev_err(hdev->dev,
    732			"Failed to get pwm info from sensor %d, error %d\n",
    733			sensor_index, rc);
    734		*value = 0;
    735	}
    736
    737	return rc;
    738}
    739
    740void hl_set_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr,
    741			long value)
    742{
    743	struct cpucp_packet pkt;
    744	int rc;
    745
    746	memset(&pkt, 0, sizeof(pkt));
    747
    748	pkt.ctl = cpu_to_le32(CPUCP_PACKET_PWM_SET <<
    749				CPUCP_PKT_CTL_OPCODE_SHIFT);
    750	pkt.sensor_index = __cpu_to_le16(sensor_index);
    751	pkt.type = __cpu_to_le16(attr);
    752	pkt.value = cpu_to_le64(value);
    753
    754	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
    755						0, NULL);
    756
    757	if (rc)
    758		dev_err(hdev->dev,
    759			"Failed to set pwm info to sensor %d, error %d\n",
    760			sensor_index, rc);
    761}
    762
    763int hl_set_voltage(struct hl_device *hdev,
    764			int sensor_index, u32 attr, long value)
    765{
    766	struct cpucp_packet pkt;
    767	int rc;
    768
    769	memset(&pkt, 0, sizeof(pkt));
    770
    771	pkt.ctl = cpu_to_le32(CPUCP_PACKET_VOLTAGE_SET <<
    772				CPUCP_PKT_CTL_OPCODE_SHIFT);
    773	pkt.sensor_index = __cpu_to_le16(sensor_index);
    774	pkt.type = __cpu_to_le16(attr);
    775	pkt.value = __cpu_to_le64(value);
    776
    777	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
    778						0, NULL);
    779
    780	if (rc)
    781		dev_err(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),
    803						0, NULL);
    804
    805	if (rc)
    806		dev_err(hdev->dev,
    807			"Failed to set current of sensor %d, error %d\n",
    808			sensor_index, rc);
    809
    810	return rc;
    811}
    812
    813int hl_set_power(struct hl_device *hdev,
    814			int sensor_index, u32 attr, long value)
    815{
    816	struct cpucp_packet pkt;
    817	struct asic_fixed_properties *prop = &hdev->asic_prop;
    818	int rc;
    819
    820	memset(&pkt, 0, sizeof(pkt));
    821
    822	if (prop->use_get_power_for_reset_history)
    823		pkt.ctl = cpu_to_le32(CPUCP_PACKET_POWER_GET <<
    824				CPUCP_PKT_CTL_OPCODE_SHIFT);
    825	else
    826		pkt.ctl = cpu_to_le32(CPUCP_PACKET_POWER_SET <<
    827				CPUCP_PKT_CTL_OPCODE_SHIFT);
    828
    829	pkt.sensor_index = __cpu_to_le16(sensor_index);
    830	pkt.type = __cpu_to_le16(attr);
    831	pkt.value = __cpu_to_le64(value);
    832
    833	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
    834						0, NULL);
    835
    836	if (rc)
    837		dev_err(hdev->dev,
    838			"Failed to set power of sensor %d, error %d\n",
    839			sensor_index, rc);
    840
    841	return rc;
    842}
    843
    844int hl_get_power(struct hl_device *hdev,
    845			int sensor_index, u32 attr, long *value)
    846{
    847	struct cpucp_packet pkt;
    848	u64 result;
    849	int rc;
    850
    851	memset(&pkt, 0, sizeof(pkt));
    852
    853	pkt.ctl = cpu_to_le32(CPUCP_PACKET_POWER_GET <<
    854				CPUCP_PKT_CTL_OPCODE_SHIFT);
    855	pkt.sensor_index = __cpu_to_le16(sensor_index);
    856	pkt.type = __cpu_to_le16(attr);
    857
    858	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
    859						0, &result);
    860
    861	*value = (long) result;
    862
    863	if (rc) {
    864		dev_err(hdev->dev,
    865			"Failed to get power of sensor %d, error %d\n",
    866			sensor_index, rc);
    867		*value = 0;
    868	}
    869
    870	return rc;
    871}
    872
    873int hl_hwmon_init(struct hl_device *hdev)
    874{
    875	struct device *dev = hdev->pdev ? &hdev->pdev->dev : hdev->dev;
    876	struct asic_fixed_properties *prop = &hdev->asic_prop;
    877	int rc;
    878
    879	if ((hdev->hwmon_initialized) || !(hdev->cpu_queues_enable))
    880		return 0;
    881
    882	if (hdev->hl_chip_info->info) {
    883		hdev->hl_chip_info->ops = &hl_hwmon_ops;
    884
    885		hdev->hwmon_dev = hwmon_device_register_with_info(dev,
    886					prop->cpucp_info.card_name, hdev,
    887					hdev->hl_chip_info, NULL);
    888		if (IS_ERR(hdev->hwmon_dev)) {
    889			rc = PTR_ERR(hdev->hwmon_dev);
    890			dev_err(hdev->dev,
    891				"Unable to register hwmon device: %d\n", rc);
    892			return rc;
    893		}
    894
    895		dev_info(hdev->dev, "%s: add sensors information\n",
    896			dev_name(hdev->hwmon_dev));
    897
    898		hdev->hwmon_initialized = true;
    899	} else {
    900		dev_info(hdev->dev, "no available sensors\n");
    901	}
    902
    903	return 0;
    904}
    905
    906void hl_hwmon_fini(struct hl_device *hdev)
    907{
    908	if (!hdev->hwmon_initialized)
    909		return;
    910
    911	hwmon_device_unregister(hdev->hwmon_dev);
    912}