linux/drivers/gpu/drm/nouveau/nouveau_hwmon.c
<<
>>
Prefs
   1/*
   2 * Copyright 2010 Red Hat Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: Ben Skeggs
  23 */
  24
  25#ifdef CONFIG_ACPI
  26#include <linux/acpi.h>
  27#endif
  28#include <linux/power_supply.h>
  29#include <linux/hwmon.h>
  30#include <linux/hwmon-sysfs.h>
  31
  32#include "nouveau_drv.h"
  33#include "nouveau_hwmon.h"
  34
  35#include <nvkm/subdev/iccsense.h>
  36#include <nvkm/subdev/volt.h>
  37
  38#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
  39
  40static ssize_t
  41nouveau_hwmon_show_temp1_auto_point1_pwm(struct device *d,
  42                                         struct device_attribute *a, char *buf)
  43{
  44        return snprintf(buf, PAGE_SIZE, "%d\n", 100);
  45}
  46static SENSOR_DEVICE_ATTR(temp1_auto_point1_pwm, 0444,
  47                          nouveau_hwmon_show_temp1_auto_point1_pwm, NULL, 0);
  48
  49static ssize_t
  50nouveau_hwmon_temp1_auto_point1_temp(struct device *d,
  51                                     struct device_attribute *a, char *buf)
  52{
  53        struct drm_device *dev = dev_get_drvdata(d);
  54        struct nouveau_drm *drm = nouveau_drm(dev);
  55        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
  56
  57        return snprintf(buf, PAGE_SIZE, "%d\n",
  58              therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST) * 1000);
  59}
  60static ssize_t
  61nouveau_hwmon_set_temp1_auto_point1_temp(struct device *d,
  62                                         struct device_attribute *a,
  63                                         const char *buf, size_t count)
  64{
  65        struct drm_device *dev = dev_get_drvdata(d);
  66        struct nouveau_drm *drm = nouveau_drm(dev);
  67        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
  68        long value;
  69
  70        if (kstrtol(buf, 10, &value))
  71                return -EINVAL;
  72
  73        therm->attr_set(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST,
  74                        value / 1000);
  75
  76        return count;
  77}
  78static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp, 0644,
  79                          nouveau_hwmon_temp1_auto_point1_temp,
  80                          nouveau_hwmon_set_temp1_auto_point1_temp, 0);
  81
  82static ssize_t
  83nouveau_hwmon_temp1_auto_point1_temp_hyst(struct device *d,
  84                                          struct device_attribute *a, char *buf)
  85{
  86        struct drm_device *dev = dev_get_drvdata(d);
  87        struct nouveau_drm *drm = nouveau_drm(dev);
  88        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
  89
  90        return snprintf(buf, PAGE_SIZE, "%d\n",
  91         therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000);
  92}
  93static ssize_t
  94nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device *d,
  95                                              struct device_attribute *a,
  96                                              const char *buf, size_t count)
  97{
  98        struct drm_device *dev = dev_get_drvdata(d);
  99        struct nouveau_drm *drm = nouveau_drm(dev);
 100        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 101        long value;
 102
 103        if (kstrtol(buf, 10, &value))
 104                return -EINVAL;
 105
 106        therm->attr_set(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST,
 107                        value / 1000);
 108
 109        return count;
 110}
 111static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp_hyst, 0644,
 112                          nouveau_hwmon_temp1_auto_point1_temp_hyst,
 113                          nouveau_hwmon_set_temp1_auto_point1_temp_hyst, 0);
 114
 115static ssize_t
 116nouveau_hwmon_get_pwm1_max(struct device *d,
 117                           struct device_attribute *a, char *buf)
 118{
 119        struct drm_device *dev = dev_get_drvdata(d);
 120        struct nouveau_drm *drm = nouveau_drm(dev);
 121        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 122        int ret;
 123
 124        ret = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MAX_DUTY);
 125        if (ret < 0)
 126                return ret;
 127
 128        return sprintf(buf, "%i\n", ret);
 129}
 130
 131static ssize_t
 132nouveau_hwmon_get_pwm1_min(struct device *d,
 133                           struct device_attribute *a, char *buf)
 134{
 135        struct drm_device *dev = dev_get_drvdata(d);
 136        struct nouveau_drm *drm = nouveau_drm(dev);
 137        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 138        int ret;
 139
 140        ret = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MIN_DUTY);
 141        if (ret < 0)
 142                return ret;
 143
 144        return sprintf(buf, "%i\n", ret);
 145}
 146
 147static ssize_t
 148nouveau_hwmon_set_pwm1_min(struct device *d, struct device_attribute *a,
 149                           const char *buf, size_t count)
 150{
 151        struct drm_device *dev = dev_get_drvdata(d);
 152        struct nouveau_drm *drm = nouveau_drm(dev);
 153        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 154        long value;
 155        int ret;
 156
 157        if (kstrtol(buf, 10, &value))
 158                return -EINVAL;
 159
 160        ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MIN_DUTY, value);
 161        if (ret < 0)
 162                return ret;
 163
 164        return count;
 165}
 166static SENSOR_DEVICE_ATTR(pwm1_min, 0644,
 167                          nouveau_hwmon_get_pwm1_min,
 168                          nouveau_hwmon_set_pwm1_min, 0);
 169
 170static ssize_t
 171nouveau_hwmon_set_pwm1_max(struct device *d, struct device_attribute *a,
 172                           const char *buf, size_t count)
 173{
 174        struct drm_device *dev = dev_get_drvdata(d);
 175        struct nouveau_drm *drm = nouveau_drm(dev);
 176        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 177        long value;
 178        int ret;
 179
 180        if (kstrtol(buf, 10, &value))
 181                return -EINVAL;
 182
 183        ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MAX_DUTY, value);
 184        if (ret < 0)
 185                return ret;
 186
 187        return count;
 188}
 189static SENSOR_DEVICE_ATTR(pwm1_max, 0644,
 190                          nouveau_hwmon_get_pwm1_max,
 191                          nouveau_hwmon_set_pwm1_max, 0);
 192
 193static struct attribute *pwm_fan_sensor_attrs[] = {
 194        &sensor_dev_attr_pwm1_min.dev_attr.attr,
 195        &sensor_dev_attr_pwm1_max.dev_attr.attr,
 196        NULL
 197};
 198static const struct attribute_group pwm_fan_sensor_group = {
 199        .attrs = pwm_fan_sensor_attrs,
 200};
 201
 202static struct attribute *temp1_auto_point_sensor_attrs[] = {
 203        &sensor_dev_attr_temp1_auto_point1_pwm.dev_attr.attr,
 204        &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
 205        &sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr,
 206        NULL
 207};
 208static const struct attribute_group temp1_auto_point_sensor_group = {
 209        .attrs = temp1_auto_point_sensor_attrs,
 210};
 211
 212#define N_ATTR_GROUPS   3
 213
 214static const u32 nouveau_config_chip[] = {
 215        HWMON_C_UPDATE_INTERVAL,
 216        0
 217};
 218
 219static const u32 nouveau_config_in[] = {
 220        HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX | HWMON_I_LABEL,
 221        0
 222};
 223
 224static const u32 nouveau_config_temp[] = {
 225        HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST |
 226        HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_EMERGENCY |
 227        HWMON_T_EMERGENCY_HYST,
 228        0
 229};
 230
 231static const u32 nouveau_config_fan[] = {
 232        HWMON_F_INPUT,
 233        0
 234};
 235
 236static const u32 nouveau_config_pwm[] = {
 237        HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
 238        0
 239};
 240
 241static const u32 nouveau_config_power[] = {
 242        HWMON_P_INPUT | HWMON_P_CAP_MAX | HWMON_P_CRIT,
 243        0
 244};
 245
 246static const struct hwmon_channel_info nouveau_chip = {
 247        .type = hwmon_chip,
 248        .config = nouveau_config_chip,
 249};
 250
 251static const struct hwmon_channel_info nouveau_temp = {
 252        .type = hwmon_temp,
 253        .config = nouveau_config_temp,
 254};
 255
 256static const struct hwmon_channel_info nouveau_fan = {
 257        .type = hwmon_fan,
 258        .config = nouveau_config_fan,
 259};
 260
 261static const struct hwmon_channel_info nouveau_in = {
 262        .type = hwmon_in,
 263        .config = nouveau_config_in,
 264};
 265
 266static const struct hwmon_channel_info nouveau_pwm = {
 267        .type = hwmon_pwm,
 268        .config = nouveau_config_pwm,
 269};
 270
 271static const struct hwmon_channel_info nouveau_power = {
 272        .type = hwmon_power,
 273        .config = nouveau_config_power,
 274};
 275
 276static const struct hwmon_channel_info *nouveau_info[] = {
 277        &nouveau_chip,
 278        &nouveau_temp,
 279        &nouveau_fan,
 280        &nouveau_in,
 281        &nouveau_pwm,
 282        &nouveau_power,
 283        NULL
 284};
 285
 286static umode_t
 287nouveau_chip_is_visible(const void *data, u32 attr, int channel)
 288{
 289        switch (attr) {
 290        case hwmon_chip_update_interval:
 291                return 0444;
 292        default:
 293                return 0;
 294        }
 295}
 296
 297static umode_t
 298nouveau_power_is_visible(const void *data, u32 attr, int channel)
 299{
 300        struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data);
 301        struct nvkm_iccsense *iccsense = nvxx_iccsense(&drm->client.device);
 302
 303        if (!iccsense || !iccsense->data_valid || list_empty(&iccsense->rails))
 304                return 0;
 305
 306        switch (attr) {
 307        case hwmon_power_input:
 308                return 0444;
 309        case hwmon_power_max:
 310                if (iccsense->power_w_max)
 311                        return 0444;
 312                return 0;
 313        case hwmon_power_crit:
 314                if (iccsense->power_w_crit)
 315                        return 0444;
 316                return 0;
 317        default:
 318                return 0;
 319        }
 320}
 321
 322static umode_t
 323nouveau_temp_is_visible(const void *data, u32 attr, int channel)
 324{
 325        struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data);
 326        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 327
 328        if (!therm || !therm->attr_get || nvkm_therm_temp_get(therm) < 0)
 329                return 0;
 330
 331        switch (attr) {
 332        case hwmon_temp_input:
 333                return 0444;
 334        case hwmon_temp_max:
 335        case hwmon_temp_max_hyst:
 336        case hwmon_temp_crit:
 337        case hwmon_temp_crit_hyst:
 338        case hwmon_temp_emergency:
 339        case hwmon_temp_emergency_hyst:
 340                return 0644;
 341        default:
 342                return 0;
 343        }
 344}
 345
 346static umode_t
 347nouveau_pwm_is_visible(const void *data, u32 attr, int channel)
 348{
 349        struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data);
 350        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 351
 352        if (!therm || !therm->attr_get || !therm->fan_get ||
 353            therm->fan_get(therm) < 0)
 354                return 0;
 355
 356        switch (attr) {
 357        case hwmon_pwm_enable:
 358        case hwmon_pwm_input:
 359                return 0644;
 360        default:
 361                return 0;
 362        }
 363}
 364
 365static umode_t
 366nouveau_input_is_visible(const void *data, u32 attr, int channel)
 367{
 368        struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data);
 369        struct nvkm_volt *volt = nvxx_volt(&drm->client.device);
 370
 371        if (!volt || nvkm_volt_get(volt) < 0)
 372                return 0;
 373
 374        switch (attr) {
 375        case hwmon_in_input:
 376        case hwmon_in_label:
 377        case hwmon_in_min:
 378        case hwmon_in_max:
 379                return 0444;
 380        default:
 381                return 0;
 382        }
 383}
 384
 385static umode_t
 386nouveau_fan_is_visible(const void *data, u32 attr, int channel)
 387{
 388        struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data);
 389        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 390
 391        if (!therm || !therm->attr_get || nvkm_therm_fan_sense(therm) < 0)
 392                return 0;
 393
 394        switch (attr) {
 395        case hwmon_fan_input:
 396                return 0444;
 397        default:
 398                return 0;
 399        }
 400}
 401
 402static int
 403nouveau_chip_read(struct device *dev, u32 attr, int channel, long *val)
 404{
 405        switch (attr) {
 406        case hwmon_chip_update_interval:
 407                *val = 1000;
 408                break;
 409        default:
 410                return -EOPNOTSUPP;
 411        }
 412
 413        return 0;
 414}
 415
 416static int
 417nouveau_temp_read(struct device *dev, u32 attr, int channel, long *val)
 418{
 419        struct drm_device *drm_dev = dev_get_drvdata(dev);
 420        struct nouveau_drm *drm = nouveau_drm(drm_dev);
 421        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 422        int ret;
 423
 424        if (!therm || !therm->attr_get)
 425                return -EOPNOTSUPP;
 426
 427        switch (attr) {
 428        case hwmon_temp_input:
 429                if (drm_dev->switch_power_state != DRM_SWITCH_POWER_ON)
 430                        return -EINVAL;
 431                ret = nvkm_therm_temp_get(therm);
 432                *val = ret < 0 ? ret : (ret * 1000);
 433                break;
 434        case hwmon_temp_max:
 435                *val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK)
 436                                        * 1000;
 437                break;
 438        case hwmon_temp_max_hyst:
 439                *val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST)
 440                                        * 1000;
 441                break;
 442        case hwmon_temp_crit:
 443                *val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_CRITICAL)
 444                                        * 1000;
 445                break;
 446        case hwmon_temp_crit_hyst:
 447                *val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_CRITICAL_HYST)
 448                                        * 1000;
 449                break;
 450        case hwmon_temp_emergency:
 451                *val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN)
 452                                        * 1000;
 453                break;
 454        case hwmon_temp_emergency_hyst:
 455                *val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST)
 456                                        * 1000;
 457                break;
 458        default:
 459                return -EOPNOTSUPP;
 460        }
 461
 462        return 0;
 463}
 464
 465static int
 466nouveau_fan_read(struct device *dev, u32 attr, int channel, long *val)
 467{
 468        struct drm_device *drm_dev = dev_get_drvdata(dev);
 469        struct nouveau_drm *drm = nouveau_drm(drm_dev);
 470        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 471
 472        if (!therm)
 473                return -EOPNOTSUPP;
 474
 475        switch (attr) {
 476        case hwmon_fan_input:
 477                if (drm_dev->switch_power_state != DRM_SWITCH_POWER_ON)
 478                        return -EINVAL;
 479                *val = nvkm_therm_fan_sense(therm);
 480                break;
 481        default:
 482                return -EOPNOTSUPP;
 483        }
 484
 485        return 0;
 486}
 487
 488static int
 489nouveau_in_read(struct device *dev, u32 attr, int channel, long *val)
 490{
 491        struct drm_device *drm_dev = dev_get_drvdata(dev);
 492        struct nouveau_drm *drm = nouveau_drm(drm_dev);
 493        struct nvkm_volt *volt = nvxx_volt(&drm->client.device);
 494        int ret;
 495
 496        if (!volt)
 497                return -EOPNOTSUPP;
 498
 499        switch (attr) {
 500        case hwmon_in_input:
 501                if (drm_dev->switch_power_state != DRM_SWITCH_POWER_ON)
 502                        return -EINVAL;
 503                ret = nvkm_volt_get(volt);
 504                *val = ret < 0 ? ret : (ret / 1000);
 505                break;
 506        case hwmon_in_min:
 507                *val = volt->min_uv > 0 ? (volt->min_uv / 1000) : -ENODEV;
 508                break;
 509        case hwmon_in_max:
 510                *val = volt->max_uv > 0 ? (volt->max_uv / 1000) : -ENODEV;
 511                break;
 512        default:
 513                return -EOPNOTSUPP;
 514        }
 515
 516        return 0;
 517}
 518
 519static int
 520nouveau_pwm_read(struct device *dev, u32 attr, int channel, long *val)
 521{
 522        struct drm_device *drm_dev = dev_get_drvdata(dev);
 523        struct nouveau_drm *drm = nouveau_drm(drm_dev);
 524        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 525
 526        if (!therm || !therm->attr_get || !therm->fan_get)
 527                return -EOPNOTSUPP;
 528
 529        switch (attr) {
 530        case hwmon_pwm_enable:
 531                *val = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MODE);
 532                break;
 533        case hwmon_pwm_input:
 534                if (drm_dev->switch_power_state != DRM_SWITCH_POWER_ON)
 535                        return -EINVAL;
 536                *val = therm->fan_get(therm);
 537                break;
 538        default:
 539                return -EOPNOTSUPP;
 540        }
 541
 542        return 0;
 543}
 544
 545static int
 546nouveau_power_read(struct device *dev, u32 attr, int channel, long *val)
 547{
 548        struct drm_device *drm_dev = dev_get_drvdata(dev);
 549        struct nouveau_drm *drm = nouveau_drm(drm_dev);
 550        struct nvkm_iccsense *iccsense = nvxx_iccsense(&drm->client.device);
 551
 552        if (!iccsense)
 553                return -EOPNOTSUPP;
 554
 555        switch (attr) {
 556        case hwmon_power_input:
 557                if (drm_dev->switch_power_state != DRM_SWITCH_POWER_ON)
 558                        return -EINVAL;
 559                *val = nvkm_iccsense_read_all(iccsense);
 560                break;
 561        case hwmon_power_max:
 562                *val = iccsense->power_w_max;
 563                break;
 564        case hwmon_power_crit:
 565                *val = iccsense->power_w_crit;
 566                break;
 567        default:
 568                return -EOPNOTSUPP;
 569        }
 570
 571        return 0;
 572}
 573
 574static int
 575nouveau_temp_write(struct device *dev, u32 attr, int channel, long val)
 576{
 577        struct drm_device *drm_dev = dev_get_drvdata(dev);
 578        struct nouveau_drm *drm = nouveau_drm(drm_dev);
 579        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 580
 581        if (!therm || !therm->attr_set)
 582                return -EOPNOTSUPP;
 583
 584        switch (attr) {
 585        case hwmon_temp_max:
 586                return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK,
 587                                        val / 1000);
 588        case hwmon_temp_max_hyst:
 589                return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST,
 590                                        val / 1000);
 591        case hwmon_temp_crit:
 592                return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_CRITICAL,
 593                                        val / 1000);
 594        case hwmon_temp_crit_hyst:
 595                return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_CRITICAL_HYST,
 596                                        val / 1000);
 597        case hwmon_temp_emergency:
 598                return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN,
 599                                        val / 1000);
 600        case hwmon_temp_emergency_hyst:
 601                return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST,
 602                                        val / 1000);
 603        default:
 604                return -EOPNOTSUPP;
 605        }
 606}
 607
 608static int
 609nouveau_pwm_write(struct device *dev, u32 attr, int channel, long val)
 610{
 611        struct drm_device *drm_dev = dev_get_drvdata(dev);
 612        struct nouveau_drm *drm = nouveau_drm(drm_dev);
 613        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 614
 615        if (!therm || !therm->attr_set)
 616                return -EOPNOTSUPP;
 617
 618        switch (attr) {
 619        case hwmon_pwm_input:
 620                return therm->fan_set(therm, val);
 621        case hwmon_pwm_enable:
 622                return therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MODE, val);
 623        default:
 624                return -EOPNOTSUPP;
 625        }
 626}
 627
 628static umode_t
 629nouveau_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr,
 630                        int channel)
 631{
 632        switch (type) {
 633        case hwmon_chip:
 634                return nouveau_chip_is_visible(data, attr, channel);
 635        case hwmon_temp:
 636                return nouveau_temp_is_visible(data, attr, channel);
 637        case hwmon_fan:
 638                return nouveau_fan_is_visible(data, attr, channel);
 639        case hwmon_in:
 640                return nouveau_input_is_visible(data, attr, channel);
 641        case hwmon_pwm:
 642                return nouveau_pwm_is_visible(data, attr, channel);
 643        case hwmon_power:
 644                return nouveau_power_is_visible(data, attr, channel);
 645        default:
 646                return 0;
 647        }
 648}
 649
 650static const char input_label[] = "GPU core";
 651
 652static int
 653nouveau_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr,
 654                    int channel, const char **buf)
 655{
 656        if (type == hwmon_in && attr == hwmon_in_label) {
 657                *buf = input_label;
 658                return 0;
 659        }
 660
 661        return -EOPNOTSUPP;
 662}
 663
 664static int
 665nouveau_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
 666                                                        int channel, long *val)
 667{
 668        switch (type) {
 669        case hwmon_chip:
 670                return nouveau_chip_read(dev, attr, channel, val);
 671        case hwmon_temp:
 672                return nouveau_temp_read(dev, attr, channel, val);
 673        case hwmon_fan:
 674                return nouveau_fan_read(dev, attr, channel, val);
 675        case hwmon_in:
 676                return nouveau_in_read(dev, attr, channel, val);
 677        case hwmon_pwm:
 678                return nouveau_pwm_read(dev, attr, channel, val);
 679        case hwmon_power:
 680                return nouveau_power_read(dev, attr, channel, val);
 681        default:
 682                return -EOPNOTSUPP;
 683        }
 684}
 685
 686static int
 687nouveau_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
 688                                                        int channel, long val)
 689{
 690        switch (type) {
 691        case hwmon_temp:
 692                return nouveau_temp_write(dev, attr, channel, val);
 693        case hwmon_pwm:
 694                return nouveau_pwm_write(dev, attr, channel, val);
 695        default:
 696                return -EOPNOTSUPP;
 697        }
 698}
 699
 700static const struct hwmon_ops nouveau_hwmon_ops = {
 701        .is_visible = nouveau_is_visible,
 702        .read = nouveau_read,
 703        .read_string = nouveau_read_string,
 704        .write = nouveau_write,
 705};
 706
 707static const struct hwmon_chip_info nouveau_chip_info = {
 708        .ops = &nouveau_hwmon_ops,
 709        .info = nouveau_info,
 710};
 711#endif
 712
 713int
 714nouveau_hwmon_init(struct drm_device *dev)
 715{
 716#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
 717        struct nouveau_drm *drm = nouveau_drm(dev);
 718        struct nvkm_iccsense *iccsense = nvxx_iccsense(&drm->client.device);
 719        struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
 720        struct nvkm_volt *volt = nvxx_volt(&drm->client.device);
 721        const struct attribute_group *special_groups[N_ATTR_GROUPS];
 722        struct nouveau_hwmon *hwmon;
 723        struct device *hwmon_dev;
 724        int ret = 0;
 725        int i = 0;
 726
 727        if (!iccsense && !therm && !volt) {
 728                NV_DEBUG(drm, "Skipping hwmon registration\n");
 729                return 0;
 730        }
 731
 732        hwmon = drm->hwmon = kzalloc(sizeof(*hwmon), GFP_KERNEL);
 733        if (!hwmon)
 734                return -ENOMEM;
 735        hwmon->dev = dev;
 736
 737        if (therm && therm->attr_get && therm->attr_set) {
 738                if (nvkm_therm_temp_get(therm) >= 0)
 739                        special_groups[i++] = &temp1_auto_point_sensor_group;
 740                if (therm->fan_get && therm->fan_get(therm) >= 0)
 741                        special_groups[i++] = &pwm_fan_sensor_group;
 742        }
 743
 744        special_groups[i] = NULL;
 745        hwmon_dev = hwmon_device_register_with_info(dev->dev, "nouveau", dev,
 746                                                        &nouveau_chip_info,
 747                                                        special_groups);
 748        if (IS_ERR(hwmon_dev)) {
 749                ret = PTR_ERR(hwmon_dev);
 750                NV_ERROR(drm, "Unable to register hwmon device: %d\n", ret);
 751                return ret;
 752        }
 753
 754        hwmon->hwmon = hwmon_dev;
 755        return 0;
 756#else
 757        return 0;
 758#endif
 759}
 760
 761void
 762nouveau_hwmon_fini(struct drm_device *dev)
 763{
 764#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
 765        struct nouveau_hwmon *hwmon = nouveau_hwmon(dev);
 766
 767        if (!hwmon)
 768                return;
 769
 770        if (hwmon->hwmon)
 771                hwmon_device_unregister(hwmon->hwmon);
 772
 773        nouveau_drm(dev)->hwmon = NULL;
 774        kfree(hwmon);
 775#endif
 776}
 777