162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci/* 462306a36Sopenharmony_ci * Copyright 2016-2019 HabanaLabs, Ltd. 562306a36Sopenharmony_ci * All Rights Reserved. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "habanalabs.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/pci.h> 1162306a36Sopenharmony_ci#include <linux/hwmon.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define HWMON_NR_SENSOR_TYPES (hwmon_max) 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#ifdef _HAS_HWMON_HWMON_T_ENABLE 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistatic u32 fixup_flags_legacy_fw(struct hl_device *hdev, enum hwmon_sensor_types type, 1862306a36Sopenharmony_ci u32 cpucp_flags) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci u32 flags; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci switch (type) { 2362306a36Sopenharmony_ci case hwmon_temp: 2462306a36Sopenharmony_ci flags = (cpucp_flags << 1) | HWMON_T_ENABLE; 2562306a36Sopenharmony_ci break; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci case hwmon_in: 2862306a36Sopenharmony_ci flags = (cpucp_flags << 1) | HWMON_I_ENABLE; 2962306a36Sopenharmony_ci break; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci case hwmon_curr: 3262306a36Sopenharmony_ci flags = (cpucp_flags << 1) | HWMON_C_ENABLE; 3362306a36Sopenharmony_ci break; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci case hwmon_fan: 3662306a36Sopenharmony_ci flags = (cpucp_flags << 1) | HWMON_F_ENABLE; 3762306a36Sopenharmony_ci break; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci case hwmon_power: 4062306a36Sopenharmony_ci flags = (cpucp_flags << 1) | HWMON_P_ENABLE; 4162306a36Sopenharmony_ci break; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci case hwmon_pwm: 4462306a36Sopenharmony_ci /* enable bit was here from day 1, so no need to adjust */ 4562306a36Sopenharmony_ci flags = cpucp_flags; 4662306a36Sopenharmony_ci break; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci default: 4962306a36Sopenharmony_ci dev_err(hdev->dev, "unsupported h/w sensor type %d\n", type); 5062306a36Sopenharmony_ci flags = cpucp_flags; 5162306a36Sopenharmony_ci break; 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci return flags; 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic u32 fixup_attr_legacy_fw(u32 attr) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci return (attr - 1); 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#else 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic u32 fixup_flags_legacy_fw(struct hl_device *hdev, enum hwmon_sensor_types type, 6562306a36Sopenharmony_ci u32 cpucp_flags) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci return cpucp_flags; 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic u32 fixup_attr_legacy_fw(u32 attr) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci return attr; 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci#endif /* !_HAS_HWMON_HWMON_T_ENABLE */ 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic u32 adjust_hwmon_flags(struct hl_device *hdev, enum hwmon_sensor_types type, u32 cpucp_flags) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci u32 flags, cpucp_input_val; 8062306a36Sopenharmony_ci bool use_cpucp_enum; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci use_cpucp_enum = (hdev->asic_prop.fw_app_cpu_boot_dev_sts0 & 8362306a36Sopenharmony_ci CPU_BOOT_DEV_STS0_MAP_HWMON_EN) ? true : false; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci /* If f/w is using it's own enum, we need to check if the properties values are aligned. 8662306a36Sopenharmony_ci * If not, it means we need to adjust the values to the new format that is used in the 8762306a36Sopenharmony_ci * kernel since 5.6 (enum values were incremented by 1 by adding a new enable value). 8862306a36Sopenharmony_ci */ 8962306a36Sopenharmony_ci if (use_cpucp_enum) { 9062306a36Sopenharmony_ci switch (type) { 9162306a36Sopenharmony_ci case hwmon_temp: 9262306a36Sopenharmony_ci cpucp_input_val = cpucp_temp_input; 9362306a36Sopenharmony_ci if (cpucp_input_val == hwmon_temp_input) 9462306a36Sopenharmony_ci flags = cpucp_flags; 9562306a36Sopenharmony_ci else 9662306a36Sopenharmony_ci flags = (cpucp_flags << 1) | HWMON_T_ENABLE; 9762306a36Sopenharmony_ci break; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci case hwmon_in: 10062306a36Sopenharmony_ci cpucp_input_val = cpucp_in_input; 10162306a36Sopenharmony_ci if (cpucp_input_val == hwmon_in_input) 10262306a36Sopenharmony_ci flags = cpucp_flags; 10362306a36Sopenharmony_ci else 10462306a36Sopenharmony_ci flags = (cpucp_flags << 1) | HWMON_I_ENABLE; 10562306a36Sopenharmony_ci break; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci case hwmon_curr: 10862306a36Sopenharmony_ci cpucp_input_val = cpucp_curr_input; 10962306a36Sopenharmony_ci if (cpucp_input_val == hwmon_curr_input) 11062306a36Sopenharmony_ci flags = cpucp_flags; 11162306a36Sopenharmony_ci else 11262306a36Sopenharmony_ci flags = (cpucp_flags << 1) | HWMON_C_ENABLE; 11362306a36Sopenharmony_ci break; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci case hwmon_fan: 11662306a36Sopenharmony_ci cpucp_input_val = cpucp_fan_input; 11762306a36Sopenharmony_ci if (cpucp_input_val == hwmon_fan_input) 11862306a36Sopenharmony_ci flags = cpucp_flags; 11962306a36Sopenharmony_ci else 12062306a36Sopenharmony_ci flags = (cpucp_flags << 1) | HWMON_F_ENABLE; 12162306a36Sopenharmony_ci break; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci case hwmon_pwm: 12462306a36Sopenharmony_ci /* enable bit was here from day 1, so no need to adjust */ 12562306a36Sopenharmony_ci flags = cpucp_flags; 12662306a36Sopenharmony_ci break; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci case hwmon_power: 12962306a36Sopenharmony_ci cpucp_input_val = CPUCP_POWER_INPUT; 13062306a36Sopenharmony_ci if (cpucp_input_val == hwmon_power_input) 13162306a36Sopenharmony_ci flags = cpucp_flags; 13262306a36Sopenharmony_ci else 13362306a36Sopenharmony_ci flags = (cpucp_flags << 1) | HWMON_P_ENABLE; 13462306a36Sopenharmony_ci break; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci default: 13762306a36Sopenharmony_ci dev_err(hdev->dev, "unsupported h/w sensor type %d\n", type); 13862306a36Sopenharmony_ci flags = cpucp_flags; 13962306a36Sopenharmony_ci break; 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci } else { 14262306a36Sopenharmony_ci flags = fixup_flags_legacy_fw(hdev, type, cpucp_flags); 14362306a36Sopenharmony_ci } 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci return flags; 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ciint hl_build_hwmon_channel_info(struct hl_device *hdev, struct cpucp_sensor *sensors_arr) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci u32 num_sensors_for_type, flags, num_active_sensor_types = 0, arr_size = 0, *curr_arr; 15162306a36Sopenharmony_ci u32 sensors_by_type_next_index[HWMON_NR_SENSOR_TYPES] = {0}; 15262306a36Sopenharmony_ci u32 *sensors_by_type[HWMON_NR_SENSOR_TYPES] = {NULL}; 15362306a36Sopenharmony_ci struct hwmon_channel_info **channels_info; 15462306a36Sopenharmony_ci u32 counts[HWMON_NR_SENSOR_TYPES] = {0}; 15562306a36Sopenharmony_ci enum hwmon_sensor_types type; 15662306a36Sopenharmony_ci int rc, i, j; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci for (i = 0 ; i < CPUCP_MAX_SENSORS ; i++) { 15962306a36Sopenharmony_ci type = le32_to_cpu(sensors_arr[i].type); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci if ((type == 0) && (sensors_arr[i].flags == 0)) 16262306a36Sopenharmony_ci break; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci if (type >= HWMON_NR_SENSOR_TYPES) { 16562306a36Sopenharmony_ci dev_err(hdev->dev, "Got wrong sensor type %d from device\n", type); 16662306a36Sopenharmony_ci return -EINVAL; 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci counts[type]++; 17062306a36Sopenharmony_ci arr_size++; 17162306a36Sopenharmony_ci } 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) { 17462306a36Sopenharmony_ci if (counts[i] == 0) 17562306a36Sopenharmony_ci continue; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci num_sensors_for_type = counts[i] + 1; 17862306a36Sopenharmony_ci dev_dbg(hdev->dev, "num_sensors_for_type %d = %d\n", i, num_sensors_for_type); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci curr_arr = kcalloc(num_sensors_for_type, sizeof(*curr_arr), GFP_KERNEL); 18162306a36Sopenharmony_ci if (!curr_arr) { 18262306a36Sopenharmony_ci rc = -ENOMEM; 18362306a36Sopenharmony_ci goto sensors_type_err; 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci num_active_sensor_types++; 18762306a36Sopenharmony_ci sensors_by_type[i] = curr_arr; 18862306a36Sopenharmony_ci } 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci for (i = 0 ; i < arr_size ; i++) { 19162306a36Sopenharmony_ci type = le32_to_cpu(sensors_arr[i].type); 19262306a36Sopenharmony_ci curr_arr = sensors_by_type[type]; 19362306a36Sopenharmony_ci flags = adjust_hwmon_flags(hdev, type, le32_to_cpu(sensors_arr[i].flags)); 19462306a36Sopenharmony_ci curr_arr[sensors_by_type_next_index[type]++] = flags; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci channels_info = kcalloc(num_active_sensor_types + 1, sizeof(struct hwmon_channel_info *), 19862306a36Sopenharmony_ci GFP_KERNEL); 19962306a36Sopenharmony_ci if (!channels_info) { 20062306a36Sopenharmony_ci rc = -ENOMEM; 20162306a36Sopenharmony_ci goto channels_info_array_err; 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci for (i = 0 ; i < num_active_sensor_types ; i++) { 20562306a36Sopenharmony_ci channels_info[i] = kzalloc(sizeof(*channels_info[i]), GFP_KERNEL); 20662306a36Sopenharmony_ci if (!channels_info[i]) { 20762306a36Sopenharmony_ci rc = -ENOMEM; 20862306a36Sopenharmony_ci goto channel_info_err; 20962306a36Sopenharmony_ci } 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci for (i = 0, j = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) { 21362306a36Sopenharmony_ci if (!sensors_by_type[i]) 21462306a36Sopenharmony_ci continue; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci channels_info[j]->type = i; 21762306a36Sopenharmony_ci channels_info[j]->config = sensors_by_type[i]; 21862306a36Sopenharmony_ci j++; 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci hdev->hl_chip_info->info = (const struct hwmon_channel_info **)channels_info; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci return 0; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cichannel_info_err: 22662306a36Sopenharmony_ci for (i = 0 ; i < num_active_sensor_types ; i++) { 22762306a36Sopenharmony_ci if (channels_info[i]) { 22862306a36Sopenharmony_ci kfree(channels_info[i]->config); 22962306a36Sopenharmony_ci kfree(channels_info[i]); 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci kfree(channels_info); 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cichannels_info_array_err: 23562306a36Sopenharmony_cisensors_type_err: 23662306a36Sopenharmony_ci for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) 23762306a36Sopenharmony_ci kfree(sensors_by_type[i]); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci return rc; 24062306a36Sopenharmony_ci} 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_cistatic int hl_read(struct device *dev, enum hwmon_sensor_types type, 24362306a36Sopenharmony_ci u32 attr, int channel, long *val) 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci struct hl_device *hdev = dev_get_drvdata(dev); 24662306a36Sopenharmony_ci bool use_cpucp_enum; 24762306a36Sopenharmony_ci u32 cpucp_attr; 24862306a36Sopenharmony_ci int rc; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci if (!hl_device_operational(hdev, NULL)) 25162306a36Sopenharmony_ci return -ENODEV; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci use_cpucp_enum = (hdev->asic_prop.fw_app_cpu_boot_dev_sts0 & 25462306a36Sopenharmony_ci CPU_BOOT_DEV_STS0_MAP_HWMON_EN) ? true : false; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci switch (type) { 25762306a36Sopenharmony_ci case hwmon_temp: 25862306a36Sopenharmony_ci switch (attr) { 25962306a36Sopenharmony_ci case hwmon_temp_input: 26062306a36Sopenharmony_ci cpucp_attr = cpucp_temp_input; 26162306a36Sopenharmony_ci break; 26262306a36Sopenharmony_ci case hwmon_temp_max: 26362306a36Sopenharmony_ci cpucp_attr = cpucp_temp_max; 26462306a36Sopenharmony_ci break; 26562306a36Sopenharmony_ci case hwmon_temp_crit: 26662306a36Sopenharmony_ci cpucp_attr = cpucp_temp_crit; 26762306a36Sopenharmony_ci break; 26862306a36Sopenharmony_ci case hwmon_temp_max_hyst: 26962306a36Sopenharmony_ci cpucp_attr = cpucp_temp_max_hyst; 27062306a36Sopenharmony_ci break; 27162306a36Sopenharmony_ci case hwmon_temp_crit_hyst: 27262306a36Sopenharmony_ci cpucp_attr = cpucp_temp_crit_hyst; 27362306a36Sopenharmony_ci break; 27462306a36Sopenharmony_ci case hwmon_temp_offset: 27562306a36Sopenharmony_ci cpucp_attr = cpucp_temp_offset; 27662306a36Sopenharmony_ci break; 27762306a36Sopenharmony_ci case hwmon_temp_highest: 27862306a36Sopenharmony_ci cpucp_attr = cpucp_temp_highest; 27962306a36Sopenharmony_ci break; 28062306a36Sopenharmony_ci default: 28162306a36Sopenharmony_ci return -EINVAL; 28262306a36Sopenharmony_ci } 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci if (use_cpucp_enum) 28562306a36Sopenharmony_ci rc = hl_get_temperature(hdev, channel, cpucp_attr, val); 28662306a36Sopenharmony_ci else 28762306a36Sopenharmony_ci rc = hl_get_temperature(hdev, channel, fixup_attr_legacy_fw(attr), val); 28862306a36Sopenharmony_ci break; 28962306a36Sopenharmony_ci case hwmon_in: 29062306a36Sopenharmony_ci switch (attr) { 29162306a36Sopenharmony_ci case hwmon_in_input: 29262306a36Sopenharmony_ci cpucp_attr = cpucp_in_input; 29362306a36Sopenharmony_ci break; 29462306a36Sopenharmony_ci case hwmon_in_min: 29562306a36Sopenharmony_ci cpucp_attr = cpucp_in_min; 29662306a36Sopenharmony_ci break; 29762306a36Sopenharmony_ci case hwmon_in_max: 29862306a36Sopenharmony_ci cpucp_attr = cpucp_in_max; 29962306a36Sopenharmony_ci break; 30062306a36Sopenharmony_ci case hwmon_in_highest: 30162306a36Sopenharmony_ci cpucp_attr = cpucp_in_highest; 30262306a36Sopenharmony_ci break; 30362306a36Sopenharmony_ci default: 30462306a36Sopenharmony_ci return -EINVAL; 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci if (use_cpucp_enum) 30862306a36Sopenharmony_ci rc = hl_get_voltage(hdev, channel, cpucp_attr, val); 30962306a36Sopenharmony_ci else 31062306a36Sopenharmony_ci rc = hl_get_voltage(hdev, channel, fixup_attr_legacy_fw(attr), val); 31162306a36Sopenharmony_ci break; 31262306a36Sopenharmony_ci case hwmon_curr: 31362306a36Sopenharmony_ci switch (attr) { 31462306a36Sopenharmony_ci case hwmon_curr_input: 31562306a36Sopenharmony_ci cpucp_attr = cpucp_curr_input; 31662306a36Sopenharmony_ci break; 31762306a36Sopenharmony_ci case hwmon_curr_min: 31862306a36Sopenharmony_ci cpucp_attr = cpucp_curr_min; 31962306a36Sopenharmony_ci break; 32062306a36Sopenharmony_ci case hwmon_curr_max: 32162306a36Sopenharmony_ci cpucp_attr = cpucp_curr_max; 32262306a36Sopenharmony_ci break; 32362306a36Sopenharmony_ci case hwmon_curr_highest: 32462306a36Sopenharmony_ci cpucp_attr = cpucp_curr_highest; 32562306a36Sopenharmony_ci break; 32662306a36Sopenharmony_ci default: 32762306a36Sopenharmony_ci return -EINVAL; 32862306a36Sopenharmony_ci } 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci if (use_cpucp_enum) 33162306a36Sopenharmony_ci rc = hl_get_current(hdev, channel, cpucp_attr, val); 33262306a36Sopenharmony_ci else 33362306a36Sopenharmony_ci rc = hl_get_current(hdev, channel, fixup_attr_legacy_fw(attr), val); 33462306a36Sopenharmony_ci break; 33562306a36Sopenharmony_ci case hwmon_fan: 33662306a36Sopenharmony_ci switch (attr) { 33762306a36Sopenharmony_ci case hwmon_fan_input: 33862306a36Sopenharmony_ci cpucp_attr = cpucp_fan_input; 33962306a36Sopenharmony_ci break; 34062306a36Sopenharmony_ci case hwmon_fan_min: 34162306a36Sopenharmony_ci cpucp_attr = cpucp_fan_min; 34262306a36Sopenharmony_ci break; 34362306a36Sopenharmony_ci case hwmon_fan_max: 34462306a36Sopenharmony_ci cpucp_attr = cpucp_fan_max; 34562306a36Sopenharmony_ci break; 34662306a36Sopenharmony_ci default: 34762306a36Sopenharmony_ci return -EINVAL; 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci if (use_cpucp_enum) 35162306a36Sopenharmony_ci rc = hl_get_fan_speed(hdev, channel, cpucp_attr, val); 35262306a36Sopenharmony_ci else 35362306a36Sopenharmony_ci rc = hl_get_fan_speed(hdev, channel, fixup_attr_legacy_fw(attr), val); 35462306a36Sopenharmony_ci break; 35562306a36Sopenharmony_ci case hwmon_pwm: 35662306a36Sopenharmony_ci switch (attr) { 35762306a36Sopenharmony_ci case hwmon_pwm_input: 35862306a36Sopenharmony_ci cpucp_attr = cpucp_pwm_input; 35962306a36Sopenharmony_ci break; 36062306a36Sopenharmony_ci case hwmon_pwm_enable: 36162306a36Sopenharmony_ci cpucp_attr = cpucp_pwm_enable; 36262306a36Sopenharmony_ci break; 36362306a36Sopenharmony_ci default: 36462306a36Sopenharmony_ci return -EINVAL; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci if (use_cpucp_enum) 36862306a36Sopenharmony_ci rc = hl_get_pwm_info(hdev, channel, cpucp_attr, val); 36962306a36Sopenharmony_ci else 37062306a36Sopenharmony_ci /* no need for fixup as pwm was aligned from day 1 */ 37162306a36Sopenharmony_ci rc = hl_get_pwm_info(hdev, channel, attr, val); 37262306a36Sopenharmony_ci break; 37362306a36Sopenharmony_ci case hwmon_power: 37462306a36Sopenharmony_ci switch (attr) { 37562306a36Sopenharmony_ci case hwmon_power_input: 37662306a36Sopenharmony_ci cpucp_attr = CPUCP_POWER_INPUT; 37762306a36Sopenharmony_ci break; 37862306a36Sopenharmony_ci case hwmon_power_input_highest: 37962306a36Sopenharmony_ci cpucp_attr = CPUCP_POWER_INPUT_HIGHEST; 38062306a36Sopenharmony_ci break; 38162306a36Sopenharmony_ci default: 38262306a36Sopenharmony_ci return -EINVAL; 38362306a36Sopenharmony_ci } 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci if (use_cpucp_enum) 38662306a36Sopenharmony_ci rc = hl_get_power(hdev, channel, cpucp_attr, val); 38762306a36Sopenharmony_ci else 38862306a36Sopenharmony_ci rc = hl_get_power(hdev, channel, fixup_attr_legacy_fw(attr), val); 38962306a36Sopenharmony_ci break; 39062306a36Sopenharmony_ci default: 39162306a36Sopenharmony_ci return -EINVAL; 39262306a36Sopenharmony_ci } 39362306a36Sopenharmony_ci return rc; 39462306a36Sopenharmony_ci} 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cistatic int hl_write(struct device *dev, enum hwmon_sensor_types type, 39762306a36Sopenharmony_ci u32 attr, int channel, long val) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci struct hl_device *hdev = dev_get_drvdata(dev); 40062306a36Sopenharmony_ci u32 cpucp_attr; 40162306a36Sopenharmony_ci bool use_cpucp_enum = (hdev->asic_prop.fw_app_cpu_boot_dev_sts0 & 40262306a36Sopenharmony_ci CPU_BOOT_DEV_STS0_MAP_HWMON_EN) ? true : false; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci if (!hl_device_operational(hdev, NULL)) 40562306a36Sopenharmony_ci return -ENODEV; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci switch (type) { 40862306a36Sopenharmony_ci case hwmon_temp: 40962306a36Sopenharmony_ci switch (attr) { 41062306a36Sopenharmony_ci case hwmon_temp_offset: 41162306a36Sopenharmony_ci cpucp_attr = cpucp_temp_offset; 41262306a36Sopenharmony_ci break; 41362306a36Sopenharmony_ci case hwmon_temp_reset_history: 41462306a36Sopenharmony_ci cpucp_attr = cpucp_temp_reset_history; 41562306a36Sopenharmony_ci break; 41662306a36Sopenharmony_ci default: 41762306a36Sopenharmony_ci return -EINVAL; 41862306a36Sopenharmony_ci } 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci if (use_cpucp_enum) 42162306a36Sopenharmony_ci hl_set_temperature(hdev, channel, cpucp_attr, val); 42262306a36Sopenharmony_ci else 42362306a36Sopenharmony_ci hl_set_temperature(hdev, channel, fixup_attr_legacy_fw(attr), val); 42462306a36Sopenharmony_ci break; 42562306a36Sopenharmony_ci case hwmon_pwm: 42662306a36Sopenharmony_ci switch (attr) { 42762306a36Sopenharmony_ci case hwmon_pwm_input: 42862306a36Sopenharmony_ci cpucp_attr = cpucp_pwm_input; 42962306a36Sopenharmony_ci break; 43062306a36Sopenharmony_ci case hwmon_pwm_enable: 43162306a36Sopenharmony_ci cpucp_attr = cpucp_pwm_enable; 43262306a36Sopenharmony_ci break; 43362306a36Sopenharmony_ci default: 43462306a36Sopenharmony_ci return -EINVAL; 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci if (use_cpucp_enum) 43862306a36Sopenharmony_ci hl_set_pwm_info(hdev, channel, cpucp_attr, val); 43962306a36Sopenharmony_ci else 44062306a36Sopenharmony_ci /* no need for fixup as pwm was aligned from day 1 */ 44162306a36Sopenharmony_ci hl_set_pwm_info(hdev, channel, attr, val); 44262306a36Sopenharmony_ci break; 44362306a36Sopenharmony_ci case hwmon_in: 44462306a36Sopenharmony_ci switch (attr) { 44562306a36Sopenharmony_ci case hwmon_in_reset_history: 44662306a36Sopenharmony_ci cpucp_attr = cpucp_in_reset_history; 44762306a36Sopenharmony_ci break; 44862306a36Sopenharmony_ci default: 44962306a36Sopenharmony_ci return -EINVAL; 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci if (use_cpucp_enum) 45362306a36Sopenharmony_ci hl_set_voltage(hdev, channel, cpucp_attr, val); 45462306a36Sopenharmony_ci else 45562306a36Sopenharmony_ci hl_set_voltage(hdev, channel, fixup_attr_legacy_fw(attr), val); 45662306a36Sopenharmony_ci break; 45762306a36Sopenharmony_ci case hwmon_curr: 45862306a36Sopenharmony_ci switch (attr) { 45962306a36Sopenharmony_ci case hwmon_curr_reset_history: 46062306a36Sopenharmony_ci cpucp_attr = cpucp_curr_reset_history; 46162306a36Sopenharmony_ci break; 46262306a36Sopenharmony_ci default: 46362306a36Sopenharmony_ci return -EINVAL; 46462306a36Sopenharmony_ci } 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci if (use_cpucp_enum) 46762306a36Sopenharmony_ci hl_set_current(hdev, channel, cpucp_attr, val); 46862306a36Sopenharmony_ci else 46962306a36Sopenharmony_ci hl_set_current(hdev, channel, fixup_attr_legacy_fw(attr), val); 47062306a36Sopenharmony_ci break; 47162306a36Sopenharmony_ci case hwmon_power: 47262306a36Sopenharmony_ci switch (attr) { 47362306a36Sopenharmony_ci case hwmon_power_reset_history: 47462306a36Sopenharmony_ci cpucp_attr = CPUCP_POWER_RESET_INPUT_HISTORY; 47562306a36Sopenharmony_ci break; 47662306a36Sopenharmony_ci default: 47762306a36Sopenharmony_ci return -EINVAL; 47862306a36Sopenharmony_ci } 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci if (use_cpucp_enum) 48162306a36Sopenharmony_ci hl_set_power(hdev, channel, cpucp_attr, val); 48262306a36Sopenharmony_ci else 48362306a36Sopenharmony_ci hl_set_power(hdev, channel, fixup_attr_legacy_fw(attr), val); 48462306a36Sopenharmony_ci break; 48562306a36Sopenharmony_ci default: 48662306a36Sopenharmony_ci return -EINVAL; 48762306a36Sopenharmony_ci } 48862306a36Sopenharmony_ci return 0; 48962306a36Sopenharmony_ci} 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_cistatic umode_t hl_is_visible(const void *data, enum hwmon_sensor_types type, 49262306a36Sopenharmony_ci u32 attr, int channel) 49362306a36Sopenharmony_ci{ 49462306a36Sopenharmony_ci switch (type) { 49562306a36Sopenharmony_ci case hwmon_temp: 49662306a36Sopenharmony_ci switch (attr) { 49762306a36Sopenharmony_ci case hwmon_temp_input: 49862306a36Sopenharmony_ci case hwmon_temp_max: 49962306a36Sopenharmony_ci case hwmon_temp_max_hyst: 50062306a36Sopenharmony_ci case hwmon_temp_crit: 50162306a36Sopenharmony_ci case hwmon_temp_crit_hyst: 50262306a36Sopenharmony_ci case hwmon_temp_highest: 50362306a36Sopenharmony_ci return 0444; 50462306a36Sopenharmony_ci case hwmon_temp_offset: 50562306a36Sopenharmony_ci return 0644; 50662306a36Sopenharmony_ci case hwmon_temp_reset_history: 50762306a36Sopenharmony_ci return 0200; 50862306a36Sopenharmony_ci } 50962306a36Sopenharmony_ci break; 51062306a36Sopenharmony_ci case hwmon_in: 51162306a36Sopenharmony_ci switch (attr) { 51262306a36Sopenharmony_ci case hwmon_in_input: 51362306a36Sopenharmony_ci case hwmon_in_min: 51462306a36Sopenharmony_ci case hwmon_in_max: 51562306a36Sopenharmony_ci case hwmon_in_highest: 51662306a36Sopenharmony_ci return 0444; 51762306a36Sopenharmony_ci case hwmon_in_reset_history: 51862306a36Sopenharmony_ci return 0200; 51962306a36Sopenharmony_ci } 52062306a36Sopenharmony_ci break; 52162306a36Sopenharmony_ci case hwmon_curr: 52262306a36Sopenharmony_ci switch (attr) { 52362306a36Sopenharmony_ci case hwmon_curr_input: 52462306a36Sopenharmony_ci case hwmon_curr_min: 52562306a36Sopenharmony_ci case hwmon_curr_max: 52662306a36Sopenharmony_ci case hwmon_curr_highest: 52762306a36Sopenharmony_ci return 0444; 52862306a36Sopenharmony_ci case hwmon_curr_reset_history: 52962306a36Sopenharmony_ci return 0200; 53062306a36Sopenharmony_ci } 53162306a36Sopenharmony_ci break; 53262306a36Sopenharmony_ci case hwmon_fan: 53362306a36Sopenharmony_ci switch (attr) { 53462306a36Sopenharmony_ci case hwmon_fan_input: 53562306a36Sopenharmony_ci case hwmon_fan_min: 53662306a36Sopenharmony_ci case hwmon_fan_max: 53762306a36Sopenharmony_ci return 0444; 53862306a36Sopenharmony_ci } 53962306a36Sopenharmony_ci break; 54062306a36Sopenharmony_ci case hwmon_pwm: 54162306a36Sopenharmony_ci switch (attr) { 54262306a36Sopenharmony_ci case hwmon_pwm_input: 54362306a36Sopenharmony_ci case hwmon_pwm_enable: 54462306a36Sopenharmony_ci return 0644; 54562306a36Sopenharmony_ci } 54662306a36Sopenharmony_ci break; 54762306a36Sopenharmony_ci case hwmon_power: 54862306a36Sopenharmony_ci switch (attr) { 54962306a36Sopenharmony_ci case hwmon_power_input: 55062306a36Sopenharmony_ci case hwmon_power_input_highest: 55162306a36Sopenharmony_ci return 0444; 55262306a36Sopenharmony_ci case hwmon_power_reset_history: 55362306a36Sopenharmony_ci return 0200; 55462306a36Sopenharmony_ci } 55562306a36Sopenharmony_ci break; 55662306a36Sopenharmony_ci default: 55762306a36Sopenharmony_ci break; 55862306a36Sopenharmony_ci } 55962306a36Sopenharmony_ci return 0; 56062306a36Sopenharmony_ci} 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_cistatic const struct hwmon_ops hl_hwmon_ops = { 56362306a36Sopenharmony_ci .is_visible = hl_is_visible, 56462306a36Sopenharmony_ci .read = hl_read, 56562306a36Sopenharmony_ci .write = hl_write 56662306a36Sopenharmony_ci}; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ciint hl_get_temperature(struct hl_device *hdev, 56962306a36Sopenharmony_ci int sensor_index, u32 attr, long *value) 57062306a36Sopenharmony_ci{ 57162306a36Sopenharmony_ci struct cpucp_packet pkt; 57262306a36Sopenharmony_ci u64 result; 57362306a36Sopenharmony_ci int rc; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci pkt.ctl = cpu_to_le32(CPUCP_PACKET_TEMPERATURE_GET << 57862306a36Sopenharmony_ci CPUCP_PKT_CTL_OPCODE_SHIFT); 57962306a36Sopenharmony_ci pkt.sensor_index = __cpu_to_le16(sensor_index); 58062306a36Sopenharmony_ci pkt.type = __cpu_to_le16(attr); 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci dev_dbg(hdev->dev, "get temp, ctl 0x%x, sensor %d, type %d\n", 58362306a36Sopenharmony_ci pkt.ctl, pkt.sensor_index, pkt.type); 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 58662306a36Sopenharmony_ci 0, &result); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci *value = (long) result; 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci if (rc) { 59162306a36Sopenharmony_ci dev_err(hdev->dev, 59262306a36Sopenharmony_ci "Failed to get temperature from sensor %d, error %d\n", 59362306a36Sopenharmony_ci sensor_index, rc); 59462306a36Sopenharmony_ci *value = 0; 59562306a36Sopenharmony_ci } 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci return rc; 59862306a36Sopenharmony_ci} 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ciint hl_set_temperature(struct hl_device *hdev, 60162306a36Sopenharmony_ci int sensor_index, u32 attr, long value) 60262306a36Sopenharmony_ci{ 60362306a36Sopenharmony_ci struct cpucp_packet pkt; 60462306a36Sopenharmony_ci int rc; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci pkt.ctl = cpu_to_le32(CPUCP_PACKET_TEMPERATURE_SET << 60962306a36Sopenharmony_ci CPUCP_PKT_CTL_OPCODE_SHIFT); 61062306a36Sopenharmony_ci pkt.sensor_index = __cpu_to_le16(sensor_index); 61162306a36Sopenharmony_ci pkt.type = __cpu_to_le16(attr); 61262306a36Sopenharmony_ci pkt.value = __cpu_to_le64(value); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 61562306a36Sopenharmony_ci 0, NULL); 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci if (rc) 61862306a36Sopenharmony_ci dev_err(hdev->dev, 61962306a36Sopenharmony_ci "Failed to set temperature of sensor %d, error %d\n", 62062306a36Sopenharmony_ci sensor_index, rc); 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci return rc; 62362306a36Sopenharmony_ci} 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ciint hl_get_voltage(struct hl_device *hdev, 62662306a36Sopenharmony_ci int sensor_index, u32 attr, long *value) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci struct cpucp_packet pkt; 62962306a36Sopenharmony_ci u64 result; 63062306a36Sopenharmony_ci int rc; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci pkt.ctl = cpu_to_le32(CPUCP_PACKET_VOLTAGE_GET << 63562306a36Sopenharmony_ci CPUCP_PKT_CTL_OPCODE_SHIFT); 63662306a36Sopenharmony_ci pkt.sensor_index = __cpu_to_le16(sensor_index); 63762306a36Sopenharmony_ci pkt.type = __cpu_to_le16(attr); 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 64062306a36Sopenharmony_ci 0, &result); 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci *value = (long) result; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci if (rc) { 64562306a36Sopenharmony_ci dev_err(hdev->dev, 64662306a36Sopenharmony_ci "Failed to get voltage from sensor %d, error %d\n", 64762306a36Sopenharmony_ci sensor_index, rc); 64862306a36Sopenharmony_ci *value = 0; 64962306a36Sopenharmony_ci } 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci return rc; 65262306a36Sopenharmony_ci} 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ciint hl_get_current(struct hl_device *hdev, 65562306a36Sopenharmony_ci int sensor_index, u32 attr, long *value) 65662306a36Sopenharmony_ci{ 65762306a36Sopenharmony_ci struct cpucp_packet pkt; 65862306a36Sopenharmony_ci u64 result; 65962306a36Sopenharmony_ci int rc; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci pkt.ctl = cpu_to_le32(CPUCP_PACKET_CURRENT_GET << 66462306a36Sopenharmony_ci CPUCP_PKT_CTL_OPCODE_SHIFT); 66562306a36Sopenharmony_ci pkt.sensor_index = __cpu_to_le16(sensor_index); 66662306a36Sopenharmony_ci pkt.type = __cpu_to_le16(attr); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 66962306a36Sopenharmony_ci 0, &result); 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci *value = (long) result; 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci if (rc) { 67462306a36Sopenharmony_ci dev_err(hdev->dev, 67562306a36Sopenharmony_ci "Failed to get current from sensor %d, error %d\n", 67662306a36Sopenharmony_ci sensor_index, rc); 67762306a36Sopenharmony_ci *value = 0; 67862306a36Sopenharmony_ci } 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci return rc; 68162306a36Sopenharmony_ci} 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ciint hl_get_fan_speed(struct hl_device *hdev, 68462306a36Sopenharmony_ci int sensor_index, u32 attr, long *value) 68562306a36Sopenharmony_ci{ 68662306a36Sopenharmony_ci struct cpucp_packet pkt; 68762306a36Sopenharmony_ci u64 result; 68862306a36Sopenharmony_ci int rc; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci pkt.ctl = cpu_to_le32(CPUCP_PACKET_FAN_SPEED_GET << 69362306a36Sopenharmony_ci CPUCP_PKT_CTL_OPCODE_SHIFT); 69462306a36Sopenharmony_ci pkt.sensor_index = __cpu_to_le16(sensor_index); 69562306a36Sopenharmony_ci pkt.type = __cpu_to_le16(attr); 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 69862306a36Sopenharmony_ci 0, &result); 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci *value = (long) result; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci if (rc) { 70362306a36Sopenharmony_ci dev_err(hdev->dev, 70462306a36Sopenharmony_ci "Failed to get fan speed from sensor %d, error %d\n", 70562306a36Sopenharmony_ci sensor_index, rc); 70662306a36Sopenharmony_ci *value = 0; 70762306a36Sopenharmony_ci } 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci return rc; 71062306a36Sopenharmony_ci} 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ciint hl_get_pwm_info(struct hl_device *hdev, 71362306a36Sopenharmony_ci int sensor_index, u32 attr, long *value) 71462306a36Sopenharmony_ci{ 71562306a36Sopenharmony_ci struct cpucp_packet pkt; 71662306a36Sopenharmony_ci u64 result; 71762306a36Sopenharmony_ci int rc; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci pkt.ctl = cpu_to_le32(CPUCP_PACKET_PWM_GET << 72262306a36Sopenharmony_ci CPUCP_PKT_CTL_OPCODE_SHIFT); 72362306a36Sopenharmony_ci pkt.sensor_index = __cpu_to_le16(sensor_index); 72462306a36Sopenharmony_ci pkt.type = __cpu_to_le16(attr); 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 72762306a36Sopenharmony_ci 0, &result); 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci *value = (long) result; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci if (rc) { 73262306a36Sopenharmony_ci dev_err(hdev->dev, 73362306a36Sopenharmony_ci "Failed to get pwm info from sensor %d, error %d\n", 73462306a36Sopenharmony_ci sensor_index, rc); 73562306a36Sopenharmony_ci *value = 0; 73662306a36Sopenharmony_ci } 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci return rc; 73962306a36Sopenharmony_ci} 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_civoid hl_set_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr, 74262306a36Sopenharmony_ci long value) 74362306a36Sopenharmony_ci{ 74462306a36Sopenharmony_ci struct cpucp_packet pkt; 74562306a36Sopenharmony_ci int rc; 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci pkt.ctl = cpu_to_le32(CPUCP_PACKET_PWM_SET << 75062306a36Sopenharmony_ci CPUCP_PKT_CTL_OPCODE_SHIFT); 75162306a36Sopenharmony_ci pkt.sensor_index = __cpu_to_le16(sensor_index); 75262306a36Sopenharmony_ci pkt.type = __cpu_to_le16(attr); 75362306a36Sopenharmony_ci pkt.value = cpu_to_le64(value); 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 75662306a36Sopenharmony_ci 0, NULL); 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci if (rc) 75962306a36Sopenharmony_ci dev_err(hdev->dev, 76062306a36Sopenharmony_ci "Failed to set pwm info to sensor %d, error %d\n", 76162306a36Sopenharmony_ci sensor_index, rc); 76262306a36Sopenharmony_ci} 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ciint hl_set_voltage(struct hl_device *hdev, 76562306a36Sopenharmony_ci int sensor_index, u32 attr, long value) 76662306a36Sopenharmony_ci{ 76762306a36Sopenharmony_ci struct cpucp_packet pkt; 76862306a36Sopenharmony_ci int rc; 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci pkt.ctl = cpu_to_le32(CPUCP_PACKET_VOLTAGE_SET << 77362306a36Sopenharmony_ci CPUCP_PKT_CTL_OPCODE_SHIFT); 77462306a36Sopenharmony_ci pkt.sensor_index = __cpu_to_le16(sensor_index); 77562306a36Sopenharmony_ci pkt.type = __cpu_to_le16(attr); 77662306a36Sopenharmony_ci pkt.value = __cpu_to_le64(value); 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 77962306a36Sopenharmony_ci 0, NULL); 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci if (rc) 78262306a36Sopenharmony_ci dev_err(hdev->dev, 78362306a36Sopenharmony_ci "Failed to set voltage of sensor %d, error %d\n", 78462306a36Sopenharmony_ci sensor_index, rc); 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci return rc; 78762306a36Sopenharmony_ci} 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ciint hl_set_current(struct hl_device *hdev, 79062306a36Sopenharmony_ci int sensor_index, u32 attr, long value) 79162306a36Sopenharmony_ci{ 79262306a36Sopenharmony_ci struct cpucp_packet pkt; 79362306a36Sopenharmony_ci int rc; 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci pkt.ctl = cpu_to_le32(CPUCP_PACKET_CURRENT_SET << 79862306a36Sopenharmony_ci CPUCP_PKT_CTL_OPCODE_SHIFT); 79962306a36Sopenharmony_ci pkt.sensor_index = __cpu_to_le16(sensor_index); 80062306a36Sopenharmony_ci pkt.type = __cpu_to_le16(attr); 80162306a36Sopenharmony_ci pkt.value = __cpu_to_le64(value); 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 80462306a36Sopenharmony_ci 0, NULL); 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci if (rc) 80762306a36Sopenharmony_ci dev_err(hdev->dev, 80862306a36Sopenharmony_ci "Failed to set current of sensor %d, error %d\n", 80962306a36Sopenharmony_ci sensor_index, rc); 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci return rc; 81262306a36Sopenharmony_ci} 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ciint hl_set_power(struct hl_device *hdev, 81562306a36Sopenharmony_ci int sensor_index, u32 attr, long value) 81662306a36Sopenharmony_ci{ 81762306a36Sopenharmony_ci struct cpucp_packet pkt; 81862306a36Sopenharmony_ci struct asic_fixed_properties *prop = &hdev->asic_prop; 81962306a36Sopenharmony_ci int rc; 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci if (prop->use_get_power_for_reset_history) 82462306a36Sopenharmony_ci pkt.ctl = cpu_to_le32(CPUCP_PACKET_POWER_GET << 82562306a36Sopenharmony_ci CPUCP_PKT_CTL_OPCODE_SHIFT); 82662306a36Sopenharmony_ci else 82762306a36Sopenharmony_ci pkt.ctl = cpu_to_le32(CPUCP_PACKET_POWER_SET << 82862306a36Sopenharmony_ci CPUCP_PKT_CTL_OPCODE_SHIFT); 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci pkt.sensor_index = __cpu_to_le16(sensor_index); 83162306a36Sopenharmony_ci pkt.type = __cpu_to_le16(attr); 83262306a36Sopenharmony_ci pkt.value = __cpu_to_le64(value); 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 83562306a36Sopenharmony_ci 0, NULL); 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci if (rc) 83862306a36Sopenharmony_ci dev_err(hdev->dev, 83962306a36Sopenharmony_ci "Failed to set power of sensor %d, error %d\n", 84062306a36Sopenharmony_ci sensor_index, rc); 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci return rc; 84362306a36Sopenharmony_ci} 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ciint hl_get_power(struct hl_device *hdev, 84662306a36Sopenharmony_ci int sensor_index, u32 attr, long *value) 84762306a36Sopenharmony_ci{ 84862306a36Sopenharmony_ci struct cpucp_packet pkt; 84962306a36Sopenharmony_ci u64 result; 85062306a36Sopenharmony_ci int rc; 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci pkt.ctl = cpu_to_le32(CPUCP_PACKET_POWER_GET << 85562306a36Sopenharmony_ci CPUCP_PKT_CTL_OPCODE_SHIFT); 85662306a36Sopenharmony_ci pkt.sensor_index = __cpu_to_le16(sensor_index); 85762306a36Sopenharmony_ci pkt.type = __cpu_to_le16(attr); 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 86062306a36Sopenharmony_ci 0, &result); 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci *value = (long) result; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci if (rc) { 86562306a36Sopenharmony_ci dev_err(hdev->dev, 86662306a36Sopenharmony_ci "Failed to get power of sensor %d, error %d\n", 86762306a36Sopenharmony_ci sensor_index, rc); 86862306a36Sopenharmony_ci *value = 0; 86962306a36Sopenharmony_ci } 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci return rc; 87262306a36Sopenharmony_ci} 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ciint hl_hwmon_init(struct hl_device *hdev) 87562306a36Sopenharmony_ci{ 87662306a36Sopenharmony_ci struct device *dev = hdev->pdev ? &hdev->pdev->dev : hdev->dev; 87762306a36Sopenharmony_ci struct asic_fixed_properties *prop = &hdev->asic_prop; 87862306a36Sopenharmony_ci int rc; 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci if ((hdev->hwmon_initialized) || !(hdev->cpu_queues_enable)) 88162306a36Sopenharmony_ci return 0; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci if (hdev->hl_chip_info->info) { 88462306a36Sopenharmony_ci hdev->hl_chip_info->ops = &hl_hwmon_ops; 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci hdev->hwmon_dev = hwmon_device_register_with_info(dev, 88762306a36Sopenharmony_ci prop->cpucp_info.card_name, hdev, 88862306a36Sopenharmony_ci hdev->hl_chip_info, NULL); 88962306a36Sopenharmony_ci if (IS_ERR(hdev->hwmon_dev)) { 89062306a36Sopenharmony_ci rc = PTR_ERR(hdev->hwmon_dev); 89162306a36Sopenharmony_ci dev_err(hdev->dev, 89262306a36Sopenharmony_ci "Unable to register hwmon device: %d\n", rc); 89362306a36Sopenharmony_ci return rc; 89462306a36Sopenharmony_ci } 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci dev_info(hdev->dev, "%s: add sensors information\n", 89762306a36Sopenharmony_ci dev_name(hdev->hwmon_dev)); 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci hdev->hwmon_initialized = true; 90062306a36Sopenharmony_ci } else { 90162306a36Sopenharmony_ci dev_info(hdev->dev, "no available sensors\n"); 90262306a36Sopenharmony_ci } 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci return 0; 90562306a36Sopenharmony_ci} 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_civoid hl_hwmon_fini(struct hl_device *hdev) 90862306a36Sopenharmony_ci{ 90962306a36Sopenharmony_ci if (!hdev->hwmon_initialized) 91062306a36Sopenharmony_ci return; 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci hwmon_device_unregister(hdev->hwmon_dev); 91362306a36Sopenharmony_ci} 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_civoid hl_hwmon_release_resources(struct hl_device *hdev) 91662306a36Sopenharmony_ci{ 91762306a36Sopenharmony_ci const struct hwmon_channel_info * const *channel_info_arr; 91862306a36Sopenharmony_ci int i = 0; 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci if (!hdev->hl_chip_info->info) 92162306a36Sopenharmony_ci return; 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci channel_info_arr = hdev->hl_chip_info->info; 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci while (channel_info_arr[i]) { 92662306a36Sopenharmony_ci kfree(channel_info_arr[i]->config); 92762306a36Sopenharmony_ci kfree(channel_info_arr[i]); 92862306a36Sopenharmony_ci i++; 92962306a36Sopenharmony_ci } 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci kfree(channel_info_arr); 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci hdev->hl_chip_info->info = NULL; 93462306a36Sopenharmony_ci} 935