1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /* Copyright (c) 2015-2018 Mellanox Technologies. All rights reserved */ 3 4 #include <linux/kernel.h> 5 #include <linux/types.h> 6 #include <linux/device.h> 7 #include <linux/sysfs.h> 8 #include <linux/hwmon.h> 9 #include <linux/err.h> 10 11 #include "core.h" 12 13 #define MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT 127 14 #define MLXSW_HWMON_ATTR_COUNT (MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT * 4 + \ 15 MLXSW_MFCR_TACHOS_MAX + MLXSW_MFCR_PWMS_MAX) 16 17 struct mlxsw_hwmon_attr { 18 struct device_attribute dev_attr; 19 struct mlxsw_hwmon *hwmon; 20 unsigned int type_index; 21 char name[32]; 22 }; 23 24 struct mlxsw_hwmon { 25 struct mlxsw_core *core; 26 const struct mlxsw_bus_info *bus_info; 27 struct device *hwmon_dev; 28 struct attribute_group group; 29 const struct attribute_group *groups[2]; 30 struct attribute *attrs[MLXSW_HWMON_ATTR_COUNT + 1]; 31 struct mlxsw_hwmon_attr hwmon_attrs[MLXSW_HWMON_ATTR_COUNT]; 32 unsigned int attrs_count; 33 }; 34 35 static ssize_t mlxsw_hwmon_temp_show(struct device *dev, 36 struct device_attribute *attr, 37 char *buf) 38 { 39 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 40 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 41 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 42 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 43 unsigned int temp; 44 int err; 45 46 mlxsw_reg_mtmp_pack(mtmp_pl, mlwsw_hwmon_attr->type_index, 47 false, false); 48 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); 49 if (err) { 50 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n"); 51 return err; 52 } 53 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL); 54 return sprintf(buf, "%u\n", temp); 55 } 56 57 static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev, 58 struct device_attribute *attr, 59 char *buf) 60 { 61 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 62 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 63 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 64 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 65 unsigned int temp_max; 66 int err; 67 68 mlxsw_reg_mtmp_pack(mtmp_pl, mlwsw_hwmon_attr->type_index, 69 false, false); 70 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); 71 if (err) { 72 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n"); 73 return err; 74 } 75 mlxsw_reg_mtmp_unpack(mtmp_pl, NULL, &temp_max, NULL); 76 return sprintf(buf, "%u\n", temp_max); 77 } 78 79 static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev, 80 struct device_attribute *attr, 81 const char *buf, size_t len) 82 { 83 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 84 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 85 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 86 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 87 unsigned long val; 88 int err; 89 90 err = kstrtoul(buf, 10, &val); 91 if (err) 92 return err; 93 if (val != 1) 94 return -EINVAL; 95 96 mlxsw_reg_mtmp_pack(mtmp_pl, mlwsw_hwmon_attr->type_index, true, true); 97 err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); 98 if (err) { 99 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to reset temp sensor history\n"); 100 return err; 101 } 102 return len; 103 } 104 105 static ssize_t mlxsw_hwmon_fan_rpm_show(struct device *dev, 106 struct device_attribute *attr, 107 char *buf) 108 { 109 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 110 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 111 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 112 char mfsm_pl[MLXSW_REG_MFSM_LEN]; 113 int err; 114 115 mlxsw_reg_mfsm_pack(mfsm_pl, mlwsw_hwmon_attr->type_index); 116 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfsm), mfsm_pl); 117 if (err) { 118 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query fan\n"); 119 return err; 120 } 121 return sprintf(buf, "%u\n", mlxsw_reg_mfsm_rpm_get(mfsm_pl)); 122 } 123 124 static ssize_t mlxsw_hwmon_pwm_show(struct device *dev, 125 struct device_attribute *attr, 126 char *buf) 127 { 128 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 129 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 130 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 131 char mfsc_pl[MLXSW_REG_MFSC_LEN]; 132 int err; 133 134 mlxsw_reg_mfsc_pack(mfsc_pl, mlwsw_hwmon_attr->type_index, 0); 135 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfsc), mfsc_pl); 136 if (err) { 137 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query PWM\n"); 138 return err; 139 } 140 return sprintf(buf, "%u\n", 141 mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl)); 142 } 143 144 static ssize_t mlxsw_hwmon_pwm_store(struct device *dev, 145 struct device_attribute *attr, 146 const char *buf, size_t len) 147 { 148 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 149 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 150 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 151 char mfsc_pl[MLXSW_REG_MFSC_LEN]; 152 unsigned long val; 153 int err; 154 155 err = kstrtoul(buf, 10, &val); 156 if (err) 157 return err; 158 if (val > 255) 159 return -EINVAL; 160 161 mlxsw_reg_mfsc_pack(mfsc_pl, mlwsw_hwmon_attr->type_index, val); 162 err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mfsc), mfsc_pl); 163 if (err) { 164 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to write PWM\n"); 165 return err; 166 } 167 return len; 168 } 169 170 enum mlxsw_hwmon_attr_type { 171 MLXSW_HWMON_ATTR_TYPE_TEMP, 172 MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, 173 MLXSW_HWMON_ATTR_TYPE_TEMP_RST, 174 MLXSW_HWMON_ATTR_TYPE_FAN_RPM, 175 MLXSW_HWMON_ATTR_TYPE_PWM, 176 }; 177 178 static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon, 179 enum mlxsw_hwmon_attr_type attr_type, 180 unsigned int type_index, unsigned int num) { 181 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr; 182 unsigned int attr_index; 183 184 attr_index = mlxsw_hwmon->attrs_count; 185 mlxsw_hwmon_attr = &mlxsw_hwmon->hwmon_attrs[attr_index]; 186 187 switch (attr_type) { 188 case MLXSW_HWMON_ATTR_TYPE_TEMP: 189 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_temp_show; 190 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 191 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 192 "temp%u_input", num + 1); 193 break; 194 case MLXSW_HWMON_ATTR_TYPE_TEMP_MAX: 195 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_temp_max_show; 196 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 197 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 198 "temp%u_highest", num + 1); 199 break; 200 case MLXSW_HWMON_ATTR_TYPE_TEMP_RST: 201 mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_temp_rst_store; 202 mlxsw_hwmon_attr->dev_attr.attr.mode = 0200; 203 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 204 "temp%u_reset_history", num + 1); 205 break; 206 case MLXSW_HWMON_ATTR_TYPE_FAN_RPM: 207 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_fan_rpm_show; 208 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 209 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 210 "fan%u_input", num + 1); 211 break; 212 case MLXSW_HWMON_ATTR_TYPE_PWM: 213 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_pwm_show; 214 mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_pwm_store; 215 mlxsw_hwmon_attr->dev_attr.attr.mode = 0644; 216 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 217 "pwm%u", num + 1); 218 break; 219 default: 220 WARN_ON(1); 221 } 222 223 mlxsw_hwmon_attr->type_index = type_index; 224 mlxsw_hwmon_attr->hwmon = mlxsw_hwmon; 225 mlxsw_hwmon_attr->dev_attr.attr.name = mlxsw_hwmon_attr->name; 226 sysfs_attr_init(&mlxsw_hwmon_attr->dev_attr.attr); 227 228 mlxsw_hwmon->attrs[attr_index] = &mlxsw_hwmon_attr->dev_attr.attr; 229 mlxsw_hwmon->attrs_count++; 230 } 231 232 static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon) 233 { 234 char mtcap_pl[MLXSW_REG_MTCAP_LEN] = {0}; 235 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 236 u8 sensor_count; 237 int i; 238 int err; 239 240 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtcap), mtcap_pl); 241 if (err) { 242 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get number of temp sensors\n"); 243 return err; 244 } 245 sensor_count = mlxsw_reg_mtcap_sensor_count_get(mtcap_pl); 246 for (i = 0; i < sensor_count; i++) { 247 mlxsw_reg_mtmp_pack(mtmp_pl, i, true, true); 248 err = mlxsw_reg_write(mlxsw_hwmon->core, 249 MLXSW_REG(mtmp), mtmp_pl); 250 if (err) { 251 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to setup temp sensor number %d\n", 252 i); 253 return err; 254 } 255 mlxsw_hwmon_attr_add(mlxsw_hwmon, 256 MLXSW_HWMON_ATTR_TYPE_TEMP, i, i); 257 mlxsw_hwmon_attr_add(mlxsw_hwmon, 258 MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, i, i); 259 mlxsw_hwmon_attr_add(mlxsw_hwmon, 260 MLXSW_HWMON_ATTR_TYPE_TEMP_RST, i, i); 261 } 262 return 0; 263 } 264 265 static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon) 266 { 267 char mfcr_pl[MLXSW_REG_MFCR_LEN] = {0}; 268 enum mlxsw_reg_mfcr_pwm_frequency freq; 269 unsigned int type_index; 270 unsigned int num; 271 u16 tacho_active; 272 u8 pwm_active; 273 int err; 274 275 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfcr), mfcr_pl); 276 if (err) { 277 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get to probe PWMs and Tachometers\n"); 278 return err; 279 } 280 mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active); 281 num = 0; 282 for (type_index = 0; type_index < MLXSW_MFCR_TACHOS_MAX; type_index++) { 283 if (tacho_active & BIT(type_index)) 284 mlxsw_hwmon_attr_add(mlxsw_hwmon, 285 MLXSW_HWMON_ATTR_TYPE_FAN_RPM, 286 type_index, num++); 287 } 288 num = 0; 289 for (type_index = 0; type_index < MLXSW_MFCR_PWMS_MAX; type_index++) { 290 if (pwm_active & BIT(type_index)) 291 mlxsw_hwmon_attr_add(mlxsw_hwmon, 292 MLXSW_HWMON_ATTR_TYPE_PWM, 293 type_index, num++); 294 } 295 return 0; 296 } 297 298 int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, 299 const struct mlxsw_bus_info *mlxsw_bus_info, 300 struct mlxsw_hwmon **p_hwmon) 301 { 302 struct mlxsw_hwmon *mlxsw_hwmon; 303 struct device *hwmon_dev; 304 int err; 305 306 mlxsw_hwmon = kzalloc(sizeof(*mlxsw_hwmon), GFP_KERNEL); 307 if (!mlxsw_hwmon) 308 return -ENOMEM; 309 mlxsw_hwmon->core = mlxsw_core; 310 mlxsw_hwmon->bus_info = mlxsw_bus_info; 311 312 err = mlxsw_hwmon_temp_init(mlxsw_hwmon); 313 if (err) 314 goto err_temp_init; 315 316 err = mlxsw_hwmon_fans_init(mlxsw_hwmon); 317 if (err) 318 goto err_fans_init; 319 320 mlxsw_hwmon->groups[0] = &mlxsw_hwmon->group; 321 mlxsw_hwmon->group.attrs = mlxsw_hwmon->attrs; 322 323 hwmon_dev = hwmon_device_register_with_groups(mlxsw_bus_info->dev, 324 "mlxsw", mlxsw_hwmon, 325 mlxsw_hwmon->groups); 326 if (IS_ERR(hwmon_dev)) { 327 err = PTR_ERR(hwmon_dev); 328 goto err_hwmon_register; 329 } 330 331 mlxsw_hwmon->hwmon_dev = hwmon_dev; 332 *p_hwmon = mlxsw_hwmon; 333 return 0; 334 335 err_hwmon_register: 336 err_fans_init: 337 err_temp_init: 338 kfree(mlxsw_hwmon); 339 return err; 340 } 341 342 void mlxsw_hwmon_fini(struct mlxsw_hwmon *mlxsw_hwmon) 343 { 344 hwmon_device_unregister(mlxsw_hwmon->hwmon_dev); 345 kfree(mlxsw_hwmon); 346 } 347