Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.4.
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (C) 2023, Intel Corporation. */
  3
  4#include "ice.h"
  5#include "ice_hwmon.h"
  6#include "ice_adminq_cmd.h"
  7
  8#include <linux/hwmon.h>
  9
 10#define TEMP_FROM_REG(reg) ((reg) * 1000)
 11
 12static const struct hwmon_channel_info *ice_hwmon_info[] = {
 13	HWMON_CHANNEL_INFO(temp,
 14			   HWMON_T_INPUT | HWMON_T_MAX |
 15			   HWMON_T_CRIT | HWMON_T_EMERGENCY),
 16	NULL
 17};
 18
 19static int ice_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
 20			  u32 attr, int channel, long *val)
 21{
 22	struct ice_aqc_get_sensor_reading_resp resp;
 23	struct ice_pf *pf = dev_get_drvdata(dev);
 24	int ret;
 25
 26	if (type != hwmon_temp)
 27		return -EOPNOTSUPP;
 28
 29	ret = ice_aq_get_sensor_reading(&pf->hw, &resp);
 30	if (ret) {
 31		dev_warn_ratelimited(dev,
 32				     "%s HW read failure (%d)\n",
 33				     __func__,
 34				     ret);
 35		return ret;
 36	}
 37
 38	switch (attr) {
 39	case hwmon_temp_input:
 40		*val = TEMP_FROM_REG(resp.data.s0f0.temp);
 41		break;
 42	case hwmon_temp_max:
 43		*val = TEMP_FROM_REG(resp.data.s0f0.temp_warning_threshold);
 44		break;
 45	case hwmon_temp_crit:
 46		*val = TEMP_FROM_REG(resp.data.s0f0.temp_critical_threshold);
 47		break;
 48	case hwmon_temp_emergency:
 49		*val = TEMP_FROM_REG(resp.data.s0f0.temp_fatal_threshold);
 50		break;
 51	default:
 52		dev_dbg(dev, "%s unsupported attribute (%d)\n",
 53			__func__, attr);
 54		return -EOPNOTSUPP;
 55	}
 56
 57	return 0;
 58}
 59
 60static umode_t ice_hwmon_is_visible(const void *data,
 61				    enum hwmon_sensor_types type, u32 attr,
 62				    int channel)
 63{
 64	if (type != hwmon_temp)
 65		return 0;
 66
 67	switch (attr) {
 68	case hwmon_temp_input:
 69	case hwmon_temp_crit:
 70	case hwmon_temp_max:
 71	case hwmon_temp_emergency:
 72		return 0444;
 73	}
 74
 75	return 0;
 76}
 77
 78static const struct hwmon_ops ice_hwmon_ops = {
 79	.is_visible = ice_hwmon_is_visible,
 80	.read = ice_hwmon_read
 81};
 82
 83static const struct hwmon_chip_info ice_chip_info = {
 84	.ops = &ice_hwmon_ops,
 85	.info = ice_hwmon_info
 86};
 87
 88static bool ice_is_internal_reading_supported(struct ice_pf *pf)
 89{
 90	/* Only the first PF will report temperature for a chip.
 91	 * Note that internal temp reading is not supported
 92	 * for older FW (< v4.30).
 93	 */
 94	if (pf->hw.pf_id)
 95		return false;
 96
 97	unsigned long sensors = pf->hw.dev_caps.supported_sensors;
 98
 99	return test_bit(ICE_SENSOR_SUPPORT_E810_INT_TEMP_BIT, &sensors);
100};
101
102void ice_hwmon_init(struct ice_pf *pf)
103{
104	struct device *dev = ice_pf_to_dev(pf);
105	struct device *hdev;
106
107	if (!ice_is_internal_reading_supported(pf))
108		return;
109
110	hdev = hwmon_device_register_with_info(dev, "ice", pf, &ice_chip_info,
111					       NULL);
112	if (IS_ERR(hdev)) {
113		dev_warn(dev,
114			 "hwmon_device_register_with_info returns error (%ld)",
115			 PTR_ERR(hdev));
116		return;
117	}
118	pf->hwmon_dev = hdev;
119}
120
121void ice_hwmon_exit(struct ice_pf *pf)
122{
123	if (!pf->hwmon_dev)
124		return;
125	hwmon_device_unregister(pf->hwmon_dev);
126}