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_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
  19struct 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
  26static 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
  34struct 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_count;
  45};
  46
  47static 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_count);
  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
  70static 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_count);
  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
  93static 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_count);
 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
 122static 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
 141static 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
 162static 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
 182static 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
 208static 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
 231static 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
 273static ssize_t
 274mlxsw_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
 295static ssize_t
 296mlxsw_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
 318static ssize_t
 319mlxsw_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
 330static ssize_t
 331mlxsw_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_count + 1;
 340
 341        return sprintf(buf, "gearbox %03u\n", index);
 342}
 343
 344enum 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
 359static 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
 460static 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
 492static 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
 529static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon)
 530{
 531        unsigned int module_count = mlxsw_core_max_ports(mlxsw_hwmon->core);
 532        char pmlp_pl[MLXSW_REG_PMLP_LEN] = {0};
 533        int i, index;
 534        u8 width;
 535        int err;
 536
 537        if (!mlxsw_core_res_query_enabled(mlxsw_hwmon->core))
 538                return 0;
 539
 540        /* Add extra attributes for module temperature. Sensor index is
 541         * assigned to sensor_count value, while all indexed before
 542         * sensor_count are already utilized by the sensors connected through
 543         * mtmp register by mlxsw_hwmon_temp_init().
 544         */
 545        index = mlxsw_hwmon->sensor_count;
 546        for (i = 1; i < module_count; i++) {
 547                mlxsw_reg_pmlp_pack(pmlp_pl, i);
 548                err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(pmlp),
 549                                      pmlp_pl);
 550                if (err) {
 551                        dev_err(mlxsw_hwmon->bus_info->dev, "Failed to read module index %d\n",
 552                                i);
 553                        return err;
 554                }
 555                width = mlxsw_reg_pmlp_width_get(pmlp_pl);
 556                if (!width)
 557                        continue;
 558                mlxsw_hwmon_attr_add(mlxsw_hwmon,
 559                                     MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE, index,
 560                                     index);
 561                mlxsw_hwmon_attr_add(mlxsw_hwmon,
 562                                     MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT,
 563                                     index, index);
 564                mlxsw_hwmon_attr_add(mlxsw_hwmon,
 565                                     MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT,
 566                                     index, index);
 567                mlxsw_hwmon_attr_add(mlxsw_hwmon,
 568                                     MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG,
 569                                     index, index);
 570                mlxsw_hwmon_attr_add(mlxsw_hwmon,
 571                                     MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL,
 572                                     index, index);
 573                index++;
 574        }
 575        mlxsw_hwmon->module_sensor_count = index;
 576
 577        return 0;
 578}
 579
 580static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon)
 581{
 582        int index, max_index, sensor_index;
 583        char mgpir_pl[MLXSW_REG_MGPIR_LEN];
 584        char mtmp_pl[MLXSW_REG_MTMP_LEN];
 585        u8 gbox_num;
 586        int err;
 587
 588        mlxsw_reg_mgpir_pack(mgpir_pl);
 589        err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl);
 590        if (err)
 591                return err;
 592
 593        mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, NULL, NULL);
 594        if (!gbox_num)
 595                return 0;
 596
 597        index = mlxsw_hwmon->module_sensor_count;
 598        max_index = mlxsw_hwmon->module_sensor_count + gbox_num;
 599        while (index < max_index) {
 600                sensor_index = index % mlxsw_hwmon->module_sensor_count +
 601                               MLXSW_REG_MTMP_GBOX_INDEX_MIN;
 602                mlxsw_reg_mtmp_pack(mtmp_pl, sensor_index, true, true);
 603                err = mlxsw_reg_write(mlxsw_hwmon->core,
 604                                      MLXSW_REG(mtmp), mtmp_pl);
 605                if (err) {
 606                        dev_err(mlxsw_hwmon->bus_info->dev, "Failed to setup temp sensor number %d\n",
 607                                sensor_index);
 608                        return err;
 609                }
 610                mlxsw_hwmon_attr_add(mlxsw_hwmon, MLXSW_HWMON_ATTR_TYPE_TEMP,
 611                                     index, index);
 612                mlxsw_hwmon_attr_add(mlxsw_hwmon,
 613                                     MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, index,
 614                                     index);
 615                mlxsw_hwmon_attr_add(mlxsw_hwmon,
 616                                     MLXSW_HWMON_ATTR_TYPE_TEMP_RST, index,
 617                                     index);
 618                mlxsw_hwmon_attr_add(mlxsw_hwmon,
 619                                     MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL,
 620                                     index, index);
 621                index++;
 622        }
 623
 624        return 0;
 625}
 626
 627int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
 628                     const struct mlxsw_bus_info *mlxsw_bus_info,
 629                     struct mlxsw_hwmon **p_hwmon)
 630{
 631        struct mlxsw_hwmon *mlxsw_hwmon;
 632        struct device *hwmon_dev;
 633        int err;
 634
 635        mlxsw_hwmon = kzalloc(sizeof(*mlxsw_hwmon), GFP_KERNEL);
 636        if (!mlxsw_hwmon)
 637                return -ENOMEM;
 638        mlxsw_hwmon->core = mlxsw_core;
 639        mlxsw_hwmon->bus_info = mlxsw_bus_info;
 640
 641        err = mlxsw_hwmon_temp_init(mlxsw_hwmon);
 642        if (err)
 643                goto err_temp_init;
 644
 645        err = mlxsw_hwmon_fans_init(mlxsw_hwmon);
 646        if (err)
 647                goto err_fans_init;
 648
 649        err = mlxsw_hwmon_module_init(mlxsw_hwmon);
 650        if (err)
 651                goto err_temp_module_init;
 652
 653        err = mlxsw_hwmon_gearbox_init(mlxsw_hwmon);
 654        if (err)
 655                goto err_temp_gearbox_init;
 656
 657        mlxsw_hwmon->groups[0] = &mlxsw_hwmon->group;
 658        mlxsw_hwmon->group.attrs = mlxsw_hwmon->attrs;
 659
 660        hwmon_dev = hwmon_device_register_with_groups(mlxsw_bus_info->dev,
 661                                                      "mlxsw", mlxsw_hwmon,
 662                                                      mlxsw_hwmon->groups);
 663        if (IS_ERR(hwmon_dev)) {
 664                err = PTR_ERR(hwmon_dev);
 665                goto err_hwmon_register;
 666        }
 667
 668        mlxsw_hwmon->hwmon_dev = hwmon_dev;
 669        *p_hwmon = mlxsw_hwmon;
 670        return 0;
 671
 672err_hwmon_register:
 673err_temp_gearbox_init:
 674err_temp_module_init:
 675err_fans_init:
 676err_temp_init:
 677        kfree(mlxsw_hwmon);
 678        return err;
 679}
 680
 681void mlxsw_hwmon_fini(struct mlxsw_hwmon *mlxsw_hwmon)
 682{
 683        hwmon_device_unregister(mlxsw_hwmon->hwmon_dev);
 684        kfree(mlxsw_hwmon);
 685}
 686