1 // SPDX-License-Identifier: GPL-2.0-only
3 * SolidRun DPU driver for control plane
5 * Copyright (C) 2022-2023 SolidRun
7 * Author: Alvaro Karsz <alvaro.karsz@solid-run.com>
10 #include <linux/hwmon.h>
12 #include "snet_vdpa.h"
15 #define SNET_MON_TMP0_IN_OFF 0x00
16 #define SNET_MON_TMP0_MAX_OFF 0x08
17 #define SNET_MON_TMP0_CRIT_OFF 0x10
18 #define SNET_MON_TMP1_IN_OFF 0x18
19 #define SNET_MON_TMP1_CRIT_OFF 0x20
20 #define SNET_MON_CURR_IN_OFF 0x28
21 #define SNET_MON_CURR_MAX_OFF 0x30
22 #define SNET_MON_CURR_CRIT_OFF 0x38
23 #define SNET_MON_PWR_IN_OFF 0x40
24 #define SNET_MON_VOLT_IN_OFF 0x48
25 #define SNET_MON_VOLT_CRIT_OFF 0x50
26 #define SNET_MON_VOLT_LCRIT_OFF 0x58
28 static void snet_hwmon_read_reg(struct psnet
*psnet
, u32 reg
, long *out
)
30 *out
= psnet_read64(psnet
, psnet
->cfg
.hwmon_off
+ reg
);
33 static umode_t
snet_howmon_is_visible(const void *data
,
34 enum hwmon_sensor_types type
,
35 u32 attr
, int channel
)
40 static int snet_howmon_read(struct device
*dev
, enum hwmon_sensor_types type
,
41 u32 attr
, int channel
, long *val
)
43 struct psnet
*psnet
= dev_get_drvdata(dev
);
50 snet_hwmon_read_reg(psnet
, SNET_MON_VOLT_LCRIT_OFF
, val
);
53 snet_hwmon_read_reg(psnet
, SNET_MON_VOLT_CRIT_OFF
, val
);
56 snet_hwmon_read_reg(psnet
, SNET_MON_VOLT_IN_OFF
, val
);
66 case hwmon_power_input
:
67 snet_hwmon_read_reg(psnet
, SNET_MON_PWR_IN_OFF
, val
);
78 case hwmon_curr_input
:
79 snet_hwmon_read_reg(psnet
, SNET_MON_CURR_IN_OFF
, val
);
82 snet_hwmon_read_reg(psnet
, SNET_MON_CURR_MAX_OFF
, val
);
85 snet_hwmon_read_reg(psnet
, SNET_MON_CURR_CRIT_OFF
, val
);
95 case hwmon_temp_input
:
97 snet_hwmon_read_reg(psnet
, SNET_MON_TMP0_IN_OFF
, val
);
99 snet_hwmon_read_reg(psnet
, SNET_MON_TMP1_IN_OFF
, val
);
103 snet_hwmon_read_reg(psnet
, SNET_MON_TMP0_MAX_OFF
, val
);
107 case hwmon_temp_crit
:
109 snet_hwmon_read_reg(psnet
, SNET_MON_TMP0_CRIT_OFF
, val
);
111 snet_hwmon_read_reg(psnet
, SNET_MON_TMP1_CRIT_OFF
, val
);
127 static int snet_hwmon_read_string(struct device
*dev
,
128 enum hwmon_sensor_types type
, u32 attr
,
129 int channel
, const char **str
)
145 *str
= "power_stage_temp";
147 *str
= "ic_junction_temp";
156 static const struct hwmon_ops snet_hwmon_ops
= {
157 .is_visible
= snet_howmon_is_visible
,
158 .read
= snet_howmon_read
,
159 .read_string
= snet_hwmon_read_string
162 static const struct hwmon_channel_info
* const snet_hwmon_info
[] = {
163 HWMON_CHANNEL_INFO(temp
, HWMON_T_INPUT
| HWMON_T_MAX
| HWMON_T_CRIT
| HWMON_T_LABEL
,
164 HWMON_T_INPUT
| HWMON_T_CRIT
| HWMON_T_LABEL
),
165 HWMON_CHANNEL_INFO(power
, HWMON_P_INPUT
| HWMON_P_LABEL
),
166 HWMON_CHANNEL_INFO(curr
, HWMON_C_INPUT
| HWMON_C_MAX
| HWMON_C_CRIT
| HWMON_C_LABEL
),
167 HWMON_CHANNEL_INFO(in
, HWMON_I_INPUT
| HWMON_I_CRIT
| HWMON_I_LCRIT
| HWMON_I_LABEL
),
171 static const struct hwmon_chip_info snet_hwmono_info
= {
172 .ops
= &snet_hwmon_ops
,
173 .info
= snet_hwmon_info
,
176 /* Create an HW monitor device */
177 void psnet_create_hwmon(struct pci_dev
*pdev
)
179 struct device
*hwmon
;
180 struct psnet
*psnet
= pci_get_drvdata(pdev
);
182 snprintf(psnet
->hwmon_name
, SNET_NAME_SIZE
, "snet_%s", pci_name(pdev
));
183 hwmon
= devm_hwmon_device_register_with_info(&pdev
->dev
, psnet
->hwmon_name
, psnet
,
184 &snet_hwmono_info
, NULL
);
185 /* The monitor is not mandatory, Just alert user in case of an error */
187 SNET_WARN(pdev
, "Failed to create SNET hwmon, error %ld\n", PTR_ERR(hwmon
));