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