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 #include <linux/sfp.h> 11 12 #include "core.h" 13 #include "core_env.h" 14 15 #define MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT 127 16 #define MLXSW_HWMON_ATTR_COUNT (MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT * 4 + \ 17 MLXSW_MFCR_TACHOS_MAX + MLXSW_MFCR_PWMS_MAX) 18 19 struct mlxsw_hwmon_attr { 20 struct device_attribute dev_attr; 21 struct mlxsw_hwmon *hwmon; 22 unsigned int type_index; 23 char name[32]; 24 }; 25 26 static int mlxsw_hwmon_get_attr_index(int index, int count) 27 { 28 if (index >= count) 29 return index % count + MLXSW_REG_MTMP_GBOX_INDEX_MIN; 30 31 return index; 32 } 33 34 struct mlxsw_hwmon { 35 struct mlxsw_core *core; 36 const struct mlxsw_bus_info *bus_info; 37 struct device *hwmon_dev; 38 struct attribute_group group; 39 const struct attribute_group *groups[2]; 40 struct attribute *attrs[MLXSW_HWMON_ATTR_COUNT + 1]; 41 struct mlxsw_hwmon_attr hwmon_attrs[MLXSW_HWMON_ATTR_COUNT]; 42 unsigned int attrs_count; 43 u8 sensor_count; 44 u8 module_sensor_max; 45 }; 46 47 static ssize_t mlxsw_hwmon_temp_show(struct device *dev, 48 struct device_attribute *attr, 49 char *buf) 50 { 51 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 52 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 53 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 54 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 55 int temp, index; 56 int err; 57 58 index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index, 59 mlxsw_hwmon->module_sensor_max); 60 mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false); 61 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); 62 if (err) { 63 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n"); 64 return err; 65 } 66 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL); 67 return sprintf(buf, "%d\n", temp); 68 } 69 70 static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev, 71 struct device_attribute *attr, 72 char *buf) 73 { 74 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 75 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 76 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 77 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 78 int temp_max, index; 79 int err; 80 81 index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index, 82 mlxsw_hwmon->module_sensor_max); 83 mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false); 84 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); 85 if (err) { 86 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n"); 87 return err; 88 } 89 mlxsw_reg_mtmp_unpack(mtmp_pl, NULL, &temp_max, NULL); 90 return sprintf(buf, "%d\n", temp_max); 91 } 92 93 static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev, 94 struct device_attribute *attr, 95 const char *buf, size_t len) 96 { 97 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 98 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 99 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 100 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 101 unsigned long val; 102 int index; 103 int err; 104 105 err = kstrtoul(buf, 10, &val); 106 if (err) 107 return err; 108 if (val != 1) 109 return -EINVAL; 110 111 index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index, 112 mlxsw_hwmon->module_sensor_max); 113 mlxsw_reg_mtmp_pack(mtmp_pl, index, true, true); 114 err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); 115 if (err) { 116 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to reset temp sensor history\n"); 117 return err; 118 } 119 return len; 120 } 121 122 static ssize_t mlxsw_hwmon_fan_rpm_show(struct device *dev, 123 struct device_attribute *attr, 124 char *buf) 125 { 126 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 127 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 128 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 129 char mfsm_pl[MLXSW_REG_MFSM_LEN]; 130 int err; 131 132 mlxsw_reg_mfsm_pack(mfsm_pl, mlwsw_hwmon_attr->type_index); 133 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfsm), mfsm_pl); 134 if (err) { 135 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query fan\n"); 136 return err; 137 } 138 return sprintf(buf, "%u\n", mlxsw_reg_mfsm_rpm_get(mfsm_pl)); 139 } 140 141 static ssize_t mlxsw_hwmon_fan_fault_show(struct device *dev, 142 struct device_attribute *attr, 143 char *buf) 144 { 145 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 146 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 147 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 148 char fore_pl[MLXSW_REG_FORE_LEN]; 149 bool fault; 150 int err; 151 152 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(fore), fore_pl); 153 if (err) { 154 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query fan\n"); 155 return err; 156 } 157 mlxsw_reg_fore_unpack(fore_pl, mlwsw_hwmon_attr->type_index, &fault); 158 159 return sprintf(buf, "%u\n", fault); 160 } 161 162 static ssize_t mlxsw_hwmon_pwm_show(struct device *dev, 163 struct device_attribute *attr, 164 char *buf) 165 { 166 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 167 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 168 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 169 char mfsc_pl[MLXSW_REG_MFSC_LEN]; 170 int err; 171 172 mlxsw_reg_mfsc_pack(mfsc_pl, mlwsw_hwmon_attr->type_index, 0); 173 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfsc), mfsc_pl); 174 if (err) { 175 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query PWM\n"); 176 return err; 177 } 178 return sprintf(buf, "%u\n", 179 mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl)); 180 } 181 182 static ssize_t mlxsw_hwmon_pwm_store(struct device *dev, 183 struct device_attribute *attr, 184 const char *buf, size_t len) 185 { 186 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 187 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 188 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 189 char mfsc_pl[MLXSW_REG_MFSC_LEN]; 190 unsigned long val; 191 int err; 192 193 err = kstrtoul(buf, 10, &val); 194 if (err) 195 return err; 196 if (val > 255) 197 return -EINVAL; 198 199 mlxsw_reg_mfsc_pack(mfsc_pl, mlwsw_hwmon_attr->type_index, val); 200 err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mfsc), mfsc_pl); 201 if (err) { 202 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to write PWM\n"); 203 return err; 204 } 205 return len; 206 } 207 208 static ssize_t mlxsw_hwmon_module_temp_show(struct device *dev, 209 struct device_attribute *attr, 210 char *buf) 211 { 212 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 213 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 214 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 215 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 216 u8 module; 217 int temp; 218 int err; 219 220 module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; 221 mlxsw_reg_mtmp_pack(mtmp_pl, MLXSW_REG_MTMP_MODULE_INDEX_MIN + module, 222 false, false); 223 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); 224 if (err) 225 return err; 226 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL); 227 228 return sprintf(buf, "%d\n", temp); 229 } 230 231 static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev, 232 struct device_attribute *attr, 233 char *buf) 234 { 235 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 236 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 237 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 238 char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0}; 239 u8 module, fault; 240 u16 temp; 241 int err; 242 243 module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; 244 mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, 245 1); 246 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl); 247 if (err) { 248 dev_err(dev, "Failed to query module temperature sensor\n"); 249 return err; 250 } 251 252 mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL); 253 254 /* Update status and temperature cache. */ 255 switch (temp) { 256 case MLXSW_REG_MTBR_BAD_SENS_INFO: 257 /* Untrusted cable is connected. Reading temperature from its 258 * sensor is faulty. 259 */ 260 fault = 1; 261 break; 262 case MLXSW_REG_MTBR_NO_CONN: /* fall-through */ 263 case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */ 264 case MLXSW_REG_MTBR_INDEX_NA: 265 default: 266 fault = 0; 267 break; 268 } 269 270 return sprintf(buf, "%u\n", fault); 271 } 272 273 static ssize_t 274 mlxsw_hwmon_module_temp_critical_show(struct device *dev, 275 struct device_attribute *attr, char *buf) 276 { 277 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 278 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 279 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 280 int temp; 281 u8 module; 282 int err; 283 284 module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; 285 err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module, 286 SFP_TEMP_HIGH_WARN, &temp); 287 if (err) { 288 dev_err(dev, "Failed to query module temperature thresholds\n"); 289 return err; 290 } 291 292 return sprintf(buf, "%u\n", temp); 293 } 294 295 static ssize_t 296 mlxsw_hwmon_module_temp_emergency_show(struct device *dev, 297 struct device_attribute *attr, 298 char *buf) 299 { 300 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 301 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 302 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 303 u8 module; 304 int temp; 305 int err; 306 307 module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; 308 err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module, 309 SFP_TEMP_HIGH_ALARM, &temp); 310 if (err) { 311 dev_err(dev, "Failed to query module temperature thresholds\n"); 312 return err; 313 } 314 315 return sprintf(buf, "%u\n", temp); 316 } 317 318 static ssize_t 319 mlxsw_hwmon_module_temp_label_show(struct device *dev, 320 struct device_attribute *attr, 321 char *buf) 322 { 323 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 324 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 325 326 return sprintf(buf, "front panel %03u\n", 327 mlwsw_hwmon_attr->type_index); 328 } 329 330 static ssize_t 331 mlxsw_hwmon_gbox_temp_label_show(struct device *dev, 332 struct device_attribute *attr, 333 char *buf) 334 { 335 struct mlxsw_hwmon_attr *mlwsw_hwmon_attr = 336 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 337 struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; 338 int index = mlwsw_hwmon_attr->type_index - 339 mlxsw_hwmon->module_sensor_max + 1; 340 341 return sprintf(buf, "gearbox %03u\n", index); 342 } 343 344 enum mlxsw_hwmon_attr_type { 345 MLXSW_HWMON_ATTR_TYPE_TEMP, 346 MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, 347 MLXSW_HWMON_ATTR_TYPE_TEMP_RST, 348 MLXSW_HWMON_ATTR_TYPE_FAN_RPM, 349 MLXSW_HWMON_ATTR_TYPE_FAN_FAULT, 350 MLXSW_HWMON_ATTR_TYPE_PWM, 351 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE, 352 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT, 353 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT, 354 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG, 355 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL, 356 MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL, 357 }; 358 359 static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon, 360 enum mlxsw_hwmon_attr_type attr_type, 361 unsigned int type_index, unsigned int num) { 362 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr; 363 unsigned int attr_index; 364 365 attr_index = mlxsw_hwmon->attrs_count; 366 mlxsw_hwmon_attr = &mlxsw_hwmon->hwmon_attrs[attr_index]; 367 368 switch (attr_type) { 369 case MLXSW_HWMON_ATTR_TYPE_TEMP: 370 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_temp_show; 371 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 372 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 373 "temp%u_input", num + 1); 374 break; 375 case MLXSW_HWMON_ATTR_TYPE_TEMP_MAX: 376 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_temp_max_show; 377 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 378 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 379 "temp%u_highest", num + 1); 380 break; 381 case MLXSW_HWMON_ATTR_TYPE_TEMP_RST: 382 mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_temp_rst_store; 383 mlxsw_hwmon_attr->dev_attr.attr.mode = 0200; 384 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 385 "temp%u_reset_history", num + 1); 386 break; 387 case MLXSW_HWMON_ATTR_TYPE_FAN_RPM: 388 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_fan_rpm_show; 389 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 390 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 391 "fan%u_input", num + 1); 392 break; 393 case MLXSW_HWMON_ATTR_TYPE_FAN_FAULT: 394 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_fan_fault_show; 395 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 396 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 397 "fan%u_fault", num + 1); 398 break; 399 case MLXSW_HWMON_ATTR_TYPE_PWM: 400 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_pwm_show; 401 mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_pwm_store; 402 mlxsw_hwmon_attr->dev_attr.attr.mode = 0644; 403 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 404 "pwm%u", num + 1); 405 break; 406 case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE: 407 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_module_temp_show; 408 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 409 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 410 "temp%u_input", num + 1); 411 break; 412 case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT: 413 mlxsw_hwmon_attr->dev_attr.show = 414 mlxsw_hwmon_module_temp_fault_show; 415 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 416 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 417 "temp%u_fault", num + 1); 418 break; 419 case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT: 420 mlxsw_hwmon_attr->dev_attr.show = 421 mlxsw_hwmon_module_temp_critical_show; 422 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 423 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 424 "temp%u_crit", num + 1); 425 break; 426 case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG: 427 mlxsw_hwmon_attr->dev_attr.show = 428 mlxsw_hwmon_module_temp_emergency_show; 429 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 430 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 431 "temp%u_emergency", num + 1); 432 break; 433 case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL: 434 mlxsw_hwmon_attr->dev_attr.show = 435 mlxsw_hwmon_module_temp_label_show; 436 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 437 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 438 "temp%u_label", num + 1); 439 break; 440 case MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL: 441 mlxsw_hwmon_attr->dev_attr.show = 442 mlxsw_hwmon_gbox_temp_label_show; 443 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 444 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 445 "temp%u_label", num + 1); 446 break; 447 default: 448 WARN_ON(1); 449 } 450 451 mlxsw_hwmon_attr->type_index = type_index; 452 mlxsw_hwmon_attr->hwmon = mlxsw_hwmon; 453 mlxsw_hwmon_attr->dev_attr.attr.name = mlxsw_hwmon_attr->name; 454 sysfs_attr_init(&mlxsw_hwmon_attr->dev_attr.attr); 455 456 mlxsw_hwmon->attrs[attr_index] = &mlxsw_hwmon_attr->dev_attr.attr; 457 mlxsw_hwmon->attrs_count++; 458 } 459 460 static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon) 461 { 462 char mtcap_pl[MLXSW_REG_MTCAP_LEN] = {0}; 463 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 464 int i; 465 int err; 466 467 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtcap), mtcap_pl); 468 if (err) { 469 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get number of temp sensors\n"); 470 return err; 471 } 472 mlxsw_hwmon->sensor_count = mlxsw_reg_mtcap_sensor_count_get(mtcap_pl); 473 for (i = 0; i < mlxsw_hwmon->sensor_count; i++) { 474 mlxsw_reg_mtmp_pack(mtmp_pl, i, true, true); 475 err = mlxsw_reg_write(mlxsw_hwmon->core, 476 MLXSW_REG(mtmp), mtmp_pl); 477 if (err) { 478 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to setup temp sensor number %d\n", 479 i); 480 return err; 481 } 482 mlxsw_hwmon_attr_add(mlxsw_hwmon, 483 MLXSW_HWMON_ATTR_TYPE_TEMP, i, i); 484 mlxsw_hwmon_attr_add(mlxsw_hwmon, 485 MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, i, i); 486 mlxsw_hwmon_attr_add(mlxsw_hwmon, 487 MLXSW_HWMON_ATTR_TYPE_TEMP_RST, i, i); 488 } 489 return 0; 490 } 491 492 static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon) 493 { 494 char mfcr_pl[MLXSW_REG_MFCR_LEN] = {0}; 495 enum mlxsw_reg_mfcr_pwm_frequency freq; 496 unsigned int type_index; 497 unsigned int num; 498 u16 tacho_active; 499 u8 pwm_active; 500 int err; 501 502 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfcr), mfcr_pl); 503 if (err) { 504 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get to probe PWMs and Tachometers\n"); 505 return err; 506 } 507 mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active); 508 num = 0; 509 for (type_index = 0; type_index < MLXSW_MFCR_TACHOS_MAX; type_index++) { 510 if (tacho_active & BIT(type_index)) { 511 mlxsw_hwmon_attr_add(mlxsw_hwmon, 512 MLXSW_HWMON_ATTR_TYPE_FAN_RPM, 513 type_index, num); 514 mlxsw_hwmon_attr_add(mlxsw_hwmon, 515 MLXSW_HWMON_ATTR_TYPE_FAN_FAULT, 516 type_index, num++); 517 } 518 } 519 num = 0; 520 for (type_index = 0; type_index < MLXSW_MFCR_PWMS_MAX; type_index++) { 521 if (pwm_active & BIT(type_index)) 522 mlxsw_hwmon_attr_add(mlxsw_hwmon, 523 MLXSW_HWMON_ATTR_TYPE_PWM, 524 type_index, num++); 525 } 526 return 0; 527 } 528 529 static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon) 530 { 531 char mgpir_pl[MLXSW_REG_MGPIR_LEN]; 532 u8 module_sensor_max; 533 int i, err; 534 535 if (!mlxsw_core_res_query_enabled(mlxsw_hwmon->core)) 536 return 0; 537 538 mlxsw_reg_mgpir_pack(mgpir_pl); 539 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl); 540 if (err) 541 return err; 542 543 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, 544 &module_sensor_max); 545 546 /* Add extra attributes for module temperature. Sensor index is 547 * assigned to sensor_count value, while all indexed before 548 * sensor_count are already utilized by the sensors connected through 549 * mtmp register by mlxsw_hwmon_temp_init(). 550 */ 551 mlxsw_hwmon->module_sensor_max = mlxsw_hwmon->sensor_count + 552 module_sensor_max; 553 for (i = mlxsw_hwmon->sensor_count; 554 i < mlxsw_hwmon->module_sensor_max; i++) { 555 mlxsw_hwmon_attr_add(mlxsw_hwmon, 556 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE, i, i); 557 mlxsw_hwmon_attr_add(mlxsw_hwmon, 558 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT, 559 i, i); 560 mlxsw_hwmon_attr_add(mlxsw_hwmon, 561 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT, i, 562 i); 563 mlxsw_hwmon_attr_add(mlxsw_hwmon, 564 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG, 565 i, i); 566 mlxsw_hwmon_attr_add(mlxsw_hwmon, 567 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL, 568 i, i); 569 } 570 571 return 0; 572 } 573 574 static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon) 575 { 576 int index, max_index, sensor_index; 577 char mgpir_pl[MLXSW_REG_MGPIR_LEN]; 578 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 579 u8 gbox_num; 580 int err; 581 582 mlxsw_reg_mgpir_pack(mgpir_pl); 583 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl); 584 if (err) 585 return err; 586 587 mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, NULL, NULL, NULL); 588 if (!gbox_num) 589 return 0; 590 591 index = mlxsw_hwmon->module_sensor_max; 592 max_index = mlxsw_hwmon->module_sensor_max + gbox_num; 593 while (index < max_index) { 594 sensor_index = index % mlxsw_hwmon->module_sensor_max + 595 MLXSW_REG_MTMP_GBOX_INDEX_MIN; 596 mlxsw_reg_mtmp_pack(mtmp_pl, sensor_index, true, true); 597 err = mlxsw_reg_write(mlxsw_hwmon->core, 598 MLXSW_REG(mtmp), mtmp_pl); 599 if (err) { 600 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to setup temp sensor number %d\n", 601 sensor_index); 602 return err; 603 } 604 mlxsw_hwmon_attr_add(mlxsw_hwmon, MLXSW_HWMON_ATTR_TYPE_TEMP, 605 index, index); 606 mlxsw_hwmon_attr_add(mlxsw_hwmon, 607 MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, index, 608 index); 609 mlxsw_hwmon_attr_add(mlxsw_hwmon, 610 MLXSW_HWMON_ATTR_TYPE_TEMP_RST, index, 611 index); 612 mlxsw_hwmon_attr_add(mlxsw_hwmon, 613 MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL, 614 index, index); 615 index++; 616 } 617 618 return 0; 619 } 620 621 int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, 622 const struct mlxsw_bus_info *mlxsw_bus_info, 623 struct mlxsw_hwmon **p_hwmon) 624 { 625 struct mlxsw_hwmon *mlxsw_hwmon; 626 struct device *hwmon_dev; 627 int err; 628 629 mlxsw_hwmon = kzalloc(sizeof(*mlxsw_hwmon), GFP_KERNEL); 630 if (!mlxsw_hwmon) 631 return -ENOMEM; 632 mlxsw_hwmon->core = mlxsw_core; 633 mlxsw_hwmon->bus_info = mlxsw_bus_info; 634 635 err = mlxsw_hwmon_temp_init(mlxsw_hwmon); 636 if (err) 637 goto err_temp_init; 638 639 err = mlxsw_hwmon_fans_init(mlxsw_hwmon); 640 if (err) 641 goto err_fans_init; 642 643 err = mlxsw_hwmon_module_init(mlxsw_hwmon); 644 if (err) 645 goto err_temp_module_init; 646 647 err = mlxsw_hwmon_gearbox_init(mlxsw_hwmon); 648 if (err) 649 goto err_temp_gearbox_init; 650 651 mlxsw_hwmon->groups[0] = &mlxsw_hwmon->group; 652 mlxsw_hwmon->group.attrs = mlxsw_hwmon->attrs; 653 654 hwmon_dev = hwmon_device_register_with_groups(mlxsw_bus_info->dev, 655 "mlxsw", mlxsw_hwmon, 656 mlxsw_hwmon->groups); 657 if (IS_ERR(hwmon_dev)) { 658 err = PTR_ERR(hwmon_dev); 659 goto err_hwmon_register; 660 } 661 662 mlxsw_hwmon->hwmon_dev = hwmon_dev; 663 *p_hwmon = mlxsw_hwmon; 664 return 0; 665 666 err_hwmon_register: 667 err_temp_gearbox_init: 668 err_temp_module_init: 669 err_fans_init: 670 err_temp_init: 671 kfree(mlxsw_hwmon); 672 return err; 673 } 674 675 void mlxsw_hwmon_fini(struct mlxsw_hwmon *mlxsw_hwmon) 676 { 677 hwmon_device_unregister(mlxsw_hwmon->hwmon_dev); 678 kfree(mlxsw_hwmon); 679 } 680