linux/drivers/misc/habanalabs/hwmon.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2
   3/*
   4 * Copyright 2016-2019 HabanaLabs, Ltd.
   5 * All Rights Reserved.
   6 */
   7
   8#include "habanalabs.h"
   9
  10#include <linux/pci.h>
  11#include <linux/hwmon.h>
  12
  13#define SENSORS_PKT_TIMEOUT             1000000 /* 1s */
  14#define HWMON_NR_SENSOR_TYPES           (hwmon_pwm + 1)
  15
  16int hl_build_hwmon_channel_info(struct hl_device *hdev,
  17                                struct armcp_sensor *sensors_arr)
  18{
  19        u32 counts[HWMON_NR_SENSOR_TYPES] = {0};
  20        u32 *sensors_by_type[HWMON_NR_SENSOR_TYPES] = {NULL};
  21        u32 sensors_by_type_next_index[HWMON_NR_SENSOR_TYPES] = {0};
  22        struct hwmon_channel_info **channels_info;
  23        u32 num_sensors_for_type, num_active_sensor_types = 0,
  24                        arr_size = 0, *curr_arr;
  25        enum hwmon_sensor_types type;
  26        int rc, i, j;
  27
  28        for (i = 0 ; i < ARMCP_MAX_SENSORS ; i++) {
  29                type = __le32_to_cpu(sensors_arr[i].type);
  30
  31                if ((type == 0) && (sensors_arr[i].flags == 0))
  32                        break;
  33
  34                if (type >= HWMON_NR_SENSOR_TYPES) {
  35                        dev_err(hdev->dev,
  36                                "Got wrong sensor type %d from device\n", type);
  37                        return -EINVAL;
  38                }
  39
  40                counts[type]++;
  41                arr_size++;
  42        }
  43
  44        for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) {
  45                if (counts[i] == 0)
  46                        continue;
  47
  48                num_sensors_for_type = counts[i] + 1;
  49                curr_arr = kcalloc(num_sensors_for_type, sizeof(*curr_arr),
  50                                GFP_KERNEL);
  51                if (!curr_arr) {
  52                        rc = -ENOMEM;
  53                        goto sensors_type_err;
  54                }
  55
  56                num_active_sensor_types++;
  57                sensors_by_type[i] = curr_arr;
  58        }
  59
  60        for (i = 0 ; i < arr_size ; i++) {
  61                type = __le32_to_cpu(sensors_arr[i].type);
  62                curr_arr = sensors_by_type[type];
  63                curr_arr[sensors_by_type_next_index[type]++] =
  64                                __le32_to_cpu(sensors_arr[i].flags);
  65        }
  66
  67        channels_info = kcalloc(num_active_sensor_types + 1,
  68                        sizeof(*channels_info), GFP_KERNEL);
  69        if (!channels_info) {
  70                rc = -ENOMEM;
  71                goto channels_info_array_err;
  72        }
  73
  74        for (i = 0 ; i < num_active_sensor_types ; i++) {
  75                channels_info[i] = kzalloc(sizeof(*channels_info[i]),
  76                                GFP_KERNEL);
  77                if (!channels_info[i]) {
  78                        rc = -ENOMEM;
  79                        goto channel_info_err;
  80                }
  81        }
  82
  83        for (i = 0, j = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) {
  84                if (!sensors_by_type[i])
  85                        continue;
  86
  87                channels_info[j]->type = i;
  88                channels_info[j]->config = sensors_by_type[i];
  89                j++;
  90        }
  91
  92        hdev->hl_chip_info->info =
  93                        (const struct hwmon_channel_info **)channels_info;
  94
  95        return 0;
  96
  97channel_info_err:
  98        for (i = 0 ; i < num_active_sensor_types ; i++)
  99                if (channels_info[i]) {
 100                        kfree(channels_info[i]->config);
 101                        kfree(channels_info[i]);
 102                }
 103        kfree(channels_info);
 104channels_info_array_err:
 105sensors_type_err:
 106        for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++)
 107                kfree(sensors_by_type[i]);
 108
 109        return rc;
 110}
 111
 112static int hl_read(struct device *dev, enum hwmon_sensor_types type,
 113                        u32 attr, int channel, long *val)
 114{
 115        struct hl_device *hdev = dev_get_drvdata(dev);
 116
 117        if (hl_device_disabled_or_in_reset(hdev))
 118                return -ENODEV;
 119
 120        switch (type) {
 121        case hwmon_temp:
 122                switch (attr) {
 123                case hwmon_temp_input:
 124                case hwmon_temp_max:
 125                case hwmon_temp_crit:
 126                case hwmon_temp_max_hyst:
 127                case hwmon_temp_crit_hyst:
 128                        break;
 129                default:
 130                        return -EINVAL;
 131                }
 132
 133                *val = hl_get_temperature(hdev, channel, attr);
 134                break;
 135        case hwmon_in:
 136                switch (attr) {
 137                case hwmon_in_input:
 138                case hwmon_in_min:
 139                case hwmon_in_max:
 140                        break;
 141                default:
 142                        return -EINVAL;
 143                }
 144
 145                *val = hl_get_voltage(hdev, channel, attr);
 146                break;
 147        case hwmon_curr:
 148                switch (attr) {
 149                case hwmon_curr_input:
 150                case hwmon_curr_min:
 151                case hwmon_curr_max:
 152                        break;
 153                default:
 154                        return -EINVAL;
 155                }
 156
 157                *val = hl_get_current(hdev, channel, attr);
 158                break;
 159        case hwmon_fan:
 160                switch (attr) {
 161                case hwmon_fan_input:
 162                case hwmon_fan_min:
 163                case hwmon_fan_max:
 164                        break;
 165                default:
 166                        return -EINVAL;
 167                }
 168                *val = hl_get_fan_speed(hdev, channel, attr);
 169                break;
 170        case hwmon_pwm:
 171                switch (attr) {
 172                case hwmon_pwm_input:
 173                case hwmon_pwm_enable:
 174                        break;
 175                default:
 176                        return -EINVAL;
 177                }
 178                *val = hl_get_pwm_info(hdev, channel, attr);
 179                break;
 180        default:
 181                return -EINVAL;
 182        }
 183        return 0;
 184}
 185
 186static int hl_write(struct device *dev, enum hwmon_sensor_types type,
 187                        u32 attr, int channel, long val)
 188{
 189        struct hl_device *hdev = dev_get_drvdata(dev);
 190
 191        if (hl_device_disabled_or_in_reset(hdev))
 192                return -ENODEV;
 193
 194        switch (type) {
 195        case hwmon_pwm:
 196                switch (attr) {
 197                case hwmon_pwm_input:
 198                case hwmon_pwm_enable:
 199                        break;
 200                default:
 201                        return -EINVAL;
 202                }
 203                hl_set_pwm_info(hdev, channel, attr, val);
 204                break;
 205        default:
 206                return -EINVAL;
 207        }
 208        return 0;
 209}
 210
 211static umode_t hl_is_visible(const void *data, enum hwmon_sensor_types type,
 212                                u32 attr, int channel)
 213{
 214        switch (type) {
 215        case hwmon_temp:
 216                switch (attr) {
 217                case hwmon_temp_input:
 218                case hwmon_temp_max:
 219                case hwmon_temp_max_hyst:
 220                case hwmon_temp_crit:
 221                case hwmon_temp_crit_hyst:
 222                        return 0444;
 223                }
 224                break;
 225        case hwmon_in:
 226                switch (attr) {
 227                case hwmon_in_input:
 228                case hwmon_in_min:
 229                case hwmon_in_max:
 230                        return 0444;
 231                }
 232                break;
 233        case hwmon_curr:
 234                switch (attr) {
 235                case hwmon_curr_input:
 236                case hwmon_curr_min:
 237                case hwmon_curr_max:
 238                        return 0444;
 239                }
 240                break;
 241        case hwmon_fan:
 242                switch (attr) {
 243                case hwmon_fan_input:
 244                case hwmon_fan_min:
 245                case hwmon_fan_max:
 246                        return 0444;
 247                }
 248                break;
 249        case hwmon_pwm:
 250                switch (attr) {
 251                case hwmon_pwm_input:
 252                case hwmon_pwm_enable:
 253                        return 0644;
 254                }
 255                break;
 256        default:
 257                break;
 258        }
 259        return 0;
 260}
 261
 262static const struct hwmon_ops hl_hwmon_ops = {
 263        .is_visible = hl_is_visible,
 264        .read = hl_read,
 265        .write = hl_write
 266};
 267
 268long hl_get_temperature(struct hl_device *hdev, int sensor_index, u32 attr)
 269{
 270        struct armcp_packet pkt;
 271        long result;
 272        int rc;
 273
 274        memset(&pkt, 0, sizeof(pkt));
 275
 276        pkt.ctl = __cpu_to_le32(ARMCP_PACKET_TEMPERATURE_GET <<
 277                                ARMCP_PKT_CTL_OPCODE_SHIFT);
 278        pkt.sensor_index = __cpu_to_le16(sensor_index);
 279        pkt.type = __cpu_to_le16(attr);
 280
 281        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
 282                        SENSORS_PKT_TIMEOUT, &result);
 283
 284        if (rc) {
 285                dev_err(hdev->dev,
 286                        "Failed to get temperature from sensor %d, error %d\n",
 287                        sensor_index, rc);
 288                result = 0;
 289        }
 290
 291        return result;
 292}
 293
 294long hl_get_voltage(struct hl_device *hdev, int sensor_index, u32 attr)
 295{
 296        struct armcp_packet pkt;
 297        long result;
 298        int rc;
 299
 300        memset(&pkt, 0, sizeof(pkt));
 301
 302        pkt.ctl = __cpu_to_le32(ARMCP_PACKET_VOLTAGE_GET <<
 303                                ARMCP_PKT_CTL_OPCODE_SHIFT);
 304        pkt.sensor_index = __cpu_to_le16(sensor_index);
 305        pkt.type = __cpu_to_le16(attr);
 306
 307        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
 308                                        SENSORS_PKT_TIMEOUT, &result);
 309
 310        if (rc) {
 311                dev_err(hdev->dev,
 312                        "Failed to get voltage from sensor %d, error %d\n",
 313                        sensor_index, rc);
 314                result = 0;
 315        }
 316
 317        return result;
 318}
 319
 320long hl_get_current(struct hl_device *hdev, int sensor_index, u32 attr)
 321{
 322        struct armcp_packet pkt;
 323        long result;
 324        int rc;
 325
 326        memset(&pkt, 0, sizeof(pkt));
 327
 328        pkt.ctl = __cpu_to_le32(ARMCP_PACKET_CURRENT_GET <<
 329                                ARMCP_PKT_CTL_OPCODE_SHIFT);
 330        pkt.sensor_index = __cpu_to_le16(sensor_index);
 331        pkt.type = __cpu_to_le16(attr);
 332
 333        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
 334                                        SENSORS_PKT_TIMEOUT, &result);
 335
 336        if (rc) {
 337                dev_err(hdev->dev,
 338                        "Failed to get current from sensor %d, error %d\n",
 339                        sensor_index, rc);
 340                result = 0;
 341        }
 342
 343        return result;
 344}
 345
 346long hl_get_fan_speed(struct hl_device *hdev, int sensor_index, u32 attr)
 347{
 348        struct armcp_packet pkt;
 349        long result;
 350        int rc;
 351
 352        memset(&pkt, 0, sizeof(pkt));
 353
 354        pkt.ctl = __cpu_to_le32(ARMCP_PACKET_FAN_SPEED_GET <<
 355                                ARMCP_PKT_CTL_OPCODE_SHIFT);
 356        pkt.sensor_index = __cpu_to_le16(sensor_index);
 357        pkt.type = __cpu_to_le16(attr);
 358
 359        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
 360                                        SENSORS_PKT_TIMEOUT, &result);
 361
 362        if (rc) {
 363                dev_err(hdev->dev,
 364                        "Failed to get fan speed from sensor %d, error %d\n",
 365                        sensor_index, rc);
 366                result = 0;
 367        }
 368
 369        return result;
 370}
 371
 372long hl_get_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr)
 373{
 374        struct armcp_packet pkt;
 375        long result;
 376        int rc;
 377
 378        memset(&pkt, 0, sizeof(pkt));
 379
 380        pkt.ctl = __cpu_to_le32(ARMCP_PACKET_PWM_GET <<
 381                                ARMCP_PKT_CTL_OPCODE_SHIFT);
 382        pkt.sensor_index = __cpu_to_le16(sensor_index);
 383        pkt.type = __cpu_to_le16(attr);
 384
 385        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
 386                                        SENSORS_PKT_TIMEOUT, &result);
 387
 388        if (rc) {
 389                dev_err(hdev->dev,
 390                        "Failed to get pwm info from sensor %d, error %d\n",
 391                        sensor_index, rc);
 392                result = 0;
 393        }
 394
 395        return result;
 396}
 397
 398void hl_set_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr,
 399                        long value)
 400{
 401        struct armcp_packet pkt;
 402        int rc;
 403
 404        memset(&pkt, 0, sizeof(pkt));
 405
 406        pkt.ctl = __cpu_to_le32(ARMCP_PACKET_PWM_SET <<
 407                                ARMCP_PKT_CTL_OPCODE_SHIFT);
 408        pkt.sensor_index = __cpu_to_le16(sensor_index);
 409        pkt.type = __cpu_to_le16(attr);
 410        pkt.value = __cpu_to_le64(value);
 411
 412        rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
 413                                        SENSORS_PKT_TIMEOUT, NULL);
 414
 415        if (rc)
 416                dev_err(hdev->dev,
 417                        "Failed to set pwm info to sensor %d, error %d\n",
 418                        sensor_index, rc);
 419}
 420
 421int hl_hwmon_init(struct hl_device *hdev)
 422{
 423        struct device *dev = hdev->pdev ? &hdev->pdev->dev : hdev->dev;
 424        int rc;
 425
 426        if ((hdev->hwmon_initialized) || !(hdev->fw_loading))
 427                return 0;
 428
 429        if (hdev->hl_chip_info->info) {
 430                hdev->hl_chip_info->ops = &hl_hwmon_ops;
 431
 432                hdev->hwmon_dev = hwmon_device_register_with_info(dev,
 433                                "habanalabs", hdev, hdev->hl_chip_info, NULL);
 434                if (IS_ERR(hdev->hwmon_dev)) {
 435                        rc = PTR_ERR(hdev->hwmon_dev);
 436                        dev_err(hdev->dev,
 437                                "Unable to register hwmon device: %d\n", rc);
 438                        return rc;
 439                }
 440
 441                dev_info(hdev->dev, "%s: add sensors information\n",
 442                        dev_name(hdev->hwmon_dev));
 443
 444                hdev->hwmon_initialized = true;
 445        } else {
 446                dev_info(hdev->dev, "no available sensors\n");
 447        }
 448
 449        return 0;
 450}
 451
 452void hl_hwmon_fini(struct hl_device *hdev)
 453{
 454        if (!hdev->hwmon_initialized)
 455                return;
 456
 457        hwmon_device_unregister(hdev->hwmon_dev);
 458}
 459